7
votes

I am having some difficulty calling a system call from inside a Linux Kernel Module. The system calls have been tested and work properly from a standard c user space program but I can't seem to get the kernel module to compile and run them.

In my user program I include the following code and the system call works:

#include <linux/unistd.h>   
#define __NR_sys_mycall 343

extern long int _syscall(long int_sysno,...)__THROW;

//and then a simple call is done as such
long value = syscall(__NR_sys_mycall);

printf("The value is %ld\n",value);

But when I try the same thing in my Linux Kernel Module I get a bunch of errors that either say error: implicit declaration of function 'syscall' (if I don't include the _syscall definition) or a long list of errors about syntax if I do...so my assumption is that I need the kernel space version to call the system call. Am I right or wrong?

//My LKM code
#include <linux/module.h>
#include <linux/unistd.h>
#define __NR_sys_mycall 343

static int start_init(void)
{
   long value = syscall(__NR_sys_mycall);
   printk("The value is %ld\n",value);

   return 0;
}

static void finish_exit(void)
{
      printk("Done!\n");
}

module_init(start_init);
module_exit(finish_exit);
2
Why are you attempting to use system calls in a kernel module? 99.95% of the time, using system calls in a kernel module is the wrong way to do whatever you're trying to do.tangrs
I need to use kmalloc repeatedly and then measure the average fragmentation caused by my rework of one of the linux memory allocators. The system calls provide the resulting information and the LKM allows me to use kmalloc...rather it is a requirement...so I would like to be able allocate and then call the system calls right after.dimlee
This sounds like a job for sysfs which is built for what you need: exporting information from the kernel to userspace. You could also write a character device driver. There's also procfs and netlink. Writing a whole new system call is probably the least correct way to do what you're trying to do.tangrs
Look for exported functions (EXPORTED_*) within the kernel source, its a better than directly calling sys_something() in most cases.askb

2 Answers

9
votes

You can directly call sys_mycall.

#include <linux/module.h>
#include <linux/unistd.h>


static int start_init(void)
{
   long value = sys_mycall (pass_arguments)
   printk("The value is %ld\n",value);

   return 0;
}

static void finish_exit(void)
{
      printk("Done!\n");
}

module_init(start_init);
module_exit(finish_exit);
5
votes

Most of system calls uses asmlinkage , which means find the arguments on the stack rather than registers. Make sure that , when you call system call , pass the arguments on stack.

Also lot many system calls just uses copy_from_user. If you pass kernel address into such system call , they do fail.