diff options
| author | Paul Moore <pmoore@redhat.com> | 2013-09-18 13:52:20 -0400 |
|---|---|---|
| committer | Paul Moore <pmoore@redhat.com> | 2013-09-18 13:52:20 -0400 |
| commit | 98f700f317967d45cf60c9843b3c42ce3c286f7c (patch) | |
| tree | 2e68b189ceb954182af56b8f6febe644119b7cd7 | |
| parent | 6e4664525b1db28f8c4e1130957f70a94c19213e (diff) | |
| parent | 0b4bdb3573a86a88c829b9e4ad702859eb923e7e (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.
| -rw-r--r-- | include/linux/security.h | 26 | ||||
| -rw-r--r-- | security/capability.c | 15 | ||||
| -rw-r--r-- | security/security.c | 13 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 146 | ||||
| -rw-r--r-- | security/selinux/include/objsec.h | 4 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 13 | ||||
| -rw-r--r-- | security/selinux/include/xfrm.h | 45 | ||||
| -rw-r--r-- | security/selinux/netnode.c | 2 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 4 | ||||
| -rw-r--r-- | security/selinux/ss/ebitmap.c | 20 | ||||
| -rw-r--r-- | security/selinux/ss/ebitmap.h | 10 | ||||
| -rw-r--r-- | security/selinux/ss/mls.c | 22 | ||||
| -rw-r--r-- | security/selinux/ss/mls_types.h | 2 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.c | 3 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 66 | ||||
| -rw-r--r-- | security/selinux/xfrm.c | 453 |
16 files changed, 448 insertions, 396 deletions
diff --git a/include/linux/security.h b/include/linux/security.h index 7ce53ae1266b..8d23951a3805 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -1052,17 +1052,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 1052 | * @xfrm_policy_delete_security: | 1052 | * @xfrm_policy_delete_security: |
| 1053 | * @ctx contains the xfrm_sec_ctx. | 1053 | * @ctx contains the xfrm_sec_ctx. |
| 1054 | * Authorize deletion of xp->security. | 1054 | * Authorize deletion of xp->security. |
| 1055 | * @xfrm_state_alloc_security: | 1055 | * @xfrm_state_alloc: |
| 1056 | * @x contains the xfrm_state being added to the Security Association | 1056 | * @x contains the xfrm_state being added to the Security Association |
| 1057 | * Database by the XFRM system. | 1057 | * Database by the XFRM system. |
| 1058 | * @sec_ctx contains the security context information being provided by | 1058 | * @sec_ctx contains the security context information being provided by |
| 1059 | * the user-level SA generation program (e.g., setkey or racoon). | 1059 | * the user-level SA generation program (e.g., setkey or racoon). |
| 1060 | * @secid contains the secid from which to take the mls portion of the context. | ||
| 1061 | * Allocate a security structure to the x->security field; the security | 1060 | * Allocate a security structure to the x->security field; the security |
| 1062 | * field is initialized to NULL when the xfrm_state is allocated. Set the | 1061 | * field is initialized to NULL when the xfrm_state is allocated. Set the |
| 1063 | * context to correspond to either sec_ctx or polsec, with the mls portion | 1062 | * context to correspond to sec_ctx. Return 0 if operation was successful |
| 1064 | * taken from secid in the latter case. | 1063 | * (memory to allocate, legal context). |
| 1065 | * Return 0 if operation was successful (memory to allocate, legal context). | 1064 | * @xfrm_state_alloc_acquire: |
| 1065 | * @x contains the xfrm_state being added to the Security Association | ||
| 1066 | * Database by the XFRM system. | ||
| 1067 | * @polsec contains the policy's security context. | ||
| 1068 | * @secid contains the secid from which to take the mls portion of the | ||
| 1069 | * context. | ||
| 1070 | * Allocate a security structure to the x->security field; the security | ||
| 1071 | * field is initialized to NULL when the xfrm_state is allocated. Set the | ||
| 1072 | * context to correspond to secid. Return 0 if operation was successful | ||
| 1073 | * (memory to allocate, legal context). | ||
| 1066 | * @xfrm_state_free_security: | 1074 | * @xfrm_state_free_security: |
| 1067 | * @x contains the xfrm_state. | 1075 | * @x contains the xfrm_state. |
| 1068 | * Deallocate x->security. | 1076 | * Deallocate x->security. |
| @@ -1679,9 +1687,11 @@ struct security_operations { | |||
| 1679 | int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx); | 1687 | int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx); |
| 1680 | void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx); | 1688 | void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx); |
| 1681 | int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx); | 1689 | int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx); |
| 1682 | int (*xfrm_state_alloc_security) (struct xfrm_state *x, | 1690 | int (*xfrm_state_alloc) (struct xfrm_state *x, |
| 1683 | struct xfrm_user_sec_ctx *sec_ctx, | 1691 | struct xfrm_user_sec_ctx *sec_ctx); |
| 1684 | u32 secid); | 1692 | int (*xfrm_state_alloc_acquire) (struct xfrm_state *x, |
| 1693 | struct xfrm_sec_ctx *polsec, | ||
| 1694 | u32 secid); | ||
| 1685 | void (*xfrm_state_free_security) (struct xfrm_state *x); | 1695 | void (*xfrm_state_free_security) (struct xfrm_state *x); |
| 1686 | int (*xfrm_state_delete_security) (struct xfrm_state *x); | 1696 | int (*xfrm_state_delete_security) (struct xfrm_state *x); |
| 1687 | int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); | 1697 | int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); |
diff --git a/security/capability.c b/security/capability.c index 32b515766df1..b6d779b6aa25 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -777,9 +777,15 @@ static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx) | |||
| 777 | return 0; | 777 | return 0; |
| 778 | } | 778 | } |
| 779 | 779 | ||
| 780 | static int cap_xfrm_state_alloc_security(struct xfrm_state *x, | 780 | static int cap_xfrm_state_alloc(struct xfrm_state *x, |
| 781 | struct xfrm_user_sec_ctx *sec_ctx, | 781 | struct xfrm_user_sec_ctx *sec_ctx) |
| 782 | u32 secid) | 782 | { |
| 783 | return 0; | ||
| 784 | } | ||
| 785 | |||
| 786 | static int cap_xfrm_state_alloc_acquire(struct xfrm_state *x, | ||
| 787 | struct xfrm_sec_ctx *polsec, | ||
| 788 | u32 secid) | ||
| 783 | { | 789 | { |
| 784 | return 0; | 790 | return 0; |
| 785 | } | 791 | } |
| @@ -1101,7 +1107,8 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
| 1101 | set_to_cap_if_null(ops, xfrm_policy_clone_security); | 1107 | set_to_cap_if_null(ops, xfrm_policy_clone_security); |
| 1102 | set_to_cap_if_null(ops, xfrm_policy_free_security); | 1108 | set_to_cap_if_null(ops, xfrm_policy_free_security); |
| 1103 | set_to_cap_if_null(ops, xfrm_policy_delete_security); | 1109 | set_to_cap_if_null(ops, xfrm_policy_delete_security); |
| 1104 | set_to_cap_if_null(ops, xfrm_state_alloc_security); | 1110 | set_to_cap_if_null(ops, xfrm_state_alloc); |
| 1111 | set_to_cap_if_null(ops, xfrm_state_alloc_acquire); | ||
| 1105 | set_to_cap_if_null(ops, xfrm_state_free_security); | 1112 | set_to_cap_if_null(ops, xfrm_state_free_security); |
| 1106 | set_to_cap_if_null(ops, xfrm_state_delete_security); | 1113 | set_to_cap_if_null(ops, xfrm_state_delete_security); |
| 1107 | set_to_cap_if_null(ops, xfrm_policy_lookup); | 1114 | set_to_cap_if_null(ops, xfrm_policy_lookup); |
diff --git a/security/security.c b/security/security.c index 94b35aef6871..94048028bdd1 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -1342,22 +1342,17 @@ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) | |||
| 1342 | return security_ops->xfrm_policy_delete_security(ctx); | 1342 | return security_ops->xfrm_policy_delete_security(ctx); |
| 1343 | } | 1343 | } |
| 1344 | 1344 | ||
| 1345 | int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) | 1345 | int security_xfrm_state_alloc(struct xfrm_state *x, |
| 1346 | struct xfrm_user_sec_ctx *sec_ctx) | ||
| 1346 | { | 1347 | { |
| 1347 | return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0); | 1348 | return security_ops->xfrm_state_alloc(x, sec_ctx); |
| 1348 | } | 1349 | } |
| 1349 | EXPORT_SYMBOL(security_xfrm_state_alloc); | 1350 | EXPORT_SYMBOL(security_xfrm_state_alloc); |
| 1350 | 1351 | ||
| 1351 | int security_xfrm_state_alloc_acquire(struct xfrm_state *x, | 1352 | int security_xfrm_state_alloc_acquire(struct xfrm_state *x, |
| 1352 | struct xfrm_sec_ctx *polsec, u32 secid) | 1353 | struct xfrm_sec_ctx *polsec, u32 secid) |
| 1353 | { | 1354 | { |
| 1354 | if (!polsec) | 1355 | return security_ops->xfrm_state_alloc_acquire(x, polsec, secid); |
| 1355 | return 0; | ||
| 1356 | /* | ||
| 1357 | * We want the context to be taken from secid which is usually | ||
| 1358 | * from the sock. | ||
| 1359 | */ | ||
| 1360 | return security_ops->xfrm_state_alloc_security(x, NULL, secid); | ||
| 1361 | } | 1356 | } |
| 1362 | 1357 | ||
| 1363 | int security_xfrm_state_delete(struct xfrm_state *x) | 1358 | int security_xfrm_state_delete(struct xfrm_state *x) |
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 | ||
| 100 | extern struct security_operations *security_ops; | 102 | extern 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 | */ |
| 145 | static int selinux_secmark_enabled(void) | 148 | static 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 | */ | ||
| 163 | static 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 | |||
| 314 | static const match_table_t tokens = { | 335 | static 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 | ||
| 379 | static 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 | |||
| 358 | static int sb_finish_set_opts(struct super_block *sb) | 402 | static 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: | |||
| 770 | out_double_mount: | 806 | out_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; |
| 2484 | out_bad_option: | 2521 | out_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; | |||
| 68 | enum { | 69 | enum { |
| 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 | ||
| 75 | extern int selinux_policycap_netpeer; | 78 | extern int selinux_policycap_netpeer; |
| 76 | extern int selinux_policycap_openperm; | 79 | extern int selinux_policycap_openperm; |
| 80 | extern 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 | ||
| 175 | int security_fs_use(const char *fstype, unsigned int *behavior, | 179 | int security_fs_use(struct super_block *sb); |
| 176 | u32 *sid); | ||
| 177 | 180 | ||
| 178 | int security_genfs_sid(const char *fstype, char *name, u16 sclass, | 181 | int 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 | ||
| 12 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, | 12 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, |
| 13 | struct xfrm_user_sec_ctx *sec_ctx); | 13 | struct xfrm_user_sec_ctx *uctx); |
| 14 | int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, | 14 | int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, |
| 15 | struct xfrm_sec_ctx **new_ctxp); | 15 | struct xfrm_sec_ctx **new_ctxp); |
| 16 | void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx); | 16 | void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx); |
| 17 | int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx); | 17 | int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx); |
| 18 | int selinux_xfrm_state_alloc(struct xfrm_state *x, | 18 | int 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); |
| 20 | int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, | ||
| 21 | struct xfrm_sec_ctx *polsec, u32 secid); | ||
| 20 | void selinux_xfrm_state_free(struct xfrm_state *x); | 22 | void selinux_xfrm_state_free(struct xfrm_state *x); |
| 21 | int selinux_xfrm_state_delete(struct xfrm_state *x); | 23 | int selinux_xfrm_state_delete(struct xfrm_state *x); |
| 22 | int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); | 24 | int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); |
| 23 | int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, | 25 | int 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 | */ | ||
| 29 | static 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 |
| 38 | extern atomic_t selinux_xfrm_refcount; | 30 | extern 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 | ||
| 45 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, | 37 | int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, |
| 46 | struct common_audit_data *ad); | 38 | struct common_audit_data *ad); |
| 47 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 39 | int 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); |
| 49 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 41 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); |
| 50 | 42 | ||
| 51 | static inline void selinux_xfrm_notify_policyload(void) | 43 | static 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 | ||
| 62 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 54 | static 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 | ||
| 68 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 60 | static 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 | ||
| 74 | static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) | 67 | static 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 | ||
| 85 | static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) | 79 | static 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 */ |
| 45 | static char *policycap_names[] = { | 45 | static 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 | ||
| 50 | unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; | 52 | unsigned 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 | ||
| 216 | int 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 | */ | ||
| 221 | int 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 | ||
| 118 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); | 124 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); |
| 119 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); | 125 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); |
| 120 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); | 126 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit); |
| 121 | int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); | 127 | int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); |
| 122 | int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); | 128 | int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); |
| 123 | void ebitmap_destroy(struct ebitmap *e); | 129 | void 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, | |||
| 160 | int mls_level_isvalid(struct policydb *p, struct mls_level *l) | 160 | int 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 | ||
| 188 | int mls_range_isvalid(struct policydb *p, struct mls_range *r) | 180 | int 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) | |||
| 35 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) | 35 | static 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 | ||
| 3204 | static int range_write(struct policydb *p, void *fp) | 3204 | static 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 | ||
| 73 | int selinux_policycap_netpeer; | 73 | int selinux_policycap_netpeer; |
| 74 | int selinux_policycap_openperm; | 74 | int selinux_policycap_openperm; |
| 75 | int selinux_policycap_alwaysnetwork; | ||
| 75 | 76 | ||
| 76 | static DEFINE_RWLOCK(policy_rwlock); | 77 | static 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 | ||
| 1817 | static int security_preserve_bools(struct policydb *p); | 1820 | static 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 | */ |
| 2330 | int security_fs_use( | 2331 | int 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 @@ | |||
| 56 | atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0); | 56 | atomic_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 | */ |
| 61 | static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx) | 61 | static 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 | */ |
| 71 | static inline int selinux_authorizable_xfrm(struct xfrm_state *x) | 71 | static 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 | */ |
| 80 | int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) | 80 | static 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 | |||
| 119 | err: | ||
| 120 | kfree(ctx); | ||
| 106 | return rc; | 121 | return rc; |
| 107 | } | 122 | } |
| 108 | 123 | ||
| 109 | /* | 124 | /* |
| 125 | * Free the xfrm_sec_ctx structure. | ||
| 126 | */ | ||
| 127 | static 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 | */ | ||
| 139 | static 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 | */ | ||
| 155 | int 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 | 177 | int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, | |
| 114 | int 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 | |||
| 160 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) | 216 | int 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 | */ | ||
| 197 | static 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 | |||
| 251 | not_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 | |||
| 275 | out: | 245 | out: |
| 276 | *ctxp = NULL; | 246 | *sid = sid_session; |
| 277 | kfree(ctx); | 247 | return 0; |
| 278 | out2: | ||
| 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 | */ |
| 287 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, | 253 | int 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 | */ |
| 306 | int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, | 263 | int 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 | */ |
| 328 | void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx) | 284 | void 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 | */ |
| 337 | int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) | 292 | int 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 | */ | ||
| 301 | int 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 | */ |
| 353 | int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx, | 311 | int 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 | */ |
| 369 | void selinux_xfrm_state_free(struct xfrm_state *x) | 348 | void 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 | */ |
| 378 | int selinux_xfrm_state_delete(struct xfrm_state *x) | 356 | int 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 | */ |
| 398 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 368 | int 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 | */ |
| 439 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 401 | int 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; |
| 482 | out: | 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 | } |
