diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6b5790bba8f9..89f446d86054 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -5226,8 +5226,12 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5226 | 5226 | ||
5227 | if (sid == 0) | 5227 | if (sid == 0) |
5228 | return -EINVAL; | 5228 | return -EINVAL; |
5229 | 5229 | /* | |
5230 | /* Only allow single threaded processes to change context */ | 5230 | * SELinux allows to change context in the following case only. |
5231 | * - Single threaded processes. | ||
5232 | * - Multi threaded processes intend to change its context into | ||
5233 | * more restricted domain (defined by TYPEBOUNDS statement). | ||
5234 | */ | ||
5231 | if (atomic_read(&p->mm->mm_users) != 1) { | 5235 | if (atomic_read(&p->mm->mm_users) != 1) { |
5232 | struct task_struct *g, *t; | 5236 | struct task_struct *g, *t; |
5233 | struct mm_struct *mm = p->mm; | 5237 | struct mm_struct *mm = p->mm; |
@@ -5235,11 +5239,16 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5235 | do_each_thread(g, t) { | 5239 | do_each_thread(g, t) { |
5236 | if (t->mm == mm && t != p) { | 5240 | if (t->mm == mm && t != p) { |
5237 | read_unlock(&tasklist_lock); | 5241 | read_unlock(&tasklist_lock); |
5238 | return -EPERM; | 5242 | error = security_bounded_transition(tsec->sid, sid); |
5243 | if (!error) | ||
5244 | goto boundary_ok; | ||
5245 | |||
5246 | return error; | ||
5239 | } | 5247 | } |
5240 | } while_each_thread(g, t); | 5248 | } while_each_thread(g, t); |
5241 | read_unlock(&tasklist_lock); | 5249 | read_unlock(&tasklist_lock); |
5242 | } | 5250 | } |
5251 | boundary_ok: | ||
5243 | 5252 | ||
5244 | /* Check permissions for the transition. */ | 5253 | /* Check permissions for the transition. */ |
5245 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, | 5254 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, |