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

signal: Simplify tracehook_report_syscall_exit

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>

+24 -28
+1 -1
arch/powerpc/include/asm/ptrace.h
··· 149 149 150 150 #define arch_has_single_step() (1) 151 151 #define arch_has_block_step() (!cpu_has_feature(CPU_FTR_601)) 152 - #define ARCH_HAS_USER_SINGLE_STEP_INFO 152 + #define ARCH_HAS_USER_SINGLE_STEP_REPORT 153 153 154 154 /* 155 155 * kprobe-based event tracer support
+2 -5
arch/powerpc/kernel/traps.c
··· 307 307 } 308 308 NOKPROBE_SYMBOL(die); 309 309 310 - void user_single_step_siginfo(struct task_struct *tsk, 311 - struct pt_regs *regs, siginfo_t *info) 310 + void user_single_step_report(struct pt_regs *regs) 312 311 { 313 - info->si_signo = SIGTRAP; 314 - info->si_code = TRAP_TRACE; 315 - info->si_addr = (void __user *)regs->nip; 312 + force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)regs->nip, current); 316 313 } 317 314 318 315 static void show_signal_msg(int signr, struct pt_regs *regs, int code,
+1 -1
arch/x86/include/asm/ptrace.h
··· 263 263 #define arch_has_block_step() (boot_cpu_data.x86 >= 6) 264 264 #endif 265 265 266 - #define ARCH_HAS_USER_SINGLE_STEP_INFO 266 + #define ARCH_HAS_USER_SINGLE_STEP_REPORT 267 267 268 268 /* 269 269 * When hitting ptrace_stop(), we cannot return using SYSRET because
+5 -6
arch/x86/kernel/ptrace.c
··· 1382 1382 info->si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; 1383 1383 } 1384 1384 1385 - void user_single_step_siginfo(struct task_struct *tsk, 1386 - struct pt_regs *regs, 1387 - struct siginfo *info) 1388 - { 1389 - fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); 1390 - } 1391 1385 1392 1386 void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, 1393 1387 int error_code, int si_code) ··· 1392 1398 fill_sigtrap_info(tsk, regs, error_code, si_code, &info); 1393 1399 /* Send us the fake SIGTRAP */ 1394 1400 force_sig_info(SIGTRAP, &info, tsk); 1401 + } 1402 + 1403 + void user_single_step_report(struct pt_regs *regs) 1404 + { 1405 + send_sigtrap(current, regs, 0, TRAP_BRKPT); 1395 1406 }
+11 -6
include/linux/ptrace.h
··· 336 336 extern void user_enable_block_step(struct task_struct *); 337 337 #endif /* arch_has_block_step */ 338 338 339 - #ifdef ARCH_HAS_USER_SINGLE_STEP_INFO 340 - extern void user_single_step_siginfo(struct task_struct *tsk, 341 - struct pt_regs *regs, siginfo_t *info); 339 + #ifdef ARCH_HAS_USER_SINGLE_STEP_REPORT 340 + extern void user_single_step_report(struct pt_regs *regs); 342 341 #else 343 - static inline void user_single_step_siginfo(struct task_struct *tsk, 344 - struct pt_regs *regs, siginfo_t *info) 342 + static inline void user_single_step_report(struct pt_regs *regs) 345 343 { 346 - info->si_signo = SIGTRAP; 344 + siginfo_t info; 345 + clear_siginfo(&info); 346 + info.si_signo = SIGTRAP; 347 + info.si_errno = 0; 348 + info.si_code = SI_USER; 349 + info.si_pid = 0; 350 + info.si_uid = 0; 351 + force_sig_info(info.si_signo, &info, current); 347 352 } 348 353 #endif 349 354
+4 -9
include/linux/tracehook.h
··· 123 123 */ 124 124 static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) 125 125 { 126 - if (step) { 127 - siginfo_t info; 128 - clear_siginfo(&info); 129 - user_single_step_siginfo(current, regs, &info); 130 - force_sig_info(SIGTRAP, &info, current); 131 - return; 132 - } 133 - 134 - ptrace_report_syscall(regs); 126 + if (step) 127 + user_single_step_report(regs); 128 + else 129 + ptrace_report_syscall(regs); 135 130 } 136 131 137 132 /**