diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/security.c | 27 | ||||
-rw-r--r-- | security/selinux/hooks.c | 52 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 38 |
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 | ||
387 | int security_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) | 387 | void 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 | } | ||
394 | EXPORT_SYMBOL(security_free_mnt_opts); | ||
395 | |||
396 | int 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 | } |
391 | EXPORT_SYMBOL(security_sb_eat_lsm_opts); | 400 | EXPORT_SYMBOL(security_sb_eat_lsm_opts); |
392 | 401 | ||
393 | int security_sb_remount(struct super_block *sb, | 402 | int 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 | } |
398 | EXPORT_SYMBOL(security_sb_remount); | 407 | EXPORT_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 | ||
431 | int security_sb_set_mnt_opts(struct super_block *sb, | 440 | int 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 | } |
440 | EXPORT_SYMBOL(security_sb_set_mnt_opts); | 449 | EXPORT_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 | } |
450 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); | 459 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); |
451 | 460 | ||
452 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 461 | int 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 | } |
456 | EXPORT_SYMBOL(security_sb_parse_opts_str); | 465 | EXPORT_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 | ||
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) |
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 | ||
570 | static 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 | */ |
626 | static int smack_parse_opts_str(char *options, | 639 | static 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 | ||
742 | static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) | 762 | static 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 | */ |
768 | static int smack_set_mnt_opts(struct super_block *sb, | 788 | static 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), |