diff options
author | Roland McGrath <roland@redhat.com> | 2008-07-25 22:45:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-26 15:00:08 -0400 |
commit | 6341c393fcc37d58727865f1ee2f65e632e9d4f0 (patch) | |
tree | 6e88d928e17f663b225884e81877a7a069d7c514 | |
parent | 88ac2921a71f788ed693bcd44731dd6bc1994640 (diff) |
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>
-rw-r--r-- | arch/x86/ia32/ia32_aout.c | 6 | ||||
-rw-r--r-- | fs/binfmt_aout.c | 6 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 6 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 7 | ||||
-rw-r--r-- | fs/binfmt_flat.c | 3 | ||||
-rw-r--r-- | fs/binfmt_som.c | 2 | ||||
-rw-r--r-- | fs/exec.c | 12 | ||||
-rw-r--r-- | include/linux/tracehook.h | 46 |
8 files changed, 50 insertions, 38 deletions
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 58cccb6483b0..a0e1dbe67dc1 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
@@ -441,12 +441,6 @@ beyond_if: | |||
441 | regs->r8 = regs->r9 = regs->r10 = regs->r11 = | 441 | regs->r8 = regs->r9 = regs->r10 = regs->r11 = |
442 | regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0; | 442 | regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0; |
443 | set_fs(USER_DS); | 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 | return 0; | 444 | return 0; |
451 | } | 445 | } |
452 | 446 | ||
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index ba4cddb92f1d..204cfd1d7676 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c | |||
@@ -444,12 +444,6 @@ beyond_if: | |||
444 | regs->gp = ex.a_gpvalue; | 444 | regs->gp = ex.a_gpvalue; |
445 | #endif | 445 | #endif |
446 | start_thread(regs, ex.a_entry, current->mm->start_stack); | 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 | return 0; | 447 | return 0; |
454 | } | 448 | } |
455 | 449 | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 3b6ff854d983..655ed8d30a86 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1003,12 +1003,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
1003 | #endif | 1003 | #endif |
1004 | 1004 | ||
1005 | start_thread(regs, elf_entry, bprm->p); | 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 | retval = 0; | 1006 | retval = 0; |
1013 | out: | 1007 | out: |
1014 | kfree(loc); | 1008 | kfree(loc); |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 1b59b1edf26d..fdeadab2f18b 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -433,13 +433,6 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
433 | entryaddr = interp_params.entry_addr ?: exec_params.entry_addr; | 433 | entryaddr = interp_params.entry_addr ?: exec_params.entry_addr; |
434 | start_thread(regs, entryaddr, current->mm->start_stack); | 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 | retval = 0; | 436 | retval = 0; |
444 | 437 | ||
445 | error: | 438 | error: |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 2cb1acda3a82..56372ecf1690 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -920,9 +920,6 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
920 | 920 | ||
921 | start_thread(regs, start_addr, current->mm->start_stack); | 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 | return 0; | 923 | return 0; |
927 | } | 924 | } |
928 | 925 | ||
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c index fdc36bfd6a7b..68be580ba289 100644 --- a/fs/binfmt_som.c +++ b/fs/binfmt_som.c | |||
@@ -274,8 +274,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
274 | map_hpux_gateway_page(current,current->mm); | 274 | map_hpux_gateway_page(current,current->mm); |
275 | 275 | ||
276 | start_thread_som(regs, som_entry, bprm->p); | 276 | start_thread_som(regs, som_entry, bprm->p); |
277 | if (current->ptrace & PT_PTRACED) | ||
278 | send_sig(SIGTRAP, current, 0); | ||
279 | return 0; | 277 | return 0; |
280 | 278 | ||
281 | /* error cleanup */ | 279 | /* error cleanup */ |
@@ -42,13 +42,13 @@ | |||
42 | #include <linux/module.h> | 42 | #include <linux/module.h> |
43 | #include <linux/namei.h> | 43 | #include <linux/namei.h> |
44 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
45 | #include <linux/ptrace.h> | ||
46 | #include <linux/mount.h> | 45 | #include <linux/mount.h> |
47 | #include <linux/security.h> | 46 | #include <linux/security.h> |
48 | #include <linux/syscalls.h> | 47 | #include <linux/syscalls.h> |
49 | #include <linux/tsacct_kern.h> | 48 | #include <linux/tsacct_kern.h> |
50 | #include <linux/cn_proc.h> | 49 | #include <linux/cn_proc.h> |
51 | #include <linux/audit.h> | 50 | #include <linux/audit.h> |
51 | #include <linux/tracehook.h> | ||
52 | 52 | ||
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | #include <asm/mmu_context.h> | 54 | #include <asm/mmu_context.h> |
@@ -1071,13 +1071,8 @@ EXPORT_SYMBOL(prepare_binprm); | |||
1071 | 1071 | ||
1072 | static int unsafe_exec(struct task_struct *p) | 1072 | static int unsafe_exec(struct task_struct *p) |
1073 | { | 1073 | { |
1074 | int unsafe = 0; | 1074 | int unsafe = tracehook_unsafe_exec(p); |
1075 | if (p->ptrace & PT_PTRACED) { | 1075 | |
1076 | if (p->ptrace & PT_PTRACE_CAP) | ||
1077 | unsafe |= LSM_UNSAFE_PTRACE_CAP; | ||
1078 | else | ||
1079 | unsafe |= LSM_UNSAFE_PTRACE; | ||
1080 | } | ||
1081 | if (atomic_read(&p->fs->count) > 1 || | 1076 | if (atomic_read(&p->fs->count) > 1 || |
1082 | atomic_read(&p->files->count) > 1 || | 1077 | atomic_read(&p->files->count) > 1 || |
1083 | atomic_read(&p->sighand->count) > 1) | 1078 | atomic_read(&p->sighand->count) > 1) |
@@ -1214,6 +1209,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1214 | read_unlock(&binfmt_lock); | 1209 | read_unlock(&binfmt_lock); |
1215 | retval = fn(bprm, regs); | 1210 | retval = fn(bprm, regs); |
1216 | if (retval >= 0) { | 1211 | if (retval >= 0) { |
1212 | tracehook_report_exec(fmt, bprm, regs); | ||
1217 | put_binfmt(fmt); | 1213 | put_binfmt(fmt); |
1218 | allow_write_access(bprm->file); | 1214 | allow_write_access(bprm->file); |
1219 | if (bprm->file) | 1215 | if (bprm->file) |
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index bea0f3eeff54..6276353709c1 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h | |||
@@ -48,5 +48,51 @@ | |||
48 | 48 | ||
49 | #include <linux/sched.h> | 49 | #include <linux/sched.h> |
50 | #include <linux/ptrace.h> | 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 | #endif /* <linux/tracehook.h> */ | 98 | #endif /* <linux/tracehook.h> */ |