Re: [PATCH 0/6] ptrace: introduce PTRACE_SET_SYSCALL_INFO API

H. Peter Anvin
2025-01-10T03:18:15Z

This would seem like a very good idea. However, it is perhaps important
to realize that it doesn't fully eliminate the problems with 64-bit
arguments on 32-bit ABIs being handled differently (never mind
inconsistencies in system call ABIs etc.) There isn't all that much that
can be done about that directly, though.

-hpa

On 1/7/25 15:01, Dmitry V. Levin wrote:
> PTRACE_SET_SYSCALL_INFO is a generic ptrace API that complements
> PTRACE_GET_SYSCALL_INFO by letting the ptracer modify details of
> system calls the tracee is blocked in.
>
> This API allows ptracers to obtain and modify system call details
> in a straightforward and architecture-agnostic way.
>
> Current implementation supports changing only those bits of system call
> information that are used by strace, namely, syscall number, syscall
> arguments, and syscall return value.
>
> Support of changing additional details returned by PTRACE_GET_SYSCALL_INFO,
> such as instruction pointer and stack pointer, could be added later
> if needed, by re-using struct ptrace_syscall_info.reserved to specify
> the additional details that should be set. Currently, the reserved
> field of struct ptrace_syscall_info must be initialized with zeroes;
> arch, instruction_pointer, and stack_pointer fields are ignored.
>
> PTRACE_SET_SYSCALL_INFO currently supports only PTRACE_SYSCALL_INFO_ENTRY,
> PTRACE_SYSCALL_INFO_EXIT, and PTRACE_SYSCALL_INFO_SECCOMP operations.
> Other operations could be added later if needed.
>
> Ideally, PTRACE_SET_SYSCALL_INFO should have been introduced along with
> PTRACE_GET_SYSCALL_INFO, but it didn't happen. The last straw that
> convinced me to implement PTRACE_SET_SYSCALL_INFO was apparent failure
> to provide an API of changing the first system call argument on riscv
> architecture [1].
>
> ptrace(2) man page:
>
> long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
> ...
> PTRACE_SET_SYSCALL_INFO
> Modify information about the system call that caused the stop.
> The "data" argument is a pointer to struct ptrace_syscall_info
> that specifies the system call information to be set.
> The "addr" argument should be set to sizeof(struct ptrace_syscall_info)).
>
> [1] https://lore.kernel.org/all/59505464-c84a-403d-972f-d4b2055eeaac@gmail.com/
>
> Dmitry V. Levin (6):
> Revert "arch: remove unused function syscall_set_arguments()"
> syscall.h: add syscall_set_arguments() on remaining
> HAVE_ARCH_TRACEHOOK arches
> syscall.h: introduce syscall_set_nr()
> ptrace_get_syscall_info: factor out ptrace_get_syscall_info_op
> ptrace: introduce PTRACE_SET_SYSCALL_INFO request
> selftests/ptrace: add a test case for PTRACE_SET_SYSCALL_INFO
>
> arch/arc/include/asm/syscall.h | 20 +
> arch/arm/include/asm/syscall.h | 25 +
> arch/arm64/include/asm/syscall.h | 20 +
> arch/csky/include/asm/syscall.h | 13 +
> arch/hexagon/include/asm/syscall.h | 14 +
> arch/loongarch/include/asm/syscall.h | 15 +
> arch/m68k/include/asm/syscall.h | 7 +
> arch/microblaze/include/asm/syscall.h | 7 +
> arch/mips/include/asm/syscall.h | 53 +++
> arch/nios2/include/asm/syscall.h | 16 +
> arch/openrisc/include/asm/syscall.h | 13 +
> arch/parisc/include/asm/syscall.h | 19 +
> arch/powerpc/include/asm/syscall.h | 15 +
> arch/riscv/include/asm/syscall.h | 16 +
> arch/s390/include/asm/syscall.h | 19 +
> arch/sh/include/asm/syscall_32.h | 19 +
> arch/sparc/include/asm/syscall.h | 17 +
> arch/um/include/asm/syscall-generic.h | 19 +
> arch/x86/include/asm/syscall.h | 43 ++
> arch/xtensa/include/asm/syscall.h | 18 +
> include/asm-generic/syscall.h | 30 ++
> include/linux/ptrace.h | 3 +
> include/uapi/linux/ptrace.h | 3 +-
> kernel/ptrace.c | 154 ++++++-
> tools/testing/selftests/ptrace/Makefile | 2 +-
> .../selftests/ptrace/set_syscall_info.c | 436 ++++++++++++++++++
> 26 files changed, 994 insertions(+), 22 deletions(-)
> create mode 100644 tools/testing/selftests/ptrace/set_syscall_info.c
>