Strip 'zfsutil,remount' from /etc/mtab
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 15 Mar 2011 18:17:33 +0000 (11:17 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 15 Mar 2011 20:33:29 +0000 (13:33 -0700)
When updating /etc/mtab we should be careful and strip certain
options.  In particular, we need to strip 'zfsutil' because if
we don't the mount utility will helpfull provide it to the
mount helper when we issue mount(8) again.  This subverts the
check that the caller is zfs(8) and not mount(8).

cmd/mount_zfs/mount_zfs.c

index 52e5992..204f9fa 100644 (file)
@@ -72,13 +72,11 @@ static const option_map_t option_map[] = {
 #ifdef MS_STRICTATIME
        { MNTOPT_DFRATIME,      MS_STRICTATIME, ZS_COMMENT      },
 #endif
-#ifdef HAVE_SELINUX
        { MNTOPT_CONTEXT,       MS_COMMENT,     ZS_NOCONTEXT    },
        { MNTOPT_NOCONTEXT,     MS_COMMENT,     ZS_NOCONTEXT    },
        { MNTOPT_FSCONTEXT,     MS_COMMENT,     ZS_NOCONTEXT    },
        { MNTOPT_DEFCONTEXT,    MS_COMMENT,     ZS_NOCONTEXT    },
        { MNTOPT_ROOTCONTEXT,   MS_COMMENT,     ZS_NOCONTEXT    },
-#endif
 #ifdef MS_I_VERSION
        { MNTOPT_IVERSION,      MS_I_VERSION,   ZS_COMMENT      },
 #endif
@@ -158,10 +156,10 @@ out:
  * otherwise they are considered fatal are copied in to badopt.
  */
 static int
-parse_options(char *mntopts, unsigned long *mntflags,
-    unsigned long *zfsflags, int sloppy, char *badopt)
+parse_options(char *mntopts, unsigned long *mntflags, unsigned long *zfsflags,
+    int sloppy, char *badopt, char *mtabopt)
 {
-       int error = 0, quote = 0, flag = 0;
+       int error = 0, quote = 0, flag = 0, count = 0;
        char *ptr, *opt, *opts;
 
        opts = strdup(mntopts);
@@ -197,6 +195,16 @@ parse_options(char *mntopts, unsigned long *mntflags,
                        if (error) {
                                strcpy(badopt, opt);
                                goto out;
+
+                       }
+
+                       if (!(*mntflags & MS_REMOUNT) &&
+                           !(*zfsflags & ZS_ZFSUTIL)) {
+                               if (count > 0)
+                                       strlcat(mtabopt, ",", MNT_LINE_MAX);
+
+                               strlcat(mtabopt, opt, MNT_LINE_MAX);
+                               count++;
                        }
 
                        opt = NULL;
@@ -297,6 +305,7 @@ main(int argc, char **argv)
        char legacy[ZFS_MAXPROPLEN];
        char mntopts[MNT_LINE_MAX] = { '\0' };
        char badopt[MNT_LINE_MAX] = { '\0' };
+       char mtabopt[MNT_LINE_MAX] = { '\0' };
        char *dataset, *mntpoint;
        unsigned long mntflags = 0, zfsflags = 0, remount_ro = 0;
        int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0;
@@ -356,24 +365,25 @@ main(int argc, char **argv)
        mntpoint = argv[1];
 
        /* validate mount options and set mntflags */
-       error = parse_options(mntopts, &mntflags, &zfsflags, sloppy, badopt);
+       error = parse_options(mntopts, &mntflags, &zfsflags, sloppy,
+           badopt, mtabopt);
        if (error) {
                switch (error) {
                case ENOMEM:
                        (void) fprintf(stderr, gettext("filesystem '%s' "
                            "cannot be mounted due to a memory allocation "
-                           "failure\n"), dataset);
+                           "failure.\n"), dataset);
                        return (MOUNT_SYSERR);
-               case EINVAL:
+               case ENOENT:
                        (void) fprintf(stderr, gettext("filesystem '%s' "
-                           "cannot be mounted of due to the invalid option "
-                           "'%s'\n"), dataset, badopt);
+                           "cannot be mounted of due invalid option "
+                           "'%s'.\n"), dataset, badopt);
                        (void) fprintf(stderr, gettext("Use the '-s' option "
                            "to ignore the bad mount option.\n"));
                        return (MOUNT_USAGE);
                default:
                        (void) fprintf(stderr, gettext("filesystem '%s' "
-                           "cannot be mounted due to internal error %d\n"),
+                           "cannot be mounted due to internal error %d.\n"),
                            dataset, error);
                        return (MOUNT_SOFTWARE);
                }
@@ -386,9 +396,12 @@ main(int argc, char **argv)
         * done until zfs is added to the default selinux policy configuration
         * as a known filesystem type which supports xattrs.
         */
-        if (is_selinux_enabled() && !(zfsflags & ZS_NOCONTEXT))
+        if (is_selinux_enabled() && !(zfsflags & ZS_NOCONTEXT)) {
                 (void) strlcat(mntopts, ",context=\"system_u:"
                     "object_r:file_t:s0\"", sizeof (mntopts));
+                (void) strlcat(mtabopt, ",context=\"system_u:"
+                    "object_r:file_t:s0\"", sizeof (mtabopt));
+       }
 #endif /* HAVE_LIBSELINUX */
 
 
@@ -396,8 +409,8 @@ main(int argc, char **argv)
                (void) fprintf(stdout, gettext("mount.zfs:\n"
                    "  dataset:    \"%s\"\n  mountpoint: \"%s\"\n"
                    "  mountflags: 0x%lx\n  zfsflags:   0x%lx\n"
-                   "  mountopts:  \"%s\"\n\n"),
-                   dataset, mntpoint, mntflags, zfsflags, mntopts);
+                   "  mountopts:  \"%s\"\n  mtabopts:   \"%s\"\n"),
+                   dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt);
 
        if (mntflags & MS_REMOUNT)
                nomtab = 1;
@@ -472,7 +485,7 @@ main(int argc, char **argv)
        }
 
        if (!nomtab && mtab_is_writeable()) {
-               error = mtab_update(dataset, mntpoint, MNTTYPE_ZFS, mntopts);
+               error = mtab_update(dataset, mntpoint, MNTTYPE_ZFS, mtabopt);
                if (error)
                        return (error);
        }