diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 03fc6a81ae32..4a7374c12d9c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -957,7 +957,8 @@ out_err: | |||
957 | return rc; | 957 | return rc; |
958 | } | 958 | } |
959 | 959 | ||
960 | void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) | 960 | static void selinux_write_opts(struct seq_file *m, |
961 | struct security_mnt_opts *opts) | ||
961 | { | 962 | { |
962 | int i; | 963 | int i; |
963 | char *prefix; | 964 | char *prefix; |
@@ -1290,7 +1291,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1290 | /* Default to the fs superblock SID. */ | 1291 | /* Default to the fs superblock SID. */ |
1291 | isec->sid = sbsec->sid; | 1292 | isec->sid = sbsec->sid; |
1292 | 1293 | ||
1293 | if (sbsec->proc) { | 1294 | if (sbsec->proc && !S_ISLNK(inode->i_mode)) { |
1294 | struct proc_inode *proci = PROC_I(inode); | 1295 | struct proc_inode *proci = PROC_I(inode); |
1295 | if (proci->pde) { | 1296 | if (proci->pde) { |
1296 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1297 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
@@ -3548,38 +3549,44 @@ out: | |||
3548 | #endif /* IPV6 */ | 3549 | #endif /* IPV6 */ |
3549 | 3550 | ||
3550 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3551 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, |
3551 | char **addrp, int src, u8 *proto) | 3552 | char **_addrp, int src, u8 *proto) |
3552 | { | 3553 | { |
3553 | int ret = 0; | 3554 | char *addrp; |
3555 | int ret; | ||
3554 | 3556 | ||
3555 | switch (ad->u.net.family) { | 3557 | switch (ad->u.net.family) { |
3556 | case PF_INET: | 3558 | case PF_INET: |
3557 | ret = selinux_parse_skb_ipv4(skb, ad, proto); | 3559 | ret = selinux_parse_skb_ipv4(skb, ad, proto); |
3558 | if (ret || !addrp) | 3560 | if (ret) |
3559 | break; | 3561 | goto parse_error; |
3560 | *addrp = (char *)(src ? &ad->u.net.v4info.saddr : | 3562 | addrp = (char *)(src ? &ad->u.net.v4info.saddr : |
3561 | &ad->u.net.v4info.daddr); | 3563 | &ad->u.net.v4info.daddr); |
3562 | break; | 3564 | goto okay; |
3563 | 3565 | ||
3564 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 3566 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
3565 | case PF_INET6: | 3567 | case PF_INET6: |
3566 | ret = selinux_parse_skb_ipv6(skb, ad, proto); | 3568 | ret = selinux_parse_skb_ipv6(skb, ad, proto); |
3567 | if (ret || !addrp) | 3569 | if (ret) |
3568 | break; | 3570 | goto parse_error; |
3569 | *addrp = (char *)(src ? &ad->u.net.v6info.saddr : | 3571 | addrp = (char *)(src ? &ad->u.net.v6info.saddr : |
3570 | &ad->u.net.v6info.daddr); | 3572 | &ad->u.net.v6info.daddr); |
3571 | break; | 3573 | goto okay; |
3572 | #endif /* IPV6 */ | 3574 | #endif /* IPV6 */ |
3573 | default: | 3575 | default: |
3574 | break; | 3576 | addrp = NULL; |
3577 | goto okay; | ||
3575 | } | 3578 | } |
3576 | 3579 | ||
3577 | if (unlikely(ret)) | 3580 | parse_error: |
3578 | printk(KERN_WARNING | 3581 | printk(KERN_WARNING |
3579 | "SELinux: failure in selinux_parse_skb()," | 3582 | "SELinux: failure in selinux_parse_skb()," |
3580 | " unable to parse packet\n"); | 3583 | " unable to parse packet\n"); |
3581 | |||
3582 | return ret; | 3584 | return ret; |
3585 | |||
3586 | okay: | ||
3587 | if (_addrp) | ||
3588 | *_addrp = addrp; | ||
3589 | return 0; | ||
3583 | } | 3590 | } |
3584 | 3591 | ||
3585 | /** | 3592 | /** |
@@ -5219,8 +5226,12 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5219 | 5226 | ||
5220 | if (sid == 0) | 5227 | if (sid == 0) |
5221 | return -EINVAL; | 5228 | return -EINVAL; |
5222 | 5229 | /* | |
5223 | /* 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 | */ | ||
5224 | if (atomic_read(&p->mm->mm_users) != 1) { | 5235 | if (atomic_read(&p->mm->mm_users) != 1) { |
5225 | struct task_struct *g, *t; | 5236 | struct task_struct *g, *t; |
5226 | struct mm_struct *mm = p->mm; | 5237 | struct mm_struct *mm = p->mm; |
@@ -5228,11 +5239,16 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5228 | do_each_thread(g, t) { | 5239 | do_each_thread(g, t) { |
5229 | if (t->mm == mm && t != p) { | 5240 | if (t->mm == mm && t != p) { |
5230 | read_unlock(&tasklist_lock); | 5241 | read_unlock(&tasklist_lock); |
5231 | return -EPERM; | 5242 | error = security_bounded_transition(tsec->sid, sid); |
5243 | if (!error) | ||
5244 | goto boundary_ok; | ||
5245 | |||
5246 | return error; | ||
5232 | } | 5247 | } |
5233 | } while_each_thread(g, t); | 5248 | } while_each_thread(g, t); |
5234 | read_unlock(&tasklist_lock); | 5249 | read_unlock(&tasklist_lock); |
5235 | } | 5250 | } |
5251 | boundary_ok: | ||
5236 | 5252 | ||
5237 | /* Check permissions for the transition. */ | 5253 | /* Check permissions for the transition. */ |
5238 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, | 5254 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, |