aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-07-31 20:37:25 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-31 20:37:25 -0400
commit57cad8084e0837e0f2c97da789ec9b3f36809be9 (patch)
treee9c790afb4286f78cb08d9664f58baa7e876fe55 /security
parentcb18bd40030c879cd93fef02fd579f74dbab473d (diff)
parent49b1e3ea19b1c95c2f012b8331ffb3b169e4c042 (diff)
Merge branch 'merge'
Diffstat (limited to 'security')
-rw-r--r--security/selinux/hooks.c135
-rw-r--r--security/selinux/include/objsec.h3
-rw-r--r--security/selinux/ss/policydb.c12
-rw-r--r--security/selinux/ss/services.c4
4 files changed, 127 insertions, 27 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 24caaeec8894..a91c961ba38b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -246,6 +246,7 @@ static int superblock_alloc_security(struct super_block *sb)
246 sbsec->sb = sb; 246 sbsec->sb = sb;
247 sbsec->sid = SECINITSID_UNLABELED; 247 sbsec->sid = SECINITSID_UNLABELED;
248 sbsec->def_sid = SECINITSID_FILE; 248 sbsec->def_sid = SECINITSID_FILE;
249 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
249 sb->s_security = sbsec; 250 sb->s_security = sbsec;
250 251
251 return 0; 252 return 0;
@@ -319,19 +320,53 @@ enum {
319 Opt_context = 1, 320 Opt_context = 1,
320 Opt_fscontext = 2, 321 Opt_fscontext = 2,
321 Opt_defcontext = 4, 322 Opt_defcontext = 4,
323 Opt_rootcontext = 8,
322}; 324};
323 325
324static match_table_t tokens = { 326static match_table_t tokens = {
325 {Opt_context, "context=%s"}, 327 {Opt_context, "context=%s"},
326 {Opt_fscontext, "fscontext=%s"}, 328 {Opt_fscontext, "fscontext=%s"},
327 {Opt_defcontext, "defcontext=%s"}, 329 {Opt_defcontext, "defcontext=%s"},
330 {Opt_rootcontext, "rootcontext=%s"},
328}; 331};
329 332
330#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"
331 334
335static int may_context_mount_sb_relabel(u32 sid,
336 struct superblock_security_struct *sbsec,
337 struct task_security_struct *tsec)
338{
339 int rc;
340
341 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
342 FILESYSTEM__RELABELFROM, NULL);
343 if (rc)
344 return rc;
345
346 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
347 FILESYSTEM__RELABELTO, NULL);
348 return rc;
349}
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
332static int try_context_mount(struct super_block *sb, void *data) 366static int try_context_mount(struct super_block *sb, void *data)
333{ 367{
334 char *context = NULL, *defcontext = NULL; 368 char *context = NULL, *defcontext = NULL;
369 char *fscontext = NULL, *rootcontext = NULL;
335 const char *name; 370 const char *name;
336 u32 sid; 371 u32 sid;
337 int alloc = 0, rc = 0, seen = 0; 372 int alloc = 0, rc = 0, seen = 0;
@@ -374,7 +409,7 @@ static int try_context_mount(struct super_block *sb, void *data)
374 409
375 switch (token) { 410 switch (token) {
376 case Opt_context: 411 case Opt_context:
377 if (seen) { 412 if (seen & (Opt_context|Opt_defcontext)) {
378 rc = -EINVAL; 413 rc = -EINVAL;
379 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); 414 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
380 goto out_free; 415 goto out_free;
@@ -390,13 +425,13 @@ static int try_context_mount(struct super_block *sb, void *data)
390 break; 425 break;
391 426
392 case Opt_fscontext: 427 case Opt_fscontext:
393 if (seen & (Opt_context|Opt_fscontext)) { 428 if (seen & Opt_fscontext) {
394 rc = -EINVAL; 429 rc = -EINVAL;
395 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); 430 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
396 goto out_free; 431 goto out_free;
397 } 432 }
398 context = match_strdup(&args[0]); 433 fscontext = match_strdup(&args[0]);
399 if (!context) { 434 if (!fscontext) {
400 rc = -ENOMEM; 435 rc = -ENOMEM;
401 goto out_free; 436 goto out_free;
402 } 437 }
@@ -405,6 +440,22 @@ static int try_context_mount(struct super_block *sb, void *data)
405 seen |= Opt_fscontext; 440 seen |= Opt_fscontext;
406 break; 441 break;
407 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
408 case Opt_defcontext: 459 case Opt_defcontext:
409 if (sbsec->behavior != SECURITY_FS_USE_XATTR) { 460 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
410 rc = -EINVAL; 461 rc = -EINVAL;
@@ -441,6 +492,28 @@ static int try_context_mount(struct super_block *sb, void *data)
441 if (!seen) 492 if (!seen)
442 goto out; 493 goto out;
443 494
495 /* sets the context of the superblock for the fs being mounted. */
496 if (fscontext) {
497 rc = security_context_to_sid(fscontext, strlen(fscontext), &sid);
498 if (rc) {
499 printk(KERN_WARNING "SELinux: security_context_to_sid"
500 "(%s) failed for (dev %s, type %s) errno=%d\n",
501 fscontext, sb->s_id, name, rc);
502 goto out_free;
503 }
504
505 rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
506 if (rc)
507 goto out_free;
508
509 sbsec->sid = sid;
510 }
511
512 /*
513 * Switch to using mount point labeling behavior.
514 * sets the label used on all file below the mountpoint, and will set
515 * the superblock context if not already set.
516 */
444 if (context) { 517 if (context) {
445 rc = security_context_to_sid(context, strlen(context), &sid); 518 rc = security_context_to_sid(context, strlen(context), &sid);
446 if (rc) { 519 if (rc) {
@@ -450,20 +523,38 @@ static int try_context_mount(struct super_block *sb, void *data)
450 goto out_free; 523 goto out_free;
451 } 524 }
452 525
453 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, 526 if (!fscontext) {
454 FILESYSTEM__RELABELFROM, NULL); 527 rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
455 if (rc) 528 if (rc)
529 goto out_free;
530 sbsec->sid = sid;
531 } else {
532 rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
533 if (rc)
534 goto out_free;
535 }
536 sbsec->mntpoint_sid = sid;
537
538 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
539 }
540
541 if (rootcontext) {
542 struct inode *inode = sb->s_root->d_inode;
543 struct inode_security_struct *isec = inode->i_security;
544 rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid);
545 if (rc) {
546 printk(KERN_WARNING "SELinux: security_context_to_sid"
547 "(%s) failed for (dev %s, type %s) errno=%d\n",
548 rootcontext, sb->s_id, name, rc);
456 goto out_free; 549 goto out_free;
550 }
457 551
458 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, 552 rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
459 FILESYSTEM__RELABELTO, NULL);
460 if (rc) 553 if (rc)
461 goto out_free; 554 goto out_free;
462 555
463 sbsec->sid = sid; 556 isec->sid = sid;
464 557 isec->initialized = 1;
465 if (seen & Opt_context)
466 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
467 } 558 }
468 559
469 if (defcontext) { 560 if (defcontext) {
@@ -478,13 +569,7 @@ static int try_context_mount(struct super_block *sb, void *data)
478 if (sid == sbsec->def_sid) 569 if (sid == sbsec->def_sid)
479 goto out_free; 570 goto out_free;
480 571
481 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, 572 rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
482 FILESYSTEM__RELABELFROM, NULL);
483 if (rc)
484 goto out_free;
485
486 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
487 FILESYSTEM__ASSOCIATE, NULL);
488 if (rc) 573 if (rc)
489 goto out_free; 574 goto out_free;
490 575
@@ -495,6 +580,8 @@ out_free:
495 if (alloc) { 580 if (alloc) {
496 kfree(context); 581 kfree(context);
497 kfree(defcontext); 582 kfree(defcontext);
583 kfree(fscontext);
584 kfree(rootcontext);
498 } 585 }
499out: 586out:
500 return rc; 587 return rc;
@@ -876,8 +963,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
876 goto out; 963 goto out;
877 isec->sid = sid; 964 isec->sid = sid;
878 break; 965 break;
966 case SECURITY_FS_USE_MNTPOINT:
967 isec->sid = sbsec->mntpoint_sid;
968 break;
879 default: 969 default:
880 /* Default to the fs SID. */ 970 /* Default to the fs superblock SID. */
881 isec->sid = sbsec->sid; 971 isec->sid = sbsec->sid;
882 972
883 if (sbsec->proc) { 973 if (sbsec->proc) {
@@ -1843,7 +1933,8 @@ static inline int selinux_option(char *option, int len)
1843{ 1933{
1844 return (match_prefix("context=", sizeof("context=")-1, option, len) || 1934 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
1845 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) || 1935 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
1846 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len)); 1936 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
1937 match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
1847} 1938}
1848 1939
1849static inline void take_option(char **to, char *from, int *first, int len) 1940static inline void take_option(char **to, char *from, int *first, int len)
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index cf54a304169a..940178865fc7 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -57,8 +57,9 @@ struct file_security_struct {
57struct superblock_security_struct { 57struct superblock_security_struct {
58 struct super_block *sb; /* back pointer to sb object */ 58 struct super_block *sb; /* back pointer to sb object */
59 struct list_head list; /* list of superblock_security_struct */ 59 struct list_head list; /* list of superblock_security_struct */
60 u32 sid; /* SID of file system */ 60 u32 sid; /* SID of file system superblock */
61 u32 def_sid; /* default SID for labeling */ 61 u32 def_sid; /* default SID for labeling */
62 u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */
62 unsigned int behavior; /* labeling behavior */ 63 unsigned int behavior; /* labeling behavior */
63 unsigned char initialized; /* initialization flag */ 64 unsigned char initialized; /* initialization flag */
64 unsigned char proc; /* proc fs */ 65 unsigned char proc; /* proc fs */
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0111990ba837..f03960e697ce 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -644,10 +644,18 @@ void policydb_destroy(struct policydb *p)
644 kfree(lra); 644 kfree(lra);
645 645
646 for (rt = p->range_tr; rt; rt = rt -> next) { 646 for (rt = p->range_tr; rt; rt = rt -> next) {
647 kfree(lrt); 647 if (lrt) {
648 ebitmap_destroy(&lrt->range.level[0].cat);
649 ebitmap_destroy(&lrt->range.level[1].cat);
650 kfree(lrt);
651 }
648 lrt = rt; 652 lrt = rt;
649 } 653 }
650 kfree(lrt); 654 if (lrt) {
655 ebitmap_destroy(&lrt->range.level[0].cat);
656 ebitmap_destroy(&lrt->range.level[1].cat);
657 kfree(lrt);
658 }
651 659
652 if (p->type_attr_map) { 660 if (p->type_attr_map) {
653 for (i = 0; i < p->p_types.nprim; i++) 661 for (i = 0; i < p->p_types.nprim; i++)
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d2e80e62ff0c..85e429884393 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -833,6 +833,8 @@ static int security_compute_sid(u32 ssid,
833 goto out; 833 goto out;
834 } 834 }
835 835
836 context_init(&newcontext);
837
836 POLICY_RDLOCK; 838 POLICY_RDLOCK;
837 839
838 scontext = sidtab_search(&sidtab, ssid); 840 scontext = sidtab_search(&sidtab, ssid);
@@ -850,8 +852,6 @@ static int security_compute_sid(u32 ssid,
850 goto out_unlock; 852 goto out_unlock;
851 } 853 }
852 854
853 context_init(&newcontext);
854
855 /* Set the user identity. */ 855 /* Set the user identity. */
856 switch (specified) { 856 switch (specified) {
857 case AVTAB_TRANSITION: 857 case AVTAB_TRANSITION: