summaryrefslogtreecommitdiff
path: root/security/smack/smack_lsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r--security/smack/smack_lsm.c38
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),