Syscalls in linux

How to add a custom syscall to linux?

Index

What is a SysCall?

Interface to the services made available by kernel

User mode vs Kernel mode

Generally, CPU can operate in one of these modes:

  • User mode
  • Kernel mode (privileged mode)

`Cp source dest`

System Call interface

OS provides SysCalls to user programs

man syscalls

man fork

man exec

man read

...

strace

Track Signals and System Calls

  • read
  • write
  • open
  • close
  • stat
  • fstat
  • ...

x86_64

  • restart_syscall

  • exit    

  • fork  

  • read  

  • write  

  • open  

  • ...

x86

System call table

  • restart_syscall

  • exit    

  • fork  

  • read  

  • write  

  • open  

  • ...

arm

Syscall tables

x86_64: arch/x86/entry/syscalls/syscall_64.tbl

x86: arch/x86/entry/syscalls/syscall_32.tbl

arm: arch/arm/tools/syscall.tbl

...

Add a SysCall function

SYSCALL_DEFINE0(syscall_name)
{
        printk("CUSTOM SYSCALL FOR FumLug\n");
        return 0;
}
SYSCALL_DEFINE1(syscall_name, const char *, argument1)
{
        printk(argument1);
        return 0;
}

...

Update makefiles

  • obj-y in local Makefile
    • obj-y := syscall_name.o
  • core-y in main Makefile
    • core-y += syscall_folder/

Compiling linux

-j$(nproc)

parallel compilation considering the number of your CPU threads

  • make defconfig/menuconfig/tinyconfig/...
  • make
  • make modules (optional in this scenario)

 We'll Use 'tinyconfig' For faster kernel compilation

  • 64-bit kernel ---> yes

  • General setup ---> Initial RAM filesystem and RAM disk (initramfs/initrd) support ---> yes

  • General setup ---> Configure standard kernel features ---> Enable support for printk ---> yes

  • Executable file formats / Emulations ---> Kernel support for ELF binaries ---> yes

  • Executable file formats / Emulations ---> Kernel support for scripts starting with #! ---> yes

  • Device Drivers ---> Character devices ---> Enable TTY ---> yes

Compile options needed using `make menuconfig`:

  • Device Drivers ---> Generic Driver Options ---> Maintain a devtmpfs filesystem to mount at /dev ---> yes

  • Device Drivers ---> Generic Driver Options ---> Automount devtmpfs at /dev, after the kernel mounted the rootfs ---> yes

  • File systems ---> Pseudo filesystems ---> /proc file system support ---> yes

  • File systems ---> Pseudo filesystems ---> sysfs file system support ---> yes

Optional

Booting the kernel

-enable-kvm

Faster virtualization using Kernel-based virtual machine

-m 1g

ram size

  • Create a minimal initramfs using busybox
  • Add your binaries to the initramfs
  • Boot the kernel with:

  • qemu-system-x86_64 -kernel ./bzImage -initrd ./initramfs

initramfs

minimal initramfs using busybox

You can use this small script (written by Alireza Arzehgar)

#!/usr/bin/env bash
URL="https://www.busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-x86_64"
[ -d /tmp/root ] && rm /tmp/root/boot

mkdir -p /tmp/root/{bin,dev,etc,lib,mnt,proc,sbin,sys,tmp,var}

# Copy custom binaries
cp ./a.out /tmp/root/

# Install Busybox
cd /tmp/root || exit
wget ${URL} --no-clobber -O bin/busybox
chmod +x bin/busybox

# Create init file
echo "#!/bin/busybox sh
/bin/busybox --install -s /bin
clear
# optional (please enable support in kernel options menu if you want these filesystems...)
#mount -t devtmpfs  devtmpfs  /dev
#mount -t proc      proc      /proc
#mount -t sysfs     sysfs     /sys
#mount -t tmpfs     tmpfs     /tmp
setsid cttyhack sh
exec /bin/sh" >init
chmod +x init

# Create initramfs
find . | cpio -ov --format=newc | gzip -9 >initramfs


cd - || exit
cp /tmp/root/initramfs .

Test your syscal

#include <unistd.h>

int main(){
	syscal(SYSCALL_NUMBER);
}
(nix-shell -p gcc musl)
gcc test.c -static

1

Add your custom syscall

2

Update Makefiles

(obj-y)

(core-y)

3

compile kernel

  • make
  • make modules (optional)

4

Create a minimal initramfs using busybox

(remember to add your binaries)

6

Test your syscall

5

Boot the kernel using qemu

qemu-system-x86_64 -kernel ./bzImage -initrd ./initramfs

Credits


M.Erfan Arasteh (github.com/erfanara)

Alireza Arzehgar (github.com/alirezaarzehgar)

Extra

https://kernelnewbies.org/FAQ

https://tiny.wiki.kernel.org/use_cases
https://tiny.wiki.kernel.org/faq
https://opensource.com/article/18/10/kbuild-and-kconfig
https://z49x2vmq.github.io/2020/12/24/linux-tiny-qemu/
https://gist.github.com/chrisdone/02e165a0004be33734ac2334f215380e
https://docs.kernel.org/kbuild/makefiles.html
https://medium.com/@jeremyphilemon/adding-a-quick-system-call-to-the-linux-kernel-cad55b421a7b
https://www.kernel.org/doc/html/v6.5/process/adding-syscalls.html
https://github.com/armi3/custom_syscall#3-config-the-kernel
https://www.nicktriller.com/blog/implementing-a-syscall/

Add new syscall to linux

By erfanara

Add new syscall to linux

  • 114