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>
This commit is contained in:
parent
dae33574dc
commit
0d094efeb1
|
@ -80,6 +80,7 @@
|
||||||
#include <linux/delayacct.h>
|
#include <linux/delayacct.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/pid_namespace.h>
|
#include <linux/pid_namespace.h>
|
||||||
|
#include <linux/tracehook.h>
|
||||||
|
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
@ -168,8 +169,12 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
ppid = pid_alive(p) ?
|
ppid = pid_alive(p) ?
|
||||||
task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
|
task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
|
||||||
tpid = pid_alive(p) && p->ptrace ?
|
tpid = 0;
|
||||||
task_pid_nr_ns(rcu_dereference(p->parent), ns) : 0;
|
if (pid_alive(p)) {
|
||||||
|
struct task_struct *tracer = tracehook_tracer_task(p);
|
||||||
|
if (tracer)
|
||||||
|
tpid = task_pid_nr_ns(tracer, ns);
|
||||||
|
}
|
||||||
seq_printf(m,
|
seq_printf(m,
|
||||||
"State:\t%s\n"
|
"State:\t%s\n"
|
||||||
"Tgid:\t%d\n"
|
"Tgid:\t%d\n"
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/tracehook.h>
|
||||||
#include <linux/cgroup.h>
|
#include <linux/cgroup.h>
|
||||||
#include <linux/cpuset.h>
|
#include <linux/cpuset.h>
|
||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
|
@ -231,10 +232,14 @@ static int check_mem_permission(struct task_struct *task)
|
||||||
* If current is actively ptrace'ing, and would also be
|
* If current is actively ptrace'ing, and would also be
|
||||||
* permitted to freshly attach with ptrace now, permit it.
|
* permitted to freshly attach with ptrace now, permit it.
|
||||||
*/
|
*/
|
||||||
if (task->parent == current && (task->ptrace & PT_PTRACED) &&
|
if (task_is_stopped_or_traced(task)) {
|
||||||
task_is_stopped_or_traced(task) &&
|
int match;
|
||||||
ptrace_may_access(task, PTRACE_MODE_ATTACH))
|
rcu_read_lock();
|
||||||
|
match = (tracehook_tracer_task(task) == current);
|
||||||
|
rcu_read_unlock();
|
||||||
|
if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Noone else is allowed.
|
* Noone else is allowed.
|
||||||
|
|
|
@ -72,6 +72,24 @@ static inline int tracehook_unsafe_exec(struct task_struct *task)
|
||||||
return unsafe;
|
return unsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tracehook_tracer_task - return the task that is tracing the given task
|
||||||
|
* @tsk: task to consider
|
||||||
|
*
|
||||||
|
* Returns NULL if noone is tracing @task, or the &struct task_struct
|
||||||
|
* pointer to its tracer.
|
||||||
|
*
|
||||||
|
* Must called under rcu_read_lock(). The pointer returned might be kept
|
||||||
|
* live only by RCU. During exec, this may be called with task_lock()
|
||||||
|
* held on @task, still held from when tracehook_unsafe_exec() was called.
|
||||||
|
*/
|
||||||
|
static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
if (task_ptrace(tsk) & PT_PTRACED)
|
||||||
|
return rcu_dereference(tsk->parent);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tracehook_report_exec - a successful exec was completed
|
* tracehook_report_exec - a successful exec was completed
|
||||||
* @fmt: &struct linux_binfmt that performed the exec
|
* @fmt: &struct linux_binfmt that performed the exec
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/tracehook.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
|
@ -1971,22 +1971,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
|
||||||
return __vm_enough_memory(mm, pages, cap_sys_admin);
|
return __vm_enough_memory(mm, pages, cap_sys_admin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* task_tracer_task - return the task that is tracing the given task
|
|
||||||
* @task: task to consider
|
|
||||||
*
|
|
||||||
* Returns NULL if noone is tracing @task, or the &struct task_struct
|
|
||||||
* pointer to its tracer.
|
|
||||||
*
|
|
||||||
* Must be called under rcu_read_lock().
|
|
||||||
*/
|
|
||||||
static struct task_struct *task_tracer_task(struct task_struct *task)
|
|
||||||
{
|
|
||||||
if (task->ptrace & PT_PTRACED)
|
|
||||||
return rcu_dereference(task->parent);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* binprm security operations */
|
/* binprm security operations */
|
||||||
|
|
||||||
static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
|
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)
|
||||||
u32 ptsid = 0;
|
u32 ptsid = 0;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
tracer = task_tracer_task(current);
|
tracer = tracehook_tracer_task(current);
|
||||||
if (likely(tracer != NULL)) {
|
if (likely(tracer != NULL)) {
|
||||||
sec = tracer->security;
|
sec = tracer->security;
|
||||||
ptsid = sec->sid;
|
ptsid = sec->sid;
|
||||||
|
@ -5247,7 +5231,7 @@ static int selinux_setprocattr(struct task_struct *p,
|
||||||
Otherwise, leave SID unchanged and fail. */
|
Otherwise, leave SID unchanged and fail. */
|
||||||
task_lock(p);
|
task_lock(p);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
tracer = task_tracer_task(p);
|
tracer = tracehook_tracer_task(p);
|
||||||
if (tracer != NULL) {
|
if (tracer != NULL) {
|
||||||
struct task_security_struct *ptsec = tracer->security;
|
struct task_security_struct *ptsec = tracer->security;
|
||||||
u32 ptsid = ptsec->sid;
|
u32 ptsid = ptsec->sid;
|
||||||
|
|
Loading…
Reference in New Issue