summaryrefslogtreecommitdiffstats
path: root/security
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
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')
-rw-r--r--security/security.c27
-rw-r--r--security/selinux/hooks.c52
-rw-r--r--security/smack/smack_lsm.c38
3 files changed, 85 insertions, 32 deletions
diff --git a/security/security.c b/security/security.c
index feb18c925349..b7a5a0051807 100644
--- a/security/security.c
+++ b/security/security.c
@@ -384,16 +384,25 @@ void security_sb_free(struct super_block *sb)
384 call_void_hook(sb_free_security, sb); 384 call_void_hook(sb_free_security, sb);
385} 385}
386 386
387int security_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) 387void security_free_mnt_opts(void **mnt_opts)
388{ 388{
389 return call_int_hook(sb_eat_lsm_opts, 0, options, opts); 389 if (!*mnt_opts)
390 return;
391 call_void_hook(sb_free_mnt_opts, *mnt_opts);
392 *mnt_opts = NULL;
393}
394EXPORT_SYMBOL(security_free_mnt_opts);
395
396int security_sb_eat_lsm_opts(char *options, void **mnt_opts)
397{
398 return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts);
390} 399}
391EXPORT_SYMBOL(security_sb_eat_lsm_opts); 400EXPORT_SYMBOL(security_sb_eat_lsm_opts);
392 401
393int security_sb_remount(struct super_block *sb, 402int security_sb_remount(struct super_block *sb,
394 struct security_mnt_opts *opts) 403 void *mnt_opts)
395{ 404{
396 return call_int_hook(sb_remount, 0, sb, opts); 405 return call_int_hook(sb_remount, 0, sb, mnt_opts);
397} 406}
398EXPORT_SYMBOL(security_sb_remount); 407EXPORT_SYMBOL(security_sb_remount);
399 408
@@ -429,13 +438,13 @@ int security_sb_pivotroot(const struct path *old_path, const struct path *new_pa
429} 438}
430 439
431int security_sb_set_mnt_opts(struct super_block *sb, 440int security_sb_set_mnt_opts(struct super_block *sb,
432 struct security_mnt_opts *opts, 441 void *mnt_opts,
433 unsigned long kern_flags, 442 unsigned long kern_flags,
434 unsigned long *set_kern_flags) 443 unsigned long *set_kern_flags)
435{ 444{
436 return call_int_hook(sb_set_mnt_opts, 445 return call_int_hook(sb_set_mnt_opts,
437 opts->num_mnt_opts ? -EOPNOTSUPP : 0, sb, 446 mnt_opts ? -EOPNOTSUPP : 0, sb,
438 opts, kern_flags, set_kern_flags); 447 mnt_opts, kern_flags, set_kern_flags);
439} 448}
440EXPORT_SYMBOL(security_sb_set_mnt_opts); 449EXPORT_SYMBOL(security_sb_set_mnt_opts);
441 450
@@ -449,9 +458,9 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
449} 458}
450EXPORT_SYMBOL(security_sb_clone_mnt_opts); 459EXPORT_SYMBOL(security_sb_clone_mnt_opts);
451 460
452int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 461int security_sb_parse_opts_str(char *options, void **mnt_opts)
453{ 462{
454 return call_int_hook(sb_parse_opts_str, 0, options, opts); 463 return call_int_hook(sb_parse_opts_str, 0, options, mnt_opts);
455} 464}
456EXPORT_SYMBOL(security_sb_parse_opts_str); 465EXPORT_SYMBOL(security_sb_parse_opts_str);
457 466
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)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 835cca277c2a..81a8112975d4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -567,6 +567,19 @@ static void smack_sb_free_security(struct super_block *sb)
567 sb->s_security = NULL; 567 sb->s_security = NULL;
568} 568}
569 569
570static void smack_free_mnt_opts(void *mnt_opts)
571{
572 struct security_mnt_opts *opts = mnt_opts;
573 int i;
574
575 if (opts->mnt_opts)
576 for (i = 0; i < opts->num_mnt_opts; i++)
577 kfree(opts->mnt_opts[i]);
578 kfree(opts->mnt_opts);
579 kfree(opts->mnt_opts_flags);
580 kfree(opts);
581}
582
570/** 583/**
571 * smack_sb_copy_data - copy mount options data for processing 584 * smack_sb_copy_data - copy mount options data for processing
572 * @orig: where to start 585 * @orig: where to start
@@ -624,8 +637,9 @@ static int smack_sb_copy_data(char *orig, char *smackopts)
624 * converts Smack specific mount options to generic security option format 637 * converts Smack specific mount options to generic security option format
625 */ 638 */
626static int smack_parse_opts_str(char *options, 639static int smack_parse_opts_str(char *options,
627 struct security_mnt_opts *opts) 640 void **mnt_opts)
628{ 641{
642 struct security_mnt_opts *opts = *mnt_opts;
629 char *p; 643 char *p;
630 char *fsdefault = NULL; 644 char *fsdefault = NULL;
631 char *fsfloor = NULL; 645 char *fsfloor = NULL;
@@ -636,11 +650,17 @@ static int smack_parse_opts_str(char *options,
636 int num_mnt_opts = 0; 650 int num_mnt_opts = 0;
637 int token; 651 int token;
638 652
639 opts->num_mnt_opts = 0;
640
641 if (!options) 653 if (!options)
642 return 0; 654 return 0;
643 655
656 if (!opts) {
657 opts = kzalloc(sizeof(struct security_mnt_opts), GFP_KERNEL);
658 *mnt_opts = opts;
659 if (!opts)
660 return -ENOMEM;
661 }
662 opts->num_mnt_opts = 0;
663
644 while ((p = strsep(&options, ",")) != NULL) { 664 while ((p = strsep(&options, ",")) != NULL) {
645 substring_t args[MAX_OPT_ARGS]; 665 substring_t args[MAX_OPT_ARGS];
646 666
@@ -735,11 +755,11 @@ out_err:
735 kfree(fshat); 755 kfree(fshat);
736 kfree(fsroot); 756 kfree(fsroot);
737 kfree(fstransmute); 757 kfree(fstransmute);
738 security_free_mnt_opts(opts); 758 security_free_mnt_opts(mnt_opts);
739 return rc; 759 return rc;
740} 760}
741 761
742static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) 762static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts)
743{ 763{
744 char *s = (char *)get_zeroed_page(GFP_KERNEL); 764 char *s = (char *)get_zeroed_page(GFP_KERNEL);
745 int err; 765 int err;
@@ -748,7 +768,7 @@ static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts)
748 return -ENOMEM; 768 return -ENOMEM;
749 err = smack_sb_copy_data(options, s); 769 err = smack_sb_copy_data(options, s);
750 if (!err) 770 if (!err)
751 err = smack_parse_opts_str(s, opts); 771 err = smack_parse_opts_str(s, mnt_opts);
752 free_page((unsigned long)s); 772 free_page((unsigned long)s);
753 return err; 773 return err;
754} 774}
@@ -766,7 +786,7 @@ static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts)
766 * labels. 786 * labels.
767 */ 787 */
768static int smack_set_mnt_opts(struct super_block *sb, 788static int smack_set_mnt_opts(struct super_block *sb,
769 struct security_mnt_opts *opts, 789 void *mnt_opts,
770 unsigned long kern_flags, 790 unsigned long kern_flags,
771 unsigned long *set_kern_flags) 791 unsigned long *set_kern_flags)
772{ 792{
@@ -776,7 +796,8 @@ static int smack_set_mnt_opts(struct super_block *sb,
776 struct inode_smack *isp; 796 struct inode_smack *isp;
777 struct smack_known *skp; 797 struct smack_known *skp;
778 int i; 798 int i;
779 int num_opts = opts->num_mnt_opts; 799 struct security_mnt_opts *opts = mnt_opts;
800 int num_opts = opts ? opts->num_mnt_opts : 0;
780 int transmute = 0; 801 int transmute = 0;
781 802
782 if (sp->smk_flags & SMK_SB_INITIALIZED) 803 if (sp->smk_flags & SMK_SB_INITIALIZED)
@@ -4651,6 +4672,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
4651 4672
4652 LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), 4673 LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
4653 LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), 4674 LSM_HOOK_INIT(sb_free_security, smack_sb_free_security),
4675 LSM_HOOK_INIT(sb_free_mnt_opts, smack_free_mnt_opts),
4654 LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts), 4676 LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts),
4655 LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), 4677 LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
4656 LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), 4678 LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts),