Reputation: 51
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
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
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
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
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
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