Fayemrost
Fayemrost

Reputation: 51

Error: conflicting types when trying to make a simple syscall

I'm brand new to Linux programming and I'm trying to implement a simple system call loosely following this guide: https://medium.com/anubhav-shrimal/adding-a-hello-world-system-call-to-linux-kernel-dad32875872. In my linux kernel directory, I created a new directory called my_syscall. Within that directory, I created my_syscall.c. Here is my_syscall.c

#include <linux/syscalls.h>
#include <linux/kernel.h>

asmlinkage long sys_my_syscall(int i) {
   prink(KERN_INFO "This is the system call.");
   return(0);
}

I then created a Makefile in the my_syscall directory with a single line:

obj-y := my_syscall.o

I then edited this line in the Makefile in the kernel directory to be:

core-y         += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ my_syscall/

Then, in the directory linux-5.4.15/arch/x86/entry/syscalls, I edited the syscall_64.tbl to include the following line at the very end:

548     64         my_syscall          sys_my_syscall

Finally, in the directory linux-5.4.15/include/linux, I edited the syscalls.h file to include this line before the #endif:

asmlinkage long sys_my_syscall(int i);

Now, when I run the command sudo make, I run into the following error soon after:

./arch/x86/include/generated/asm/syscalls_64.h:2664:19: error: conflicting types for 'sys_my_syscall'
__SYSCALL_64(548, sys_my_syscall, )

arch/x86/entry/syscall_64.c:18:60: note: in definition of macro '__SYSCALL-64'
  #define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);

In file included from arch/x86/entry/syscall_64.c:7:0:
./include/linux/syscalls.h:1423:17: note: previous declaration of 'sys_my_syscall' was here
 asmlinkage long sys_my_syscall(int i);
                 ^
make[3]: *** [arch/x86/entry/syscall_64.o] Error 1
make[2]: *** [arch/x86/entry] Error 2
make[1]: *** [arch/x86] Error 2
make: *** [sub-make] Error 2

I have no idea how to approach this error. With a conflicting types error, I would think I declared the syscall differently in someplace, but in both my_syscall.c and the syscalls.h files, the declaration is the same. These were the only two files where the syscall is declared, but it is also named within syscall_64.tbl and it seems like this is where linux is trying to point me towards. However, I don't see what's wrong with how I declared it in the table as I followed the guide directly. Any help with this would be greatly appreciated!

Info:

Kernel version: 5.4.15

Linux Distribution: Ubuntu 14

Upvotes: 1

Views: 3364

Answers (5)

Jiung Choi
Jiung Choi

Reputation: 11

    #include <linux/syscalls.h>
    #include <linux/kernel.h>

    SYSCALL_DEFINE1(my_syscall, int, i)
    {
       printk(KERN_INFO "This is the system call (param %d).\n", i);
       return(0);
    }

For kernel 5, try deleting "sys_" before "my_syscall" and try. It worked for me

Upvotes: 1

eineComadreja
eineComadreja

Reputation: 186

I just changed the location where the syscall number is defined in syscall_64.tbl.

Instead of this:

548     64         my_syscall          sys_my_syscall

I wrote this:

436     common     my_syscall          __x64_sys_my_syscall

Screen Capture of my configuration

It worked out.

Upvotes: 6

Fayemrost
Fayemrost

Reputation: 51

I eventually gave up on trying to implement this in kernel 5. Unfortunately, none of the other solutions resulted in my kernel compiling. I rolled back my kernel and followed the steps here. This resulted in the system call working correctly. I'm not sure how to make this function in kernel 5+.

Upvotes: 1

user12821817
user12821817

Reputation: 21

I'm doing something similar and got the exact same error.

What fixed the error for me is changing the last part of the syscall_64.tbl table entry from "sys_my_syscall" to "__x64_sys_my_syscall". If you scroll up, other entries have the same prefix. The kernel started compiling after I made that change.

Upvotes: 2

Ian Abbott
Ian Abbott

Reputation: 17403

Some architectures (including x86-64) use syscall wrappers to call the real syscall handler. To define the real syscall handler and its wrappers (for architectures that use syscall wrappers), use one of the SYSCALL_DEFINE<n> macros before the body of the syscall handler. The parameters of the SYSCALL_DEFINE<n> macros are the function name, followed by <n> pairs of ``type, param'' for the function parameters.

Your sys_my_syscall syscall handler function has one parameter, so use the SYSCALL_DEFINE1 macro before the body of the function:

#include <linux/syscalls.h>
#include <linux/kernel.h>

SYSCALL_DEFINE1(sys_my_syscall, int, i)
{
   printk(KERN_INFO "This is the system call (param %d).\n", i);
   return(0);
}

Upvotes: 0

Related Questions