Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When implementing a system call, how do you expose the system call number to userland?

I'm fiddling with system calls. I've added two new ones and verified they work using calls to syscall.

I would like the syscall numbers to be in a header so that userspace does not have to know the syscall number explicitly.

In arch/x86/syscalls/syscall_64.tbl I have:

317     64      krun_read_msrs                  sys_krun_read_msrs
318     64      krun_reset_msrs                 sys_krun_reset_msrs

And some grepping suggests that kbuild has auto-generated the macros for the new syscalls:

$ ag __NR_krun *
arch/x86/include/generated/uapi/asm/unistd_64.h
321:#define __NR_krun_read_msrs 317
322:#define __NR_krun_reset_msrs 318

The filename suggests that I don't need to add the entries manually, but this is contrary to what the Linux Kernel docs have to say:

Some architectures (e.g. x86) have their own architecture-specific syscall tables, but several other architectures share a generic syscall table. Add your new system call to the generic list by adding an entry to the list in include/uapi/asm-generic/unistd.h:

#define __NR_xyzzy 292
__SYSCALL(__NR_xyzzy, sys_xyzzy)

Well, my syscalls are x86_64 specific, since they read and write MSRs found only in Intel chips. So after this, I went digging to see if I could find the arch-specific header for my amd64 system.

You would expect it to be under arch/x86_64 but there are no includes at all in there. So I assume x86_64 inherits from x86. That being the case, the arch-specific header should be:

arch/x86/include/uapi/asm/unistd.h

If you open that up, it's just a little wrapper to dispatch based on arch:

# ifdef __i386__                                                                
#  include <asm/unistd_32.h>                                                    
# elif defined(__ILP32__)                                                       
#  include <asm/unistd_x32.h>                                                   
# else                                                                          
#  include <asm/unistd_64.h>                                                    
# endif

So that's presumably designed to pick up /usr/include/x86_64-linux-gnu/asm/unistd.h, but this does not yet include my new syscall numbers.

I'd expect the headers_install target to install the new headers (perhaps), but alas it does not.

I'm confused. Should I add my new syscalls to a file manually or not? If so which file? If not, how do I expose the auto-generated __NR_* macros to userspace in a standard location?

Thanks

like image 204
Edd Barrett Avatar asked Jul 24 '17 17:07

Edd Barrett


1 Answers

Well, I have a partial answer. Partial because it is Debian specific.

If you use the make deb-pkg target in the kernel sources, then .deb packages are created in the parent directory. If you then install these, then your headers get installed into the system.

After doing this for my kernel described above:

$ grep krun /usr/include
/usr/include/asm/unistd_64.h:#define __NR_krun_read_msrs 317
/usr/include/asm/unistd_64.h:#define __NR_krun_reset_msrs 318
like image 63
Edd Barrett Avatar answered Oct 12 '22 15:10

Edd Barrett