Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d094efe authored by Roland McGrath's avatar Roland McGrath Committed by Linus Torvalds
Browse files

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: default avatarRoland McGrath <roland@redhat.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Reviewed-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent dae33574
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@
#include <linux/delayacct.h>
#include <linux/seq_file.h>
#include <linux/pid_namespace.h>
#include <linux/tracehook.h>

#include <asm/pgtable.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();
	ppid = pid_alive(p) ?
		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
	tpid = pid_alive(p) && p->ptrace ?
		task_pid_nr_ns(rcu_dereference(p->parent), ns) : 0;
	tpid = 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,
		"State:\t%s\n"
		"Tgid:\t%d\n"
+9 −4
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/ptrace.h>
#include <linux/tracehook.h>
#include <linux/cgroup.h>
#include <linux/cpuset.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
	 * permitted to freshly attach with ptrace now, permit it.
	 */
	if (task->parent == current && (task->ptrace & PT_PTRACED) &&
	    task_is_stopped_or_traced(task) &&
	    ptrace_may_access(task, PTRACE_MODE_ATTACH))
	if (task_is_stopped_or_traced(task)) {
		int match;
		rcu_read_lock();
		match = (tracehook_tracer_task(task) == current);
		rcu_read_unlock();
		if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
			return 0;
	}

	/*
	 * Noone else is allowed.
+18 −0
Original line number Diff line number Diff line
@@ -72,6 +72,24 @@ static inline int tracehook_unsafe_exec(struct task_struct *task)
	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
 * @fmt:		&struct linux_binfmt that performed the exec
+3 −19
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/tracehook.h>
#include <linux/errno.h>
#include <linux/sched.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);
}

/**
 * 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 */

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;

			rcu_read_lock();
			tracer = task_tracer_task(current);
			tracer = tracehook_tracer_task(current);
			if (likely(tracer != NULL)) {
				sec = tracer->security;
				ptsid = sec->sid;
@@ -5247,7 +5231,7 @@ static int selinux_setprocattr(struct task_struct *p,
		   Otherwise, leave SID unchanged and fail. */
		task_lock(p);
		rcu_read_lock();
		tracer = task_tracer_task(p);
		tracer = tracehook_tracer_task(p);
		if (tracer != NULL) {
			struct task_security_struct *ptsec = tracer->security;
			u32 ptsid = ptsec->sid;