Skip to content

Commit 5981851

Browse files
committed
Adding support for FORK, VFORK, VFORK_DONE and CLONE events.
1 parent 4027c0f commit 5981851

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

include/linux/ptrace.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,35 @@ static inline struct task_struct *ptrace_parent(struct task_struct *task)
180180
return NULL;
181181
}
182182

183+
static inline bool proctrace_event_enabled(struct task_struct *task, int event)
184+
{
185+
struct list_head *p;
186+
struct sig_wait_queue_struct *sig_wait;
187+
list_for_each(p, &task->sig_wait_list) {
188+
sig_wait = list_entry(p, struct sig_wait_queue_struct, list);
189+
if (sig_wait->sigmask & (1ULL << event)) {
190+
return 1;
191+
}
192+
}
193+
194+
return 0;
195+
}
196+
197+
static inline bool proctrace_send_event(int event, unsigned int message)
198+
{
199+
struct list_head *p;
200+
struct sig_wait_queue_struct *sig_wait;
201+
list_for_each(p, &current->sig_wait_list) {
202+
sig_wait = list_entry(p, struct sig_wait_queue_struct, list);
203+
if (sig_wait->sigmask & (1ULL << event)) {
204+
current->ptrace_message = message;
205+
wake_up(&sig_wait->wait_queue);
206+
}
207+
}
208+
209+
return 0;
210+
}
211+
183212
/**
184213
* ptrace_event_enabled - test whether a ptrace event is enabled
185214
* @task: ptracee of interest

kernel/fork.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
10531053
unsigned long stack_size,
10541054
int __user *child_tidptr,
10551055
struct pid *pid,
1056-
int trace)
1056+
int trace,
1057+
int proctrace)
10571058
{
10581059
int retval;
10591060
struct task_struct *p;
@@ -1358,6 +1359,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
13581359

13591360
if (likely(p->pid)) {
13601361
ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
1362+
if (proctrace && proctrace_event_enabled(current, proctrace)) {
1363+
// stop it
1364+
sigaddset(&p->pending.signal, SIGSTOP);
1365+
set_tsk_thread_flag(p, TIF_SIGPENDING);
1366+
}
13611367

13621368
if (thread_group_leader(p)) {
13631369
if (is_child_reaper(pid))
@@ -1456,7 +1462,7 @@ struct task_struct * __cpuinit fork_idle(int cpu)
14561462
struct pt_regs regs;
14571463

14581464
task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL,
1459-
&init_struct_pid, 0);
1465+
&init_struct_pid, 0, 0);
14601466
if (!IS_ERR(task)) {
14611467
init_idle_pids(task->pids);
14621468
init_idle(task, cpu);
@@ -1480,6 +1486,7 @@ long do_fork(unsigned long clone_flags,
14801486
{
14811487
struct task_struct *p;
14821488
int trace = 0;
1489+
int proctrace_event = 0;
14831490
long nr;
14841491

14851492
/*
@@ -1504,19 +1511,27 @@ long do_fork(unsigned long clone_flags,
15041511
* for the type of forking is enabled.
15051512
*/
15061513
if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) {
1507-
if (clone_flags & CLONE_VFORK)
1514+
if (clone_flags & CLONE_VFORK) {
15081515
trace = PTRACE_EVENT_VFORK;
1509-
else if ((clone_flags & CSIGNAL) != SIGCHLD)
1516+
proctrace_event = PROCTRACE_VFORK;
1517+
} else if ((clone_flags & CSIGNAL) != SIGCHLD) {
15101518
trace = PTRACE_EVENT_CLONE;
1511-
else
1519+
proctrace_event = PROCTRACE_CLONE;
1520+
} else {
15121521
trace = PTRACE_EVENT_FORK;
1522+
proctrace_event = PROCTRACE_FORK;
1523+
}
15131524

15141525
if (likely(!ptrace_event_enabled(current, trace)))
15151526
trace = 0;
1527+
1528+
if (likely(!proctrace_event_enabled(current, proctrace_event)))
1529+
proctrace_event = 0;
1530+
15161531
}
15171532

15181533
p = copy_process(clone_flags, stack_start, regs, stack_size,
1519-
child_tidptr, NULL, trace);
1534+
child_tidptr, NULL, trace, proctrace_event);
15201535
/*
15211536
* Do this prior waking up the new thread - the thread pointer
15221537
* might get invalid after that point, if the thread exits quickly.
@@ -1552,11 +1567,15 @@ long do_fork(unsigned long clone_flags,
15521567
if (unlikely(trace))
15531568
ptrace_event(trace, nr);
15541569

1570+
if (unlikely(proctrace_event))
1571+
proctrace_send_event(proctrace_event, nr);
1572+
15551573
if (clone_flags & CLONE_VFORK) {
15561574
freezer_do_not_count();
15571575
wait_for_completion(&vfork);
15581576
freezer_count();
15591577
ptrace_event(PTRACE_EVENT_VFORK_DONE, nr);
1578+
proctrace_send_event(PROCTRACE_VFORK_DONE, nr);
15601579
}
15611580
} else {
15621581
nr = PTR_ERR(p);

0 commit comments

Comments
 (0)