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: Roland McGrath <roland@redhat.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
eda4f69ca5
commit
0356357c51
2 changed files with 47 additions and 25 deletions
|
@ -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)
|
||||||
|
|
||||||
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)
|
||||||
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,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.
|
/* 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;
|
||||||
|
|
||||||
|
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) {
|
if (rc) {
|
||||||
bsec->unsafe = 1;
|
bsec->unsafe = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tsec->sid = sid;
|
tsec->sid = sid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
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,
|
||||||
/* 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)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue