Commit 6341c393fcc37d58727865f1ee2f65e632e9d4f0
Committed by
Linus Torvalds
1 parent
88ac2921a7
Exists in
master
and in
39 other branches
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>
Showing 8 changed files with 50 additions and 38 deletions Side-by-side Diff
arch/x86/ia32/ia32_aout.c
... | ... | @@ -441,12 +441,6 @@ |
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 |
fs/binfmt_aout.c
... | ... | @@ -444,12 +444,6 @@ |
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 |
fs/binfmt_elf.c
... | ... | @@ -1003,12 +1003,6 @@ |
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); |
fs/binfmt_elf_fdpic.c
... | ... | @@ -433,13 +433,6 @@ |
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: |
fs/binfmt_flat.c
fs/binfmt_som.c
fs/exec.c
... | ... | @@ -42,13 +42,13 @@ |
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,13 +1071,8 @@ |
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) |
... | ... | @@ -1214,6 +1209,7 @@ |
1214 | 1209 | read_unlock(&binfmt_lock); |
1215 | 1210 | retval = fn(bprm, regs); |
1216 | 1211 | if (retval >= 0) { |
1212 | + tracehook_report_exec(fmt, bprm, regs); | |
1217 | 1213 | put_binfmt(fmt); |
1218 | 1214 | allow_write_access(bprm->file); |
1219 | 1215 | if (bprm->file) |
include/linux/tracehook.h
... | ... | @@ -48,6 +48,52 @@ |
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> */ |