diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-06-28 16:29:51 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-06-28 16:29:51 -0400 |
commit | 959d921f5eb8878ea16049a7f6e9bcbb6dfbcb88 (patch) | |
tree | 83fb4d2756fab97f508b5dccaac7578ba63a76e0 /security/selinux/hooks.c | |
parent | f112bb48994e56868870a080773c392f774fa9a2 (diff) | |
parent | 7017310ad737880d8520a7fc7e25a26b2e7e37f0 (diff) |
Merge branch 'labeled-nfs' into linux-next
* labeled-nfs:
NFS: Apply v4.1 capabilities to v4.2
NFS: Add in v4.2 callback operation
NFS: Make callbacks minor version generic
Kconfig: Add Kconfig entry for Labeled NFS V4 client
NFS: Extend NFS xattr handlers to accept the security namespace
NFS: Client implementation of Labeled-NFS
NFS: Add label lifecycle management
NFS:Add labels to client function prototypes
NFSv4: Extend fattr bitmaps to support all 3 words
NFSv4: Introduce new label structure
NFSv4: Add label recommended attribute and NFSv4 flags
NFSv4.2: Added NFS v4.2 support to the NFS client
SELinux: Add new labeling type native labels
LSM: Add flags field to security_sb_set_mnt_opts for in kernel mount data.
Security: Add Hook to test if the particular xattr is part of a MAC model.
Security: Add hook to calculate context based on a negative dentry.
NFS: Add NFSv4.2 protocol constants
Conflicts:
fs/nfs/nfs4proc.c
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 92 |
1 files changed, 81 insertions, 11 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5c6f2cd2d095..9f8e9b2e717a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <linux/syslog.h> | 81 | #include <linux/syslog.h> |
82 | #include <linux/user_namespace.h> | 82 | #include <linux/user_namespace.h> |
83 | #include <linux/export.h> | 83 | #include <linux/export.h> |
84 | #include <linux/security.h> | ||
84 | #include <linux/msg.h> | 85 | #include <linux/msg.h> |
85 | #include <linux/shm.h> | 86 | #include <linux/shm.h> |
86 | 87 | ||
@@ -284,13 +285,14 @@ static void superblock_free_security(struct super_block *sb) | |||
284 | 285 | ||
285 | /* The file system's label must be initialized prior to use. */ | 286 | /* The file system's label must be initialized prior to use. */ |
286 | 287 | ||
287 | static const char *labeling_behaviors[6] = { | 288 | static const char *labeling_behaviors[7] = { |
288 | "uses xattr", | 289 | "uses xattr", |
289 | "uses transition SIDs", | 290 | "uses transition SIDs", |
290 | "uses task SIDs", | 291 | "uses task SIDs", |
291 | "uses genfs_contexts", | 292 | "uses genfs_contexts", |
292 | "not configured for labeling", | 293 | "not configured for labeling", |
293 | "uses mountpoint labeling", | 294 | "uses mountpoint labeling", |
295 | "uses native labeling", | ||
294 | }; | 296 | }; |
295 | 297 | ||
296 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); | 298 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); |
@@ -552,7 +554,9 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, | |||
552 | * labeling information. | 554 | * labeling information. |
553 | */ | 555 | */ |
554 | static int selinux_set_mnt_opts(struct super_block *sb, | 556 | static int selinux_set_mnt_opts(struct super_block *sb, |
555 | struct security_mnt_opts *opts) | 557 | struct security_mnt_opts *opts, |
558 | unsigned long kern_flags, | ||
559 | unsigned long *set_kern_flags) | ||
556 | { | 560 | { |
557 | const struct cred *cred = current_cred(); | 561 | const struct cred *cred = current_cred(); |
558 | int rc = 0, i; | 562 | int rc = 0, i; |
@@ -580,6 +584,12 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
580 | "before the security server is initialized\n"); | 584 | "before the security server is initialized\n"); |
581 | goto out; | 585 | goto out; |
582 | } | 586 | } |
587 | if (kern_flags && !set_kern_flags) { | ||
588 | /* Specifying internal flags without providing a place to | ||
589 | * place the results is not allowed */ | ||
590 | rc = -EINVAL; | ||
591 | goto out; | ||
592 | } | ||
583 | 593 | ||
584 | /* | 594 | /* |
585 | * Binary mount data FS will come through this function twice. Once | 595 | * Binary mount data FS will come through this function twice. Once |
@@ -670,14 +680,21 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
670 | if (strcmp(sb->s_type->name, "proc") == 0) | 680 | if (strcmp(sb->s_type->name, "proc") == 0) |
671 | sbsec->flags |= SE_SBPROC; | 681 | sbsec->flags |= SE_SBPROC; |
672 | 682 | ||
673 | /* Determine the labeling behavior to use for this filesystem type. */ | 683 | if (!sbsec->behavior) { |
674 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); | 684 | /* |
675 | if (rc) { | 685 | * Determine the labeling behavior to use for this |
676 | printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", | 686 | * filesystem type. |
677 | __func__, sb->s_type->name, rc); | 687 | */ |
678 | goto out; | 688 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? |
689 | "proc" : sb->s_type->name, | ||
690 | &sbsec->behavior, &sbsec->sid); | ||
691 | if (rc) { | ||
692 | printk(KERN_WARNING | ||
693 | "%s: security_fs_use(%s) returned %d\n", | ||
694 | __func__, sb->s_type->name, rc); | ||
695 | goto out; | ||
696 | } | ||
679 | } | 697 | } |
680 | |||
681 | /* sets the context of the superblock for the fs being mounted. */ | 698 | /* sets the context of the superblock for the fs being mounted. */ |
682 | if (fscontext_sid) { | 699 | if (fscontext_sid) { |
683 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); | 700 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); |
@@ -692,6 +709,11 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
692 | * sets the label used on all file below the mountpoint, and will set | 709 | * sets the label used on all file below the mountpoint, and will set |
693 | * the superblock context if not already set. | 710 | * the superblock context if not already set. |
694 | */ | 711 | */ |
712 | if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) { | ||
713 | sbsec->behavior = SECURITY_FS_USE_NATIVE; | ||
714 | *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS; | ||
715 | } | ||
716 | |||
695 | if (context_sid) { | 717 | if (context_sid) { |
696 | if (!fscontext_sid) { | 718 | if (!fscontext_sid) { |
697 | rc = may_context_mount_sb_relabel(context_sid, sbsec, | 719 | rc = may_context_mount_sb_relabel(context_sid, sbsec, |
@@ -723,7 +745,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
723 | } | 745 | } |
724 | 746 | ||
725 | if (defcontext_sid) { | 747 | if (defcontext_sid) { |
726 | if (sbsec->behavior != SECURITY_FS_USE_XATTR) { | 748 | if (sbsec->behavior != SECURITY_FS_USE_XATTR && |
749 | sbsec->behavior != SECURITY_FS_USE_NATIVE) { | ||
727 | rc = -EINVAL; | 750 | rc = -EINVAL; |
728 | printk(KERN_WARNING "SELinux: defcontext option is " | 751 | printk(KERN_WARNING "SELinux: defcontext option is " |
729 | "invalid for this filesystem type\n"); | 752 | "invalid for this filesystem type\n"); |
@@ -980,7 +1003,7 @@ static int superblock_doinit(struct super_block *sb, void *data) | |||
980 | goto out_err; | 1003 | goto out_err; |
981 | 1004 | ||
982 | out: | 1005 | out: |
983 | rc = selinux_set_mnt_opts(sb, &opts); | 1006 | rc = selinux_set_mnt_opts(sb, &opts, 0, NULL); |
984 | 1007 | ||
985 | out_err: | 1008 | out_err: |
986 | security_free_mnt_opts(&opts); | 1009 | security_free_mnt_opts(&opts); |
@@ -1222,6 +1245,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1222 | } | 1245 | } |
1223 | 1246 | ||
1224 | switch (sbsec->behavior) { | 1247 | switch (sbsec->behavior) { |
1248 | case SECURITY_FS_USE_NATIVE: | ||
1249 | break; | ||
1225 | case SECURITY_FS_USE_XATTR: | 1250 | case SECURITY_FS_USE_XATTR: |
1226 | if (!inode->i_op->getxattr) { | 1251 | if (!inode->i_op->getxattr) { |
1227 | isec->sid = sbsec->def_sid; | 1252 | isec->sid = sbsec->def_sid; |
@@ -2515,6 +2540,40 @@ static void selinux_inode_free_security(struct inode *inode) | |||
2515 | inode_free_security(inode); | 2540 | inode_free_security(inode); |
2516 | } | 2541 | } |
2517 | 2542 | ||
2543 | static int selinux_dentry_init_security(struct dentry *dentry, int mode, | ||
2544 | struct qstr *name, void **ctx, | ||
2545 | u32 *ctxlen) | ||
2546 | { | ||
2547 | const struct cred *cred = current_cred(); | ||
2548 | struct task_security_struct *tsec; | ||
2549 | struct inode_security_struct *dsec; | ||
2550 | struct superblock_security_struct *sbsec; | ||
2551 | struct inode *dir = dentry->d_parent->d_inode; | ||
2552 | u32 newsid; | ||
2553 | int rc; | ||
2554 | |||
2555 | tsec = cred->security; | ||
2556 | dsec = dir->i_security; | ||
2557 | sbsec = dir->i_sb->s_security; | ||
2558 | |||
2559 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
2560 | newsid = tsec->create_sid; | ||
2561 | } else { | ||
2562 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
2563 | inode_mode_to_security_class(mode), | ||
2564 | name, | ||
2565 | &newsid); | ||
2566 | if (rc) { | ||
2567 | printk(KERN_WARNING | ||
2568 | "%s: security_transition_sid failed, rc=%d\n", | ||
2569 | __func__, -rc); | ||
2570 | return rc; | ||
2571 | } | ||
2572 | } | ||
2573 | |||
2574 | return security_sid_to_context(newsid, (char **)ctx, ctxlen); | ||
2575 | } | ||
2576 | |||
2518 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | 2577 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
2519 | const struct qstr *qstr, char **name, | 2578 | const struct qstr *qstr, char **name, |
2520 | void **value, size_t *len) | 2579 | void **value, size_t *len) |
@@ -2849,7 +2908,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
2849 | return; | 2908 | return; |
2850 | } | 2909 | } |
2851 | 2910 | ||
2911 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2852 | isec->sid = newsid; | 2912 | isec->sid = newsid; |
2913 | isec->initialized = 1; | ||
2914 | |||
2853 | return; | 2915 | return; |
2854 | } | 2916 | } |
2855 | 2917 | ||
@@ -2937,6 +2999,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
2937 | if (rc) | 2999 | if (rc) |
2938 | return rc; | 3000 | return rc; |
2939 | 3001 | ||
3002 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2940 | isec->sid = newsid; | 3003 | isec->sid = newsid; |
2941 | isec->initialized = 1; | 3004 | isec->initialized = 1; |
2942 | return 0; | 3005 | return 0; |
@@ -5420,6 +5483,11 @@ abort_change: | |||
5420 | return error; | 5483 | return error; |
5421 | } | 5484 | } |
5422 | 5485 | ||
5486 | static int selinux_ismaclabel(const char *name) | ||
5487 | { | ||
5488 | return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0); | ||
5489 | } | ||
5490 | |||
5423 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 5491 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
5424 | { | 5492 | { |
5425 | return security_sid_to_context(secid, secdata, seclen); | 5493 | return security_sid_to_context(secid, secdata, seclen); |
@@ -5562,6 +5630,7 @@ static struct security_operations selinux_ops = { | |||
5562 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, | 5630 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, |
5563 | .sb_parse_opts_str = selinux_parse_opts_str, | 5631 | .sb_parse_opts_str = selinux_parse_opts_str, |
5564 | 5632 | ||
5633 | .dentry_init_security = selinux_dentry_init_security, | ||
5565 | 5634 | ||
5566 | .inode_alloc_security = selinux_inode_alloc_security, | 5635 | .inode_alloc_security = selinux_inode_alloc_security, |
5567 | .inode_free_security = selinux_inode_free_security, | 5636 | .inode_free_security = selinux_inode_free_security, |
@@ -5657,6 +5726,7 @@ static struct security_operations selinux_ops = { | |||
5657 | .getprocattr = selinux_getprocattr, | 5726 | .getprocattr = selinux_getprocattr, |
5658 | .setprocattr = selinux_setprocattr, | 5727 | .setprocattr = selinux_setprocattr, |
5659 | 5728 | ||
5729 | .ismaclabel = selinux_ismaclabel, | ||
5660 | .secid_to_secctx = selinux_secid_to_secctx, | 5730 | .secid_to_secctx = selinux_secid_to_secctx, |
5661 | .secctx_to_secid = selinux_secctx_to_secid, | 5731 | .secctx_to_secid = selinux_secctx_to_secid, |
5662 | .release_secctx = selinux_release_secctx, | 5732 | .release_secctx = selinux_release_secctx, |