next up previous
Next: communicating with rt-threads Up: Kernel Threads Previous: Kernel Threads

simple example

This first example is not rt-specific, it only should give a framework of a kthread, this module declares a kernel function exec_cmd that is local to this module, a kernel thread is initiated passing this function as the routine to execute and a string via the arg pointer. The call to kernel_thread() initializes a task structure that is visible from user space (the pid of the process is printk'ed) and the thread routine (exec_cmd) is executed once. As we did not set up a specific context for this thread it runs in the inherited context of insmod and thus prints to the current console via the echo command. The thread routine is comparable to a regular user-space function that would call execve except for the privileges and the enabling of the kernels data section to store command arguments in set_fs(KERNEL_DS). This also shows one clear danger of kernel threads - if they are not set up carefully with respect to privileges they can result in a serious security problem - for details on this give the kmod kernel_thread implementation in kernel/kmod.c a look.

What we need specifically for kernel_threads:


#deine __KERNEL__
#deine __KERNEL__SYSCALLS__
#include <linux/unistd.h>
#include <asm/unistd.h>

Now on to the actual code for a kernel_thread - as usual... we start with a `Hello World` . But doing this from kernel space is not quite as simple. The setup we are going to use to write to your current console is to invoke /bin/echo and let it print the infamous string, to be able to use /bin/echo we must set up a minimum environment first.


int errno;

char cmd_path[256] = "/bin/echo";

static int 
exec_cmd(void * kthread_arg)
{
  struct task_struct *curtask = current;

To set up a minimum environment we need to fill out at least TERM and PATH but note that we still inherit the environment of who ever launched insmod of this module ! sounds dangerous ? - it is !


  static char * envp[] = { 
    "HOME=/root ", 
    "TERM=linux ", 
    "PATH=/bin", 
    NULL };
  char *argv[] = { 
    cmd_path,
    kthread_arg,
    NULL };
  int ret;

Give the kthread all effective privileges and allow it to use the kernels data segment KERNEL_DS to store the arguments to execv.


  curtask->euid = curtask->fsuid = 0;
  curtask->egid = curtask->fsgid = 0;
  cap_set_full(curtask->cap_effective);

  set_fs(KERNEL_DS);

Now we only need to call execve, which will not return unless it fails, so on success the kernel_thread terminated, on failure we printk and terminate it our selves with return.


  printk("calling execve for %s \n",
    cmd_path); 
  ret = execve(cmd_path, argv, envp);

  /* if we get here - execve failed */
  printk(KERN_ERR "%s failed (%d)\n", 
    cmd_path,
    ret);
  return -1;
}

The creation of the kernel_thread is done in init_module, and we printk the PID of the created kernel_thread so we could actually check it with the ps tools to see that it is running (due to the short life-time of our `hello world` thread though, you will hardly be able to see it...). Note that we use pid as return value on failure - init_module will terminate and dealloc'ed any resources allocated automatically by the kernel if init_module returns with anything else but 0 (but the kernel will not free any resources you explicitly requested before init_module failed - those are your job to free...).


int 
init_module(void) 
{
  pid_t pid;
  char kthread_arg[]="Hello World !";

  pid = kernel_thread(
    exec_cmd, 
    (void*) kthread_arg, 
    0);
  if (pid < 0) {
    printk(KERN_ERR \
      "fork failed, errno %d\n",
      -pid);
    return pid;
  }
  printk("fork ok, pid %d\n",
    pid);
  return 0;
}

There is nothing to be done in cleanup_module, we did not allocate any resources that will not be freed automatically - note that we don't explicitly reclaim the kernel_thread in any way, the call to execve or, on failure, the return, terminated it and freed any resources associated with this process.


next up previous
Next: communicating with rt-threads Up: Kernel Threads Previous: Kernel Threads
Der Herr Hofrat
2003-01-06