3

I am using Ubuntu with VirtualBox. I am defining a new command to my shell to output some characteristics(like sibling tree etc.) of child processes. In order to output these characteristics, I created a kernel module and used task_struct. I also tested my kernel module outside of my shell and it works. Now my problem is how to trigger this kernel module inside my shell(in C code) so that my kernel module will be loaded?

I searched and find that I need to use system calls like modprobe or insmod but did not understand how to use them. I tried the code below, but it did not work:

setuid(0);

system("/sbin/insmod /.../mymodule.ko");

Thank you for your help.

Community
  • 1
  • 1
cecemelly
  • 45
  • 1
  • 8
  • what problem did you encounter? what you don't understand? `modprobe` and `insmod` are shell builtins, not syscalls. – Jason Hu Mar 21 '15 at 14:39
  • I tried to use system("/sbin/insmod /.../mymodule.ko"); but it did not work. I mean it did not successfully load my kernel module. – cecemelly Mar 21 '15 at 14:44
  • did you use root? try to load it in shell see what happens first. – Jason Hu Mar 21 '15 at 14:45
  • I did not understand what you mean by using root? If you are asking whether or not I tried "sudo" command, I did. system("/usr/bin/sudo /sbin/insmod ./.../mymodule.ko"); but it also did not work. – cecemelly Mar 21 '15 at 14:50
  • no. this may ask you for a password. you need to run your problem with sudo. `sudo ./your_program`. and get rid of the inside one. – Jason Hu Mar 21 '15 at 14:51
  • I did not understand. I am running my c program using gcc command. Should I change that one? What did you mean by "you need to run your problem with sudo" ? Could you please be more specific? I am a beginner, sorry. – cecemelly Mar 21 '15 at 14:56
  • ah. sorry. you need to run you **program** with sudo. how did you run you program? – Jason Hu Mar 21 '15 at 14:57
  • From terminal by these commands: "gcc myshell.c" and then "./a.out" – cecemelly Mar 21 '15 at 14:59
  • I tried but still my C code could not load the kernel module. – cecemelly Mar 21 '15 at 15:03
  • try to get in root first: `su`. then `insmod your_module.ko`, see if there are error prompts. then investigate `dmesg | tail` see what the kernel says about your module. – Jason Hu Mar 21 '15 at 15:06
  • You should load your module only once. – Basile Starynkevitch Mar 21 '15 at 16:54
  • Possible duplicate of [How to load Linux kernel modules from C code?](https://stackoverflow.com/questions/5947286/how-to-load-linux-kernel-modules-from-c-code) – Ciro Santilli OurBigBook.com Apr 14 '18 at 18:13

1 Answers1

9

Loading module using system()

You are trying to become root in your application (by executing setuid(0)), but you don't have permissions to do that (if you run your program as regular user). Instead, you should check if your program was run from root (using getuid()). Also, it's good idea to test if your module file exists at all. Here is an example of such code (it's tested and does all checking needed):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

#define ROOT_UID    0
#define INSMOD_PATH "/sbin/insmod"
#define MOD_PATH    "/.../mymodule.ko"

int main(void)
{
    uid_t uid;
    int res;

    /* Check if program being run by root */
    uid = getuid();
    if (uid != ROOT_UID) {
        fprintf(stderr, "Error: Please run this program as root\n");
        return EXIT_FAILURE;
    }

    /* Check if module file exists */
    if (access(MOD_PATH, F_OK) == -1) {
        fprintf(stderr, "Error: File \"%s\" doesn't exist\n", MOD_PATH);
        return EXIT_FAILURE;
    }

    /* Load module */
    res = system(INSMOD_PATH " " MOD_PATH);
    if (res != 0) {
        fprintf(stderr, "Error loading module: %d\n", res);
        return EXIT_FAILURE;
    }

    printf("Module \"%s\" was successfully loaded\n", MOD_PATH);

    return EXIT_SUCCESS;
}

Save this code as main.c file. Be sure to replace MOD_PATH definition with actual path of your module file.

Compile it using next command:

$ gcc -Wall -O2 main.c -o load_module

Now do the next:

$ su
# ./load_module
  1. First command switches your user to root (you will be asked to enter root password). If you don't know root password, try using sudo -s command instead of su.
  2. Second command runs your program.

Pay your attention to the last character at the command prompt:

  • # means you have root permissions at this point
  • $ means you only have regular user permissions.

Loading module using finit_module()

Using system() function in C is usually considered a bad practice (because it takes a lot of time for execution and basically just trying to replace a much more simple Bash script).

If you want to load kernel module in C without using system(), you can look into source code of insmod tool. See libkmod/libkmod-module.c file, kmod_module_insert_module() function. You can see those sources here.

Pay attention to finit_module() function call. A good explanation about this system call can be found at manual pages:

$ man finit_module

Here is an example how you can use finit_module() system call:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/stat.h>
#include <fcntl.h>

#define ROOT_UID    0
#define MOD_PATH    "/.../mymodule.ko"

static inline int finit_module(int fd, const char *uargs, int flags)
{
    return syscall(__NR_finit_module, fd, uargs, flags);
}

int main(void)
{
    uid_t uid;
    long res;
    int fd;

    /* Check if program being run by root */
    uid = getuid();
    if (uid != ROOT_UID) {
        fprintf(stderr, "Error: Please run this program as root\n");
        return EXIT_FAILURE;
    }

    /* Check if module file exists */
    if (access(MOD_PATH, F_OK) == -1) {
        fprintf(stderr, "Error: File \"%s\" doesn't exist\n", MOD_PATH);
        return EXIT_FAILURE;
    }

    /* Load module */
    fd = open(MOD_PATH, O_RDONLY | O_CLOEXEC);
    if (fd < 0) {
        perror("Unable to open module file");
        return EXIT_FAILURE;
    }
    res = finit_module(fd, "", 0);
    if (res != 0) {
        perror("Error when loading module");
        close(fd);
        return EXIT_FAILURE;
    }
    close(fd);

    printf("Module \"%s\" was successfully loaded\n", MOD_PATH);

    return EXIT_SUCCESS;
}
Sam Protsenko
  • 14,045
  • 4
  • 59
  • 75