Commit 45c1a159 authored by Daniel Jacobowitz's avatar Daniel Jacobowitz

Add PTRACE_O_TRACEVFORKDONE and PTRACE_O_TRACEEXIT facilities.

parent 762cc267
...@@ -35,12 +35,16 @@ ...@@ -35,12 +35,16 @@
#define PTRACE_O_TRACEVFORK 0x00000004 #define PTRACE_O_TRACEVFORK 0x00000004
#define PTRACE_O_TRACECLONE 0x00000008 #define PTRACE_O_TRACECLONE 0x00000008
#define PTRACE_O_TRACEEXEC 0x00000010 #define PTRACE_O_TRACEEXEC 0x00000010
#define PTRACE_O_TRACEVFORKDONE 0x00000020
#define PTRACE_O_TRACEEXIT 0x00000040
/* Wait extended result codes for the above trace options. */ /* Wait extended result codes for the above trace options. */
#define PTRACE_EVENT_FORK 1 #define PTRACE_EVENT_FORK 1
#define PTRACE_EVENT_VFORK 2 #define PTRACE_EVENT_VFORK 2
#define PTRACE_EVENT_CLONE 3 #define PTRACE_EVENT_CLONE 3
#define PTRACE_EVENT_EXEC 4 #define PTRACE_EVENT_EXEC 4
#define PTRACE_EVENT_VFORK_DONE 5
#define PTRACE_EVENT_EXIT 6
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <linux/sched.h> #include <linux/sched.h>
......
...@@ -441,6 +441,8 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) ...@@ -441,6 +441,8 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PT_TRACE_VFORK 0x00000020 #define PT_TRACE_VFORK 0x00000020
#define PT_TRACE_CLONE 0x00000040 #define PT_TRACE_CLONE 0x00000040
#define PT_TRACE_EXEC 0x00000080 #define PT_TRACE_EXEC 0x00000080
#define PT_TRACE_VFORK_DONE 0x00000100
#define PT_TRACE_EXIT 0x00000200
#if CONFIG_SMP #if CONFIG_SMP
extern void set_cpus_allowed(task_t *p, unsigned long new_mask); extern void set_cpus_allowed(task_t *p, unsigned long new_mask);
......
...@@ -653,6 +653,9 @@ NORET_TYPE void do_exit(long code) ...@@ -653,6 +653,9 @@ NORET_TYPE void do_exit(long code)
profile_exit_task(tsk); profile_exit_task(tsk);
if (unlikely(current->ptrace & PT_TRACE_EXIT))
ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
fake_volatile: fake_volatile:
acct_process(code); acct_process(code);
__exit_mm(tsk); __exit_mm(tsk);
......
...@@ -1046,9 +1046,11 @@ struct task_struct *do_fork(unsigned long clone_flags, ...@@ -1046,9 +1046,11 @@ struct task_struct *do_fork(unsigned long clone_flags,
ptrace_notify ((trace << 8) | SIGTRAP); ptrace_notify ((trace << 8) | SIGTRAP);
} }
if (clone_flags & CLONE_VFORK) if (clone_flags & CLONE_VFORK) {
wait_for_completion(&vfork); wait_for_completion(&vfork);
else if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
} else
/* /*
* Let the child process run first, to avoid most of the * Let the child process run first, to avoid most of the
* COW overhead when the child exec()s afterwards. * COW overhead when the child exec()s afterwards.
......
...@@ -277,9 +277,20 @@ static int ptrace_setoptions(struct task_struct *child, long data) ...@@ -277,9 +277,20 @@ static int ptrace_setoptions(struct task_struct *child, long data)
else else
child->ptrace &= ~PT_TRACE_EXEC; child->ptrace &= ~PT_TRACE_EXEC;
if (data & PTRACE_O_TRACEVFORKDONE)
child->ptrace |= PT_TRACE_VFORK_DONE;
else
child->ptrace &= ~PT_TRACE_VFORK_DONE;
if (data & PTRACE_O_TRACEEXIT)
child->ptrace |= PT_TRACE_EXIT;
else
child->ptrace &= ~PT_TRACE_EXIT;
if ((data & (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK if ((data & (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK
| PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE
| PTRACE_O_TRACEEXEC)) | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEEXIT
| PTRACE_O_TRACEVFORKDONE))
!= data) != data)
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment