diff options
author | Roland McGrath <roland@redhat.com> | 2008-07-25 22:45:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-26 15:00:08 -0400 |
commit | 0d094efeb1e98010c6b99923f1eb7e17bf1e3a74 (patch) | |
tree | 6ee271b6da5796e5321d2ab6f9d7d9ba03c300a2 | |
parent | dae33574dcf5211e1f43c7e45fa29f73ba3e00cb (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.c | 9 | ||||
-rw-r--r-- | fs/proc/base.c | 13 | ||||
-rw-r--r-- | include/linux/tracehook.h | 18 | ||||
-rw-r--r-- | security/selinux/hooks.c | 22 |
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 | */ | ||
86 | static 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 | */ | ||
1983 | static 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 | ||
1992 | static int selinux_bprm_alloc_security(struct linux_binprm *bprm) | 1976 | static 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; |