aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-06-17 10:50:37 -0400
committerOleg Nesterov <oleg@redhat.com>2011-06-22 13:26:28 -0400
commita288eecce5253cc1565d400a52b9b476a157e040 (patch)
treea933dd8c9791be83b7a67a33502c79e7b441960e
parentf3c04b934d429b1ace21866f011b66de328c0dc9 (diff)
ptrace: kill trivial 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 trivial tracehooks. * Ones testing whether task is ptraced. Replace with ->ptrace test. tracehook_expect_breakpoints() tracehook_consider_ignored_signal() tracehook_consider_fatal_signal() * ptrace_event() wrappers. Call directly. tracehook_report_exec() tracehook_report_exit() tracehook_report_vfork_done() * ptrace_release_task() wrapper. Call directly. tracehook_finish_release_task() * noop tracehook_prepare_release_task() tracehook_report_death() This doesn't introduce any behavior change. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Christoph Hellwig <hch@infradead.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
-rw-r--r--arch/s390/kernel/traps.c4
-rw-r--r--fs/exec.c2
-rw-r--r--include/linux/tracehook.h156
-rw-r--r--kernel/exit.c7
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/signal.c8
-rw-r--r--mm/nommu.c3
7 files changed, 11 insertions, 171 deletions
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index a65d2e82f61d..a63d34c3611e 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -331,7 +331,7 @@ void __kprobes do_per_trap(struct pt_regs *regs)
331{ 331{
332 if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) 332 if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
333 return; 333 return;
334 if (tracehook_consider_fatal_signal(current, SIGTRAP)) 334 if (current->ptrace)
335 force_sig(SIGTRAP, current); 335 force_sig(SIGTRAP, current);
336} 336}
337 337
@@ -425,7 +425,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
425 if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) 425 if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
426 return; 426 return;
427 if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { 427 if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
428 if (tracehook_consider_fatal_signal(current, SIGTRAP)) 428 if (current->ptrace)
429 force_sig(SIGTRAP, current); 429 force_sig(SIGTRAP, current);
430 else 430 else
431 signal = SIGILL; 431 signal = SIGILL;
diff --git a/fs/exec.c b/fs/exec.c
index a9f2b3631bdb..b37030d0a50b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1384,7 +1384,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
1384 bprm->recursion_depth = depth; 1384 bprm->recursion_depth = depth;
1385 if (retval >= 0) { 1385 if (retval >= 0) {
1386 if (depth == 0) 1386 if (depth == 0)
1387 tracehook_report_exec(fmt, bprm, regs); 1387 ptrace_event(PTRACE_EVENT_EXEC, 0);
1388 put_binfmt(fmt); 1388 put_binfmt(fmt);
1389 allow_write_access(bprm->file); 1389 allow_write_access(bprm->file);
1390 if (bprm->file) 1390 if (bprm->file)
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 3b68aa842a92..8b06d4f2b814 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -51,21 +51,6 @@
51#include <linux/security.h> 51#include <linux/security.h>
52struct linux_binprm; 52struct linux_binprm;
53 53
54/**
55 * tracehook_expect_breakpoints - guess if task memory might be touched
56 * @task: current task, making a new mapping
57 *
58 * Return nonzero if @task is expected to want breakpoint insertion in
59 * its memory at some point. A zero return is no guarantee it won't
60 * be done, but this is a hint that it's known to be likely.
61 *
62 * May be called with @task->mm->mmap_sem held for writing.
63 */
64static inline int tracehook_expect_breakpoints(struct task_struct *task)
65{
66 return (task->ptrace & PT_PTRACED) != 0;
67}
68
69/* 54/*
70 * ptrace report for syscall entry and exit looks identical. 55 * ptrace report for syscall entry and exit looks identical.
71 */ 56 */
@@ -184,42 +169,6 @@ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
184} 169}
185 170
186/** 171/**
187 * tracehook_report_exec - a successful exec was completed
188 * @fmt: &struct linux_binfmt that performed the exec
189 * @bprm: &struct linux_binprm containing exec details
190 * @regs: user-mode register state
191 *
192 * An exec just completed, we are shortly going to return to user mode.
193 * The freshly initialized register state can be seen and changed in @regs.
194 * The name, file and other pointers in @bprm are still on hand to be
195 * inspected, but will be freed as soon as this returns.
196 *
197 * Called with no locks, but with some kernel resources held live
198 * and a reference on @fmt->module.
199 */
200static inline void tracehook_report_exec(struct linux_binfmt *fmt,
201 struct linux_binprm *bprm,
202 struct pt_regs *regs)
203{
204 ptrace_event(PTRACE_EVENT_EXEC, 0);
205}
206
207/**
208 * tracehook_report_exit - task has begun to exit
209 * @exit_code: pointer to value destined for @current->exit_code
210 *
211 * @exit_code points to the value passed to do_exit(), which tracing
212 * might change here. This is almost the first thing in do_exit(),
213 * before freeing any resources or setting the %PF_EXITING flag.
214 *
215 * Called with no locks held.
216 */
217static inline void tracehook_report_exit(long *exit_code)
218{
219 ptrace_event(PTRACE_EVENT_EXIT, *exit_code);
220}
221
222/**
223 * tracehook_prepare_clone - prepare for new child to be cloned 172 * tracehook_prepare_clone - prepare for new child to be cloned
224 * @clone_flags: %CLONE_* flags from clone/fork/vfork system call 173 * @clone_flags: %CLONE_* flags from clone/fork/vfork system call
225 * 174 *
@@ -320,52 +269,6 @@ static inline void tracehook_report_clone_complete(int trace,
320} 269}
321 270
322/** 271/**
323 * tracehook_report_vfork_done - vfork parent's child has exited or exec'd
324 * @child: child task, already running
325 * @pid: new child's PID in the parent's namespace
326 *
327 * Called after a %CLONE_VFORK parent has waited for the child to complete.
328 * The clone/vfork system call will return immediately after this.
329 * The @child pointer may be invalid if a self-reaping child died and
330 * tracehook_report_clone() took no action to prevent it from self-reaping.
331 *
332 * Called with no locks held.
333 */
334static inline void tracehook_report_vfork_done(struct task_struct *child,
335 pid_t pid)
336{
337 ptrace_event(PTRACE_EVENT_VFORK_DONE, pid);
338}
339
340/**
341 * tracehook_prepare_release_task - task is being reaped, clean up tracing
342 * @task: task in %EXIT_DEAD state
343 *
344 * This is called in release_task() just before @task gets finally reaped
345 * and freed. This would be the ideal place to remove and clean up any
346 * tracing-related state for @task.
347 *
348 * Called with no locks held.
349 */
350static inline void tracehook_prepare_release_task(struct task_struct *task)
351{
352}
353
354/**
355 * tracehook_finish_release_task - final tracing clean-up
356 * @task: task in %EXIT_DEAD state
357 *
358 * This is called in release_task() when @task is being in the middle of
359 * being reaped. After this, there must be no tracing entanglements.
360 *
361 * Called with write_lock_irq(&tasklist_lock) held.
362 */
363static inline void tracehook_finish_release_task(struct task_struct *task)
364{
365 ptrace_release_task(task);
366}
367
368/**
369 * tracehook_signal_handler - signal handler setup is complete 272 * tracehook_signal_handler - signal handler setup is complete
370 * @sig: number of signal being delivered 273 * @sig: number of signal being delivered
371 * @info: siginfo_t of signal being delivered 274 * @info: siginfo_t of signal being delivered
@@ -388,41 +291,6 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info,
388 ptrace_notify(SIGTRAP); 291 ptrace_notify(SIGTRAP);
389} 292}
390 293
391/**
392 * tracehook_consider_ignored_signal - suppress short-circuit of ignored signal
393 * @task: task receiving the signal
394 * @sig: signal number being sent
395 *
396 * Return zero iff tracing doesn't care to examine this ignored signal,
397 * so it can short-circuit normal delivery and never even get queued.
398 *
399 * Called with @task->sighand->siglock held.
400 */
401static inline int tracehook_consider_ignored_signal(struct task_struct *task,
402 int sig)
403{
404 return (task->ptrace & PT_PTRACED) != 0;
405}
406
407/**
408 * tracehook_consider_fatal_signal - suppress special handling of fatal signal
409 * @task: task receiving the signal
410 * @sig: signal number being sent
411 *
412 * Return nonzero to prevent special handling of this termination signal.
413 * Normally handler for signal is %SIG_DFL. It can be %SIG_IGN if @sig is
414 * ignored, in which case force_sig() is about to reset it to %SIG_DFL.
415 * When this returns zero, this signal might cause a quick termination
416 * that does not give the debugger a chance to intercept the signal.
417 *
418 * Called with or without @task->sighand->siglock held.
419 */
420static inline int tracehook_consider_fatal_signal(struct task_struct *task,
421 int sig)
422{
423 return (task->ptrace & PT_PTRACED) != 0;
424}
425
426#define DEATH_REAP -1 294#define DEATH_REAP -1
427#define DEATH_DELAYED_GROUP_LEADER -2 295#define DEATH_DELAYED_GROUP_LEADER -2
428 296
@@ -457,30 +325,6 @@ static inline int tracehook_notify_death(struct task_struct *task,
457 return task->ptrace ? SIGCHLD : DEATH_DELAYED_GROUP_LEADER; 325 return task->ptrace ? SIGCHLD : DEATH_DELAYED_GROUP_LEADER;
458} 326}
459 327
460/**
461 * tracehook_report_death - task is dead and ready to be reaped
462 * @task: @current task now exiting
463 * @signal: return value from tracheook_notify_death()
464 * @death_cookie: value passed back from tracehook_notify_death()
465 * @group_dead: nonzero if this was the last thread in the group to die
466 *
467 * Thread has just become a zombie or is about to self-reap. If positive,
468 * @signal is the signal number just sent to the parent (usually %SIGCHLD).
469 * If @signal is %DEATH_REAP, this thread will self-reap. If @signal is
470 * %DEATH_DELAYED_GROUP_LEADER, this is a delayed_group_leader() zombie.
471 * The @death_cookie was passed back by tracehook_notify_death().
472 *
473 * If normal reaping is not inhibited, @task->exit_state might be changing
474 * in parallel.
475 *
476 * Called without locks.
477 */
478static inline void tracehook_report_death(struct task_struct *task,
479 int signal, void *death_cookie,
480 int group_dead)
481{
482}
483
484#ifdef TIF_NOTIFY_RESUME 328#ifdef TIF_NOTIFY_RESUME
485/** 329/**
486 * set_notify_resume - cause tracehook_notify_resume() to be called 330 * set_notify_resume - cause tracehook_notify_resume() to be called
diff --git a/kernel/exit.c b/kernel/exit.c
index e5cc05644609..d49134a7f250 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -169,7 +169,6 @@ void release_task(struct task_struct * p)
169 struct task_struct *leader; 169 struct task_struct *leader;
170 int zap_leader; 170 int zap_leader;
171repeat: 171repeat:
172 tracehook_prepare_release_task(p);
173 /* don't need to get the RCU readlock here - the process is dead and 172 /* don't need to get the RCU readlock here - the process is dead and
174 * can't be modifying its own credentials. But shut RCU-lockdep up */ 173 * can't be modifying its own credentials. But shut RCU-lockdep up */
175 rcu_read_lock(); 174 rcu_read_lock();
@@ -179,7 +178,7 @@ repeat:
179 proc_flush_task(p); 178 proc_flush_task(p);
180 179
181 write_lock_irq(&tasklist_lock); 180 write_lock_irq(&tasklist_lock);
182 tracehook_finish_release_task(p); 181 ptrace_release_task(p);
183 __exit_signal(p); 182 __exit_signal(p);
184 183
185 /* 184 /*
@@ -868,8 +867,6 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
868 wake_up_process(tsk->signal->group_exit_task); 867 wake_up_process(tsk->signal->group_exit_task);
869 write_unlock_irq(&tasklist_lock); 868 write_unlock_irq(&tasklist_lock);
870 869
871 tracehook_report_death(tsk, signal, cookie, group_dead);
872
873 /* If the process is dead, release it - nobody will wait for it */ 870 /* If the process is dead, release it - nobody will wait for it */
874 if (signal == DEATH_REAP) 871 if (signal == DEATH_REAP)
875 release_task(tsk); 872 release_task(tsk);
@@ -924,7 +921,7 @@ NORET_TYPE void do_exit(long code)
924 */ 921 */
925 set_fs(USER_DS); 922 set_fs(USER_DS);
926 923
927 tracehook_report_exit(&code); 924 ptrace_event(PTRACE_EVENT_EXIT, code);
928 925
929 validate_creds_for_do_exit(tsk); 926 validate_creds_for_do_exit(tsk);
930 927
diff --git a/kernel/fork.c b/kernel/fork.c
index 0276c30401a0..d4f0dff9d617 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1527,7 +1527,7 @@ long do_fork(unsigned long clone_flags,
1527 freezer_do_not_count(); 1527 freezer_do_not_count();
1528 wait_for_completion(&vfork); 1528 wait_for_completion(&vfork);
1529 freezer_count(); 1529 freezer_count();
1530 tracehook_report_vfork_done(p, nr); 1530 ptrace_event(PTRACE_EVENT_VFORK_DONE, nr);
1531 } 1531 }
1532 } else { 1532 } else {
1533 nr = PTR_ERR(p); 1533 nr = PTR_ERR(p);
diff --git a/kernel/signal.c b/kernel/signal.c
index 0f3370872506..1550aee34f42 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -87,7 +87,7 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns)
87 /* 87 /*
88 * Tracers may want to know about even ignored signals. 88 * Tracers may want to know about even ignored signals.
89 */ 89 */
90 return !tracehook_consider_ignored_signal(t, sig); 90 return !t->ptrace;
91} 91}
92 92
93/* 93/*
@@ -493,7 +493,8 @@ int unhandled_signal(struct task_struct *tsk, int sig)
493 return 1; 493 return 1;
494 if (handler != SIG_IGN && handler != SIG_DFL) 494 if (handler != SIG_IGN && handler != SIG_DFL)
495 return 0; 495 return 0;
496 return !tracehook_consider_fatal_signal(tsk, sig); 496 /* if ptraced, let the tracer determine */
497 return !tsk->ptrace;
497} 498}
498 499
499/* 500/*
@@ -981,8 +982,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)
981 if (sig_fatal(p, sig) && 982 if (sig_fatal(p, sig) &&
982 !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && 983 !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
983 !sigismember(&t->real_blocked, sig) && 984 !sigismember(&t->real_blocked, sig) &&
984 (sig == SIGKILL || 985 (sig == SIGKILL || !t->ptrace)) {
985 !tracehook_consider_fatal_signal(t, sig))) {
986 /* 986 /*
987 * This signal will be fatal to the whole group. 987 * This signal will be fatal to the whole group.
988 */ 988 */
diff --git a/mm/nommu.c b/mm/nommu.c
index 1fd0c51b10a6..54ae707bdae8 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -22,7 +22,6 @@
22#include <linux/pagemap.h> 22#include <linux/pagemap.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
25#include <linux/tracehook.h>
26#include <linux/blkdev.h> 25#include <linux/blkdev.h>
27#include <linux/backing-dev.h> 26#include <linux/backing-dev.h>
28#include <linux/mount.h> 27#include <linux/mount.h>
@@ -1087,7 +1086,7 @@ static unsigned long determine_vm_flags(struct file *file,
1087 * it's being traced - otherwise breakpoints set in it may interfere 1086 * it's being traced - otherwise breakpoints set in it may interfere
1088 * with another untraced process 1087 * with another untraced process
1089 */ 1088 */
1090 if ((flags & MAP_PRIVATE) && tracehook_expect_breakpoints(current)) 1089 if ((flags & MAP_PRIVATE) && current->ptrace)
1091 vm_flags &= ~VM_MAYSHARE; 1090 vm_flags &= ~VM_MAYSHARE;
1092 1091
1093 return vm_flags; 1092 return vm_flags;