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