How to add a custom syscall to linux?
Interface to the services made available by kernel
Generally, CPU can operate in one of these modes:
OS provides SysCalls to user programs
man syscalls
man fork
man exec
man read
...
Track Signals and System Calls
restart_syscall
exit
fork
read
write
open
...
restart_syscall
exit
fork
read
write
open
...
x86_64: arch/x86/entry/syscalls/syscall_64.tbl
x86: arch/x86/entry/syscalls/syscall_32.tbl
arm: arch/arm/tools/syscall.tbl
...
SYSCALL_DEFINE0(syscall_name)
{
printk("CUSTOM SYSCALL FOR FumLug\n");
return 0;
}
SYSCALL_DEFINE1(syscall_name, const char *, argument1)
{
printk(argument1);
return 0;
}
...
obj-y := syscall_name.o
core-y += syscall_folder/
-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
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
-enable-kvm
Faster virtualization using Kernel-based virtual machine
-m 1g
ram size
Boot the kernel with:
qemu-system-x86_64 -kernel ./bzImage -initrd ./initramfs
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 .
#include <unistd.h>
int main(){
syscal(SYSCALL_NUMBER);
}
(nix-shell -p gcc musl)
gcc test.c -static
Add your custom syscall
Update Makefiles
(obj-y)
(core-y)
compile kernel
Create a minimal initramfs using busybox
(remember to add your binaries)
Test your syscall
Boot the kernel using qemu
qemu-system-x86_64 -kernel ./bzImage -initrd ./initramfs
M.Erfan Arasteh (github.com/erfanara)
Alireza Arzehgar (github.com/alirezaarzehgar)
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/