OSDN Git Service

signal: Simplify tracehook_report_syscall_exit
authorEric W. Biederman <ebiederm@xmission.com>
Mon, 16 Apr 2018 19:18:26 +0000 (14:18 -0500)
committerEric W. Biederman <ebiederm@xmission.com>
Wed, 19 Sep 2018 13:45:42 +0000 (15:45 +0200)
Replace user_single_step_siginfo with user_single_step_report
that allocates siginfo structure on the stack and sends it.

This allows tracehook_report_syscall_exit to become a simple
if statement that calls user_single_step_report or ptrace_report_syscall
depending on the value of step.

Update the default helper function now called user_single_step_report
to explicitly set si_code to SI_USER and to set si_uid and si_pid to 0.
The default helper has always been doing this (using memset) but it
was far from obvious.

The powerpc helper can now just call force_sig_fault.
The x86 helper can now just call send_sigtrap.

Unfortunately the default implementation of user_single_step_report
can not use force_sig_fault as it does not use a SIGTRAP si_code.
So it has to carefully setup the siginfo and use use force_sig_info.

The net result is code that is easier to understand and simpler
to maintain.

Ref: 85ec7fd9f8e5 ("ptrace: introduce user_single_step_siginfo() helper")
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
arch/powerpc/include/asm/ptrace.h
arch/powerpc/kernel/traps.c
arch/x86/include/asm/ptrace.h
arch/x86/kernel/ptrace.c
include/linux/ptrace.h
include/linux/tracehook.h

index 447cbd1..5b480e1 100644 (file)
@@ -149,7 +149,7 @@ do {                                                                              \
 
 #define arch_has_single_step() (1)
 #define arch_has_block_step()  (!cpu_has_feature(CPU_FTR_601))
-#define ARCH_HAS_USER_SINGLE_STEP_INFO
+#define ARCH_HAS_USER_SINGLE_STEP_REPORT
 
 /*
  * kprobe-based event tracer support
index c85adb8..f651fa9 100644 (file)
@@ -307,12 +307,9 @@ void die(const char *str, struct pt_regs *regs, long err)
 }
 NOKPROBE_SYMBOL(die);
 
-void user_single_step_siginfo(struct task_struct *tsk,
-                               struct pt_regs *regs, siginfo_t *info)
+void user_single_step_report(struct pt_regs *regs)
 {
-       info->si_signo = SIGTRAP;
-       info->si_code = TRAP_TRACE;
-       info->si_addr = (void __user *)regs->nip;
+       force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)regs->nip, current);
 }
 
 static void show_signal_msg(int signr, struct pt_regs *regs, int code,
index 6de1fd3..e353f08 100644 (file)
@@ -263,7 +263,7 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
 #define arch_has_block_step()  (boot_cpu_data.x86 >= 6)
 #endif
 
-#define ARCH_HAS_USER_SINGLE_STEP_INFO
+#define ARCH_HAS_USER_SINGLE_STEP_REPORT
 
 /*
  * When hitting ptrace_stop(), we cannot return using SYSRET because
index e2ee403..94bd6e8 100644 (file)
@@ -1382,12 +1382,6 @@ static void fill_sigtrap_info(struct task_struct *tsk,
        info->si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
 }
 
-void user_single_step_siginfo(struct task_struct *tsk,
-                               struct pt_regs *regs,
-                               struct siginfo *info)
-{
-       fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info);
-}
 
 void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
                                         int error_code, int si_code)
@@ -1399,3 +1393,8 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
        /* Send us the fake SIGTRAP */
        force_sig_info(SIGTRAP, &info, tsk);
 }
+
+void user_single_step_report(struct pt_regs *regs)
+{
+       send_sigtrap(current, regs, 0, TRAP_BRKPT);
+}
index 4f36431..1de2235 100644 (file)
@@ -336,14 +336,19 @@ static inline void user_enable_block_step(struct task_struct *task)
 extern void user_enable_block_step(struct task_struct *);
 #endif /* arch_has_block_step */
 
-#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO
-extern void user_single_step_siginfo(struct task_struct *tsk,
-                               struct pt_regs *regs, siginfo_t *info);
+#ifdef ARCH_HAS_USER_SINGLE_STEP_REPORT
+extern void user_single_step_report(struct pt_regs *regs);
 #else
-static inline void user_single_step_siginfo(struct task_struct *tsk,
-                               struct pt_regs *regs, siginfo_t *info)
+static inline void user_single_step_report(struct pt_regs *regs)
 {
-       info->si_signo = SIGTRAP;
+       siginfo_t info;
+       clear_siginfo(&info);
+       info.si_signo = SIGTRAP;
+       info.si_errno = 0;
+       info.si_code = SI_USER;
+       info.si_pid = 0;
+       info.si_uid = 0;
+       force_sig_info(info.si_signo, &info, current);
 }
 #endif
 
index 05589a3..40b0b4c 100644 (file)
@@ -123,15 +123,10 @@ static inline __must_check int tracehook_report_syscall_entry(
  */
 static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
 {
-       if (step) {
-               siginfo_t info;
-               clear_siginfo(&info);
-               user_single_step_siginfo(current, regs, &info);
-               force_sig_info(SIGTRAP, &info, current);
-               return;
-       }
-
-       ptrace_report_syscall(regs);
+       if (step)
+               user_single_step_report(regs);
+       else
+               ptrace_report_syscall(regs);
 }
 
 /**