aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/selinux/hooks.c71
-rw-r--r--security/selinux/include/objsec.h1
2 files changed, 47 insertions, 25 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 973e31eb1097..9d002f8484a3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -161,7 +161,7 @@ static int task_alloc_security(struct task_struct *task)
161 if (!tsec) 161 if (!tsec)
162 return -ENOMEM; 162 return -ENOMEM;
163 163
164 tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED; 164 tsec->osid = tsec->sid = SECINITSID_UNLABELED;
165 task->security = tsec; 165 task->security = tsec;
166 166
167 return 0; 167 return 0;
@@ -1671,19 +1671,13 @@ static inline u32 file_to_av(struct file *file)
1671 1671
1672static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) 1672static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1673{ 1673{
1674 struct task_security_struct *psec = parent->security;
1675 struct task_security_struct *csec = child->security;
1676 int rc; 1674 int rc;
1677 1675
1678 rc = secondary_ops->ptrace(parent,child); 1676 rc = secondary_ops->ptrace(parent,child);
1679 if (rc) 1677 if (rc)
1680 return rc; 1678 return rc;
1681 1679
1682 rc = task_has_perm(parent, child, PROCESS__PTRACE); 1680 return task_has_perm(parent, child, PROCESS__PTRACE);
1683 /* Save the SID of the tracing process for later use in apply_creds. */
1684 if (!(child->ptrace & PT_PTRACED) && !rc)
1685 csec->ptrace_sid = psec->sid;
1686 return rc;
1687} 1681}
1688 1682
1689static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, 1683static 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 return __vm_enough_memory(mm, pages, cap_sys_admin); 1899 return __vm_enough_memory(mm, pages, cap_sys_admin);
1906} 1900}
1907 1901
1902/**
1903 * task_tracer_task - return the task that is tracing the given task
1904 * @task: task to consider
1905 *
1906 * Returns NULL if noone is tracing @task, or the &struct task_struct
1907 * pointer to its tracer.
1908 *
1909 * Must be called under rcu_read_lock().
1910 */
1911static struct task_struct *task_tracer_task(struct task_struct *task)
1912{
1913 if (task->ptrace & PT_PTRACED)
1914 return rcu_dereference(task->parent);
1915 return NULL;
1916}
1917
1908/* binprm security operations */ 1918/* binprm security operations */
1909 1919
1910static int selinux_bprm_alloc_security(struct linux_binprm *bprm) 1920static 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 /* Check for ptracing, and update the task SID if ok. 2161 /* Check for ptracing, and update the task SID if ok.
2152 Otherwise, leave SID unchanged and kill. */ 2162 Otherwise, leave SID unchanged and kill. */
2153 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { 2163 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2154 rc = avc_has_perm(tsec->ptrace_sid, sid, 2164 struct task_struct *tracer;
2155 SECCLASS_PROCESS, PROCESS__PTRACE, 2165 struct task_security_struct *sec;
2156 NULL); 2166 u32 ptsid = 0;
2157 if (rc) { 2167
2158 bsec->unsafe = 1; 2168 rcu_read_lock();
2159 return; 2169 tracer = task_tracer_task(current);
2170 if (likely(tracer != NULL)) {
2171 sec = tracer->security;
2172 ptsid = sec->sid;
2173 }
2174 rcu_read_unlock();
2175
2176 if (ptsid != 0) {
2177 rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
2178 PROCESS__PTRACE, NULL);
2179 if (rc) {
2180 bsec->unsafe = 1;
2181 return;
2182 }
2160 } 2183 }
2161 } 2184 }
2162 tsec->sid = sid; 2185 tsec->sid = sid;
@@ -3112,11 +3135,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
3112 tsec2->keycreate_sid = tsec1->keycreate_sid; 3135 tsec2->keycreate_sid = tsec1->keycreate_sid;
3113 tsec2->sockcreate_sid = tsec1->sockcreate_sid; 3136 tsec2->sockcreate_sid = tsec1->sockcreate_sid;
3114 3137
3115 /* Retain ptracer SID across fork, if any.
3116 This will be reset by the ptrace hook upon any
3117 subsequent ptrace_attach operations. */
3118 tsec2->ptrace_sid = tsec1->ptrace_sid;
3119
3120 return 0; 3138 return 0;
3121} 3139}
3122 3140
@@ -5080,6 +5098,7 @@ static int selinux_setprocattr(struct task_struct *p,
5080 char *name, void *value, size_t size) 5098 char *name, void *value, size_t size)
5081{ 5099{
5082 struct task_security_struct *tsec; 5100 struct task_security_struct *tsec;
5101 struct task_struct *tracer;
5083 u32 sid = 0; 5102 u32 sid = 0;
5084 int error; 5103 int error;
5085 char *str = value; 5104 char *str = value;
@@ -5168,18 +5187,24 @@ static int selinux_setprocattr(struct task_struct *p,
5168 /* Check for ptracing, and update the task SID if ok. 5187 /* Check for ptracing, and update the task SID if ok.
5169 Otherwise, leave SID unchanged and fail. */ 5188 Otherwise, leave SID unchanged and fail. */
5170 task_lock(p); 5189 task_lock(p);
5171 if (p->ptrace & PT_PTRACED) { 5190 rcu_read_lock();
5172 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, 5191 tracer = task_tracer_task(p);
5192 if (tracer != NULL) {
5193 struct task_security_struct *ptsec = tracer->security;
5194 u32 ptsid = ptsec->sid;
5195 rcu_read_unlock();
5196 error = avc_has_perm_noaudit(ptsid, sid,
5173 SECCLASS_PROCESS, 5197 SECCLASS_PROCESS,
5174 PROCESS__PTRACE, 0, &avd); 5198 PROCESS__PTRACE, 0, &avd);
5175 if (!error) 5199 if (!error)
5176 tsec->sid = sid; 5200 tsec->sid = sid;
5177 task_unlock(p); 5201 task_unlock(p);
5178 avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, 5202 avc_audit(ptsid, sid, SECCLASS_PROCESS,
5179 PROCESS__PTRACE, &avd, error, NULL); 5203 PROCESS__PTRACE, &avd, error, NULL);
5180 if (error) 5204 if (error)
5181 return error; 5205 return error;
5182 } else { 5206 } else {
5207 rcu_read_unlock();
5183 tsec->sid = sid; 5208 tsec->sid = sid;
5184 task_unlock(p); 5209 task_unlock(p);
5185 } 5210 }
@@ -5653,5 +5678,3 @@ int selinux_disable(void)
5653 return 0; 5678 return 0;
5654} 5679}
5655#endif 5680#endif
5656
5657
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 020a8754b809..957b10d0f76f 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -34,7 +34,6 @@ struct task_security_struct {
34 u32 create_sid; /* fscreate SID */ 34 u32 create_sid; /* fscreate SID */
35 u32 keycreate_sid; /* keycreate SID */ 35 u32 keycreate_sid; /* keycreate SID */
36 u32 sockcreate_sid; /* fscreate SID */ 36 u32 sockcreate_sid; /* fscreate SID */
37 u32 ptrace_sid; /* SID of ptrace parent */
38}; 37};
39 38
40struct inode_security_struct { 39struct inode_security_struct {