aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorEric Paris <eparis@parisplace.org>2006-07-10 07:43:55 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-10 16:24:13 -0400
commit0808925ea5684a0ce25483b30e94d4f398804978 (patch)
tree62456726442d656d21bc4fa6b1339f0236f0a6e8 /security/selinux
parentc312feb2931ded0582378712727b7ea017a951bd (diff)
[PATCH] SELinux: add rootcontext= option to label root inode when mounting
Introduce a new rootcontext= option to FS mounting. This option will allow you to explicitly label the root inode of an FS being mounted before that FS or inode because visible to userspace. This was found to be useful for things like stateless linux, see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=190001 Signed-off-by: Eric Paris <eparis@parisplace.org> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c66
1 files changed, 57 insertions, 9 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7e101dbea4cb..2e8b4dfcbc74 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -320,12 +320,14 @@ enum {
320 Opt_context = 1, 320 Opt_context = 1,
321 Opt_fscontext = 2, 321 Opt_fscontext = 2,
322 Opt_defcontext = 4, 322 Opt_defcontext = 4,
323 Opt_rootcontext = 8,
323}; 324};
324 325
325static match_table_t tokens = { 326static match_table_t tokens = {
326 {Opt_context, "context=%s"}, 327 {Opt_context, "context=%s"},
327 {Opt_fscontext, "fscontext=%s"}, 328 {Opt_fscontext, "fscontext=%s"},
328 {Opt_defcontext, "defcontext=%s"}, 329 {Opt_defcontext, "defcontext=%s"},
330 {Opt_rootcontext, "rootcontext=%s"},
329}; 331};
330 332
331#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" 333#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
@@ -346,10 +348,25 @@ static int may_context_mount_sb_relabel(u32 sid,
346 return rc; 348 return rc;
347} 349}
348 350
351static int may_context_mount_inode_relabel(u32 sid,
352 struct superblock_security_struct *sbsec,
353 struct task_security_struct *tsec)
354{
355 int rc;
356 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
357 FILESYSTEM__RELABELFROM, NULL);
358 if (rc)
359 return rc;
360
361 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
362 FILESYSTEM__ASSOCIATE, NULL);
363 return rc;
364}
365
349static int try_context_mount(struct super_block *sb, void *data) 366static int try_context_mount(struct super_block *sb, void *data)
350{ 367{
351 char *context = NULL, *defcontext = NULL; 368 char *context = NULL, *defcontext = NULL;
352 char *fscontext = NULL; 369 char *fscontext = NULL, *rootcontext = NULL;
353 const char *name; 370 const char *name;
354 u32 sid; 371 u32 sid;
355 int alloc = 0, rc = 0, seen = 0; 372 int alloc = 0, rc = 0, seen = 0;
@@ -423,6 +440,22 @@ static int try_context_mount(struct super_block *sb, void *data)
423 seen |= Opt_fscontext; 440 seen |= Opt_fscontext;
424 break; 441 break;
425 442
443 case Opt_rootcontext:
444 if (seen & Opt_rootcontext) {
445 rc = -EINVAL;
446 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
447 goto out_free;
448 }
449 rootcontext = match_strdup(&args[0]);
450 if (!rootcontext) {
451 rc = -ENOMEM;
452 goto out_free;
453 }
454 if (!alloc)
455 alloc = 1;
456 seen |= Opt_rootcontext;
457 break;
458
426 case Opt_defcontext: 459 case Opt_defcontext:
427 if (sbsec->behavior != SECURITY_FS_USE_XATTR) { 460 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
428 rc = -EINVAL; 461 rc = -EINVAL;
@@ -501,6 +534,25 @@ static int try_context_mount(struct super_block *sb, void *data)
501 sbsec->behavior = SECURITY_FS_USE_MNTPOINT; 534 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
502 } 535 }
503 536
537 if (rootcontext) {
538 struct inode *inode = sb->s_root->d_inode;
539 struct inode_security_struct *isec = inode->i_security;
540 rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid);
541 if (rc) {
542 printk(KERN_WARNING "SELinux: security_context_to_sid"
543 "(%s) failed for (dev %s, type %s) errno=%d\n",
544 rootcontext, sb->s_id, name, rc);
545 goto out_free;
546 }
547
548 rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
549 if (rc)
550 goto out_free;
551
552 isec->sid = sid;
553 isec->initialized = 1;
554 }
555
504 if (defcontext) { 556 if (defcontext) {
505 rc = security_context_to_sid(defcontext, strlen(defcontext), &sid); 557 rc = security_context_to_sid(defcontext, strlen(defcontext), &sid);
506 if (rc) { 558 if (rc) {
@@ -513,13 +565,7 @@ static int try_context_mount(struct super_block *sb, void *data)
513 if (sid == sbsec->def_sid) 565 if (sid == sbsec->def_sid)
514 goto out_free; 566 goto out_free;
515 567
516 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, 568 rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
517 FILESYSTEM__RELABELFROM, NULL);
518 if (rc)
519 goto out_free;
520
521 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
522 FILESYSTEM__ASSOCIATE, NULL);
523 if (rc) 569 if (rc)
524 goto out_free; 570 goto out_free;
525 571
@@ -531,6 +577,7 @@ out_free:
531 kfree(context); 577 kfree(context);
532 kfree(defcontext); 578 kfree(defcontext);
533 kfree(fscontext); 579 kfree(fscontext);
580 kfree(rootcontext);
534 } 581 }
535out: 582out:
536 return rc; 583 return rc;
@@ -1882,7 +1929,8 @@ static inline int selinux_option(char *option, int len)
1882{ 1929{
1883 return (match_prefix("context=", sizeof("context=")-1, option, len) || 1930 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
1884 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) || 1931 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
1885 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len)); 1932 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
1933 match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
1886} 1934}
1887 1935
1888static inline void take_option(char **to, char *from, int *first, int len) 1936static inline void take_option(char **to, char *from, int *first, int len)