aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-07-25 22:45:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 15:00:08 -0400
commit0d094efeb1e98010c6b99923f1eb7e17bf1e3a74 (patch)
tree6ee271b6da5796e5321d2ab6f9d7d9ba03c300a2
parentdae33574dcf5211e1f43c7e45fa29f73ba3e00cb (diff)
tracehook: tracehook_tracer_task
This adds the tracehook_tracer_task() hook to consolidate all forms of "Who is using ptrace on me?" logic. This is used for "TracerPid:" in /proc and for permission checks. We also clean up the selinux code the called an identical accessor. Signed-off-by: Roland McGrath <roland@redhat.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Reviewed-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/proc/array.c9
-rw-r--r--fs/proc/base.c13
-rw-r--r--include/linux/tracehook.h18
-rw-r--r--security/selinux/hooks.c22
4 files changed, 37 insertions, 25 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 797d775e0354..0d6eb33597c6 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -80,6 +80,7 @@
80#include <linux/delayacct.h> 80#include <linux/delayacct.h>
81#include <linux/seq_file.h> 81#include <linux/seq_file.h>
82#include <linux/pid_namespace.h> 82#include <linux/pid_namespace.h>
83#include <linux/tracehook.h>
83 84
84#include <asm/pgtable.h> 85#include <asm/pgtable.h>
85#include <asm/processor.h> 86#include <asm/processor.h>
@@ -168,8 +169,12 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
168 rcu_read_lock(); 169 rcu_read_lock();
169 ppid = pid_alive(p) ? 170 ppid = pid_alive(p) ?
170 task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; 171 task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
171 tpid = pid_alive(p) && p->ptrace ? 172 tpid = 0;
172 task_pid_nr_ns(rcu_dereference(p->parent), ns) : 0; 173 if (pid_alive(p)) {
174 struct task_struct *tracer = tracehook_tracer_task(p);
175 if (tracer)
176 tpid = task_pid_nr_ns(tracer, ns);
177 }
173 seq_printf(m, 178 seq_printf(m,
174 "State:\t%s\n" 179 "State:\t%s\n"
175 "Tgid:\t%d\n" 180 "Tgid:\t%d\n"
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a891fe4cb43b..4b74dba69a6d 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -69,6 +69,7 @@
69#include <linux/mount.h> 69#include <linux/mount.h>
70#include <linux/security.h> 70#include <linux/security.h>
71#include <linux/ptrace.h> 71#include <linux/ptrace.h>
72#include <linux/tracehook.h>
72#include <linux/cgroup.h> 73#include <linux/cgroup.h>
73#include <linux/cpuset.h> 74#include <linux/cpuset.h>
74#include <linux/audit.h> 75#include <linux/audit.h>
@@ -231,10 +232,14 @@ static int check_mem_permission(struct task_struct *task)
231 * If current is actively ptrace'ing, and would also be 232 * If current is actively ptrace'ing, and would also be
232 * permitted to freshly attach with ptrace now, permit it. 233 * permitted to freshly attach with ptrace now, permit it.
233 */ 234 */
234 if (task->parent == current && (task->ptrace & PT_PTRACED) && 235 if (task_is_stopped_or_traced(task)) {
235 task_is_stopped_or_traced(task) && 236 int match;
236 ptrace_may_access(task, PTRACE_MODE_ATTACH)) 237 rcu_read_lock();
237 return 0; 238 match = (tracehook_tracer_task(task) == current);
239 rcu_read_unlock();
240 if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
241 return 0;
242 }
238 243
239 /* 244 /*
240 * Noone else is allowed. 245 * Noone else is allowed.
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 9a5b3be2503a..6468ca0fe69b 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -73,6 +73,24 @@ static inline int tracehook_unsafe_exec(struct task_struct *task)
73} 73}
74 74
75/** 75/**
76 * tracehook_tracer_task - return the task that is tracing the given task
77 * @tsk: task to consider
78 *
79 * Returns NULL if noone is tracing @task, or the &struct task_struct
80 * pointer to its tracer.
81 *
82 * Must called under rcu_read_lock(). The pointer returned might be kept
83 * live only by RCU. During exec, this may be called with task_lock()
84 * held on @task, still held from when tracehook_unsafe_exec() was called.
85 */
86static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
87{
88 if (task_ptrace(tsk) & PT_PTRACED)
89 return rcu_dereference(tsk->parent);
90 return NULL;
91}
92
93/**
76 * tracehook_report_exec - a successful exec was completed 94 * tracehook_report_exec - a successful exec was completed
77 * @fmt: &struct linux_binfmt that performed the exec 95 * @fmt: &struct linux_binfmt that performed the exec
78 * @bprm: &struct linux_binprm containing exec details 96 * @bprm: &struct linux_binprm containing exec details
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 63f131fc42e4..3481cde5bf15 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -25,7 +25,7 @@
25 25
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/kernel.h> 27#include <linux/kernel.h>
28#include <linux/ptrace.h> 28#include <linux/tracehook.h>
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/sched.h> 30#include <linux/sched.h>
31#include <linux/security.h> 31#include <linux/security.h>
@@ -1971,22 +1971,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
1971 return __vm_enough_memory(mm, pages, cap_sys_admin); 1971 return __vm_enough_memory(mm, pages, cap_sys_admin);
1972} 1972}
1973 1973
1974/**
1975 * task_tracer_task - return the task that is tracing the given task
1976 * @task: task to consider
1977 *
1978 * Returns NULL if noone is tracing @task, or the &struct task_struct
1979 * pointer to its tracer.
1980 *
1981 * Must be called under rcu_read_lock().
1982 */
1983static struct task_struct *task_tracer_task(struct task_struct *task)
1984{
1985 if (task->ptrace & PT_PTRACED)
1986 return rcu_dereference(task->parent);
1987 return NULL;
1988}
1989
1990/* binprm security operations */ 1974/* binprm security operations */
1991 1975
1992static int selinux_bprm_alloc_security(struct linux_binprm *bprm) 1976static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -2238,7 +2222,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2238 u32 ptsid = 0; 2222 u32 ptsid = 0;
2239 2223
2240 rcu_read_lock(); 2224 rcu_read_lock();
2241 tracer = task_tracer_task(current); 2225 tracer = tracehook_tracer_task(current);
2242 if (likely(tracer != NULL)) { 2226 if (likely(tracer != NULL)) {
2243 sec = tracer->security; 2227 sec = tracer->security;
2244 ptsid = sec->sid; 2228 ptsid = sec->sid;
@@ -5247,7 +5231,7 @@ static int selinux_setprocattr(struct task_struct *p,
5247 Otherwise, leave SID unchanged and fail. */ 5231 Otherwise, leave SID unchanged and fail. */
5248 task_lock(p); 5232 task_lock(p);
5249 rcu_read_lock(); 5233 rcu_read_lock();
5250 tracer = task_tracer_task(p); 5234 tracer = tracehook_tracer_task(p);
5251 if (tracer != NULL) { 5235 if (tracer != NULL) {
5252 struct task_security_struct *ptsec = tracer->security; 5236 struct task_security_struct *ptsec = tracer->security;
5253 u32 ptsid = ptsec->sid; 5237 u32 ptsid = ptsec->sid;