Commit 4b9d33e6d83cc05a8005a8f9a8b9677fa0f53626

Authored by Tejun Heo
Committed by Oleg Nesterov
1 parent a288eecce5

ptrace: kill clone/exec tracehooks

At this point, tracehooks aren't useful to mainline kernel and mostly
just add an extra layer of obfuscation.  Although they have comments,
without actual in-kernel users, it is difficult to tell what are their
assumptions and they're actually trying to achieve.  To mainline
kernel, they just aren't worth keeping around.

This patch kills the following clone and exec related tracehooks.

	tracehook_prepare_clone()
	tracehook_finish_clone()
	tracehook_report_clone()
	tracehook_report_clone_complete()
	tracehook_unsafe_exec()

The changes are mostly trivial - logic is moved to the caller and
comments are merged and adjusted appropriately.

The only exception is in check_unsafe_exec() where LSM_UNSAFE_PTRACE*
are OR'd to bprm->unsafe instead of setting it, which produces the
same result as the field is always zero on entry.  It also tests
p->ptrace instead of (p->ptrace & PT_PTRACED) for consistency, which
also gives the same result.

This doesn't introduce any behavior change.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>

Showing 3 changed files with 38 additions and 131 deletions Side-by-side Diff

... ... @@ -1224,7 +1224,12 @@
1224 1224 unsigned n_fs;
1225 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 1234 n_fs = 1;
1230 1235 spin_lock(&p->fs->lock);
include/linux/tracehook.h
... ... @@ -130,27 +130,6 @@
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   - */
140   -static 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 133 * tracehook_tracer_task - return the task that is tracing the given task
155 134 * @tsk: task to consider
156 135 *
... ... @@ -166,106 +145,6 @@
166 145 if (tsk->ptrace & PT_PTRACED)
167 146 return rcu_dereference(tsk->parent);
168 147 return NULL;
169   -}
170   -
171   -/**
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   - */
180   -static 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   - */
208   -static 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   - */
231   -static 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   - */
261   -static 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 148 }
270 149  
271 150 /**
... ... @@ -1340,7 +1340,7 @@
1340 1340 }
1341 1341  
1342 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 1345 if (thread_group_leader(p)) {
1346 1346 if (is_child_reaper(pid))
1347 1347  
1348 1348  
... ... @@ -1481,11 +1481,23 @@
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)))
1487   - trace = tracehook_prepare_clone(clone_flags);
  1489 + if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) {
  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;
1488 1496  
  1497 + if (likely(!ptrace_event_enabled(current, trace)))
  1498 + trace = 0;
  1499 + }
  1500 +
1489 1501 p = copy_process(clone_flags, stack_start, regs, stack_size,
1490 1502 child_tidptr, NULL, trace);
1491 1503 /*
1492 1504  
1493 1505  
1494 1506  
... ... @@ -1508,20 +1520,31 @@
1508 1520 }
1509 1521  
1510 1522 audit_finish_fork(p);
1511   - tracehook_report_clone(regs, clone_flags, nr, p);
1512 1523  
1513 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 + }
  1534 +
  1535 + /*
1514 1536 * We set PF_STARTING at creation in case tracing wants to
1515 1537 * use this to distinguish a fully live task from one that
1516   - * hasn't gotten to tracehook_report_clone() yet. Now we
1517   - * clear it and set the child going.
  1538 + * hasn't finished SIGSTOP raising yet. Now we clear it
  1539 + * and set the child going.
1518 1540 */
1519 1541 p->flags &= ~PF_STARTING;
1520 1542  
1521 1543 wake_up_new_task(p);
1522 1544  
1523   - tracehook_report_clone_complete(trace, regs,
1524   - clone_flags, nr, p);
  1545 + /* forking complete and child started to run, tell ptracer */
  1546 + if (unlikely(trace))
  1547 + ptrace_event(trace, nr);
1525 1548  
1526 1549 if (clone_flags & CLONE_VFORK) {
1527 1550 freezer_do_not_count();