]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/mount.c
mount.nfs: Fix issue with -o user,exec
[nfs-utils.git] / utils / mount / mount.c
index 71a87375868322c3dacebf86f92b5a0cad16adb5..4698d85fd98f6f9cd30c00f8644dff26ceb41082 100644 (file)
@@ -99,11 +99,9 @@ static const struct opt_map opt_map[] = {
   { "rbind",    0, 0, MS_BIND|MS_REC }, /* Idem, plus mounted subtrees */
   { "auto",     0, 0, MS_DUMMY },       /* Can be mounted using -a */
   { "noauto",   0, 0, MS_DUMMY },       /* Can  only be mounted explicitly */
-  { "users",    1, 0, MS_USERS|MS_NOEXEC|MS_NOSUID|MS_NODEV  },
-                                       /* Allow ordinary user to mount */
+  { "users",    1, 0, MS_USERS },      /* Allow ordinary user to mount */
   { "nousers",  0, 1, MS_DUMMY  },      /* Forbid ordinary user to mount */
-  { "user",     1, 0, MS_USER|MS_NOEXEC|MS_NOSUID|MS_NODEV  },
-                                       /* Allow ordinary user to mount */
+  { "user",     1, 0, MS_USER  },      /* Allow ordinary user to mount */
   { "nouser",   0, 1, MS_DUMMY   },     /* Forbid ordinary user to mount */
   { "owner",    0, 0, MS_DUMMY  },      /* Let the owner of the device mount */
   { "noowner",  0, 0, MS_DUMMY  },      /* Device owner has no special privs */
@@ -261,18 +259,30 @@ static void parse_opts (const char *options, int *flags, char **extra_opts)
 {
        if (options != NULL) {
                char *opts = xstrdup(options);
-               char *opt;
-               int len = strlen(opts) + 20;
+               char *opt, *p;
+               int len = strlen(opts) + 1;             /* include room for a null */
+               int open_quote = 0;
 
                *extra_opts = xmalloc(len);
                **extra_opts = '\0';
 
-               for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ","))
-                       parse_opt(opt, flags, *extra_opts, len);
-
+               for (p=opts, opt=NULL; p && *p; p++) {
+                       if (!opt)
+                               opt = p;                /* begin of the option item */
+                       if (*p == '"')
+                               open_quote ^= 1;        /* reverse the status */
+                       if (open_quote)
+                               continue;               /* still in a quoted block */
+                       if (*p == ',')
+                               *p = '\0';              /* terminate the option item */
+                       /* end of option item or last item */
+                       if (*p == '\0' || *(p+1) == '\0') {
+                               parse_opt(opt, flags, *extra_opts, len);
+                               opt = NULL;
+                       }
+               }
                free(opts);
        }
-
 }
 
 static void mount_error(char *node)
@@ -350,6 +360,7 @@ int main(int argc, char *argv[])
        spec = argv[1];
        mount_point = argv[2];
 
+       argv[2] = argv[0]; /* so that getopt error messages are correct */
        while ((c = getopt_long (argc - 2, argv + 2, "rt:vVwfno:hs",
                                longopts, NULL)) != -1) {
                switch (c) {
@@ -424,7 +435,7 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
-       if (strcmp(progname, "mount.nfsv4") == 0)
+       if (strcmp(progname, "mount.nfs4") == 0)
                nfs_mount_vers = 4;
 
        if (uid != 0) {
@@ -435,12 +446,18 @@ int main(int argc, char *argv[])
 
                if ((mc = getfsfile(mount_point)) == NULL ||
                    strcmp(mc->m.mnt_fsname, spec) != 0 ||
-                   strcmp(mc->m.mnt_type, (nfs_mount_vers == 4 ? "nfs4":"nfs")) != 0 || 
-                   strcmp(mc->m.mnt_opts, mount_opts) != 0) {
+                   strcmp(mc->m.mnt_type, (nfs_mount_vers == 4 ? "nfs4":"nfs")) != 0
+                   ) {
                        fprintf(stderr, "%s: permission died - no match for fstab\n",
                                progname);
                        exit(1);
                }
+               /* 'mount' munges the options from fstab before passing them
+                * to us, so it is non-trivial to test that we have the correct
+                * set of options and we don't want to trust what the user
+                * gave us, so just take whatever is in fstab
+                */
+               mount_opts = strdup(mc->m.mnt_opts);
                mounttype = 0;
        }
 
@@ -448,7 +465,7 @@ int main(int argc, char *argv[])
        if (mount_point == NULL ||
            mount_point[0] != '/') {
                fprintf(stderr, "%s: unknown mount point %s\n",
-                       progname, argv[2]);
+                       progname, mount_point ? : "");
                exit(1);
        }
        
@@ -478,7 +495,8 @@ int main(int argc, char *argv[])
        if (!fake) {
                mnt_err = do_mount_syscall(spec, mount_point,
                                           nfs_mount_vers == 4 ? "nfs4" : "nfs",
-                                          flags, mount_opts);
+                                          flags & ~(MS_USER|MS_USERS) ,
+                                          mount_opts);
 
                if (mnt_err) {
                        mount_error(mount_point);