Stage 3 · Build
Linux Kernel Internals
System Calls & VDSO
The user-kernel boundary, syscall overhead, and vDSO optimization — how programs talk to the kernel.
The Syscall Mechanism
A system call is the controlled entry point from userspace into the kernel. When a program needs to do something privileged — read a file, allocate memory, send a network packet — it invokes a syscall. On x86_64, the program places arguments in registers and executes the syscall instruction, which switches to kernel mode.
# The syscall instruction on x86_64:
# 1. Program puts syscall number in RAX
# 2. Arguments go in RDI, RSI, RDX, R10, R8, R9
# 3. Program executes "syscall"
# 4. Kernel runs the handler, returns via "sysret"
# 5. Return value is in RAX
# Example: write(1, "hello\n", 6)
# RAX = 1 (sys_write)
# RDI = 1 (fd = stdout)
# RSI = pointer to string
# RDX = 6 (length)The syscall instruction is much faster than the legacy int 0x80 method. On modern CPUs, a syscall takes roughly 100-200 nanoseconds.
Syscall Overhead
Every syscall involves a mode switch from userspace to kernel and back. While necessary, this transition is expensive: the CPU must save registers, switch page tables, and validate arguments. High-frequency syscalls like gettimeofday can become bottlenecks.
# Count syscalls per second system-wide
perf stat -e 'syscalls:sys_enter_*' -a sleep 1
# Count syscalls for a specific command
strace -c ls /tmp
# % time seconds usecs/call calls errors
# ------ ----------- ----------- --------- ---------
# 45.23 0.000234 23 10 getdents64
# 30.12 0.000156 15 10 write
# 12.45 0.000064 16 4 closegetdents64 (get directory entries) and write are the most frequent syscalls for simple file listing operations.
vDSO Optimization
The Virtual Dynamic Shared Object (vDSO) is a small shared library the kernel maps into every process's address space. It provides optimized versions of syscalls that don't need to enter the kernel, like gettimeofday() and clock_gettime(). These functions read kernel data directly from userspace memory.
# See the vDSO mapped into a process
cat /proc/self/maps | grep vdso
# 7ffd5c1fe000-7ffd5c200000 r-xp 00000000 00:00 0 [vdso]
# Check vDSO symbols
objdump -T /proc/self/exe 2>/dev/null || readelf -s /proc/self/exe 2>/dev/null
# The vDSO avoids the syscall overhead for time functions
time gettimeofday is called millions of times per second in databasesThe vDSO is transparent to applications — gettimeofday() just works. But knowing it exists helps you understand why some syscalls appear faster than expected.
The older vsyscall mechanism mapped a fixed page at a known address, which was a security risk (ROP gadgets). The vDSO uses a random address and is position-independent, making it both secure and efficient.
Tracing Syscalls
strace is the primary tool for observing syscalls. It attaches to a process and logs every syscall with its arguments and return value. This is invaluable for debugging permission issues, understanding program behavior, and diagnosing latency.
# Trace all syscalls
strace ls /tmp
# Trace only specific syscall families
strace -e trace=open,read,write cat /etc/hostname
# Trace with timing
strace -T curl -s http://localhost > /dev/null
# Attach to a running process
strace -p <pid> -e trace=networkThe -T flag shows time spent in each syscall. High values indicate the process is blocking on that operation — useful for finding I/O bottlenecks.
Common Syscalls
Understanding the most common syscalls helps you reason about performance and debug issues. Every I/O operation, process creation, and network packet involves specific syscalls.
| Syscall | Purpose | Commonly Seen In |
|---|---|---|
| read/write | File and socket I/O | Every application |
| openat/open | Open files | File processing scripts |
| mmap | Memory-mapped I/O | Databases, compilers |
| clone/fork | Process creation | Shell, servers |
| epoll_wait | Event-driven I/O | Web servers, proxies |
| futex | Fast userspace mutex | Multi-threaded apps |
Syscall Filtering with seccomp
seccomp (secure computing) lets you restrict which syscalls a process can make. Docker, systemd, and Chrome all use seccomp to sandbox processes. If a filtered syscall is invoked, the kernel kills the process or returns an error.
# Check if a process uses seccomp
grep Seccomp /proc/self/status
# Seccomp: 0 (disabled)
# Seccomp_filters: 0
# Docker containers use seccomp by default
docker run --rm alpine cat /proc/1/status | grep Seccomp
# Seccomp: 2 (filter mode)
# Seccomp_filters: 1Seccomp mode 0 is disabled, 1 is strict (only read/write/exit/sigreturn allowed), and 2 is filter mode (BPF programs decide per-syscall).
Always enable seccomp filtering for services exposed to untrusted input. The default Docker seccomp profile blocks ~44 dangerous syscalls. Create custom profiles to further restrict your attack surface.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.