aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2013-09-18 13:52:20 -0400
committerPaul Moore <pmoore@redhat.com>2013-09-18 13:52:20 -0400
commit98f700f317967d45cf60c9843b3c42ce3c286f7c (patch)
tree2e68b189ceb954182af56b8f6febe644119b7cd7 /security/selinux
parent6e4664525b1db28f8c4e1130957f70a94c19213e (diff)
parent0b4bdb3573a86a88c829b9e4ad702859eb923e7e (diff)
Merge git://git.infradead.org/users/eparis/selinux
Conflicts: security/selinux/hooks.c Pull Eric's existing SELinux tree as there are a number of patches in there that are not yet upstream. There was some minor fixup needed to resolve a conflict in security/selinux/hooks.c:selinux_set_mnt_opts() between the labeled NFS patches and Eric's security_fs_use() simplification patch.
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c146
-rw-r--r--security/selinux/include/objsec.h4
-rw-r--r--security/selinux/include/security.h13
-rw-r--r--security/selinux/include/xfrm.h45
-rw-r--r--security/selinux/netnode.c2
-rw-r--r--security/selinux/selinuxfs.c4
-rw-r--r--security/selinux/ss/ebitmap.c20
-rw-r--r--security/selinux/ss/ebitmap.h10
-rw-r--r--security/selinux/ss/mls.c22
-rw-r--r--security/selinux/ss/mls_types.h2
-rw-r--r--security/selinux/ss/policydb.c3
-rw-r--r--security/selinux/ss/services.c66
-rw-r--r--security/selinux/xfrm.c453
13 files changed, 415 insertions, 375 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c956390a9136..c09211a4d7da 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -95,7 +95,9 @@
95#include "audit.h" 95#include "audit.h"
96#include "avc_ss.h" 96#include "avc_ss.h"
97 97
98#define NUM_SEL_MNT_OPTS 5 98#define SB_TYPE_FMT "%s%s%s"
99#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
100#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
99 101
100extern struct security_operations *security_ops; 102extern struct security_operations *security_ops;
101 103
@@ -139,12 +141,28 @@ static struct kmem_cache *sel_inode_cache;
139 * This function checks the SECMARK reference counter to see if any SECMARK 141 * This function checks the SECMARK reference counter to see if any SECMARK
140 * targets are currently configured, if the reference counter is greater than 142 * targets are currently configured, if the reference counter is greater than
141 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is 143 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
142 * enabled, false (0) if SECMARK is disabled. 144 * enabled, false (0) if SECMARK is disabled. If the always_check_network
145 * policy capability is enabled, SECMARK is always considered enabled.
143 * 146 *
144 */ 147 */
145static int selinux_secmark_enabled(void) 148static int selinux_secmark_enabled(void)
146{ 149{
147 return (atomic_read(&selinux_secmark_refcount) > 0); 150 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
151}
152
153/**
154 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
155 *
156 * Description:
157 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
158 * (1) if any are enabled or false (0) if neither are enabled. If the
159 * always_check_network policy capability is enabled, peer labeling
160 * is always considered enabled.
161 *
162 */
163static int selinux_peerlbl_enabled(void)
164{
165 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
148} 166}
149 167
150/* 168/*
@@ -309,8 +327,11 @@ enum {
309 Opt_defcontext = 3, 327 Opt_defcontext = 3,
310 Opt_rootcontext = 4, 328 Opt_rootcontext = 4,
311 Opt_labelsupport = 5, 329 Opt_labelsupport = 5,
330 Opt_nextmntopt = 6,
312}; 331};
313 332
333#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
334
314static const match_table_t tokens = { 335static const match_table_t tokens = {
315 {Opt_context, CONTEXT_STR "%s"}, 336 {Opt_context, CONTEXT_STR "%s"},
316 {Opt_fscontext, FSCONTEXT_STR "%s"}, 337 {Opt_fscontext, FSCONTEXT_STR "%s"},
@@ -355,6 +376,29 @@ static int may_context_mount_inode_relabel(u32 sid,
355 return rc; 376 return rc;
356} 377}
357 378
379static int selinux_is_sblabel_mnt(struct super_block *sb)
380{
381 struct superblock_security_struct *sbsec = sb->s_security;
382
383 if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
384 sbsec->behavior == SECURITY_FS_USE_TRANS ||
385 sbsec->behavior == SECURITY_FS_USE_TASK)
386 return 1;
387
388 /* Special handling for sysfs. Is genfs but also has setxattr handler*/
389 if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
390 return 1;
391
392 /*
393 * Special handling for rootfs. Is genfs but supports
394 * setting SELinux context on in-core inodes.
395 */
396 if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
397 return 1;
398
399 return 0;
400}
401
358static int sb_finish_set_opts(struct super_block *sb) 402static int sb_finish_set_opts(struct super_block *sb)
359{ 403{
360 struct superblock_security_struct *sbsec = sb->s_security; 404 struct superblock_security_struct *sbsec = sb->s_security;
@@ -369,8 +413,8 @@ static int sb_finish_set_opts(struct super_block *sb)
369 the first boot of the SELinux kernel before we have 413 the first boot of the SELinux kernel before we have
370 assigned xattr values to the filesystem. */ 414 assigned xattr values to the filesystem. */
371 if (!root_inode->i_op->getxattr) { 415 if (!root_inode->i_op->getxattr) {
372 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " 416 printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
373 "xattr support\n", sb->s_id, sb->s_type->name); 417 "xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
374 rc = -EOPNOTSUPP; 418 rc = -EOPNOTSUPP;
375 goto out; 419 goto out;
376 } 420 }
@@ -378,35 +422,27 @@ static int sb_finish_set_opts(struct super_block *sb)
378 if (rc < 0 && rc != -ENODATA) { 422 if (rc < 0 && rc != -ENODATA) {
379 if (rc == -EOPNOTSUPP) 423 if (rc == -EOPNOTSUPP)
380 printk(KERN_WARNING "SELinux: (dev %s, type " 424 printk(KERN_WARNING "SELinux: (dev %s, type "
381 "%s) has no security xattr handler\n", 425 SB_TYPE_FMT") has no security xattr handler\n",
382 sb->s_id, sb->s_type->name); 426 sb->s_id, SB_TYPE_ARGS(sb));
383 else 427 else
384 printk(KERN_WARNING "SELinux: (dev %s, type " 428 printk(KERN_WARNING "SELinux: (dev %s, type "
385 "%s) getxattr errno %d\n", sb->s_id, 429 SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
386 sb->s_type->name, -rc); 430 SB_TYPE_ARGS(sb), -rc);
387 goto out; 431 goto out;
388 } 432 }
389 } 433 }
390 434
391 sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
392
393 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) 435 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
394 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", 436 printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
395 sb->s_id, sb->s_type->name); 437 sb->s_id, SB_TYPE_ARGS(sb));
396 else 438 else
397 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", 439 printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
398 sb->s_id, sb->s_type->name, 440 sb->s_id, SB_TYPE_ARGS(sb),
399 labeling_behaviors[sbsec->behavior-1]); 441 labeling_behaviors[sbsec->behavior-1]);
400 442
401 if (sbsec->behavior == SECURITY_FS_USE_GENFS || 443 sbsec->flags |= SE_SBINITIALIZED;
402 sbsec->behavior == SECURITY_FS_USE_MNTPOINT || 444 if (selinux_is_sblabel_mnt(sb))
403 sbsec->behavior == SECURITY_FS_USE_NONE || 445 sbsec->flags |= SBLABEL_MNT;
404 sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
405 sbsec->flags &= ~SE_SBLABELSUPP;
406
407 /* Special handling for sysfs. Is genfs but also has setxattr handler*/
408 if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
409 sbsec->flags |= SE_SBLABELSUPP;
410 446
411 /* Initialize the root inode. */ 447 /* Initialize the root inode. */
412 rc = inode_doinit_with_dentry(root_inode, root); 448 rc = inode_doinit_with_dentry(root_inode, root);
@@ -460,15 +496,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
460 if (!ss_initialized) 496 if (!ss_initialized)
461 return -EINVAL; 497 return -EINVAL;
462 498
499 /* make sure we always check enough bits to cover the mask */
500 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
501
463 tmp = sbsec->flags & SE_MNTMASK; 502 tmp = sbsec->flags & SE_MNTMASK;
464 /* count the number of mount options for this sb */ 503 /* count the number of mount options for this sb */
465 for (i = 0; i < 8; i++) { 504 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
466 if (tmp & 0x01) 505 if (tmp & 0x01)
467 opts->num_mnt_opts++; 506 opts->num_mnt_opts++;
468 tmp >>= 1; 507 tmp >>= 1;
469 } 508 }
470 /* Check if the Label support flag is set */ 509 /* Check if the Label support flag is set */
471 if (sbsec->flags & SE_SBLABELSUPP) 510 if (sbsec->flags & SBLABEL_MNT)
472 opts->num_mnt_opts++; 511 opts->num_mnt_opts++;
473 512
474 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); 513 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
@@ -515,9 +554,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
515 opts->mnt_opts[i] = context; 554 opts->mnt_opts[i] = context;
516 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; 555 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
517 } 556 }
518 if (sbsec->flags & SE_SBLABELSUPP) { 557 if (sbsec->flags & SBLABEL_MNT) {
519 opts->mnt_opts[i] = NULL; 558 opts->mnt_opts[i] = NULL;
520 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP; 559 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
521 } 560 }
522 561
523 BUG_ON(i != opts->num_mnt_opts); 562 BUG_ON(i != opts->num_mnt_opts);
@@ -561,7 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb,
561 const struct cred *cred = current_cred(); 600 const struct cred *cred = current_cred();
562 int rc = 0, i; 601 int rc = 0, i;
563 struct superblock_security_struct *sbsec = sb->s_security; 602 struct superblock_security_struct *sbsec = sb->s_security;
564 const char *name = sb->s_type->name;
565 struct inode *inode = sbsec->sb->s_root->d_inode; 603 struct inode *inode = sbsec->sb->s_root->d_inode;
566 struct inode_security_struct *root_isec = inode->i_security; 604 struct inode_security_struct *root_isec = inode->i_security;
567 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 605 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
@@ -614,14 +652,14 @@ static int selinux_set_mnt_opts(struct super_block *sb,
614 for (i = 0; i < num_opts; i++) { 652 for (i = 0; i < num_opts; i++) {
615 u32 sid; 653 u32 sid;
616 654
617 if (flags[i] == SE_SBLABELSUPP) 655 if (flags[i] == SBLABEL_MNT)
618 continue; 656 continue;
619 rc = security_context_to_sid(mount_options[i], 657 rc = security_context_to_sid(mount_options[i],
620 strlen(mount_options[i]), &sid); 658 strlen(mount_options[i]), &sid);
621 if (rc) { 659 if (rc) {
622 printk(KERN_WARNING "SELinux: security_context_to_sid" 660 printk(KERN_WARNING "SELinux: security_context_to_sid"
623 "(%s) failed for (dev %s, type %s) errno=%d\n", 661 "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
624 mount_options[i], sb->s_id, name, rc); 662 mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
625 goto out; 663 goto out;
626 } 664 }
627 switch (flags[i]) { 665 switch (flags[i]) {
@@ -685,9 +723,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
685 * Determine the labeling behavior to use for this 723 * Determine the labeling behavior to use for this
686 * filesystem type. 724 * filesystem type.
687 */ 725 */
688 rc = security_fs_use((sbsec->flags & SE_SBPROC) ? 726 rc = security_fs_use(sb);
689 "proc" : sb->s_type->name,
690 &sbsec->behavior, &sbsec->sid);
691 if (rc) { 727 if (rc) {
692 printk(KERN_WARNING 728 printk(KERN_WARNING
693 "%s: security_fs_use(%s) returned %d\n", 729 "%s: security_fs_use(%s) returned %d\n",
@@ -770,7 +806,8 @@ out:
770out_double_mount: 806out_double_mount:
771 rc = -EINVAL; 807 rc = -EINVAL;
772 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " 808 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
773 "security settings for (dev %s, type %s)\n", sb->s_id, name); 809 "security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
810 SB_TYPE_ARGS(sb));
774 goto out; 811 goto out;
775} 812}
776 813
@@ -1037,7 +1074,7 @@ static void selinux_write_opts(struct seq_file *m,
1037 case DEFCONTEXT_MNT: 1074 case DEFCONTEXT_MNT:
1038 prefix = DEFCONTEXT_STR; 1075 prefix = DEFCONTEXT_STR;
1039 break; 1076 break;
1040 case SE_SBLABELSUPP: 1077 case SBLABEL_MNT:
1041 seq_putc(m, ','); 1078 seq_putc(m, ',');
1042 seq_puts(m, LABELSUPP_STR); 1079 seq_puts(m, LABELSUPP_STR);
1043 continue; 1080 continue;
@@ -1650,7 +1687,7 @@ static int may_create(struct inode *dir,
1650 if (rc) 1687 if (rc)
1651 return rc; 1688 return rc;
1652 1689
1653 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { 1690 if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
1654 rc = security_transition_sid(sid, dsec->sid, tclass, 1691 rc = security_transition_sid(sid, dsec->sid, tclass,
1655 &dentry->d_name, &newsid); 1692 &dentry->d_name, &newsid);
1656 if (rc) 1693 if (rc)
@@ -2438,14 +2475,14 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
2438 u32 sid; 2475 u32 sid;
2439 size_t len; 2476 size_t len;
2440 2477
2441 if (flags[i] == SE_SBLABELSUPP) 2478 if (flags[i] == SBLABEL_MNT)
2442 continue; 2479 continue;
2443 len = strlen(mount_options[i]); 2480 len = strlen(mount_options[i]);
2444 rc = security_context_to_sid(mount_options[i], len, &sid); 2481 rc = security_context_to_sid(mount_options[i], len, &sid);
2445 if (rc) { 2482 if (rc) {
2446 printk(KERN_WARNING "SELinux: security_context_to_sid" 2483 printk(KERN_WARNING "SELinux: security_context_to_sid"
2447 "(%s) failed for (dev %s, type %s) errno=%d\n", 2484 "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
2448 mount_options[i], sb->s_id, sb->s_type->name, rc); 2485 mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
2449 goto out_free_opts; 2486 goto out_free_opts;
2450 } 2487 }
2451 rc = -EINVAL; 2488 rc = -EINVAL;
@@ -2483,8 +2520,8 @@ out_free_secdata:
2483 return rc; 2520 return rc;
2484out_bad_option: 2521out_bad_option:
2485 printk(KERN_WARNING "SELinux: unable to change security options " 2522 printk(KERN_WARNING "SELinux: unable to change security options "
2486 "during remount (dev %s, type=%s)\n", sb->s_id, 2523 "during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
2487 sb->s_type->name); 2524 SB_TYPE_ARGS(sb));
2488 goto out_free_opts; 2525 goto out_free_opts;
2489} 2526}
2490 2527
@@ -2606,7 +2643,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2606 if ((sbsec->flags & SE_SBINITIALIZED) && 2643 if ((sbsec->flags & SE_SBINITIALIZED) &&
2607 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) 2644 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2608 newsid = sbsec->mntpoint_sid; 2645 newsid = sbsec->mntpoint_sid;
2609 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { 2646 else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
2610 rc = security_transition_sid(sid, dsec->sid, 2647 rc = security_transition_sid(sid, dsec->sid,
2611 inode_mode_to_security_class(inode->i_mode), 2648 inode_mode_to_security_class(inode->i_mode),
2612 qstr, &newsid); 2649 qstr, &newsid);
@@ -2628,7 +2665,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2628 isec->initialized = 1; 2665 isec->initialized = 1;
2629 } 2666 }
2630 2667
2631 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP)) 2668 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
2632 return -EOPNOTSUPP; 2669 return -EOPNOTSUPP;
2633 2670
2634 if (name) { 2671 if (name) {
@@ -2836,7 +2873,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2836 return selinux_inode_setotherxattr(dentry, name); 2873 return selinux_inode_setotherxattr(dentry, name);
2837 2874
2838 sbsec = inode->i_sb->s_security; 2875 sbsec = inode->i_sb->s_security;
2839 if (!(sbsec->flags & SE_SBLABELSUPP)) 2876 if (!(sbsec->flags & SBLABEL_MNT))
2840 return -EOPNOTSUPP; 2877 return -EOPNOTSUPP;
2841 2878
2842 if (!inode_owner_or_capable(inode)) 2879 if (!inode_owner_or_capable(inode))
@@ -3797,8 +3834,12 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
3797 u32 nlbl_sid; 3834 u32 nlbl_sid;
3798 u32 nlbl_type; 3835 u32 nlbl_type;
3799 3836
3800 selinux_skb_xfrm_sid(skb, &xfrm_sid); 3837 err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
3801 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); 3838 if (unlikely(err))
3839 return -EACCES;
3840 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3841 if (unlikely(err))
3842 return -EACCES;
3802 3843
3803 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); 3844 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3804 if (unlikely(err)) { 3845 if (unlikely(err)) {
@@ -4252,7 +4293,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4252 return selinux_sock_rcv_skb_compat(sk, skb, family); 4293 return selinux_sock_rcv_skb_compat(sk, skb, family);
4253 4294
4254 secmark_active = selinux_secmark_enabled(); 4295 secmark_active = selinux_secmark_enabled();
4255 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); 4296 peerlbl_active = selinux_peerlbl_enabled();
4256 if (!secmark_active && !peerlbl_active) 4297 if (!secmark_active && !peerlbl_active)
4257 return 0; 4298 return 0;
4258 4299
@@ -4634,7 +4675,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4634 4675
4635 secmark_active = selinux_secmark_enabled(); 4676 secmark_active = selinux_secmark_enabled();
4636 netlbl_active = netlbl_enabled(); 4677 netlbl_active = netlbl_enabled();
4637 peerlbl_active = netlbl_active || selinux_xfrm_enabled(); 4678 peerlbl_active = selinux_peerlbl_enabled();
4638 if (!secmark_active && !peerlbl_active) 4679 if (!secmark_active && !peerlbl_active)
4639 return NF_ACCEPT; 4680 return NF_ACCEPT;
4640 4681
@@ -4786,7 +4827,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4786 return NF_ACCEPT; 4827 return NF_ACCEPT;
4787#endif 4828#endif
4788 secmark_active = selinux_secmark_enabled(); 4829 secmark_active = selinux_secmark_enabled();
4789 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); 4830 peerlbl_active = selinux_peerlbl_enabled();
4790 if (!secmark_active && !peerlbl_active) 4831 if (!secmark_active && !peerlbl_active)
4791 return NF_ACCEPT; 4832 return NF_ACCEPT;
4792 4833
@@ -5790,7 +5831,8 @@ static struct security_operations selinux_ops = {
5790 .xfrm_policy_clone_security = selinux_xfrm_policy_clone, 5831 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5791 .xfrm_policy_free_security = selinux_xfrm_policy_free, 5832 .xfrm_policy_free_security = selinux_xfrm_policy_free,
5792 .xfrm_policy_delete_security = selinux_xfrm_policy_delete, 5833 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
5793 .xfrm_state_alloc_security = selinux_xfrm_state_alloc, 5834 .xfrm_state_alloc = selinux_xfrm_state_alloc,
5835 .xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire,
5794 .xfrm_state_free_security = selinux_xfrm_state_free, 5836 .xfrm_state_free_security = selinux_xfrm_state_free,
5795 .xfrm_state_delete_security = selinux_xfrm_state_delete, 5837 .xfrm_state_delete_security = selinux_xfrm_state_delete,
5796 .xfrm_policy_lookup = selinux_xfrm_policy_lookup, 5838 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index aa47bcabb5f6..b1dfe1049450 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -58,8 +58,8 @@ struct superblock_security_struct {
58 u32 sid; /* SID of file system superblock */ 58 u32 sid; /* SID of file system superblock */
59 u32 def_sid; /* default SID for labeling */ 59 u32 def_sid; /* default SID for labeling */
60 u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ 60 u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */
61 unsigned int behavior; /* labeling behavior */ 61 unsigned short behavior; /* labeling behavior */
62 unsigned char flags; /* which mount options were specified */ 62 unsigned short flags; /* which mount options were specified */
63 struct mutex lock; 63 struct mutex lock;
64 struct list_head isec_head; 64 struct list_head isec_head;
65 spinlock_t isec_lock; 65 spinlock_t isec_lock;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 8fd8e18ea340..fe341ae37004 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -45,14 +45,15 @@
45/* Mask for just the mount related flags */ 45/* Mask for just the mount related flags */
46#define SE_MNTMASK 0x0f 46#define SE_MNTMASK 0x0f
47/* Super block security struct flags for mount options */ 47/* Super block security struct flags for mount options */
48/* BE CAREFUL, these need to be the low order bits for selinux_get_mnt_opts */
48#define CONTEXT_MNT 0x01 49#define CONTEXT_MNT 0x01
49#define FSCONTEXT_MNT 0x02 50#define FSCONTEXT_MNT 0x02
50#define ROOTCONTEXT_MNT 0x04 51#define ROOTCONTEXT_MNT 0x04
51#define DEFCONTEXT_MNT 0x08 52#define DEFCONTEXT_MNT 0x08
53#define SBLABEL_MNT 0x10
52/* Non-mount related flags */ 54/* Non-mount related flags */
53#define SE_SBINITIALIZED 0x10 55#define SE_SBINITIALIZED 0x0100
54#define SE_SBPROC 0x20 56#define SE_SBPROC 0x0200
55#define SE_SBLABELSUPP 0x40
56 57
57#define CONTEXT_STR "context=" 58#define CONTEXT_STR "context="
58#define FSCONTEXT_STR "fscontext=" 59#define FSCONTEXT_STR "fscontext="
@@ -68,12 +69,15 @@ extern int selinux_enabled;
68enum { 69enum {
69 POLICYDB_CAPABILITY_NETPEER, 70 POLICYDB_CAPABILITY_NETPEER,
70 POLICYDB_CAPABILITY_OPENPERM, 71 POLICYDB_CAPABILITY_OPENPERM,
72 POLICYDB_CAPABILITY_REDHAT1,
73 POLICYDB_CAPABILITY_ALWAYSNETWORK,
71 __POLICYDB_CAPABILITY_MAX 74 __POLICYDB_CAPABILITY_MAX
72}; 75};
73#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) 76#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
74 77
75extern int selinux_policycap_netpeer; 78extern int selinux_policycap_netpeer;
76extern int selinux_policycap_openperm; 79extern int selinux_policycap_openperm;
80extern int selinux_policycap_alwaysnetwork;
77 81
78/* 82/*
79 * type_datum properties 83 * type_datum properties
@@ -172,8 +176,7 @@ int security_get_allow_unknown(void);
172#define SECURITY_FS_USE_NATIVE 7 /* use native label support */ 176#define SECURITY_FS_USE_NATIVE 7 /* use native label support */
173#define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */ 177#define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */
174 178
175int security_fs_use(const char *fstype, unsigned int *behavior, 179int security_fs_use(struct super_block *sb);
176 u32 *sid);
177 180
178int security_genfs_sid(const char *fstype, char *name, u16 sclass, 181int security_genfs_sid(const char *fstype, char *name, u16 sclass,
179 u32 *sid); 182 u32 *sid);
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 65f67cb0aefb..7605251936f5 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -10,29 +10,21 @@
10#include <net/flow.h> 10#include <net/flow.h>
11 11
12int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, 12int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
13 struct xfrm_user_sec_ctx *sec_ctx); 13 struct xfrm_user_sec_ctx *uctx);
14int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, 14int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
15 struct xfrm_sec_ctx **new_ctxp); 15 struct xfrm_sec_ctx **new_ctxp);
16void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx); 16void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
17int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx); 17int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
18int selinux_xfrm_state_alloc(struct xfrm_state *x, 18int selinux_xfrm_state_alloc(struct xfrm_state *x,
19 struct xfrm_user_sec_ctx *sec_ctx, u32 secid); 19 struct xfrm_user_sec_ctx *uctx);
20int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
21 struct xfrm_sec_ctx *polsec, u32 secid);
20void selinux_xfrm_state_free(struct xfrm_state *x); 22void selinux_xfrm_state_free(struct xfrm_state *x);
21int selinux_xfrm_state_delete(struct xfrm_state *x); 23int selinux_xfrm_state_delete(struct xfrm_state *x);
22int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); 24int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
23int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, 25int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
24 struct xfrm_policy *xp, const struct flowi *fl); 26 struct xfrm_policy *xp,
25 27 const struct flowi *fl);
26/*
27 * Extract the security blob from the sock (it's actually on the socket)
28 */
29static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
30{
31 if (!sk->sk_socket)
32 return NULL;
33
34 return SOCK_INODE(sk->sk_socket)->i_security;
35}
36 28
37#ifdef CONFIG_SECURITY_NETWORK_XFRM 29#ifdef CONFIG_SECURITY_NETWORK_XFRM
38extern atomic_t selinux_xfrm_refcount; 30extern atomic_t selinux_xfrm_refcount;
@@ -42,10 +34,10 @@ static inline int selinux_xfrm_enabled(void)
42 return (atomic_read(&selinux_xfrm_refcount) > 0); 34 return (atomic_read(&selinux_xfrm_refcount) > 0);
43} 35}
44 36
45int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, 37int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
46 struct common_audit_data *ad); 38 struct common_audit_data *ad);
47int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 39int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
48 struct common_audit_data *ad, u8 proto); 40 struct common_audit_data *ad, u8 proto);
49int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); 41int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
50 42
51static inline void selinux_xfrm_notify_policyload(void) 43static inline void selinux_xfrm_notify_policyload(void)
@@ -59,19 +51,21 @@ static inline int selinux_xfrm_enabled(void)
59 return 0; 51 return 0;
60} 52}
61 53
62static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, 54static inline int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
63 struct common_audit_data *ad) 55 struct common_audit_data *ad)
64{ 56{
65 return 0; 57 return 0;
66} 58}
67 59
68static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 60static inline int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
69 struct common_audit_data *ad, u8 proto) 61 struct common_audit_data *ad,
62 u8 proto)
70{ 63{
71 return 0; 64 return 0;
72} 65}
73 66
74static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 67static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
68 int ckall)
75{ 69{
76 *sid = SECSID_NULL; 70 *sid = SECSID_NULL;
77 return 0; 71 return 0;
@@ -82,10 +76,9 @@ static inline void selinux_xfrm_notify_policyload(void)
82} 76}
83#endif 77#endif
84 78
85static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) 79static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
86{ 80{
87 int err = selinux_xfrm_decode_session(skb, sid, 0); 81 return selinux_xfrm_decode_session(skb, sid, 0);
88 BUG_ON(err);
89} 82}
90 83
91#endif /* _SELINUX_XFRM_H_ */ 84#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index c5454c0477c3..03a72c32afd7 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -166,6 +166,7 @@ static void sel_netnode_insert(struct sel_netnode *node)
166 break; 166 break;
167 default: 167 default:
168 BUG(); 168 BUG();
169 return;
169 } 170 }
170 171
171 /* we need to impose a limit on the growth of the hash table so check 172 /* we need to impose a limit on the growth of the hash table so check
@@ -225,6 +226,7 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
225 break; 226 break;
226 default: 227 default:
227 BUG(); 228 BUG();
229 ret = -EINVAL;
228 } 230 }
229 if (ret != 0) 231 if (ret != 0)
230 goto out; 232 goto out;
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index ff427733c290..5122affe06a8 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -44,7 +44,9 @@
44/* Policy capability filenames */ 44/* Policy capability filenames */
45static char *policycap_names[] = { 45static char *policycap_names[] = {
46 "network_peer_controls", 46 "network_peer_controls",
47 "open_perms" 47 "open_perms",
48 "redhat1",
49 "always_check_network"
48}; 50};
49 51
50unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; 52unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 30f119b1d1ec..820313a04d49 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -213,7 +213,12 @@ netlbl_import_failure:
213} 213}
214#endif /* CONFIG_NETLABEL */ 214#endif /* CONFIG_NETLABEL */
215 215
216int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) 216/*
217 * Check to see if all the bits set in e2 are also set in e1. Optionally,
218 * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
219 * last_e2bit.
220 */
221int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit)
217{ 222{
218 struct ebitmap_node *n1, *n2; 223 struct ebitmap_node *n1, *n2;
219 int i; 224 int i;
@@ -223,14 +228,25 @@ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
223 228
224 n1 = e1->node; 229 n1 = e1->node;
225 n2 = e2->node; 230 n2 = e2->node;
231
226 while (n1 && n2 && (n1->startbit <= n2->startbit)) { 232 while (n1 && n2 && (n1->startbit <= n2->startbit)) {
227 if (n1->startbit < n2->startbit) { 233 if (n1->startbit < n2->startbit) {
228 n1 = n1->next; 234 n1 = n1->next;
229 continue; 235 continue;
230 } 236 }
231 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { 237 for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i]; )
238 i--; /* Skip trailing NULL map entries */
239 if (last_e2bit && (i >= 0)) {
240 u32 lastsetbit = n2->startbit + i * EBITMAP_UNIT_SIZE +
241 __fls(n2->maps[i]);
242 if (lastsetbit > last_e2bit)
243 return 0;
244 }
245
246 while (i >= 0) {
232 if ((n1->maps[i] & n2->maps[i]) != n2->maps[i]) 247 if ((n1->maps[i] & n2->maps[i]) != n2->maps[i])
233 return 0; 248 return 0;
249 i--;
234 } 250 }
235 251
236 n1 = n1->next; 252 n1 = n1->next;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 922f8afa89dd..712c8a7b8e8b 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -16,7 +16,13 @@
16 16
17#include <net/netlabel.h> 17#include <net/netlabel.h>
18 18
19#define EBITMAP_UNIT_NUMS ((32 - sizeof(void *) - sizeof(u32)) \ 19#ifdef CONFIG_64BIT
20#define EBITMAP_NODE_SIZE 64
21#else
22#define EBITMAP_NODE_SIZE 32
23#endif
24
25#define EBITMAP_UNIT_NUMS ((EBITMAP_NODE_SIZE-sizeof(void *)-sizeof(u32))\
20 / sizeof(unsigned long)) 26 / sizeof(unsigned long))
21#define EBITMAP_UNIT_SIZE BITS_PER_LONG 27#define EBITMAP_UNIT_SIZE BITS_PER_LONG
22#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE) 28#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
@@ -117,7 +123,7 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
117 123
118int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); 124int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
119int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); 125int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
120int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); 126int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit);
121int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); 127int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
122int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); 128int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
123void ebitmap_destroy(struct ebitmap *e); 129void ebitmap_destroy(struct ebitmap *e);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 40de8d3f208e..c85bc1ec040c 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -160,8 +160,6 @@ void mls_sid_to_context(struct context *context,
160int mls_level_isvalid(struct policydb *p, struct mls_level *l) 160int mls_level_isvalid(struct policydb *p, struct mls_level *l)
161{ 161{
162 struct level_datum *levdatum; 162 struct level_datum *levdatum;
163 struct ebitmap_node *node;
164 int i;
165 163
166 if (!l->sens || l->sens > p->p_levels.nprim) 164 if (!l->sens || l->sens > p->p_levels.nprim)
167 return 0; 165 return 0;
@@ -170,19 +168,13 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
170 if (!levdatum) 168 if (!levdatum)
171 return 0; 169 return 0;
172 170
173 ebitmap_for_each_positive_bit(&l->cat, node, i) { 171 /*
174 if (i > p->p_cats.nprim) 172 * Return 1 iff all the bits set in l->cat are also be set in
175 return 0; 173 * levdatum->level->cat and no bit in l->cat is larger than
176 if (!ebitmap_get_bit(&levdatum->level->cat, i)) { 174 * p->p_cats.nprim.
177 /* 175 */
178 * Category may not be associated with 176 return ebitmap_contains(&levdatum->level->cat, &l->cat,
179 * sensitivity. 177 p->p_cats.nprim);
180 */
181 return 0;
182 }
183 }
184
185 return 1;
186} 178}
187 179
188int mls_range_isvalid(struct policydb *p, struct mls_range *r) 180int mls_range_isvalid(struct policydb *p, struct mls_range *r)
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
index 03bed52a8052..e93648774137 100644
--- a/security/selinux/ss/mls_types.h
+++ b/security/selinux/ss/mls_types.h
@@ -35,7 +35,7 @@ static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
35static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) 35static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
36{ 36{
37 return ((l1->sens >= l2->sens) && 37 return ((l1->sens >= l2->sens) &&
38 ebitmap_contains(&l1->cat, &l2->cat)); 38 ebitmap_contains(&l1->cat, &l2->cat, 0));
39} 39}
40 40
41#define mls_level_incomp(l1, l2) \ 41#define mls_level_incomp(l1, l2) \
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index c8adde3aff8f..f6195ebde3c9 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -3203,9 +3203,8 @@ static int range_write_helper(void *key, void *data, void *ptr)
3203 3203
3204static int range_write(struct policydb *p, void *fp) 3204static int range_write(struct policydb *p, void *fp)
3205{ 3205{
3206 size_t nel;
3207 __le32 buf[1]; 3206 __le32 buf[1];
3208 int rc; 3207 int rc, nel;
3209 struct policy_data pd; 3208 struct policy_data pd;
3210 3209
3211 pd.p = p; 3210 pd.p = p;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b4feecc3fe01..ee470a0b5c27 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -72,6 +72,7 @@
72 72
73int selinux_policycap_netpeer; 73int selinux_policycap_netpeer;
74int selinux_policycap_openperm; 74int selinux_policycap_openperm;
75int selinux_policycap_alwaysnetwork;
75 76
76static DEFINE_RWLOCK(policy_rwlock); 77static DEFINE_RWLOCK(policy_rwlock);
77 78
@@ -1812,6 +1813,8 @@ static void security_load_policycaps(void)
1812 POLICYDB_CAPABILITY_NETPEER); 1813 POLICYDB_CAPABILITY_NETPEER);
1813 selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps, 1814 selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
1814 POLICYDB_CAPABILITY_OPENPERM); 1815 POLICYDB_CAPABILITY_OPENPERM);
1816 selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
1817 POLICYDB_CAPABILITY_ALWAYSNETWORK);
1815} 1818}
1816 1819
1817static int security_preserve_bools(struct policydb *p); 1820static int security_preserve_bools(struct policydb *p);
@@ -2323,43 +2326,74 @@ out:
2323 2326
2324/** 2327/**
2325 * security_fs_use - Determine how to handle labeling for a filesystem. 2328 * security_fs_use - Determine how to handle labeling for a filesystem.
2326 * @fstype: filesystem type 2329 * @sb: superblock in question
2327 * @behavior: labeling behavior
2328 * @sid: SID for filesystem (superblock)
2329 */ 2330 */
2330int security_fs_use( 2331int security_fs_use(struct super_block *sb)
2331 const char *fstype,
2332 unsigned int *behavior,
2333 u32 *sid)
2334{ 2332{
2335 int rc = 0; 2333 int rc = 0;
2336 struct ocontext *c; 2334 struct ocontext *c;
2335 struct superblock_security_struct *sbsec = sb->s_security;
2336 const char *fstype = sb->s_type->name;
2337 const char *subtype = (sb->s_subtype && sb->s_subtype[0]) ? sb->s_subtype : NULL;
2338 struct ocontext *base = NULL;
2337 2339
2338 read_lock(&policy_rwlock); 2340 read_lock(&policy_rwlock);
2339 2341
2340 c = policydb.ocontexts[OCON_FSUSE]; 2342 for (c = policydb.ocontexts[OCON_FSUSE]; c; c = c->next) {
2341 while (c) { 2343 char *sub;
2342 if (strcmp(fstype, c->u.name) == 0) 2344 int baselen;
2345
2346 baselen = strlen(fstype);
2347
2348 /* if base does not match, this is not the one */
2349 if (strncmp(fstype, c->u.name, baselen))
2350 continue;
2351
2352 /* if there is no subtype, this is the one! */
2353 if (!subtype)
2354 break;
2355
2356 /* skip past the base in this entry */
2357 sub = c->u.name + baselen;
2358
2359 /* entry is only a base. save it. keep looking for subtype */
2360 if (sub[0] == '\0') {
2361 base = c;
2362 continue;
2363 }
2364
2365 /* entry is not followed by a subtype, so it is not a match */
2366 if (sub[0] != '.')
2367 continue;
2368
2369 /* whew, we found a subtype of this fstype */
2370 sub++; /* move past '.' */
2371
2372 /* exact match of fstype AND subtype */
2373 if (!strcmp(subtype, sub))
2343 break; 2374 break;
2344 c = c->next;
2345 } 2375 }
2346 2376
2377 /* in case we had found an fstype match but no subtype match */
2378 if (!c)
2379 c = base;
2380
2347 if (c) { 2381 if (c) {
2348 *behavior = c->v.behavior; 2382 sbsec->behavior = c->v.behavior;
2349 if (!c->sid[0]) { 2383 if (!c->sid[0]) {
2350 rc = sidtab_context_to_sid(&sidtab, &c->context[0], 2384 rc = sidtab_context_to_sid(&sidtab, &c->context[0],
2351 &c->sid[0]); 2385 &c->sid[0]);
2352 if (rc) 2386 if (rc)
2353 goto out; 2387 goto out;
2354 } 2388 }
2355 *sid = c->sid[0]; 2389 sbsec->sid = c->sid[0];
2356 } else { 2390 } else {
2357 rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid); 2391 rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, &sbsec->sid);
2358 if (rc) { 2392 if (rc) {
2359 *behavior = SECURITY_FS_USE_NONE; 2393 sbsec->behavior = SECURITY_FS_USE_NONE;
2360 rc = 0; 2394 rc = 0;
2361 } else { 2395 } else {
2362 *behavior = SECURITY_FS_USE_GENFS; 2396 sbsec->behavior = SECURITY_FS_USE_GENFS;
2363 } 2397 }
2364 } 2398 }
2365 2399
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index d03081886214..425b9f91d755 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -56,7 +56,7 @@
56atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0); 56atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
57 57
58/* 58/*
59 * Returns true if an LSM/SELinux context 59 * Returns true if the context is an LSM/SELinux context.
60 */ 60 */
61static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx) 61static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
62{ 62{
@@ -66,7 +66,7 @@ static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
66} 66}
67 67
68/* 68/*
69 * Returns true if the xfrm contains a security blob for SELinux 69 * Returns true if the xfrm contains a security blob for SELinux.
70 */ 70 */
71static inline int selinux_authorizable_xfrm(struct xfrm_state *x) 71static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
72{ 72{
@@ -74,48 +74,111 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
74} 74}
75 75
76/* 76/*
77 * LSM hook implementation that authorizes that a flow can use 77 * Allocates a xfrm_sec_state and populates it using the supplied security
78 * a xfrm policy rule. 78 * xfrm_user_sec_ctx context.
79 */ 79 */
80int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) 80static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
81 struct xfrm_user_sec_ctx *uctx)
81{ 82{
82 int rc; 83 int rc;
83 u32 sel_sid; 84 const struct task_security_struct *tsec = current_security();
85 struct xfrm_sec_ctx *ctx = NULL;
86 u32 str_len;
84 87
85 /* Context sid is either set to label or ANY_ASSOC */ 88 if (ctxp == NULL || uctx == NULL ||
86 if (ctx) { 89 uctx->ctx_doi != XFRM_SC_DOI_LSM ||
87 if (!selinux_authorizable_ctx(ctx)) 90 uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
88 return -EINVAL; 91 return -EINVAL;
89
90 sel_sid = ctx->ctx_sid;
91 } else
92 /*
93 * All flows should be treated as polmatch'ing an
94 * otherwise applicable "non-labeled" policy. This
95 * would prevent inadvertent "leaks".
96 */
97 return 0;
98 92
99 rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION, 93 str_len = uctx->ctx_len;
100 ASSOCIATION__POLMATCH, 94 if (str_len >= PAGE_SIZE)
101 NULL); 95 return -ENOMEM;
102 96
103 if (rc == -EACCES) 97 ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL);
104 return -ESRCH; 98 if (!ctx)
99 return -ENOMEM;
105 100
101 ctx->ctx_doi = XFRM_SC_DOI_LSM;
102 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
103 ctx->ctx_len = str_len;
104 memcpy(ctx->ctx_str, &uctx[1], str_len);
105 ctx->ctx_str[str_len] = '\0';
106 rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid);
107 if (rc)
108 goto err;
109
110 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
111 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
112 if (rc)
113 goto err;
114
115 *ctxp = ctx;
116 atomic_inc(&selinux_xfrm_refcount);
117 return 0;
118
119err:
120 kfree(ctx);
106 return rc; 121 return rc;
107} 122}
108 123
109/* 124/*
125 * Free the xfrm_sec_ctx structure.
126 */
127static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx)
128{
129 if (!ctx)
130 return;
131
132 atomic_dec(&selinux_xfrm_refcount);
133 kfree(ctx);
134}
135
136/*
137 * Authorize the deletion of a labeled SA or policy rule.
138 */
139static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
140{
141 const struct task_security_struct *tsec = current_security();
142
143 if (!ctx)
144 return 0;
145
146 return avc_has_perm(tsec->sid, ctx->ctx_sid,
147 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
148 NULL);
149}
150
151/*
152 * LSM hook implementation that authorizes that a flow can use a xfrm policy
153 * rule.
154 */
155int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
156{
157 int rc;
158
159 /* All flows should be treated as polmatch'ing an otherwise applicable
160 * "non-labeled" policy. This would prevent inadvertent "leaks". */
161 if (!ctx)
162 return 0;
163
164 /* Context sid is either set to label or ANY_ASSOC */
165 if (!selinux_authorizable_ctx(ctx))
166 return -EINVAL;
167
168 rc = avc_has_perm(fl_secid, ctx->ctx_sid,
169 SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL);
170 return (rc == -EACCES ? -ESRCH : rc);
171}
172
173/*
110 * LSM hook implementation that authorizes that a state matches 174 * LSM hook implementation that authorizes that a state matches
111 * the given policy, flow combo. 175 * the given policy, flow combo.
112 */ 176 */
113 177int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
114int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, 178 struct xfrm_policy *xp,
115 const struct flowi *fl) 179 const struct flowi *fl)
116{ 180{
117 u32 state_sid; 181 u32 state_sid;
118 int rc;
119 182
120 if (!xp->security) 183 if (!xp->security)
121 if (x->security) 184 if (x->security)
@@ -138,187 +201,80 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
138 if (fl->flowi_secid != state_sid) 201 if (fl->flowi_secid != state_sid)
139 return 0; 202 return 0;
140 203
141 rc = avc_has_perm(fl->flowi_secid, state_sid, SECCLASS_ASSOCIATION, 204 /* We don't need a separate SA Vs. policy polmatch check since the SA
142 ASSOCIATION__SENDTO, 205 * is now of the same label as the flow and a flow Vs. policy polmatch
143 NULL)? 0:1; 206 * check had already happened in selinux_xfrm_policy_lookup() above. */
144 207 return (avc_has_perm(fl->flowi_secid, state_sid,
145 /* 208 SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
146 * We don't need a separate SA Vs. policy polmatch check 209 NULL) ? 0 : 1);
147 * since the SA is now of the same label as the flow and
148 * a flow Vs. policy polmatch check had already happened
149 * in selinux_xfrm_policy_lookup() above.
150 */
151
152 return rc;
153} 210}
154 211
155/* 212/*
156 * LSM hook implementation that checks and/or returns the xfrm sid for the 213 * LSM hook implementation that checks and/or returns the xfrm sid for the
157 * incoming packet. 214 * incoming packet.
158 */ 215 */
159
160int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 216int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
161{ 217{
218 u32 sid_session = SECSID_NULL;
162 struct sec_path *sp; 219 struct sec_path *sp;
163 220
164 *sid = SECSID_NULL;
165
166 if (skb == NULL) 221 if (skb == NULL)
167 return 0; 222 goto out;
168 223
169 sp = skb->sp; 224 sp = skb->sp;
170 if (sp) { 225 if (sp) {
171 int i, sid_set = 0; 226 int i;
172 227
173 for (i = sp->len-1; i >= 0; i--) { 228 for (i = sp->len - 1; i >= 0; i--) {
174 struct xfrm_state *x = sp->xvec[i]; 229 struct xfrm_state *x = sp->xvec[i];
175 if (selinux_authorizable_xfrm(x)) { 230 if (selinux_authorizable_xfrm(x)) {
176 struct xfrm_sec_ctx *ctx = x->security; 231 struct xfrm_sec_ctx *ctx = x->security;
177 232
178 if (!sid_set) { 233 if (sid_session == SECSID_NULL) {
179 *sid = ctx->ctx_sid; 234 sid_session = ctx->ctx_sid;
180 sid_set = 1;
181
182 if (!ckall) 235 if (!ckall)
183 break; 236 goto out;
184 } else if (*sid != ctx->ctx_sid) 237 } else if (sid_session != ctx->ctx_sid) {
238 *sid = SECSID_NULL;
185 return -EINVAL; 239 return -EINVAL;
240 }
186 } 241 }
187 } 242 }
188 } 243 }
189 244
190 return 0;
191}
192
193/*
194 * Security blob allocation for xfrm_policy and xfrm_state
195 * CTX does not have a meaningful value on input
196 */
197static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
198 struct xfrm_user_sec_ctx *uctx, u32 sid)
199{
200 int rc = 0;
201 const struct task_security_struct *tsec = current_security();
202 struct xfrm_sec_ctx *ctx = NULL;
203 char *ctx_str = NULL;
204 u32 str_len;
205
206 BUG_ON(uctx && sid);
207
208 if (!uctx)
209 goto not_from_user;
210
211 if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
212 return -EINVAL;
213
214 str_len = uctx->ctx_len;
215 if (str_len >= PAGE_SIZE)
216 return -ENOMEM;
217
218 *ctxp = ctx = kmalloc(sizeof(*ctx) +
219 str_len + 1,
220 GFP_KERNEL);
221
222 if (!ctx)
223 return -ENOMEM;
224
225 ctx->ctx_doi = uctx->ctx_doi;
226 ctx->ctx_len = str_len;
227 ctx->ctx_alg = uctx->ctx_alg;
228
229 memcpy(ctx->ctx_str,
230 uctx+1,
231 str_len);
232 ctx->ctx_str[str_len] = 0;
233 rc = security_context_to_sid(ctx->ctx_str,
234 str_len,
235 &ctx->ctx_sid);
236
237 if (rc)
238 goto out;
239
240 /*
241 * Does the subject have permission to set security context?
242 */
243 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
244 SECCLASS_ASSOCIATION,
245 ASSOCIATION__SETCONTEXT, NULL);
246 if (rc)
247 goto out;
248
249 return rc;
250
251not_from_user:
252 rc = security_sid_to_context(sid, &ctx_str, &str_len);
253 if (rc)
254 goto out;
255
256 *ctxp = ctx = kmalloc(sizeof(*ctx) +
257 str_len,
258 GFP_ATOMIC);
259
260 if (!ctx) {
261 rc = -ENOMEM;
262 goto out;
263 }
264
265 ctx->ctx_doi = XFRM_SC_DOI_LSM;
266 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
267 ctx->ctx_sid = sid;
268 ctx->ctx_len = str_len;
269 memcpy(ctx->ctx_str,
270 ctx_str,
271 str_len);
272
273 goto out2;
274
275out: 245out:
276 *ctxp = NULL; 246 *sid = sid_session;
277 kfree(ctx); 247 return 0;
278out2:
279 kfree(ctx_str);
280 return rc;
281} 248}
282 249
283/* 250/*
284 * LSM hook implementation that allocs and transfers uctx spec to 251 * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
285 * xfrm_policy.
286 */ 252 */
287int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, 253int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
288 struct xfrm_user_sec_ctx *uctx) 254 struct xfrm_user_sec_ctx *uctx)
289{ 255{
290 int err; 256 return selinux_xfrm_alloc_user(ctxp, uctx);
291
292 BUG_ON(!uctx);
293
294 err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
295 if (err == 0)
296 atomic_inc(&selinux_xfrm_refcount);
297
298 return err;
299} 257}
300 258
301
302/* 259/*
303 * LSM hook implementation that copies security data structure from old to 260 * LSM hook implementation that copies security data structure from old to new
304 * new for policy cloning. 261 * for policy cloning.
305 */ 262 */
306int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, 263int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
307 struct xfrm_sec_ctx **new_ctxp) 264 struct xfrm_sec_ctx **new_ctxp)
308{ 265{
309 struct xfrm_sec_ctx *new_ctx; 266 struct xfrm_sec_ctx *new_ctx;
310 267
311 if (old_ctx) { 268 if (!old_ctx)
312 new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len, 269 return 0;
313 GFP_ATOMIC); 270
314 if (!new_ctx) 271 new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len, GFP_ATOMIC);
315 return -ENOMEM; 272 if (!new_ctx)
273 return -ENOMEM;
274 memcpy(new_ctx, old_ctx, sizeof(*old_ctx) + old_ctx->ctx_len);
275 atomic_inc(&selinux_xfrm_refcount);
276 *new_ctxp = new_ctx;
316 277
317 memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
318 memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
319 atomic_inc(&selinux_xfrm_refcount);
320 *new_ctxp = new_ctx;
321 }
322 return 0; 278 return 0;
323} 279}
324 280
@@ -327,8 +283,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
327 */ 283 */
328void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx) 284void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
329{ 285{
330 atomic_dec(&selinux_xfrm_refcount); 286 selinux_xfrm_free(ctx);
331 kfree(ctx);
332} 287}
333 288
334/* 289/*
@@ -336,31 +291,55 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
336 */ 291 */
337int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) 292int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
338{ 293{
339 const struct task_security_struct *tsec = current_security(); 294 return selinux_xfrm_delete(ctx);
340 295}
341 if (!ctx)
342 return 0;
343 296
344 return avc_has_perm(tsec->sid, ctx->ctx_sid, 297/*
345 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, 298 * LSM hook implementation that allocates a xfrm_sec_state, populates it using
346 NULL); 299 * the supplied security context, and assigns it to the xfrm_state.
300 */
301int selinux_xfrm_state_alloc(struct xfrm_state *x,
302 struct xfrm_user_sec_ctx *uctx)
303{
304 return selinux_xfrm_alloc_user(&x->security, uctx);
347} 305}
348 306
349/* 307/*
350 * LSM hook implementation that allocs and transfers sec_ctx spec to 308 * LSM hook implementation that allocates a xfrm_sec_state and populates based
351 * xfrm_state. 309 * on a secid.
352 */ 310 */
353int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx, 311int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
354 u32 secid) 312 struct xfrm_sec_ctx *polsec, u32 secid)
355{ 313{
356 int err; 314 int rc;
315 struct xfrm_sec_ctx *ctx;
316 char *ctx_str = NULL;
317 int str_len;
318
319 if (!polsec)
320 return 0;
357 321
358 BUG_ON(!x); 322 if (secid == 0)
323 return -EINVAL;
359 324
360 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid); 325 rc = security_sid_to_context(secid, &ctx_str, &str_len);
361 if (err == 0) 326 if (rc)
362 atomic_inc(&selinux_xfrm_refcount); 327 return rc;
363 return err; 328
329 ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
330 if (!ctx)
331 return -ENOMEM;
332
333 ctx->ctx_doi = XFRM_SC_DOI_LSM;
334 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
335 ctx->ctx_sid = secid;
336 ctx->ctx_len = str_len;
337 memcpy(ctx->ctx_str, ctx_str, str_len);
338 kfree(ctx_str);
339
340 x->security = ctx;
341 atomic_inc(&selinux_xfrm_refcount);
342 return 0;
364} 343}
365 344
366/* 345/*
@@ -368,24 +347,15 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
368 */ 347 */
369void selinux_xfrm_state_free(struct xfrm_state *x) 348void selinux_xfrm_state_free(struct xfrm_state *x)
370{ 349{
371 atomic_dec(&selinux_xfrm_refcount); 350 selinux_xfrm_free(x->security);
372 kfree(x->security);
373} 351}
374 352
375 /* 353/*
376 * LSM hook implementation that authorizes deletion of labeled SAs. 354 * LSM hook implementation that authorizes deletion of labeled SAs.
377 */ 355 */
378int selinux_xfrm_state_delete(struct xfrm_state *x) 356int selinux_xfrm_state_delete(struct xfrm_state *x)
379{ 357{
380 const struct task_security_struct *tsec = current_security(); 358 return selinux_xfrm_delete(x->security);
381 struct xfrm_sec_ctx *ctx = x->security;
382
383 if (!ctx)
384 return 0;
385
386 return avc_has_perm(tsec->sid, ctx->ctx_sid,
387 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
388 NULL);
389} 359}
390 360
391/* 361/*
@@ -395,14 +365,12 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
395 * we need to check for unlabelled access since this may not have 365 * we need to check for unlabelled access since this may not have
396 * gone thru the IPSec process. 366 * gone thru the IPSec process.
397 */ 367 */
398int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, 368int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
399 struct common_audit_data *ad) 369 struct common_audit_data *ad)
400{ 370{
401 int i, rc = 0; 371 int i;
402 struct sec_path *sp; 372 struct sec_path *sp = skb->sp;
403 u32 sel_sid = SECINITSID_UNLABELED; 373 u32 peer_sid = SECINITSID_UNLABELED;
404
405 sp = skb->sp;
406 374
407 if (sp) { 375 if (sp) {
408 for (i = 0; i < sp->len; i++) { 376 for (i = 0; i < sp->len; i++) {
@@ -410,23 +378,17 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
410 378
411 if (x && selinux_authorizable_xfrm(x)) { 379 if (x && selinux_authorizable_xfrm(x)) {
412 struct xfrm_sec_ctx *ctx = x->security; 380 struct xfrm_sec_ctx *ctx = x->security;
413 sel_sid = ctx->ctx_sid; 381 peer_sid = ctx->ctx_sid;
414 break; 382 break;
415 } 383 }
416 } 384 }
417 } 385 }
418 386
419 /* 387 /* This check even when there's no association involved is intended,
420 * This check even when there's no association involved is 388 * according to Trent Jaeger, to make sure a process can't engage in
421 * intended, according to Trent Jaeger, to make sure a 389 * non-IPsec communication unless explicitly allowed by policy. */
422 * process can't engage in non-ipsec communication unless 390 return avc_has_perm(sk_sid, peer_sid,
423 * explicitly allowed by policy. 391 SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad);
424 */
425
426 rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
427 ASSOCIATION__RECVFROM, ad);
428
429 return rc;
430} 392}
431 393
432/* 394/*
@@ -436,49 +398,38 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
436 * If we do have a authorizable security association, then it has already been 398 * If we do have a authorizable security association, then it has already been
437 * checked in the selinux_xfrm_state_pol_flow_match hook above. 399 * checked in the selinux_xfrm_state_pol_flow_match hook above.
438 */ 400 */
439int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 401int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
440 struct common_audit_data *ad, u8 proto) 402 struct common_audit_data *ad, u8 proto)
441{ 403{
442 struct dst_entry *dst; 404 struct dst_entry *dst;
443 int rc = 0;
444
445 dst = skb_dst(skb);
446
447 if (dst) {
448 struct dst_entry *dst_test;
449
450 for (dst_test = dst; dst_test != NULL;
451 dst_test = dst_test->child) {
452 struct xfrm_state *x = dst_test->xfrm;
453
454 if (x && selinux_authorizable_xfrm(x))
455 goto out;
456 }
457 }
458 405
459 switch (proto) { 406 switch (proto) {
460 case IPPROTO_AH: 407 case IPPROTO_AH:
461 case IPPROTO_ESP: 408 case IPPROTO_ESP:
462 case IPPROTO_COMP: 409 case IPPROTO_COMP:
463 /* 410 /* We should have already seen this packet once before it
464 * We should have already seen this packet once before 411 * underwent xfrm(s). No need to subject it to the unlabeled
465 * it underwent xfrm(s). No need to subject it to the 412 * check. */
466 * unlabeled check. 413 return 0;
467 */
468 goto out;
469 default: 414 default:
470 break; 415 break;
471 } 416 }
472 417
473 /* 418 dst = skb_dst(skb);
474 * This check even when there's no association involved is 419 if (dst) {
475 * intended, according to Trent Jaeger, to make sure a 420 struct dst_entry *iter;
476 * process can't engage in non-ipsec communication unless
477 * explicitly allowed by policy.
478 */
479 421
480 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, 422 for (iter = dst; iter != NULL; iter = iter->child) {
481 ASSOCIATION__SENDTO, ad); 423 struct xfrm_state *x = iter->xfrm;
482out: 424
483 return rc; 425 if (x && selinux_authorizable_xfrm(x))
426 return 0;
427 }
428 }
429
430 /* This check even when there's no association involved is intended,
431 * according to Trent Jaeger, to make sure a process can't engage in
432 * non-IPsec communication unless explicitly allowed by policy. */
433 return avc_has_perm(sk_sid, SECINITSID_UNLABELED,
434 SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad);
484} 435}