]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
selinux: new helper - selinux_add_opt()
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 15 Dec 2018 01:28:15 +0000 (20:28 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 21 Dec 2018 16:49:18 +0000 (11:49 -0500)
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>
security/selinux/hooks.c

index 238907d69e8be4b3f6093c052b748e7309be384e..26ec7d67e15dac915e18483dd819bd8069d21af3 100644 (file)
@@ -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)