Own syscall implementation

Oleg Kutkov elenbert at gmail.com
Mon Oct 11 09:49:49 EDT 2010

Thank you for answer.
Sorry, now i made some changes due to actual kernel version

2010/10/11 Russell King - ARM Linux <linux at arm.linux.org.uk>:
> That's fine, except that there's no bounds checking for the value of
> 'call', which if it were negative or a large positive number would
> overflow the nargs array.  You're also not propagating the error back.

asmlinkage long sys_mycall(int call, unsigned long __user *args);

SYSCALL_DEFINE2(mycall, int, call, unsigned long __user *, args)
  unsigned long a[6];
  int err;

  if (call < 1 || call > SYS_ACCEPT4) {
       return -EINVAL;

  if (err = copy_from_user(a, args, nargs[call])) {
      return -EFAULT;

  switch (call) {
     case 0: /*some work*/ break;
     case 1: /*some work*/ break;
     default: break;

  return err;

> You don't say what kernel version.

My kernel version is 2.6.29

> As 312 is already taken (we're now up to 369), and you're using .long, I
> can only assume this is quite an old kernel...  Modern kernels use CALL()
> in calls.S to ensure that the number of syscalls are properly counted.



> So it's really not a good idea to create new syscalls for production code.
> It's usually safer to write something like a char device driver and use
> the read/write/ioctl methods instead.

I understood. I just want to understand "how it works"

> Have you checked the value of 'call' and nargs[call] ?  Note that
> copy_from_user() takes the number of _bytes_ to copy, not the number
> of arguments.

Yes, i checked "call", as i show in code before. nargs i found in
net/socket.c and it defined as:
#define AL(x) ((x) * sizeof(unsigned long))
static const unsigned char nargs[19]={

I looking on SYSCALL_DEFINE2(socketcall, int, call, unsigned long
__user *, args) and here is: if (copy_from_user(a, args,
I used that just as an example that i found..

More information about the linux-arm-kernel mailing list