Adding a System Call

Intro

This document describes how to add a system call to User-mode Linux to the 4.19.15 kernel.

Define the entry point

The first thing you need to do is modify the file unistd_64.h in the directory arch/x86/include/generated/uapi/asm/unistd_64.h. In this file, you need to add a line providing an id for your system call. Locate the bunch of lines of the form #define __NR_somename, and add a new entry for your system call.

#define __NR_io_pgetevents 333
#define __NR_rseq 334
#define __NR_hellokernel   335 (1)
  1. This is the line you should add! Except (1)

Next, you must add and entry refering to your call in the system calls table. To do this, modify syscall_64.tbl file in ./arch/x86/entry/syscalls/ and edit the following:

333	common	io_pgetevents	__x64_sys_io_pgetevents
334	common	rseq			__x64_sys_rseq
335 common  hellokernel     __x64_sys_hellokernel (1)
  1. This is the line you should add! Except (1)

Now we will implement a system call.

Implementation code

First of all, create a header file hellokernel.h for your system call and place it in arch/um/include/asm as shown here:

#ifndef __UML_HELLOKERNEL_H__
#define __UML_HELLOKERNEL_H__

extern int sys_hellokernel( int );

#endif

Then, write out the implementation hellokernel.c of your system call in arch/um/kernel/ as shown here. (Note the use of the asmlinkage modifier. This macro tells the compiler to pass all function arguments on the stack.):

#include "linux/kernel.h"
#include "linux/unistd.h"

asmlinkage
int sys_hellokernel( int flag ) {
  printk("Your kernel greets you %d times! \n", flag);
  return 0;
}

Finally, modify the respective Makefile in arch/um/kernel and add hellokernel.o to the list of build targets.

extra-y := vmlinux.lds
clean-files :=

obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
        physmem.o process.o ptrace.o reboot.o sigio.o \
        signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
        um_arch.o umid.o maccess.o hellokernel.o skas/

Now you have to recompile the kernel. Change to the kernel source root directory and recompile :

cd ~/dm510/linux-4.19.15
make ARCH=um linux

Creating a stub for your system call

You call the new functions as identified by their index through the syscall function. With the syscall function, you can call a system call by specifying. For example, the short application shown below calls your sys_hellokernel using its index. The program can be compiled with the command gcc -o testsystemcall testsystemcall.c.

testsystemcall.c
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include "arch/x86/include/generated/uapi/asm/unistd_64.h"

int main(int argc, char ** argv) {
	printf("Calling ... \n");
	syscall(__NR_hellokernel,42);
}

Run user mode linux

./linux

Login, and mount your home directory, and change to the directory where your newly compiled program is stored:

mount none /mnt/tmp -t hostfs -o /home/<your-login>/dm510
cd /mnt/tmp/linux-4.19.15

Execute the program. The result should be similar to the following:

dm510:/mnt/tmp/linux-4.15# ./testsyscall
Calling ...
Your kernel greets you 42 times!

Note that the kernel messages are maybe printed in another terminal than the messages that are printed by printf commands of the program. Besides of that, you will find the messages from the kernel in /var/log/kern.log.

Additional Material

Further information can be found here: