diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 11cf2feb27b3..caf7ca7abfc1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -433,6 +433,19 @@ static void superblock_free_security(struct super_block *sb) | |||
433 | kfree(sbsec); | 433 | kfree(sbsec); |
434 | } | 434 | } |
435 | 435 | ||
436 | static void selinux_free_mnt_opts(void *mnt_opts) | ||
437 | { | ||
438 | struct security_mnt_opts *opts = mnt_opts; | ||
439 | int i; | ||
440 | |||
441 | if (opts->mnt_opts) | ||
442 | for (i = 0; i < opts->num_mnt_opts; i++) | ||
443 | kfree(opts->mnt_opts[i]); | ||
444 | kfree(opts->mnt_opts); | ||
445 | kfree(opts->mnt_opts_flags); | ||
446 | kfree(opts); | ||
447 | } | ||
448 | |||
436 | static inline int inode_doinit(struct inode *inode) | 449 | static inline int inode_doinit(struct inode *inode) |
437 | { | 450 | { |
438 | return inode_doinit_with_dentry(inode, NULL); | 451 | return inode_doinit_with_dentry(inode, NULL); |
@@ -616,7 +629,7 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, | |||
616 | * labeling information. | 629 | * labeling information. |
617 | */ | 630 | */ |
618 | static int selinux_set_mnt_opts(struct super_block *sb, | 631 | static int selinux_set_mnt_opts(struct super_block *sb, |
619 | struct security_mnt_opts *opts, | 632 | void *mnt_opts, |
620 | unsigned long kern_flags, | 633 | unsigned long kern_flags, |
621 | unsigned long *set_kern_flags) | 634 | unsigned long *set_kern_flags) |
622 | { | 635 | { |
@@ -628,9 +641,10 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
628 | struct inode_security_struct *root_isec; | 641 | struct inode_security_struct *root_isec; |
629 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; | 642 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; |
630 | u32 defcontext_sid = 0; | 643 | u32 defcontext_sid = 0; |
631 | char **mount_options = opts->mnt_opts; | 644 | struct security_mnt_opts *opts = mnt_opts; |
632 | int *flags = opts->mnt_opts_flags; | 645 | char **mount_options = opts ? opts->mnt_opts : NULL; |
633 | int num_opts = opts->num_mnt_opts; | 646 | int *flags = opts ? opts->mnt_opts_flags : NULL; |
647 | int num_opts = opts ? opts->num_mnt_opts : 0; | ||
634 | 648 | ||
635 | mutex_lock(&sbsec->lock); | 649 | mutex_lock(&sbsec->lock); |
636 | 650 | ||
@@ -982,12 +996,20 @@ out: | |||
982 | } | 996 | } |
983 | 997 | ||
984 | static int selinux_parse_opts_str(char *options, | 998 | static int selinux_parse_opts_str(char *options, |
985 | struct security_mnt_opts *opts) | 999 | void **mnt_opts) |
986 | { | 1000 | { |
987 | char *p; | 1001 | char *p; |
988 | char *context = NULL, *defcontext = NULL; | 1002 | char *context = NULL, *defcontext = NULL; |
989 | char *fscontext = NULL, *rootcontext = NULL; | 1003 | char *fscontext = NULL, *rootcontext = NULL; |
990 | int rc, num_mnt_opts = 0; | 1004 | int rc, num_mnt_opts = 0; |
1005 | struct security_mnt_opts *opts = *mnt_opts; | ||
1006 | |||
1007 | if (!opts) { | ||
1008 | opts = kzalloc(sizeof(struct security_mnt_opts), GFP_KERNEL); | ||
1009 | *mnt_opts = opts; | ||
1010 | if (!opts) | ||
1011 | return -ENOMEM; | ||
1012 | } | ||
991 | 1013 | ||
992 | opts->num_mnt_opts = 0; | 1014 | opts->num_mnt_opts = 0; |
993 | 1015 | ||
@@ -1094,7 +1116,7 @@ static int selinux_parse_opts_str(char *options, | |||
1094 | return 0; | 1116 | return 0; |
1095 | 1117 | ||
1096 | out_err: | 1118 | out_err: |
1097 | security_free_mnt_opts(opts); | 1119 | security_free_mnt_opts(mnt_opts); |
1098 | kfree(context); | 1120 | kfree(context); |
1099 | kfree(defcontext); | 1121 | kfree(defcontext); |
1100 | kfree(fscontext); | 1122 | kfree(fscontext); |
@@ -2714,7 +2736,7 @@ out: | |||
2714 | return rc; | 2736 | return rc; |
2715 | } | 2737 | } |
2716 | 2738 | ||
2717 | static int selinux_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) | 2739 | static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) |
2718 | { | 2740 | { |
2719 | char *s = (char *)get_zeroed_page(GFP_KERNEL); | 2741 | char *s = (char *)get_zeroed_page(GFP_KERNEL); |
2720 | int err; | 2742 | int err; |
@@ -2723,14 +2745,14 @@ static int selinux_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts | |||
2723 | return -ENOMEM; | 2745 | return -ENOMEM; |
2724 | err = selinux_sb_copy_data(options, s); | 2746 | err = selinux_sb_copy_data(options, s); |
2725 | if (!err) | 2747 | if (!err) |
2726 | err = selinux_parse_opts_str(s, opts); | 2748 | err = selinux_parse_opts_str(s, mnt_opts); |
2727 | free_page((unsigned long)s); | 2749 | free_page((unsigned long)s); |
2728 | return err; | 2750 | return err; |
2729 | } | 2751 | } |
2730 | 2752 | ||
2731 | static int selinux_sb_remount(struct super_block *sb, | 2753 | static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) |
2732 | struct security_mnt_opts *opts) | ||
2733 | { | 2754 | { |
2755 | struct security_mnt_opts *opts = mnt_opts; | ||
2734 | int i, *flags; | 2756 | int i, *flags; |
2735 | char **mount_options; | 2757 | char **mount_options; |
2736 | struct superblock_security_struct *sbsec = sb->s_security; | 2758 | struct superblock_security_struct *sbsec = sb->s_security; |
@@ -2738,6 +2760,9 @@ static int selinux_sb_remount(struct super_block *sb, | |||
2738 | if (!(sbsec->flags & SE_SBINITIALIZED)) | 2760 | if (!(sbsec->flags & SE_SBINITIALIZED)) |
2739 | return 0; | 2761 | return 0; |
2740 | 2762 | ||
2763 | if (!opts) | ||
2764 | return 0; | ||
2765 | |||
2741 | mount_options = opts->mnt_opts; | 2766 | mount_options = opts->mnt_opts; |
2742 | flags = opts->mnt_opts_flags; | 2767 | flags = opts->mnt_opts_flags; |
2743 | 2768 | ||
@@ -6782,6 +6807,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
6782 | LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security), | 6807 | LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security), |
6783 | LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), | 6808 | LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), |
6784 | LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts), | 6809 | LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts), |
6810 | LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts), | ||
6785 | LSM_HOOK_INIT(sb_remount, selinux_sb_remount), | 6811 | LSM_HOOK_INIT(sb_remount, selinux_sb_remount), |
6786 | LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), | 6812 | LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), |
6787 | LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options), | 6813 | LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options), |
@@ -7051,11 +7077,7 @@ static __init int selinux_init(void) | |||
7051 | 7077 | ||
7052 | static void delayed_superblock_init(struct super_block *sb, void *unused) | 7078 | static void delayed_superblock_init(struct super_block *sb, void *unused) |
7053 | { | 7079 | { |
7054 | struct security_mnt_opts opts; | 7080 | selinux_set_mnt_opts(sb, NULL, 0, NULL); |
7055 | |||
7056 | security_init_mnt_opts(&opts); | ||
7057 | selinux_set_mnt_opts(sb, &opts, 0, NULL); | ||
7058 | security_free_mnt_opts(&opts); | ||
7059 | } | 7081 | } |
7060 | 7082 | ||
7061 | void selinux_complete_init(void) | 7083 | void selinux_complete_init(void) |