aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smack_lsm.c
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/smack/smack_lsm.c
parentselinux: kill selinux_sb_get_mnt_opts() (diff)
downloadlinux-dev-204cc0ccf1d49c6292aeef4c8edd1b3d10ff933c.tar.xz
linux-dev-204cc0ccf1d49c6292aeef4c8edd1b3d10ff933c.zip
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/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),