diff options
author | Eric Paris <eparis@parisplace.org> | 2006-07-10 07:43:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-10 16:24:13 -0400 |
commit | c312feb2931ded0582378712727b7ea017a951bd (patch) | |
tree | dd985aa4dd0b759690af9557a5170dabf589d87f /security/selinux/hooks.c | |
parent | 2ed6e34f88a0d896a6f889b00693cae0fadacfd0 (diff) |
[PATCH] SELinux: decouple fscontext/context mount options
Remove the conflict between fscontext and context mount options. If
context= is specified without fscontext it will operate just as before, if
both are specified we will use mount point labeling and all inodes will get
the label specified by context=. The superblock will be labeled with the
label of fscontext=, thus affecting operations which check the superblock
security context, such as associate permissions.
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/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 69 |
1 files changed, 54 insertions, 15 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 24caaeec8894..7e101dbea4cb 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; |
@@ -329,9 +330,26 @@ static match_table_t tokens = { | |||
329 | 330 | ||
330 | #define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" | 331 | #define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" |
331 | 332 | ||
333 | static int may_context_mount_sb_relabel(u32 sid, | ||
334 | struct superblock_security_struct *sbsec, | ||
335 | struct task_security_struct *tsec) | ||
336 | { | ||
337 | int rc; | ||
338 | |||
339 | rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | ||
340 | FILESYSTEM__RELABELFROM, NULL); | ||
341 | if (rc) | ||
342 | return rc; | ||
343 | |||
344 | rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, | ||
345 | FILESYSTEM__RELABELTO, NULL); | ||
346 | return rc; | ||
347 | } | ||
348 | |||
332 | static int try_context_mount(struct super_block *sb, void *data) | 349 | static int try_context_mount(struct super_block *sb, void *data) |
333 | { | 350 | { |
334 | char *context = NULL, *defcontext = NULL; | 351 | char *context = NULL, *defcontext = NULL; |
352 | char *fscontext = NULL; | ||
335 | const char *name; | 353 | const char *name; |
336 | u32 sid; | 354 | u32 sid; |
337 | int alloc = 0, rc = 0, seen = 0; | 355 | int alloc = 0, rc = 0, seen = 0; |
@@ -374,7 +392,7 @@ static int try_context_mount(struct super_block *sb, void *data) | |||
374 | 392 | ||
375 | switch (token) { | 393 | switch (token) { |
376 | case Opt_context: | 394 | case Opt_context: |
377 | if (seen) { | 395 | if (seen & (Opt_context|Opt_defcontext)) { |
378 | rc = -EINVAL; | 396 | rc = -EINVAL; |
379 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 397 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); |
380 | goto out_free; | 398 | goto out_free; |
@@ -390,13 +408,13 @@ static int try_context_mount(struct super_block *sb, void *data) | |||
390 | break; | 408 | break; |
391 | 409 | ||
392 | case Opt_fscontext: | 410 | case Opt_fscontext: |
393 | if (seen & (Opt_context|Opt_fscontext)) { | 411 | if (seen & Opt_fscontext) { |
394 | rc = -EINVAL; | 412 | rc = -EINVAL; |
395 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 413 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); |
396 | goto out_free; | 414 | goto out_free; |
397 | } | 415 | } |
398 | context = match_strdup(&args[0]); | 416 | fscontext = match_strdup(&args[0]); |
399 | if (!context) { | 417 | if (!fscontext) { |
400 | rc = -ENOMEM; | 418 | rc = -ENOMEM; |
401 | goto out_free; | 419 | goto out_free; |
402 | } | 420 | } |
@@ -441,29 +459,46 @@ static int try_context_mount(struct super_block *sb, void *data) | |||
441 | if (!seen) | 459 | if (!seen) |
442 | goto out; | 460 | goto out; |
443 | 461 | ||
444 | if (context) { | 462 | /* sets the context of the superblock for the fs being mounted. */ |
445 | rc = security_context_to_sid(context, strlen(context), &sid); | 463 | if (fscontext) { |
464 | rc = security_context_to_sid(fscontext, strlen(fscontext), &sid); | ||
446 | if (rc) { | 465 | if (rc) { |
447 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 466 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
448 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 467 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
449 | context, sb->s_id, name, rc); | 468 | fscontext, sb->s_id, name, rc); |
450 | goto out_free; | 469 | goto out_free; |
451 | } | 470 | } |
452 | 471 | ||
453 | rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | 472 | rc = may_context_mount_sb_relabel(sid, sbsec, tsec); |
454 | FILESYSTEM__RELABELFROM, NULL); | ||
455 | if (rc) | 473 | if (rc) |
456 | goto out_free; | 474 | goto out_free; |
457 | 475 | ||
458 | rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, | 476 | sbsec->sid = sid; |
459 | FILESYSTEM__RELABELTO, NULL); | 477 | } |
478 | |||
479 | /* | ||
480 | * Switch to using mount point labeling behavior. | ||
481 | * sets the label used on all file below the mountpoint, and will set | ||
482 | * the superblock context if not already set. | ||
483 | */ | ||
484 | if (context) { | ||
485 | rc = security_context_to_sid(context, strlen(context), &sid); | ||
486 | if (rc) { | ||
487 | printk(KERN_WARNING "SELinux: security_context_to_sid" | ||
488 | "(%s) failed for (dev %s, type %s) errno=%d\n", | ||
489 | context, sb->s_id, name, rc); | ||
490 | goto out_free; | ||
491 | } | ||
492 | |||
493 | rc = may_context_mount_sb_relabel(sid, sbsec, tsec); | ||
460 | if (rc) | 494 | if (rc) |
461 | goto out_free; | 495 | goto out_free; |
462 | 496 | ||
463 | sbsec->sid = sid; | 497 | if (!fscontext) |
498 | sbsec->sid = sid; | ||
499 | sbsec->mntpoint_sid = sid; | ||
464 | 500 | ||
465 | if (seen & Opt_context) | 501 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; |
466 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; | ||
467 | } | 502 | } |
468 | 503 | ||
469 | if (defcontext) { | 504 | if (defcontext) { |
@@ -495,6 +530,7 @@ out_free: | |||
495 | if (alloc) { | 530 | if (alloc) { |
496 | kfree(context); | 531 | kfree(context); |
497 | kfree(defcontext); | 532 | kfree(defcontext); |
533 | kfree(fscontext); | ||
498 | } | 534 | } |
499 | out: | 535 | out: |
500 | return rc; | 536 | return rc; |
@@ -876,8 +912,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
876 | goto out; | 912 | goto out; |
877 | isec->sid = sid; | 913 | isec->sid = sid; |
878 | break; | 914 | break; |
915 | case SECURITY_FS_USE_MNTPOINT: | ||
916 | isec->sid = sbsec->mntpoint_sid; | ||
917 | break; | ||
879 | default: | 918 | default: |
880 | /* Default to the fs SID. */ | 919 | /* Default to the fs superblock SID. */ |
881 | isec->sid = sbsec->sid; | 920 | isec->sid = sbsec->sid; |
882 | 921 | ||
883 | if (sbsec->proc) { | 922 | if (sbsec->proc) { |