summaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-12-13 13:41:47 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2018-12-21 11:48:34 -0500
commit204cc0ccf1d49c6292aeef4c8edd1b3d10ff933c (patch)
treeb372464222a21a2a0356fde8421eb86cb991a378 /security/selinux
parente3489f8974e178d723259a842a1e61708dd7dc1e (diff)
LSM: hide struct security_mnt_opts from any generic code
Keep void * instead, allocate on demand (in parse_str_opts, at the moment). Eventually both selinux and smack will be better off with private structures with several strings in those, rather than this "counter and two pointers to dynamically allocated arrays" ugliness. This commit allows to do that at leisure, without disrupting anything outside of given module. Changes: * instead of struct security_mnt_opt use an opaque pointer initialized to NULL. * security_sb_eat_lsm_opts(), security_sb_parse_opts_str() and security_free_mnt_opts() take it as var argument (i.e. as void **); call sites are unchanged. * security_sb_set_mnt_opts() and security_sb_remount() take it by value (i.e. as void *). * new method: ->sb_free_mnt_opts(). Takes void *, does whatever freeing that needs to be done. * ->sb_set_mnt_opts() and ->sb_remount() might get NULL as mnt_opts argument, meaning "empty". Reviewed-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c52
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
436static 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
436static inline int inode_doinit(struct inode *inode) 449static 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 */
618static int selinux_set_mnt_opts(struct super_block *sb, 631static 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
984static int selinux_parse_opts_str(char *options, 998static 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
1096out_err: 1118out_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
2717static int selinux_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) 2739static 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
2731static int selinux_sb_remount(struct super_block *sb, 2753static 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
7052static void delayed_superblock_init(struct super_block *sb, void *unused) 7078static 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
7061void selinux_complete_init(void) 7083void selinux_complete_init(void)