aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 15:09:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 15:09:43 -0400
commitbe0c5d8c0bb0023e11f5c6d38e90f7b0f24edb64 (patch)
tree6d7a6e290f8ed2f2ca250965a8debdd9f02a9cc9 /security/selinux/hooks.c
parent1f792dd1765e6f047ecd2d5f6a81f025b50d471a (diff)
parent959d921f5eb8878ea16049a7f6e9bcbb6dfbcb88 (diff)
Merge tag 'nfs-for-3.11-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust: "Feature highlights include: - Add basic client support for NFSv4.2 - Add basic client support for Labeled NFS (selinux for NFSv4.2) - Fix the use of credentials in NFSv4.1 stateful operations, and add support for NFSv4.1 state protection. Bugfix highlights: - Fix another NFSv4 open state recovery race - Fix an NFSv4.1 back channel session regression - Various rpc_pipefs races - Fix another issue with NFSv3 auth negotiation Please note that Labeled NFS does require some additional support from the security subsystem. The relevant changesets have all been reviewed and acked by James Morris." * tag 'nfs-for-3.11-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (54 commits) NFS: Set NFS_CS_MIGRATION for NFSv4 mounts NFSv4.1 Refactor nfs4_init_session and nfs4_init_channel_attrs nfs: have NFSv3 try server-specified auth flavors in turn nfs: have nfs_mount fake up a auth_flavs list when the server didn't provide it nfs: move server_authlist into nfs_try_mount_request nfs: refactor "need_mount" code out of nfs_try_mount SUNRPC: PipeFS MOUNT notification optimization for dying clients SUNRPC: split client creation routine into setup and registration SUNRPC: fix races on PipeFS UMOUNT notifications SUNRPC: fix races on PipeFS MOUNT notifications NFSv4.1 use pnfs_device maxcount for the objectlayout gdia_maxcount NFSv4.1 use pnfs_device maxcount for the blocklayout gdia_maxcount NFSv4.1 Fix gdia_maxcount calculation to fit in ca_maxresponsesize NFS: Improve legacy idmapping fallback NFSv4.1 end back channel session draining NFS: Apply v4.1 capabilities to v4.2 NFSv4.1: Clean up layout segment comparison helper names NFSv4.1: layout segment comparison helpers should take 'const' parameters NFSv4: Move the DNS resolver into the NFSv4 module rpc_pipefs: only set rpc_dentry_ops if d_op isn't already set ...
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c92
1 files changed, 81 insertions, 11 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index db1fca990a24..c956390a9136 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
287static const char *labeling_behaviors[6] = { 288static 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
296static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); 298static 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 */
554static int selinux_set_mnt_opts(struct super_block *sb, 556static 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
982out: 1005out:
983 rc = selinux_set_mnt_opts(sb, &opts); 1006 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
984 1007
985out_err: 1008out_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;
@@ -2527,6 +2552,40 @@ static void selinux_inode_free_security(struct inode *inode)
2527 inode_free_security(inode); 2552 inode_free_security(inode);
2528} 2553}
2529 2554
2555static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2556 struct qstr *name, void **ctx,
2557 u32 *ctxlen)
2558{
2559 const struct cred *cred = current_cred();
2560 struct task_security_struct *tsec;
2561 struct inode_security_struct *dsec;
2562 struct superblock_security_struct *sbsec;
2563 struct inode *dir = dentry->d_parent->d_inode;
2564 u32 newsid;
2565 int rc;
2566
2567 tsec = cred->security;
2568 dsec = dir->i_security;
2569 sbsec = dir->i_sb->s_security;
2570
2571 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2572 newsid = tsec->create_sid;
2573 } else {
2574 rc = security_transition_sid(tsec->sid, dsec->sid,
2575 inode_mode_to_security_class(mode),
2576 name,
2577 &newsid);
2578 if (rc) {
2579 printk(KERN_WARNING
2580 "%s: security_transition_sid failed, rc=%d\n",
2581 __func__, -rc);
2582 return rc;
2583 }
2584 }
2585
2586 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2587}
2588
2530static int selinux_inode_init_security(struct inode *inode, struct inode *dir, 2589static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2531 const struct qstr *qstr, char **name, 2590 const struct qstr *qstr, char **name,
2532 void **value, size_t *len) 2591 void **value, size_t *len)
@@ -2861,7 +2920,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
2861 return; 2920 return;
2862 } 2921 }
2863 2922
2923 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2864 isec->sid = newsid; 2924 isec->sid = newsid;
2925 isec->initialized = 1;
2926
2865 return; 2927 return;
2866} 2928}
2867 2929
@@ -2949,6 +3011,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
2949 if (rc) 3011 if (rc)
2950 return rc; 3012 return rc;
2951 3013
3014 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2952 isec->sid = newsid; 3015 isec->sid = newsid;
2953 isec->initialized = 1; 3016 isec->initialized = 1;
2954 return 0; 3017 return 0;
@@ -5432,6 +5495,11 @@ abort_change:
5432 return error; 5495 return error;
5433} 5496}
5434 5497
5498static int selinux_ismaclabel(const char *name)
5499{
5500 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5501}
5502
5435static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) 5503static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5436{ 5504{
5437 return security_sid_to_context(secid, secdata, seclen); 5505 return security_sid_to_context(secid, secdata, seclen);
@@ -5574,6 +5642,7 @@ static struct security_operations selinux_ops = {
5574 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, 5642 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
5575 .sb_parse_opts_str = selinux_parse_opts_str, 5643 .sb_parse_opts_str = selinux_parse_opts_str,
5576 5644
5645 .dentry_init_security = selinux_dentry_init_security,
5577 5646
5578 .inode_alloc_security = selinux_inode_alloc_security, 5647 .inode_alloc_security = selinux_inode_alloc_security,
5579 .inode_free_security = selinux_inode_free_security, 5648 .inode_free_security = selinux_inode_free_security,
@@ -5669,6 +5738,7 @@ static struct security_operations selinux_ops = {
5669 .getprocattr = selinux_getprocattr, 5738 .getprocattr = selinux_getprocattr,
5670 .setprocattr = selinux_setprocattr, 5739 .setprocattr = selinux_setprocattr,
5671 5740
5741 .ismaclabel = selinux_ismaclabel,
5672 .secid_to_secctx = selinux_secid_to_secctx, 5742 .secid_to_secctx = selinux_secid_to_secctx,
5673 .secctx_to_secid = selinux_secctx_to_secid, 5743 .secctx_to_secid = selinux_secctx_to_secid,
5674 .release_secctx = selinux_release_secctx, 5744 .release_secctx = selinux_release_secctx,