diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-12-15 02:28:15 +0100 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-12-21 17:49:18 +0100 |
commit | ba6418623385abf19a6c15cf0b1cfaacfdf9afc8 (patch) | |
tree | f6ffef1eb1886b5b94677979ac03de3e5d48036c /security/selinux | |
parent | LSM: bury struct security_mnt_opts (diff) | |
download | linux-ba6418623385abf19a6c15cf0b1cfaacfdf9afc8.tar.xz linux-ba6418623385abf19a6c15cf0b1cfaacfdf9afc8.zip |
selinux: new helper - selinux_add_opt()
the guts of the loop in selinux_parse_opts_str() - takes one
(already recognized) option and adds it to growing selinux_mnt_opts.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/hooks.c | 126 |
1 files changed, 53 insertions, 73 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 238907d69e8b..26ec7d67e15d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -984,97 +984,77 @@ out: return rc; } +static int selinux_add_opt(int token, const char *s, void **mnt_opts) +{ + struct selinux_mnt_opts *opts = *mnt_opts; + + if (!opts) { + opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL); + if (!opts) + return -ENOMEM; + *mnt_opts = opts; + } + if (!s) + return -ENOMEM; + switch (token) { + case Opt_context: + if (opts->context || opts->defcontext) + goto Einval; + opts->context = s; + break; + case Opt_fscontext: + if (opts->fscontext) + goto Einval; + opts->fscontext = s; + break; + case Opt_rootcontext: + if (opts->rootcontext) + goto Einval; + opts->rootcontext = s; + break; + case Opt_defcontext: + if (opts->context || opts->defcontext) + goto Einval; + opts->defcontext = s; + break; + } + return 0; +Einval: + pr_warn(SEL_MOUNT_FAIL_MSG); + kfree(s); + return -EINVAL; +} + static int selinux_parse_opts_str(char *options, void **mnt_opts) { - struct selinux_mnt_opts *opts = *mnt_opts; char *p; - int rc; /* Standard string-based options. */ while ((p = strsep(&options, "|")) != NULL) { - int token; + int token, rc; substring_t args[MAX_OPT_ARGS]; + const char *arg; if (!*p) continue; token = match_token(p, tokens, args); - if (!opts) { - opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL); - if (!opts) - return -ENOMEM; - } - - switch (token) { - case Opt_context: - if (opts->context || opts->defcontext) { - rc = -EINVAL; - pr_warn(SEL_MOUNT_FAIL_MSG); - goto out_err; - } - opts->context = match_strdup(&args[0]); - if (!opts->context) { - rc = -ENOMEM; - goto out_err; - } - break; - - case Opt_fscontext: - if (opts->fscontext) { - rc = -EINVAL; - pr_warn(SEL_MOUNT_FAIL_MSG); - goto out_err; - } - opts->fscontext = match_strdup(&args[0]); - if (!opts->fscontext) { - rc = -ENOMEM; - goto out_err; - } - break; - - case Opt_rootcontext: - if (opts->rootcontext) { - rc = -EINVAL; - pr_warn(SEL_MOUNT_FAIL_MSG); - goto out_err; - } - opts->rootcontext = match_strdup(&args[0]); - if (!opts->rootcontext) { - rc = -ENOMEM; - goto out_err; - } - break; - - case Opt_defcontext: - if (opts->context || opts->defcontext) { - rc = -EINVAL; - pr_warn(SEL_MOUNT_FAIL_MSG); - goto out_err; - } - opts->defcontext = match_strdup(&args[0]); - if (!opts->defcontext) { - rc = -ENOMEM; - goto out_err; + if (token == Opt_labelsupport) /* eaten and completely ignored */ + continue; + arg = match_strdup(&args[0]); + rc = selinux_add_opt(token, arg, mnt_opts); + if (unlikely(rc)) { + kfree(arg); + if (*mnt_opts) { + selinux_free_mnt_opts(*mnt_opts); + *mnt_opts = NULL; } - break; - case Opt_labelsupport: - break; - default: - rc = -EINVAL; - pr_warn("SELinux: unknown mount option\n"); - goto out_err; - + return rc; } } - *mnt_opts = opts; return 0; - -out_err: - if (opts) - selinux_free_mnt_opts(opts); - return rc; } static int show_sid(struct seq_file *m, u32 sid) |