Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/ptrace: Add support for PTRACE_SYSEMU

This is a patch that adds support for PTRACE_SYSEMU ptrace request in
PowerPC architecture.

When ptrace(PTRACE_SYSEMU, ...) request is called, it will be handled by
the arch independent function ptrace_resume(), which will tag the task with
the TIF_SYSCALL_EMU flag. This flag needs to be handled from a platform
dependent point of view, which is what this patch does.

This patch adds this task's flag as part of the _TIF_SYSCALL_DOTRACE, which
is the MACRO that is used to trace syscalls at entrance/exit.

Since TIF_SYSCALL_EMU is now part of _TIF_SYSCALL_DOTRACE, if the task has
_TIF_SYSCALL_DOTRACE set, it will hit do_syscall_trace_enter() at syscall
entrance and do_syscall_trace_leave() at syscall leave.
do_syscall_trace_enter() needs to handle the TIF_SYSCALL_EMU flag properly,
which will interrupt the syscall executing if TIF_SYSCALL_EMU is set. The
output values should not be changed, i.e. the return value (r3) should
contain the original syscall argument on exit.

With this flag set, the syscall is not executed fundamentally, because
do_syscall_trace_enter() is returning -1 which is bigger than NR_syscall,
thus, skipping the syscall execution and exiting userspace.

Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Breno Leitao and committed by
Michael Ellerman
5521eb4b 16d7c69c

+18 -1
+3 -1
arch/powerpc/include/asm/thread_info.h
··· 81 81 #define TIF_SIGPENDING 1 /* signal pending */ 82 82 #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ 83 83 #define TIF_FSCHECK 3 /* Check FS is USER_DS on return */ 84 + #define TIF_SYSCALL_EMU 4 /* syscall emulation active */ 84 85 #define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */ 85 86 #define TIF_PATCH_PENDING 6 /* pending live patching update */ 86 87 #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ ··· 121 120 #define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) 122 121 #define _TIF_NOHZ (1<<TIF_NOHZ) 123 122 #define _TIF_FSCHECK (1<<TIF_FSCHECK) 123 + #define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU) 124 124 #define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ 125 125 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ 126 - _TIF_NOHZ) 126 + _TIF_NOHZ | _TIF_SYSCALL_EMU) 127 127 128 128 #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 129 129 _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
+4
arch/powerpc/include/uapi/asm/ptrace.h
··· 160 160 #define PTRACE_GETVSRREGS 0x1b 161 161 #define PTRACE_SETVSRREGS 0x1c 162 162 163 + /* Syscall emulation defines */ 164 + #define PTRACE_SYSEMU 0x1d 165 + #define PTRACE_SYSEMU_SINGLESTEP 0x1e 166 + 163 167 /* 164 168 * Get or set a debug register. The first 16 are DABR registers and the 165 169 * second 16 are IABR registers.
+11
arch/powerpc/kernel/ptrace.c
··· 2508 2508 { 2509 2509 /* make sure the single step bit is not set. */ 2510 2510 user_disable_single_step(child); 2511 + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); 2511 2512 } 2512 2513 2513 2514 #ifdef CONFIG_PPC_ADV_DEBUG_REGS ··· 3264 3263 long do_syscall_trace_enter(struct pt_regs *regs) 3265 3264 { 3266 3265 user_exit(); 3266 + 3267 + if (test_thread_flag(TIF_SYSCALL_EMU)) { 3268 + ptrace_report_syscall(regs); 3269 + /* 3270 + * Returning -1 will skip the syscall execution. We want to 3271 + * avoid clobbering any register also, thus, not 'gotoing' 3272 + * skip label. 3273 + */ 3274 + return -1; 3275 + } 3267 3276 3268 3277 /* 3269 3278 * The tracer may decide to abort the syscall, if so tracehook