Looks like as of writing (2019-02-08), this is impossible.
And even strace
gets it wrong.
Edit: Linus Torvalds talks about it here, also analysing possible (but commented-out) workarounds in the strace
code that directly look at the instructions made in the binary. This code was removed here as part of the patchset I mention below. It says It works, but is too complicated, and strictly speaking, unreliable
, but it is unclear to me in which cases the "strictly speaking, unreliably" applies, if that is only in the case of a multi-threaded executable rewriting itself at runtime (thus not suitable for forbidding certain syscalls for security use cases), or also in other cases.
Edit: The "unreliable" part was added in this commit.
Edit: I have now tried out strace's opcode-peeking implementation (version v4.25
), and suspect that it was bugged: When activating that code path by changing this line to #if 0
and this line to #elif 1
, no syscalls are printed because scno
is not set at all. I added scno = x86_64_regs.orig_rax;
after this line to make it work.
See the presentation How to make strace happy, slide 2, problem 2:
There is no reliable way to distinguish between x86_64 and x86 syscalls.
Details shown on slides 4-6. There is a proposed solution to be added to the kernel:
Extend the ptrace API with PTRACE_GET_SYSCALL_INFO request
But this solution isn't merged to the kernel.
The patchset is called ptrace: add PTRACE_GET_SYSCALL_INFO request
and it's still being worked on in January 2019. Hopefully it will soon be merged.
strace
already has support for it since release 4.26 (but it shouldn't work unless you apply the kernel patch manually):
Implemented obtainment of system call information using PTRACE_GET_SYSCALL_INFO
ptrace API.