aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c7
-rw-r--r--include/linux/tracehook.h121
-rw-r--r--kernel/fork.c41
3 files changed, 38 insertions, 131 deletions
diff --git a/fs/exec.c b/fs/exec.c
index b37030d0a50..8dca45b0dae 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1224,7 +1224,12 @@ int check_unsafe_exec(struct linux_binprm *bprm)
1224 unsigned n_fs; 1224 unsigned n_fs;
1225 int res = 0; 1225 int res = 0;
1226 1226
1227 bprm->unsafe = tracehook_unsafe_exec(p); 1227 if (p->ptrace) {
1228 if (p->ptrace & PT_PTRACE_CAP)
1229 bprm->unsafe |= LSM_UNSAFE_PTRACE_CAP;
1230 else
1231 bprm->unsafe |= LSM_UNSAFE_PTRACE;
1232 }
1228 1233
1229 n_fs = 1; 1234 n_fs = 1;
1230 spin_lock(&p->fs->lock); 1235 spin_lock(&p->fs->lock);
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 8b06d4f2b81..bcc4ca762ae 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -130,27 +130,6 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
130} 130}
131 131
132/** 132/**
133 * tracehook_unsafe_exec - check for exec declared unsafe due to tracing
134 * @task: current task doing exec
135 *
136 * Return %LSM_UNSAFE_* bits applied to an exec because of tracing.
137 *
138 * @task->signal->cred_guard_mutex is held by the caller through the do_execve().
139 */
140static inline int tracehook_unsafe_exec(struct task_struct *task)
141{
142 int unsafe = 0;
143 int ptrace = task->ptrace;
144 if (ptrace & PT_PTRACED) {
145 if (ptrace & PT_PTRACE_CAP)
146 unsafe |= LSM_UNSAFE_PTRACE_CAP;
147 else
148 unsafe |= LSM_UNSAFE_PTRACE;
149 }
150 return unsafe;
151}
152
153/**
154 * tracehook_tracer_task - return the task that is tracing the given task 133 * tracehook_tracer_task - return the task that is tracing the given task
155 * @tsk: task to consider 134 * @tsk: task to consider
156 * 135 *
@@ -169,106 +148,6 @@ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
169} 148}
170 149
171/** 150/**
172 * tracehook_prepare_clone - prepare for new child to be cloned
173 * @clone_flags: %CLONE_* flags from clone/fork/vfork system call
174 *
175 * This is called before a new user task is to be cloned.
176 * Its return value will be passed to tracehook_finish_clone().
177 *
178 * Called with no locks held.
179 */
180static inline int tracehook_prepare_clone(unsigned clone_flags)
181{
182 int event = 0;
183
184 if (clone_flags & CLONE_UNTRACED)
185 return 0;
186
187 if (clone_flags & CLONE_VFORK)
188 event = PTRACE_EVENT_VFORK;
189 else if ((clone_flags & CSIGNAL) != SIGCHLD)
190 event = PTRACE_EVENT_CLONE;
191 else
192 event = PTRACE_EVENT_FORK;
193
194 return ptrace_event_enabled(current, event) ? event : 0;
195}
196
197/**
198 * tracehook_finish_clone - new child created and being attached
199 * @child: new child task
200 * @clone_flags: %CLONE_* flags from clone/fork/vfork system call
201 * @trace: return value from tracehook_prepare_clone()
202 *
203 * This is called immediately after adding @child to its parent's children list.
204 * The @trace value is that returned by tracehook_prepare_clone().
205 *
206 * Called with current's siglock and write_lock_irq(&tasklist_lock) held.
207 */
208static inline void tracehook_finish_clone(struct task_struct *child,
209 unsigned long clone_flags, int trace)
210{
211 ptrace_init_task(child, (clone_flags & CLONE_PTRACE) || trace);
212}
213
214/**
215 * tracehook_report_clone - in parent, new child is about to start running
216 * @regs: parent's user register state
217 * @clone_flags: flags from parent's system call
218 * @pid: new child's PID in the parent's namespace
219 * @child: new child task
220 *
221 * Called after a child is set up, but before it has been started running.
222 * This is not a good place to block, because the child has not started
223 * yet. Suspend the child here if desired, and then block in
224 * tracehook_report_clone_complete(). This must prevent the child from
225 * self-reaping if tracehook_report_clone_complete() uses the @child
226 * pointer; otherwise it might have died and been released by the time
227 * tracehook_report_clone_complete() is called.
228 *
229 * Called with no locks held, but the child cannot run until this returns.
230 */
231static inline void tracehook_report_clone(struct pt_regs *regs,
232 unsigned long clone_flags,
233 pid_t pid, struct task_struct *child)
234{
235 if (unlikely(child->ptrace)) {
236 /*
237 * It doesn't matter who attached/attaching to this
238 * task, the pending SIGSTOP is right in any case.
239 */
240 sigaddset(&child->pending.signal, SIGSTOP);
241 set_tsk_thread_flag(child, TIF_SIGPENDING);
242 }
243}
244
245/**
246 * tracehook_report_clone_complete - new child is running
247 * @trace: return value from tracehook_prepare_clone()
248 * @regs: parent's user register state
249 * @clone_flags: flags from parent's system call
250 * @pid: new child's PID in the parent's namespace
251 * @child: child task, already running
252 *
253 * This is called just after the child has started running. This is
254 * just before the clone/fork syscall returns, or blocks for vfork
255 * child completion if @clone_flags has the %CLONE_VFORK bit set.
256 * The @child pointer may be invalid if a self-reaping child died and
257 * tracehook_report_clone() took no action to prevent it from self-reaping.
258 *
259 * Called with no locks held.
260 */
261static inline void tracehook_report_clone_complete(int trace,
262 struct pt_regs *regs,
263 unsigned long clone_flags,
264 pid_t pid,
265 struct task_struct *child)
266{
267 if (unlikely(trace))
268 ptrace_event(trace, pid);
269}
270
271/**
272 * tracehook_signal_handler - signal handler setup is complete 151 * tracehook_signal_handler - signal handler setup is complete
273 * @sig: number of signal being delivered 152 * @sig: number of signal being delivered
274 * @info: siginfo_t of signal being delivered 153 * @info: siginfo_t of signal being delivered
diff --git a/kernel/fork.c b/kernel/fork.c
index d4f0dff9d61..3c72a5b321a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1340,7 +1340,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1340 } 1340 }
1341 1341
1342 if (likely(p->pid)) { 1342 if (likely(p->pid)) {
1343 tracehook_finish_clone(p, clone_flags, trace); 1343 ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
1344 1344
1345 if (thread_group_leader(p)) { 1345 if (thread_group_leader(p)) {
1346 if (is_child_reaper(pid)) 1346 if (is_child_reaper(pid))
@@ -1481,10 +1481,22 @@ long do_fork(unsigned long clone_flags,
1481 } 1481 }
1482 1482
1483 /* 1483 /*
1484 * When called from kernel_thread, don't do user tracing stuff. 1484 * Determine whether and which event to report to ptracer. When
1485 * called from kernel_thread or CLONE_UNTRACED is explicitly
1486 * requested, no event is reported; otherwise, report if the event
1487 * for the type of forking is enabled.
1485 */ 1488 */
1486 if (likely(user_mode(regs))) 1489 if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) {
1487 trace = tracehook_prepare_clone(clone_flags); 1490 if (clone_flags & CLONE_VFORK)
1491 trace = PTRACE_EVENT_VFORK;
1492 else if ((clone_flags & CSIGNAL) != SIGCHLD)
1493 trace = PTRACE_EVENT_CLONE;
1494 else
1495 trace = PTRACE_EVENT_FORK;
1496
1497 if (likely(!ptrace_event_enabled(current, trace)))
1498 trace = 0;
1499 }
1488 1500
1489 p = copy_process(clone_flags, stack_start, regs, stack_size, 1501 p = copy_process(clone_flags, stack_start, regs, stack_size,
1490 child_tidptr, NULL, trace); 1502 child_tidptr, NULL, trace);
@@ -1508,20 +1520,31 @@ long do_fork(unsigned long clone_flags,
1508 } 1520 }
1509 1521
1510 audit_finish_fork(p); 1522 audit_finish_fork(p);
1511 tracehook_report_clone(regs, clone_flags, nr, p); 1523
1524 /*
1525 * Child is ready but hasn't started running yet. Queue
1526 * SIGSTOP if it's gonna be ptraced - it doesn't matter who
1527 * attached/attaching to this task, the pending SIGSTOP is
1528 * right in any case.
1529 */
1530 if (unlikely(p->ptrace)) {
1531 sigaddset(&p->pending.signal, SIGSTOP);
1532 set_tsk_thread_flag(p, TIF_SIGPENDING);
1533 }
1512 1534
1513 /* 1535 /*
1514 * We set PF_STARTING at creation in case tracing wants to 1536 * We set PF_STARTING at creation in case tracing wants to
1515 * use this to distinguish a fully live task from one that 1537 * use this to distinguish a fully live task from one that
1516 * hasn't gotten to tracehook_report_clone() yet. Now we 1538 * hasn't finished SIGSTOP raising yet. Now we clear it
1517 * clear it and set the child going. 1539 * and set the child going.
1518 */ 1540 */
1519 p->flags &= ~PF_STARTING; 1541 p->flags &= ~PF_STARTING;
1520 1542
1521 wake_up_new_task(p); 1543 wake_up_new_task(p);
1522 1544
1523 tracehook_report_clone_complete(trace, regs, 1545 /* forking complete and child started to run, tell ptracer */
1524 clone_flags, nr, p); 1546 if (unlikely(trace))
1547 ptrace_event(trace, nr);
1525 1548
1526 if (clone_flags & CLONE_VFORK) { 1549 if (clone_flags & CLONE_VFORK) {
1527 freezer_do_not_count(); 1550 freezer_do_not_count();