From ba6418623385abf19a6c15cf0b1cfaacfdf9afc8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 14 Dec 2018 20:28:15 -0500 Subject: 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 Signed-off-by: Al Viro --- security/selinux/hooks.c | 126 ++++++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 73 deletions(-) (limited to 'security/selinux') 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) -- cgit v1.2.3-59-g8ed1b