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

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
...@@ -161,7 +161,7 @@ static int task_alloc_security(struct task_struct *task) ...@@ -161,7 +161,7 @@ static int task_alloc_security(struct task_struct *task)
if (!tsec) if (!tsec)
return -ENOMEM; return -ENOMEM;
tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED; tsec->osid = tsec->sid = SECINITSID_UNLABELED;
task->security = tsec; task->security = tsec;
return 0; return 0;
...@@ -1671,19 +1671,13 @@ static inline u32 file_to_av(struct file *file) ...@@ -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) 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; int rc;
rc = secondary_ops->ptrace(parent,child); rc = secondary_ops->ptrace(parent,child);
if (rc) if (rc)
return rc; return rc;
rc = task_has_perm(parent, child, PROCESS__PTRACE); return 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;
} }
static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, 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) ...@@ -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); 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)
...@@ -2151,12 +2161,25 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) ...@@ -2151,12 +2161,25 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
/* Check for ptracing, and update the task SID if ok. /* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and kill. */ Otherwise, leave SID unchanged and kill. */
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
rc = avc_has_perm(tsec->ptrace_sid, sid, struct task_struct *tracer;
SECCLASS_PROCESS, PROCESS__PTRACE, struct task_security_struct *sec;
NULL); u32 ptsid = 0;
if (rc) {
bsec->unsafe = 1; rcu_read_lock();
return; 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; tsec->sid = sid;
...@@ -3112,11 +3135,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk) ...@@ -3112,11 +3135,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
tsec2->keycreate_sid = tsec1->keycreate_sid; tsec2->keycreate_sid = tsec1->keycreate_sid;
tsec2->sockcreate_sid = tsec1->sockcreate_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; return 0;
} }
...@@ -5080,6 +5098,7 @@ static int selinux_setprocattr(struct task_struct *p, ...@@ -5080,6 +5098,7 @@ static int selinux_setprocattr(struct task_struct *p,
char *name, void *value, size_t size) char *name, void *value, size_t size)
{ {
struct task_security_struct *tsec; struct task_security_struct *tsec;
struct task_struct *tracer;
u32 sid = 0; u32 sid = 0;
int error; int error;
char *str = value; char *str = value;
...@@ -5168,18 +5187,24 @@ static int selinux_setprocattr(struct task_struct *p, ...@@ -5168,18 +5187,24 @@ static int selinux_setprocattr(struct task_struct *p,
/* Check for ptracing, and update the task SID if ok. /* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and fail. */ Otherwise, leave SID unchanged and fail. */
task_lock(p); task_lock(p);
if (p->ptrace & PT_PTRACED) { rcu_read_lock();
error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, 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, SECCLASS_PROCESS,
PROCESS__PTRACE, 0, &avd); PROCESS__PTRACE, 0, &avd);
if (!error) if (!error)
tsec->sid = sid; tsec->sid = sid;
task_unlock(p); task_unlock(p);
avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, avc_audit(ptsid, sid, SECCLASS_PROCESS,
PROCESS__PTRACE, &avd, error, NULL); PROCESS__PTRACE, &avd, error, NULL);
if (error) if (error)
return error; return error;
} else { } else {
rcu_read_unlock();
tsec->sid = sid; tsec->sid = sid;
task_unlock(p); task_unlock(p);
} }
...@@ -5653,5 +5678,3 @@ int selinux_disable(void) ...@@ -5653,5 +5678,3 @@ int selinux_disable(void)
return 0; return 0;
} }
#endif #endif
...@@ -34,7 +34,6 @@ struct task_security_struct { ...@@ -34,7 +34,6 @@ struct task_security_struct {
u32 create_sid; /* fscreate SID */ u32 create_sid; /* fscreate SID */
u32 keycreate_sid; /* keycreate SID */ u32 keycreate_sid; /* keycreate SID */
u32 sockcreate_sid; /* fscreate SID */ u32 sockcreate_sid; /* fscreate SID */
u32 ptrace_sid; /* SID of ptrace parent */
}; };
struct inode_security_struct { struct inode_security_struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment