History

ptrace: introduce PTRACE_SET_SYSCALL_INFO request

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, providing a consistent way of manipulating the system call number and arguments across architectures. As in case of PTRACE_GET_SYSCALL_INFO, PTRACE_SET_SYSCALL_INFO also does not aim to address numerous architecture-specific system call ABI peculiarities, like differences in the number of system call arguments for such system calls as pread64 and preadv. The current implementation supports changing only those bits of system call information that are used by strace system call tampering, 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 using struct ptrace_syscall_info.flags to specify the additional details that should be set. Currently, "flags" and "reserved" fields of struct ptrace_syscall_info must be initialized with zeroes; "arch", "instruction_pointer", and "stack_pointer" fields are currently 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. 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)).

Dmitry V. Levin committed 1 year ago

Commit 26bb3271 parent c354ec92 files · +126 −2Browse files

Showing the changes to include/uapi (1 of 2 files). Show all

Unified · Split

include/uapi/linux/ptrace.h+6−1
@@ -74,6 +74,7 @@ struct seccomp_metadata { · 73 unmodified lines
74};74};
75 75
76#define PTRACE_GET_SYSCALL_INFO 0x420e76#define PTRACE_GET_SYSCALL_INFO 0x420e
77#define PTRACE_SET_SYSCALL_INFO 0x4212
77#define PTRACE_SYSCALL_INFO_NONE 078#define PTRACE_SYSCALL_INFO_NONE 0
78#define PTRACE_SYSCALL_INFO_ENTRY 179#define PTRACE_SYSCALL_INFO_ENTRY 1
79#define PTRACE_SYSCALL_INFO_EXIT 280#define PTRACE_SYSCALL_INFO_EXIT 2
@@ -81,7 +82,8 @@ struct seccomp_metadata { · 1 unmodified line
81 82
82struct ptrace_syscall_info {83struct ptrace_syscall_info {
83 __u8 op; /* PTRACE_SYSCALL_INFO_* */84 __u8 op; /* PTRACE_SYSCALL_INFO_* */
84 __u8 pad[3];85 __u8 reserved;
86 __u16 flags;
85 __u32 arch;87 __u32 arch;
86 __u64 instruction_pointer;88 __u64 instruction_pointer;
87 __u64 stack_pointer;89 __u64 stack_pointer;
@@ -98,6 +100,7 @@ struct ptrace_syscall_info { · 10 unmodified lines
98 __u64 nr;100 __u64 nr;
99 __u64 args[6];101 __u64 args[6];
100 __u32 ret_data;102 __u32 ret_data;
103 __u32 reserved2;
101 } seccomp;104 } seccomp;
102 };105 };
103};106};
@@ -142,6 +145,8 @@ struct ptrace_sud_config { · 38 unmodified lines
142 __u64 len;145 __u64 len;
143};146};
144 147
148/* 0x4212 is PTRACE_SET_SYSCALL_INFO */
149
145/*150/*
146 * These values are stored in task->ptrace_message151 * These values are stored in task->ptrace_message
147 * by ptrace_stop to describe the current syscall-stop.152 * by ptrace_stop to describe the current syscall-stop.