diff options
author | David P. Quigley <dpquigl@tycho.nsa.gov> | 2009-01-16 09:22:03 -0500 |
---|---|---|
committer | James Morris <jmorris@macbook.localdomain> | 2009-01-18 17:47:06 -0500 |
commit | 11689d47f0957121920c9ec646eb5d838755853a (patch) | |
tree | 187b4179c0b7b9430bb9e62f6bba474a2d011235 /security/selinux/hooks.c | |
parent | 0d90a7ec48c704025307b129413bc62451b20ab3 (diff) |
SELinux: Add new security mount option to indicate security label support.
There is no easy way to tell if a file system supports SELinux security labeling.
Because of this a new flag is being added to the super block security structure
to indicate that the particular super block supports labeling. This flag is set
for file systems using the xattr, task, and transition labeling methods unless
that behavior is overridden by context mounts.
Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
Acked-by: Eric Paris <eparis@redhat.com>
Signed-off-by: James Morris <jmorris@macbook.localdomain>
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 473adc5f4f9a..1a9768a8b644 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -89,7 +89,7 @@ | |||
89 | #define XATTR_SELINUX_SUFFIX "selinux" | 89 | #define XATTR_SELINUX_SUFFIX "selinux" |
90 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX | 90 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX |
91 | 91 | ||
92 | #define NUM_SEL_MNT_OPTS 4 | 92 | #define NUM_SEL_MNT_OPTS 5 |
93 | 93 | ||
94 | extern unsigned int policydb_loaded_version; | 94 | extern unsigned int policydb_loaded_version; |
95 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 95 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
@@ -353,6 +353,7 @@ enum { | |||
353 | Opt_fscontext = 2, | 353 | Opt_fscontext = 2, |
354 | Opt_defcontext = 3, | 354 | Opt_defcontext = 3, |
355 | Opt_rootcontext = 4, | 355 | Opt_rootcontext = 4, |
356 | Opt_labelsupport = 5, | ||
356 | }; | 357 | }; |
357 | 358 | ||
358 | static const match_table_t tokens = { | 359 | static const match_table_t tokens = { |
@@ -360,6 +361,7 @@ static const match_table_t tokens = { | |||
360 | {Opt_fscontext, FSCONTEXT_STR "%s"}, | 361 | {Opt_fscontext, FSCONTEXT_STR "%s"}, |
361 | {Opt_defcontext, DEFCONTEXT_STR "%s"}, | 362 | {Opt_defcontext, DEFCONTEXT_STR "%s"}, |
362 | {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, | 363 | {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, |
364 | {Opt_labelsupport, LABELSUPP_STR}, | ||
363 | {Opt_error, NULL}, | 365 | {Opt_error, NULL}, |
364 | }; | 366 | }; |
365 | 367 | ||
@@ -431,7 +433,7 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
431 | } | 433 | } |
432 | } | 434 | } |
433 | 435 | ||
434 | sbsec->flags |= SE_SBINITIALIZED; | 436 | sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP); |
435 | 437 | ||
436 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 438 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
437 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", | 439 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", |
@@ -441,6 +443,12 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
441 | sb->s_id, sb->s_type->name, | 443 | sb->s_id, sb->s_type->name, |
442 | labeling_behaviors[sbsec->behavior-1]); | 444 | labeling_behaviors[sbsec->behavior-1]); |
443 | 445 | ||
446 | if (sbsec->behavior == SECURITY_FS_USE_GENFS || | ||
447 | sbsec->behavior == SECURITY_FS_USE_MNTPOINT || | ||
448 | sbsec->behavior == SECURITY_FS_USE_NONE || | ||
449 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | ||
450 | sbsec->flags &= ~SE_SBLABELSUPP; | ||
451 | |||
444 | /* Initialize the root inode. */ | 452 | /* Initialize the root inode. */ |
445 | rc = inode_doinit_with_dentry(root_inode, root); | 453 | rc = inode_doinit_with_dentry(root_inode, root); |
446 | 454 | ||
@@ -500,6 +508,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb, | |||
500 | opts->num_mnt_opts++; | 508 | opts->num_mnt_opts++; |
501 | tmp >>= 1; | 509 | tmp >>= 1; |
502 | } | 510 | } |
511 | /* Check if the Label support flag is set */ | ||
512 | if (sbsec->flags & SE_SBLABELSUPP) | ||
513 | opts->num_mnt_opts++; | ||
503 | 514 | ||
504 | opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); | 515 | opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); |
505 | if (!opts->mnt_opts) { | 516 | if (!opts->mnt_opts) { |
@@ -545,6 +556,10 @@ static int selinux_get_mnt_opts(const struct super_block *sb, | |||
545 | opts->mnt_opts[i] = context; | 556 | opts->mnt_opts[i] = context; |
546 | opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; | 557 | opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; |
547 | } | 558 | } |
559 | if (sbsec->flags & SE_SBLABELSUPP) { | ||
560 | opts->mnt_opts[i] = NULL; | ||
561 | opts->mnt_opts_flags[i++] = SE_SBLABELSUPP; | ||
562 | } | ||
548 | 563 | ||
549 | BUG_ON(i != opts->num_mnt_opts); | 564 | BUG_ON(i != opts->num_mnt_opts); |
550 | 565 | ||
@@ -635,6 +650,9 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
635 | */ | 650 | */ |
636 | for (i = 0; i < num_opts; i++) { | 651 | for (i = 0; i < num_opts; i++) { |
637 | u32 sid; | 652 | u32 sid; |
653 | |||
654 | if (flags[i] == SE_SBLABELSUPP) | ||
655 | continue; | ||
638 | rc = security_context_to_sid(mount_options[i], | 656 | rc = security_context_to_sid(mount_options[i], |
639 | strlen(mount_options[i]), &sid); | 657 | strlen(mount_options[i]), &sid); |
640 | if (rc) { | 658 | if (rc) { |
@@ -915,7 +933,8 @@ static int selinux_parse_opts_str(char *options, | |||
915 | goto out_err; | 933 | goto out_err; |
916 | } | 934 | } |
917 | break; | 935 | break; |
918 | 936 | case Opt_labelsupport: | |
937 | break; | ||
919 | default: | 938 | default: |
920 | rc = -EINVAL; | 939 | rc = -EINVAL; |
921 | printk(KERN_WARNING "SELinux: unknown mount option\n"); | 940 | printk(KERN_WARNING "SELinux: unknown mount option\n"); |
@@ -997,7 +1016,12 @@ static void selinux_write_opts(struct seq_file *m, | |||
997 | char *prefix; | 1016 | char *prefix; |
998 | 1017 | ||
999 | for (i = 0; i < opts->num_mnt_opts; i++) { | 1018 | for (i = 0; i < opts->num_mnt_opts; i++) { |
1000 | char *has_comma = strchr(opts->mnt_opts[i], ','); | 1019 | char *has_comma; |
1020 | |||
1021 | if (opts->mnt_opts[i]) | ||
1022 | has_comma = strchr(opts->mnt_opts[i], ','); | ||
1023 | else | ||
1024 | has_comma = NULL; | ||
1001 | 1025 | ||
1002 | switch (opts->mnt_opts_flags[i]) { | 1026 | switch (opts->mnt_opts_flags[i]) { |
1003 | case CONTEXT_MNT: | 1027 | case CONTEXT_MNT: |
@@ -1012,6 +1036,10 @@ static void selinux_write_opts(struct seq_file *m, | |||
1012 | case DEFCONTEXT_MNT: | 1036 | case DEFCONTEXT_MNT: |
1013 | prefix = DEFCONTEXT_STR; | 1037 | prefix = DEFCONTEXT_STR; |
1014 | break; | 1038 | break; |
1039 | case SE_SBLABELSUPP: | ||
1040 | seq_putc(m, ','); | ||
1041 | seq_puts(m, LABELSUPP_STR); | ||
1042 | continue; | ||
1015 | default: | 1043 | default: |
1016 | BUG(); | 1044 | BUG(); |
1017 | }; | 1045 | }; |
@@ -2398,7 +2426,8 @@ static inline int selinux_option(char *option, int len) | |||
2398 | return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || | 2426 | return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || |
2399 | match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || | 2427 | match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || |
2400 | match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || | 2428 | match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || |
2401 | match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len)); | 2429 | match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) || |
2430 | match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len)); | ||
2402 | } | 2431 | } |
2403 | 2432 | ||
2404 | static inline void take_option(char **to, char *from, int *first, int len) | 2433 | static inline void take_option(char **to, char *from, int *first, int len) |