diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 38 |
1 files changed, 30 insertions, 8 deletions
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) sb->s_security = NULL; } +static void smack_free_mnt_opts(void *mnt_opts) +{ + struct security_mnt_opts *opts = mnt_opts; + int i; + + if (opts->mnt_opts) + for (i = 0; i < opts->num_mnt_opts; i++) + kfree(opts->mnt_opts[i]); + kfree(opts->mnt_opts); + kfree(opts->mnt_opts_flags); + kfree(opts); +} + /** * smack_sb_copy_data - copy mount options data for processing * @orig: where to start @@ -624,8 +637,9 @@ static int smack_sb_copy_data(char *orig, char *smackopts) * converts Smack specific mount options to generic security option format */ static int smack_parse_opts_str(char *options, - struct security_mnt_opts *opts) + void **mnt_opts) { + struct security_mnt_opts *opts = *mnt_opts; char *p; char *fsdefault = NULL; char *fsfloor = NULL; @@ -636,11 +650,17 @@ static int smack_parse_opts_str(char *options, int num_mnt_opts = 0; int token; - opts->num_mnt_opts = 0; - if (!options) return 0; + if (!opts) { + opts = kzalloc(sizeof(struct security_mnt_opts), GFP_KERNEL); + *mnt_opts = opts; + if (!opts) + return -ENOMEM; + } + opts->num_mnt_opts = 0; + while ((p = strsep(&options, ",")) != NULL) { substring_t args[MAX_OPT_ARGS]; @@ -735,11 +755,11 @@ out_err: kfree(fshat); kfree(fsroot); kfree(fstransmute); - security_free_mnt_opts(opts); + security_free_mnt_opts(mnt_opts); return rc; } -static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) +static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts) { char *s = (char *)get_zeroed_page(GFP_KERNEL); int err; @@ -748,7 +768,7 @@ static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) return -ENOMEM; err = smack_sb_copy_data(options, s); if (!err) - err = smack_parse_opts_str(s, opts); + err = smack_parse_opts_str(s, mnt_opts); free_page((unsigned long)s); return err; } @@ -766,7 +786,7 @@ static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) * labels. */ static int smack_set_mnt_opts(struct super_block *sb, - struct security_mnt_opts *opts, + void *mnt_opts, unsigned long kern_flags, unsigned long *set_kern_flags) { @@ -776,7 +796,8 @@ static int smack_set_mnt_opts(struct super_block *sb, struct inode_smack *isp; struct smack_known *skp; int i; - int num_opts = opts->num_mnt_opts; + struct security_mnt_opts *opts = mnt_opts; + int num_opts = opts ? opts->num_mnt_opts : 0; int transmute = 0; if (sp->smk_flags & SMK_SB_INITIALIZED) @@ -4651,6 +4672,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), + LSM_HOOK_INIT(sb_free_mnt_opts, smack_free_mnt_opts), LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts), LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), |