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

tracehook: exec

This moves all the ptrace hooks related to exec into tracehook.h inlines.

This also lifts the calls for tracing out of the binfmt load_binary hooks
into search_binary_handler() after it calls into the binfmt module. This
change has no effect, since all the binfmt modules' load_binary functions
did the call at the end on success, and now search_binary_handler() does
it immediately after return if successful. We consolidate the repeated
code, and binfmt modules no longer need to import ptrace_notify().

Signed-off-by: Roland McGrath <roland@redhat.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Reviewed-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Roland McGrath and committed by
Linus Torvalds
6341c393 88ac2921

+50 -38
-6
arch/x86/ia32/ia32_aout.c
··· 441 441 regs->r8 = regs->r9 = regs->r10 = regs->r11 = 442 442 regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0; 443 443 set_fs(USER_DS); 444 - if (unlikely(current->ptrace & PT_PTRACED)) { 445 - if (current->ptrace & PT_TRACE_EXEC) 446 - ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP); 447 - else 448 - send_sig(SIGTRAP, current, 0); 449 - } 450 444 return 0; 451 445 } 452 446
-6
fs/binfmt_aout.c
··· 444 444 regs->gp = ex.a_gpvalue; 445 445 #endif 446 446 start_thread(regs, ex.a_entry, current->mm->start_stack); 447 - if (unlikely(current->ptrace & PT_PTRACED)) { 448 - if (current->ptrace & PT_TRACE_EXEC) 449 - ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); 450 - else 451 - send_sig(SIGTRAP, current, 0); 452 - } 453 447 return 0; 454 448 } 455 449
-6
fs/binfmt_elf.c
··· 1003 1003 #endif 1004 1004 1005 1005 start_thread(regs, elf_entry, bprm->p); 1006 - if (unlikely(current->ptrace & PT_PTRACED)) { 1007 - if (current->ptrace & PT_TRACE_EXEC) 1008 - ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); 1009 - else 1010 - send_sig(SIGTRAP, current, 0); 1011 - } 1012 1006 retval = 0; 1013 1007 out: 1014 1008 kfree(loc);
-7
fs/binfmt_elf_fdpic.c
··· 433 433 entryaddr = interp_params.entry_addr ?: exec_params.entry_addr; 434 434 start_thread(regs, entryaddr, current->mm->start_stack); 435 435 436 - if (unlikely(current->ptrace & PT_PTRACED)) { 437 - if (current->ptrace & PT_TRACE_EXEC) 438 - ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP); 439 - else 440 - send_sig(SIGTRAP, current, 0); 441 - } 442 - 443 436 retval = 0; 444 437 445 438 error:
-3
fs/binfmt_flat.c
··· 920 920 921 921 start_thread(regs, start_addr, current->mm->start_stack); 922 922 923 - if (current->ptrace & PT_PTRACED) 924 - send_sig(SIGTRAP, current, 0); 925 - 926 923 return 0; 927 924 } 928 925
-2
fs/binfmt_som.c
··· 274 274 map_hpux_gateway_page(current,current->mm); 275 275 276 276 start_thread_som(regs, som_entry, bprm->p); 277 - if (current->ptrace & PT_PTRACED) 278 - send_sig(SIGTRAP, current, 0); 279 277 return 0; 280 278 281 279 /* error cleanup */
+4 -8
fs/exec.c
··· 42 42 #include <linux/module.h> 43 43 #include <linux/namei.h> 44 44 #include <linux/proc_fs.h> 45 - #include <linux/ptrace.h> 46 45 #include <linux/mount.h> 47 46 #include <linux/security.h> 48 47 #include <linux/syscalls.h> 49 48 #include <linux/tsacct_kern.h> 50 49 #include <linux/cn_proc.h> 51 50 #include <linux/audit.h> 51 + #include <linux/tracehook.h> 52 52 53 53 #include <asm/uaccess.h> 54 54 #include <asm/mmu_context.h> ··· 1071 1071 1072 1072 static int unsafe_exec(struct task_struct *p) 1073 1073 { 1074 - int unsafe = 0; 1075 - if (p->ptrace & PT_PTRACED) { 1076 - if (p->ptrace & PT_PTRACE_CAP) 1077 - unsafe |= LSM_UNSAFE_PTRACE_CAP; 1078 - else 1079 - unsafe |= LSM_UNSAFE_PTRACE; 1080 - } 1074 + int unsafe = tracehook_unsafe_exec(p); 1075 + 1081 1076 if (atomic_read(&p->fs->count) > 1 || 1082 1077 atomic_read(&p->files->count) > 1 || 1083 1078 atomic_read(&p->sighand->count) > 1) ··· 1209 1214 read_unlock(&binfmt_lock); 1210 1215 retval = fn(bprm, regs); 1211 1216 if (retval >= 0) { 1217 + tracehook_report_exec(fmt, bprm, regs); 1212 1218 put_binfmt(fmt); 1213 1219 allow_write_access(bprm->file); 1214 1220 if (bprm->file)
+46
include/linux/tracehook.h
··· 48 48 49 49 #include <linux/sched.h> 50 50 #include <linux/ptrace.h> 51 + #include <linux/security.h> 52 + struct linux_binprm; 53 + 54 + /** 55 + * tracehook_unsafe_exec - check for exec declared unsafe due to tracing 56 + * @task: current task doing exec 57 + * 58 + * Return %LSM_UNSAFE_* bits applied to an exec because of tracing. 59 + * 60 + * Called with task_lock() held on @task. 61 + */ 62 + static inline int tracehook_unsafe_exec(struct task_struct *task) 63 + { 64 + int unsafe = 0; 65 + int ptrace = task_ptrace(task); 66 + if (ptrace & PT_PTRACED) { 67 + if (ptrace & PT_PTRACE_CAP) 68 + unsafe |= LSM_UNSAFE_PTRACE_CAP; 69 + else 70 + unsafe |= LSM_UNSAFE_PTRACE; 71 + } 72 + return unsafe; 73 + } 74 + 75 + /** 76 + * tracehook_report_exec - a successful exec was completed 77 + * @fmt: &struct linux_binfmt that performed the exec 78 + * @bprm: &struct linux_binprm containing exec details 79 + * @regs: user-mode register state 80 + * 81 + * An exec just completed, we are shortly going to return to user mode. 82 + * The freshly initialized register state can be seen and changed in @regs. 83 + * The name, file and other pointers in @bprm are still on hand to be 84 + * inspected, but will be freed as soon as this returns. 85 + * 86 + * Called with no locks, but with some kernel resources held live 87 + * and a reference on @fmt->module. 88 + */ 89 + static inline void tracehook_report_exec(struct linux_binfmt *fmt, 90 + struct linux_binprm *bprm, 91 + struct pt_regs *regs) 92 + { 93 + if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && 94 + unlikely(task_ptrace(current) & PT_PTRACED)) 95 + send_sig(SIGTRAP, current, 0); 96 + } 51 97 52 98 #endif /* <linux/tracehook.h> */