Intercepting and Emulating Linux System Calls with Ptrace
nullprogram.com
nullprogram.com
The tagline was "strace meets expect". You could write a Python script to control what happened when the process being traced made a syscall of your choice! This was super-fun and super-educational and also came with a little manifesto about ensuring users' control over software rather than the other way around.
Unfortunately subterfugue hasn't been maintained in years and I think it hasn't worked with the last few major releases of the Linux kernel. It would be amazing to see a similar tool nowadays.
Some things that helped me scale ptrace-interception up:
- SECCOMP_BPF filter (getting these right matters a lot)
- moving all of your intercept work to a single side (enter or exit)
- ensure affinity between the traced and tracing processes
- nuke vdso
- remove vdso from the aux vector (otherwise good libc's will find it again)
At the end of the day unfortunately the better solution would have been to write kernel support for what I wanted to do, but it's a fun exercise in learning about system calls.
See the answer on https://stackoverflow.com/questions/4414605/how-can-linux-pt... for an example of a potential race. I believe OpenBSD’s systrace had some issues like this.
This is actually possible. How? The obvious way... You intercept and emulate ptrace calls with ptrace.
https://robert.ocallahan.org/2016/04/using-rr-to-debug-rr.ht... explains how this works in practice.
PRoot is pretty useful as a pure-userland solution for jobs that container-ish things might otherwise do, e.g. user-mode installation of Nix/Guix.
FWIW, Micorsoft's implementations of Win32 have swapped out the kernel a few times anyway, so it's not the biggest leap for a third party (DOS/Win32s, Win9x, WinNT).
Because of this, Microsoft considers the system call layer to be unstable, and appears to go out of their way to change the system call table every service pack. So the dll entry points are the stable ABI, and that's what 99.99% of developers rely on.
Now why are those calls needed? I think some of it relates to DRM provisions. I also want to say that some of it is necessary to implement various features of COM (i.e., remote procedure call stuff), but that might not be the case, given that the reports suggest that ptrace support is often unnecessary.
PTRACE_TRACEME: This process is to be traced by its parent. PTRACE_SYSCALL: Continue, but stop at the next system call entrance or exit. PTRACE_GETREGS: Get a copy of the tracee’s registers.
You have three things here ;)