Skip to content

Commit

Permalink
tracehook: exec
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Reviewed-by: Ingo Molnar <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Roland McGrath authored and torvalds committed Jul 26, 2008
1 parent 88ac292 commit 6341c39
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 38 deletions.
6 changes: 0 additions & 6 deletions arch/x86/ia32/ia32_aout.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,12 +441,6 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
regs->r8 = regs->r9 = regs->r10 = regs->r11 =
regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
set_fs(USER_DS);
if (unlikely(current->ptrace & PT_PTRACED)) {
if (current->ptrace & PT_TRACE_EXEC)
ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
else
send_sig(SIGTRAP, current, 0);
}
return 0;
}

Expand Down
6 changes: 0 additions & 6 deletions fs/binfmt_aout.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,12 +444,6 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
regs->gp = ex.a_gpvalue;
#endif
start_thread(regs, ex.a_entry, current->mm->start_stack);
if (unlikely(current->ptrace & PT_PTRACED)) {
if (current->ptrace & PT_TRACE_EXEC)
ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
else
send_sig(SIGTRAP, current, 0);
}
return 0;
}

Expand Down
6 changes: 0 additions & 6 deletions fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1003,12 +1003,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
#endif

start_thread(regs, elf_entry, bprm->p);
if (unlikely(current->ptrace & PT_PTRACED)) {
if (current->ptrace & PT_TRACE_EXEC)
ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
else
send_sig(SIGTRAP, current, 0);
}
retval = 0;
out:
kfree(loc);
Expand Down
7 changes: 0 additions & 7 deletions fs/binfmt_elf_fdpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,13 +433,6 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
entryaddr = interp_params.entry_addr ?: exec_params.entry_addr;
start_thread(regs, entryaddr, current->mm->start_stack);

if (unlikely(current->ptrace & PT_PTRACED)) {
if (current->ptrace & PT_TRACE_EXEC)
ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
else
send_sig(SIGTRAP, current, 0);
}

retval = 0;

error:
Expand Down
3 changes: 0 additions & 3 deletions fs/binfmt_flat.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,9 +920,6 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)

start_thread(regs, start_addr, current->mm->start_stack);

if (current->ptrace & PT_PTRACED)
send_sig(SIGTRAP, current, 0);

return 0;
}

Expand Down
2 changes: 0 additions & 2 deletions fs/binfmt_som.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
map_hpux_gateway_page(current,current->mm);

start_thread_som(regs, som_entry, bprm->p);
if (current->ptrace & PT_PTRACED)
send_sig(SIGTRAP, current, 0);
return 0;

/* error cleanup */
Expand Down
12 changes: 4 additions & 8 deletions fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/proc_fs.h>
#include <linux/ptrace.h>
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/tsacct_kern.h>
#include <linux/cn_proc.h>
#include <linux/audit.h>
#include <linux/tracehook.h>

#include <asm/uaccess.h>
#include <asm/mmu_context.h>
Expand Down Expand Up @@ -1071,13 +1071,8 @@ EXPORT_SYMBOL(prepare_binprm);

static int unsafe_exec(struct task_struct *p)
{
int unsafe = 0;
if (p->ptrace & PT_PTRACED) {
if (p->ptrace & PT_PTRACE_CAP)
unsafe |= LSM_UNSAFE_PTRACE_CAP;
else
unsafe |= LSM_UNSAFE_PTRACE;
}
int unsafe = tracehook_unsafe_exec(p);

if (atomic_read(&p->fs->count) > 1 ||
atomic_read(&p->files->count) > 1 ||
atomic_read(&p->sighand->count) > 1)
Expand Down Expand Up @@ -1214,6 +1209,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
read_unlock(&binfmt_lock);
retval = fn(bprm, regs);
if (retval >= 0) {
tracehook_report_exec(fmt, bprm, regs);
put_binfmt(fmt);
allow_write_access(bprm->file);
if (bprm->file)
Expand Down
46 changes: 46 additions & 0 deletions include/linux/tracehook.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,51 @@

#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/security.h>
struct linux_binprm;

/**
* tracehook_unsafe_exec - check for exec declared unsafe due to tracing
* @task: current task doing exec
*
* Return %LSM_UNSAFE_* bits applied to an exec because of tracing.
*
* Called with task_lock() held on @task.
*/
static inline int tracehook_unsafe_exec(struct task_struct *task)
{
int unsafe = 0;
int ptrace = task_ptrace(task);
if (ptrace & PT_PTRACED) {
if (ptrace & PT_PTRACE_CAP)
unsafe |= LSM_UNSAFE_PTRACE_CAP;
else
unsafe |= LSM_UNSAFE_PTRACE;
}
return unsafe;
}

/**
* tracehook_report_exec - a successful exec was completed
* @fmt: &struct linux_binfmt that performed the exec
* @bprm: &struct linux_binprm containing exec details
* @regs: user-mode register state
*
* An exec just completed, we are shortly going to return to user mode.
* The freshly initialized register state can be seen and changed in @regs.
* The name, file and other pointers in @bprm are still on hand to be
* inspected, but will be freed as soon as this returns.
*
* Called with no locks, but with some kernel resources held live
* and a reference on @fmt->module.
*/
static inline void tracehook_report_exec(struct linux_binfmt *fmt,
struct linux_binprm *bprm,
struct pt_regs *regs)
{
if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) &&
unlikely(task_ptrace(current) & PT_PTRACED))
send_sig(SIGTRAP, current, 0);
}

#endif /* <linux/tracehook.h> */

0 comments on commit 6341c39

Please sign in to comment.