powerpc/ptrace: Add support for PTRACE_SYSEMU
authorBreno Leitao <leitao@debian.org>
Thu, 20 Sep 2018 16:45:06 +0000 (13:45 -0300)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 3 Oct 2018 05:40:04 +0000 (15:40 +1000)
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>
arch/powerpc/include/asm/thread_info.h
arch/powerpc/include/uapi/asm/ptrace.h
arch/powerpc/kernel/ptrace.c

index 1a52e14ec3ee4ed01ec9314c61e56c4998d32968..3185f8ac1182d2598994c4bb8435e32e41af7266 100644 (file)
@@ -81,6 +81,7 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src
 #define TIF_SIGPENDING         1       /* signal pending */
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
 #define TIF_FSCHECK            3       /* Check FS is USER_DS on return */
+#define TIF_SYSCALL_EMU                4       /* syscall emulation active */
 #define TIF_RESTORE_TM         5       /* need to restore TM FP/VEC/VSX */
 #define TIF_PATCH_PENDING      6       /* pending live patching update */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
@@ -120,9 +121,10 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src
 #define _TIF_EMULATE_STACK_STORE       (1<<TIF_EMULATE_STACK_STORE)
 #define _TIF_NOHZ              (1<<TIF_NOHZ)
 #define _TIF_FSCHECK           (1<<TIF_FSCHECK)
+#define _TIF_SYSCALL_EMU       (1<<TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_DOTRACE   (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
                                 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \
-                                _TIF_NOHZ)
+                                _TIF_NOHZ | _TIF_SYSCALL_EMU)
 
 #define _TIF_USER_WORK_MASK    (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                                 _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
index 5e3edc2a7634e859693191197ae600537dd145a2..55c7a131d2ab83e208cb060a1161f267577d33a3 100644 (file)
@@ -160,6 +160,10 @@ struct pt_regs {
 #define PTRACE_GETVSRREGS      0x1b
 #define PTRACE_SETVSRREGS      0x1c
 
+/* Syscall emulation defines */
+#define PTRACE_SYSEMU                  0x1d
+#define PTRACE_SYSEMU_SINGLESTEP       0x1e
+
 /*
  * Get or set a debug register. The first 16 are DABR registers and the
  * second 16 are IABR registers.
index 9667666eb18e56d4afcc7f76b76b9779b1ac6536..4e372f54088fce07c4b26533401ac33bf6c2a967 100644 (file)
@@ -2508,6 +2508,7 @@ void ptrace_disable(struct task_struct *child)
 {
        /* make sure the single step bit is not set. */
        user_disable_single_step(child);
+       clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
 }
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
@@ -3264,6 +3265,16 @@ long do_syscall_trace_enter(struct pt_regs *regs)
 {
        user_exit();
 
+       if (test_thread_flag(TIF_SYSCALL_EMU)) {
+               ptrace_report_syscall(regs);
+               /*
+                * Returning -1 will skip the syscall execution. We want to
+                * avoid clobbering any register also, thus, not 'gotoing'
+                * skip label.
+                */
+               return -1;
+       }
+
        /*
         * The tracer may decide to abort the syscall, if so tracehook
         * will return !0. Note that the tracer may also just change