Master the fundamental concepts of system calls & kernel interface through this focused micro-challenge.
ptrace lets one process observe and control another: stop on syscalls, inspect registers, rewrite memory. Debuggers and strace build on this interface, though modern Linux prefers ptrace alternatives for performance.
Tracer workflow:
PTRACE_ATTACH or trace-at-forkSIGTRAP at syscall entry/exit stopsorig_rax for syscall number and argumentsPTRACE_SYSCALL to continueFor example, intercepting write(fd=1, ...) lets you log payloads before the tracee resumes.
ptrace is the exact syscall gdb, strace, and Docker's --cap-add=SYS_PTRACE debugging workflows are built on, and it's also how sandboxes like early gVisor and rr's record-and-replay debugger intercept every syscall a traced process makes. The orig_rax-versus-rax distinction you'll implement here (entry vs exit stop) is a real, easy-to-get-backwards detail that trips up first-time strace-clone authors.
Before you call the implementation done, walk failure modes on purpose. Test empty structures, single-element edge cases, maximum concurrency, and errno paths that must not crash the program. OS code usually fails in production when happy-path tests pass but invariants break under contention or memory pressure.
Keep structures small and name fields after kernel counterparts when possible. That lets you read man pages and kernel source side by side while you work. Print observable events during development; remove noisy logs once tests pass reliably.
You will write a tracer that prints syscall name and arguments for each entry. Understanding stop points matters because off-by-one continue calls hang the tracee forever.
Implement system call interceptor using ptrace.
Requirements:
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
All starter code and reference implementations are available for your local setup.
View on Github