aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-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)