aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnand Avati <avati@redhat.com>2013-04-16 18:56:19 -0400
committerEric Paris <eparis@redhat.com>2013-08-28 14:44:52 -0400
commit102aefdda4d8275ce7d7100bc16c88c74272b260 (patch)
tree808ea5ebeb04abbf5e8d9c024f261225a41420d7
parent2be4d74f2fd45460d70d4fe65cc1972ef45bf849 (diff)
selinux: consider filesystem subtype in policies
Not considering sub filesystem has the following limitation. Support for SELinux in FUSE is dependent on the particular userspace filesystem, which is identified by the subtype. For e.g, GlusterFS, a FUSE based filesystem supports SELinux (by mounting and processing FUSE requests in different threads, avoiding the mount time deadlock), whereas other FUSE based filesystems (identified by a different subtype) have the mount time deadlock. By considering the subtype of the filesytem in the SELinux policies, allows us to specify a filesystem subtype, in the following way: fs_use_xattr fuse.glusterfs gen_context(system_u:object_r:fs_t,s0); This way not all FUSE filesystems are put in the same bucket and subjected to the limitations of the other subtypes. Signed-off-by: Anand Avati <avati@redhat.com> Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--security/selinux/hooks.c40
-rw-r--r--security/selinux/ss/services.c42
2 files changed, 60 insertions, 22 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4fbf2c5f26ce..0d4408debb45 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -94,6 +94,10 @@
94#include "audit.h" 94#include "audit.h"
95#include "avc_ss.h" 95#include "avc_ss.h"
96 96
97#define SB_TYPE_FMT "%s%s%s"
98#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
99#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
100
97extern struct security_operations *security_ops; 101extern struct security_operations *security_ops;
98 102
99/* SECMARK reference count */ 103/* SECMARK reference count */
@@ -407,8 +411,8 @@ static int sb_finish_set_opts(struct super_block *sb)
407 the first boot of the SELinux kernel before we have 411 the first boot of the SELinux kernel before we have
408 assigned xattr values to the filesystem. */ 412 assigned xattr values to the filesystem. */
409 if (!root_inode->i_op->getxattr) { 413 if (!root_inode->i_op->getxattr) {
410 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " 414 printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
411 "xattr support\n", sb->s_id, sb->s_type->name); 415 "xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
412 rc = -EOPNOTSUPP; 416 rc = -EOPNOTSUPP;
413 goto out; 417 goto out;
414 } 418 }
@@ -416,22 +420,22 @@ static int sb_finish_set_opts(struct super_block *sb)
416 if (rc < 0 && rc != -ENODATA) { 420 if (rc < 0 && rc != -ENODATA) {
417 if (rc == -EOPNOTSUPP) 421 if (rc == -EOPNOTSUPP)
418 printk(KERN_WARNING "SELinux: (dev %s, type " 422 printk(KERN_WARNING "SELinux: (dev %s, type "
419 "%s) has no security xattr handler\n", 423 SB_TYPE_FMT") has no security xattr handler\n",
420 sb->s_id, sb->s_type->name); 424 sb->s_id, SB_TYPE_ARGS(sb));
421 else 425 else
422 printk(KERN_WARNING "SELinux: (dev %s, type " 426 printk(KERN_WARNING "SELinux: (dev %s, type "
423 "%s) getxattr errno %d\n", sb->s_id, 427 SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
424 sb->s_type->name, -rc); 428 SB_TYPE_ARGS(sb), -rc);
425 goto out; 429 goto out;
426 } 430 }
427 } 431 }
428 432
429 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) 433 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
430 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", 434 printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
431 sb->s_id, sb->s_type->name); 435 sb->s_id, SB_TYPE_ARGS(sb));
432 else 436 else
433 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", 437 printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
434 sb->s_id, sb->s_type->name, 438 sb->s_id, SB_TYPE_ARGS(sb),
435 labeling_behaviors[sbsec->behavior-1]); 439 labeling_behaviors[sbsec->behavior-1]);
436 440
437 sbsec->flags |= SE_SBINITIALIZED; 441 sbsec->flags |= SE_SBINITIALIZED;
@@ -589,7 +593,6 @@ static int selinux_set_mnt_opts(struct super_block *sb,
589 const struct cred *cred = current_cred(); 593 const struct cred *cred = current_cred();
590 int rc = 0, i; 594 int rc = 0, i;
591 struct superblock_security_struct *sbsec = sb->s_security; 595 struct superblock_security_struct *sbsec = sb->s_security;
592 const char *name = sb->s_type->name;
593 struct inode *inode = sbsec->sb->s_root->d_inode; 596 struct inode *inode = sbsec->sb->s_root->d_inode;
594 struct inode_security_struct *root_isec = inode->i_security; 597 struct inode_security_struct *root_isec = inode->i_security;
595 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 598 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
@@ -642,8 +645,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
642 strlen(mount_options[i]), &sid); 645 strlen(mount_options[i]), &sid);
643 if (rc) { 646 if (rc) {
644 printk(KERN_WARNING "SELinux: security_context_to_sid" 647 printk(KERN_WARNING "SELinux: security_context_to_sid"
645 "(%s) failed for (dev %s, type %s) errno=%d\n", 648 "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
646 mount_options[i], sb->s_id, name, rc); 649 mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
647 goto out; 650 goto out;
648 } 651 }
649 switch (flags[i]) { 652 switch (flags[i]) {
@@ -779,7 +782,8 @@ out:
779out_double_mount: 782out_double_mount:
780 rc = -EINVAL; 783 rc = -EINVAL;
781 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " 784 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
782 "security settings for (dev %s, type %s)\n", sb->s_id, name); 785 "security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
786 SB_TYPE_ARGS(sb));
783 goto out; 787 goto out;
784} 788}
785 789
@@ -2439,8 +2443,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
2439 rc = security_context_to_sid(mount_options[i], len, &sid); 2443 rc = security_context_to_sid(mount_options[i], len, &sid);
2440 if (rc) { 2444 if (rc) {
2441 printk(KERN_WARNING "SELinux: security_context_to_sid" 2445 printk(KERN_WARNING "SELinux: security_context_to_sid"
2442 "(%s) failed for (dev %s, type %s) errno=%d\n", 2446 "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
2443 mount_options[i], sb->s_id, sb->s_type->name, rc); 2447 mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
2444 goto out_free_opts; 2448 goto out_free_opts;
2445 } 2449 }
2446 rc = -EINVAL; 2450 rc = -EINVAL;
@@ -2478,8 +2482,8 @@ out_free_secdata:
2478 return rc; 2482 return rc;
2479out_bad_option: 2483out_bad_option:
2480 printk(KERN_WARNING "SELinux: unable to change security options " 2484 printk(KERN_WARNING "SELinux: unable to change security options "
2481 "during remount (dev %s, type=%s)\n", sb->s_id, 2485 "during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
2482 sb->s_type->name); 2486 SB_TYPE_ARGS(sb));
2483 goto out_free_opts; 2487 goto out_free_opts;
2484} 2488}
2485 2489
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d106733ad987..ee470a0b5c27 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2334,16 +2334,50 @@ int security_fs_use(struct super_block *sb)
2334 struct ocontext *c; 2334 struct ocontext *c;
2335 struct superblock_security_struct *sbsec = sb->s_security; 2335 struct superblock_security_struct *sbsec = sb->s_security;
2336 const char *fstype = sb->s_type->name; 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 sbsec->behavior = c->v.behavior; 2382 sbsec->behavior = c->v.behavior;
2349 if (!c->sid[0]) { 2383 if (!c->sid[0]) {