PTRACE_SET_SYSCALL_INFO is a generic ptrace API that complements PTRACE_GET_SYSCALL_INFO by allowing a tracer to modify details of a system call in which the tracee is currently blocked.
This patch set extends PTRACE_SET_SYSCALL_INFO with support for skipping a system call at a PTRACE_EVENT_SECCOMP stop and setting its return value. To do this, the tracer changes 'op' from PTRACE_SYSCALL_INFO_SECCOMP to PTRACE_SYSCALL_INFO_EXIT and fills in the exit union fields (rval and is_error). Michal pointed out in the review of v7 [1] that the register state alone cannot tell whether a syscall has to be executed or skipped with a preset return value, since on some architectures the return value shares a register with the syscall number or the arguments, and that the "already dispatched" information should be architecture independent rather than an architecture-specific thread flag. v8 does exactly that: the tracer no longer sets the syscall number to -1 and relies on syscall_get_nr() reading it back as negative. Instead, patch 1 adds a per-task flag owned by seccomp, which the tracer sets while the tracee is stopped. When the tracee resumes, seccomp skips the system call just like for SECCOMP_RET_ERRNO, a path every architecture already handles without touching the return value. This also fixes skipping on s390, where -1 is read back as syscall 65535. On powerpc, this series depends on the fix posted separately [2]: syscall_set_return_value() currently sets TIF_SYSCALL_RET on the *caller*, i.e. on the tracer when called from PTRACE_SET_SYSCALL_INFO, and skipped system calls lose non-error return values. Both problems are regressions in v7.3-rc and already break the existing set_syscall_info selftest and seccomp_bpf user_notification_basic on ppc64le. [1] https://lore.kernel.org/lkml/[email protected]/ [2] https://lore.kernel.org/lkml/[email protected]/ Testing (QEMU, v7.3-rc6, tools/testing/selftests/ptrace/set_syscall_info and tools/testing/selftests/seccomp/seccomp_bpf): x86_64 (KVM) ppc64le (TCG) s390x (TCG) ptrace/set_syscall_info 2/2 2/2 2/2 seccomp/seccomp_bpf 111/111 111/111 110/111 (*) Skipping getpid() at a PTRACE_EVENT_SECCOMP stop, with a filter that kills the process on unknown syscall numbers: op=SECCOMP, nr=-1 (before) error r3 left as is SIGSYS kill op=SECCOMP->EXIT (this) -ESRCH -ESRCH -ESRCH (*) user_notification_wait_killable_after_reply timed out under TCG while another VM was running; it passes 5/5 both with and without this series on an idle x86_64 KVM guest. Build-tested also with CONFIG_SECCOMP=n and CONFIG_SECCOMP_FILTER=n. Not tested: MIPS, arm64, riscv, loongarch, real hardware. Changes in v9: * selftests/ptrace/set_syscall_info.c: check for seccomp filter support, fix failure report * rebased to Linux 7.3 Changes in v8: * skip the system call via a seccomp per-task flag instead of syscall_set_nr(-1), as suggested by Michal Suchánek * new helper ptrace_set_syscall_info_seccomp_skip() instead of a bool argument to ptrace_set_syscall_info_exit() (Michal Suchánek) * once the system call is skipped, reject further PTRACE_SYSCALL_INFO_SECCOMP updates during the same stop * selftest: also test an error return value and the above * dropped the Reviewed-by tags of Oleg and Dmitry, as patch 2 changed significantly Changes in v7: * rebased to Linux 7.3-rc1 Changes in v6: * selftests/ptrace/set_syscall_info.c: improve messages in case of failure. Changes in v5: * reworded the explanation for not supporting PTRACE_SYSCALL_INFO_ENTRY yet. * selftests/ptrace: removed a redundant check. Changes in v4: * Reworded the commit messages for clarity. * Renamed the local variable child_op to op in ptrace_set_syscall_info() * Clean up and improve the coding style of selftests/ptrace/set_syscall_info.c (suggested by Dmitry V. Levin) Changes in v3: * restrict the syscall skipping feature to PTRACE_SYSCALL_INFO_SECCOMP Changes in v2: bugfix: _NONE -> _EXIT transition was erroneously permitted Davide Berardi (1): seccomp: let the tracer skip a syscall independently of its number Renzo Davoli (2): ptrace: add PTRACE_SET_SYSCALL_INFO syscall skipping support selftests/ptrace: add a test case for PTRACE_SET_SYSCALL_INFO syscall skipping include/linux/seccomp.h | 33 +++ include/linux/seccomp_types.h | 4 + kernel/ptrace.c | 45 +++- kernel/seccomp.c | 11 +- .../selftests/ptrace/set_syscall_info.c | 230 +++++++++++++++++- 5 files changed, 319 insertions(+), 4 deletions(-) base-commit: f47d223627f80cb7a1eb14c585fe6cb35de5e984 prerequisite-patch-id: abdd0fc0973bc3845ae7bfe84d855a7213ccd3d7 -- 2.55.0
