diff options
author | Al Viro | 2018-12-16 01:37:06 -0500 |
---|---|---|
committer | Al Viro | 2018-12-21 11:51:02 -0500 |
commit | d2497e12e230c3f1be8ca6a0609a98c8c609fb80 (patch) | |
tree | 91156d8db61b4929b980bc4d4856803a4acb1685 /security | |
parent | c3300aaf95fb4e5be41e731fa6427d0d996d32ac (diff) |
smack: rewrite smack_sb_eat_lsm_opts()
make it use smack_add_opt() and avoid separate copies - gather
non-LSM options by memmove() in place
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/smack/smack_lsm.c | 108 |
1 files changed, 23 insertions, 85 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d479def4d6a0..24a00d93d8c3 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -599,53 +599,6 @@ static void smack_free_mnt_opts(void *mnt_opts) kfree(opts); } -/** - * smack_sb_copy_data - copy mount options data for processing - * @orig: where to start - * @smackopts: mount options string - * - * Returns 0 on success or -ENOMEM on error. - * - * Copy the Smack specific mount options out of the mount - * options list. - */ -static int smack_sb_copy_data(char *orig, char *smackopts) -{ - char *cp, *commap, *otheropts, *dp; - - otheropts = (char *)get_zeroed_page(GFP_KERNEL); - if (otheropts == NULL) - return -ENOMEM; - - for (cp = orig, commap = orig; commap != NULL; cp = commap + 1) { - if (strstr(cp, SMK_FSDEFAULT) == cp) - dp = smackopts; - else if (strstr(cp, SMK_FSFLOOR) == cp) - dp = smackopts; - else if (strstr(cp, SMK_FSHAT) == cp) - dp = smackopts; - else if (strstr(cp, SMK_FSROOT) == cp) - dp = smackopts; - else if (strstr(cp, SMK_FSTRANS) == cp) - dp = smackopts; - else - dp = otheropts; - - commap = strchr(cp, ','); - if (commap != NULL) - *commap = '\0'; - - if (*dp != '\0') - strcat(dp, ","); - strcat(dp, cp); - } - - strcpy(orig, otheropts); - free_page((unsigned long)otheropts); - - return 0; -} - static int smack_add_opt(int token, const char *s, void **mnt_opts) { struct smack_mnt_opts *opts = *mnt_opts; @@ -656,7 +609,6 @@ static int smack_add_opt(int token, const char *s, void **mnt_opts) return -ENOMEM; *mnt_opts = opts; } - if (!s) return -ENOMEM; @@ -694,22 +646,10 @@ out_opt_err: return -EINVAL; } -/** - * smack_parse_opts_str - parse Smack specific mount options - * @options: mount options string - * @opts: where to store converted mount opts - * - * Returns 0 on success or -ENOMEM on error. - * - * converts Smack specific mount options to generic security option format - */ -static int smack_parse_opts_str(char *options, - void **mnt_opts) +static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts) { - char *from = options; - - if (!options) - return 0; + char *from = options, *to = options; + bool first = true; while (1) { char *next = strchr(from, ','); @@ -722,36 +662,34 @@ static int smack_parse_opts_str(char *options, len = strlen(from); token = match_opt_prefix(from, len, &arg); - arg = kmemdup_nul(arg, from + len - arg, GFP_KERNEL); - rc = smack_add_opt(token, arg, mnt_opts); - if (unlikely(rc)) { - kfree(arg); - if (*mnt_opts) - smack_free_mnt_opts(*mnt_opts); - *mnt_opts = NULL; - return rc; + if (token != Opt_error) { + arg = kmemdup_nul(arg, from + len - arg, GFP_KERNEL); + rc = smack_add_opt(token, arg, mnt_opts); + if (unlikely(rc)) { + kfree(arg); + if (*mnt_opts) + smack_free_mnt_opts(*mnt_opts); + *mnt_opts = NULL; + return rc; + } + } else { + if (!first) { // copy with preceding comma + from--; + len++; + } + if (to != from) + memmove(to, from, len); + to += len; + first = false; } if (!from[len]) break; from += len + 1; } + *to = '\0'; return 0; } -static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts) -{ - char *s = (char *)get_zeroed_page(GFP_KERNEL); - int err; - - if (!s) - return -ENOMEM; - err = smack_sb_copy_data(options, s); - if (!err) - err = smack_parse_opts_str(s, mnt_opts); - free_page((unsigned long)s); - return err; -} - /** * smack_set_mnt_opts - set Smack specific mount options * @sb: the file system superblock |