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

Commit 0356357c authored by Roland McGrath's avatar Roland McGrath Committed by James Morris
Browse files

selinux: remove ptrace_sid



This changes checks related to ptrace to get rid of the ptrace_sid tracking.
It's good to disentangle the security model from the ptrace implementation
internals.  It's sufficient to check against the SID of the ptracer at the
time a tracee attempts a transition.

Signed-off-by: default avatarRoland McGrath <roland@redhat.com>
Acked-by: default avatarStephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent eda4f69c
Loading
Loading
Loading
Loading
+47 −24
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ static int task_alloc_security(struct task_struct *task)
	if (!tsec)
		return -ENOMEM;

	tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
	tsec->osid = tsec->sid = SECINITSID_UNLABELED;
	task->security = tsec;

	return 0;
@@ -1671,19 +1671,13 @@ static inline u32 file_to_av(struct file *file)

static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
{
	struct task_security_struct *psec = parent->security;
	struct task_security_struct *csec = child->security;
	int rc;

	rc = secondary_ops->ptrace(parent,child);
	if (rc)
		return rc;

	rc = task_has_perm(parent, child, PROCESS__PTRACE);
	/* Save the SID of the tracing process for later use in apply_creds. */
	if (!(child->ptrace & PT_PTRACED) && !rc)
		csec->ptrace_sid = psec->sid;
	return rc;
	return task_has_perm(parent, child, PROCESS__PTRACE);
}

static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
@@ -1905,6 +1899,22 @@ 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)
@@ -2151,14 +2161,27 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
		/* Check for ptracing, and update the task SID if ok.
		   Otherwise, leave SID unchanged and kill. */
		if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
			rc = avc_has_perm(tsec->ptrace_sid, sid,
					  SECCLASS_PROCESS, PROCESS__PTRACE,
					  NULL);
			struct task_struct *tracer;
			struct task_security_struct *sec;
			u32 ptsid = 0;

			rcu_read_lock();
			tracer = task_tracer_task(current);
			if (likely(tracer != NULL)) {
				sec = tracer->security;
				ptsid = sec->sid;
			}
			rcu_read_unlock();

			if (ptsid != 0) {
				rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
						  PROCESS__PTRACE, NULL);
				if (rc) {
					bsec->unsafe = 1;
					return;
				}
			}
		}
		tsec->sid = sid;
	}
}
@@ -3112,11 +3135,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
	tsec2->keycreate_sid = tsec1->keycreate_sid;
	tsec2->sockcreate_sid = tsec1->sockcreate_sid;

	/* Retain ptracer SID across fork, if any.
	   This will be reset by the ptrace hook upon any
	   subsequent ptrace_attach operations. */
	tsec2->ptrace_sid = tsec1->ptrace_sid;

	return 0;
}

@@ -5080,6 +5098,7 @@ static int selinux_setprocattr(struct task_struct *p,
			       char *name, void *value, size_t size)
{
	struct task_security_struct *tsec;
	struct task_struct *tracer;
	u32 sid = 0;
	int error;
	char *str = value;
@@ -5168,18 +5187,24 @@ static int selinux_setprocattr(struct task_struct *p,
		/* Check for ptracing, and update the task SID if ok.
		   Otherwise, leave SID unchanged and fail. */
		task_lock(p);
		if (p->ptrace & PT_PTRACED) {
			error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
		rcu_read_lock();
		tracer = task_tracer_task(p);
		if (tracer != NULL) {
			struct task_security_struct *ptsec = tracer->security;
			u32 ptsid = ptsec->sid;
			rcu_read_unlock();
			error = avc_has_perm_noaudit(ptsid, sid,
						     SECCLASS_PROCESS,
						     PROCESS__PTRACE, 0, &avd);
			if (!error)
				tsec->sid = sid;
			task_unlock(p);
			avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
			avc_audit(ptsid, sid, SECCLASS_PROCESS,
				  PROCESS__PTRACE, &avd, error, NULL);
			if (error)
				return error;
		} else {
			rcu_read_unlock();
			tsec->sid = sid;
			task_unlock(p);
		}
@@ -5653,5 +5678,3 @@ int selinux_disable(void)
	return 0;
}
#endif

+0 −1
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ struct task_security_struct {
	u32 create_sid;      /* fscreate SID */
	u32 keycreate_sid;   /* keycreate SID */
	u32 sockcreate_sid;  /* fscreate SID */
	u32 ptrace_sid;      /* SID of ptrace parent */
};

struct inode_security_struct {