X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=security%2Fselinux%2Fhooks.c;fp=security%2Fselinux%2Fhooks.c;h=0b32f3020703df2ed266764b87aed32b0724f4ad;hb=e0ff8aa1acd079b70e796571917ae0449b7c465b;hp=fc515fe8627fe35d05b6cff8fc01f6c18ed2feab;hpb=bef9ea3086d47cf98cfd0ea389953a0af0b60114;p=linux-2.6.git diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fc515fe86..0b32f3020 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -159,7 +159,7 @@ static int task_alloc_security(struct task_struct *task) return -ENOMEM; tsec->task = task; - tsec->osid = tsec->sid = SECINITSID_UNLABELED; + tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED; task->security = tsec; return 0; @@ -1387,13 +1387,19 @@ static int inode_security_set_sid(struct inode *inode, u32 sid) 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; - return task_has_perm(parent, child, PROCESS__PTRACE); + 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; } static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, @@ -1821,24 +1827,12 @@ 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)) { - struct task_struct *t; - - rcu_read_lock(); - t = tracehook_tracer_task(current); - if (unlikely(t == NULL)) - rcu_read_unlock(); - else { - struct task_security_struct *sec = t->security; - u32 ptsid = sec->sid; - rcu_read_unlock(); - - rc = avc_has_perm(ptsid, sid, - SECCLASS_PROCESS, - PROCESS__PTRACE, NULL); - if (rc) { - bsec->unsafe = 1; - return; - } + rc = avc_has_perm(tsec->ptrace_sid, sid, + SECCLASS_PROCESS, PROCESS__PTRACE, + NULL); + if (rc) { + bsec->unsafe = 1; + return; } } tsec->sid = sid; @@ -2692,6 +2686,11 @@ 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; } @@ -4296,7 +4295,6 @@ 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; @@ -4385,24 +4383,18 @@ 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); - rcu_read_lock(); - tracer = tracehook_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, + if (p->ptrace & PT_PTRACED) { + error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, &avd); if (!error) tsec->sid = sid; task_unlock(p); - avc_audit(ptsid, sid, SECCLASS_PROCESS, + avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, &avd, error, NULL); if (error) return error; } else { - rcu_read_unlock(); tsec->sid = sid; task_unlock(p); }