The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 /*
   23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
   24  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   25  * Copyright (c) 2014, 2021 by Delphix. All rights reserved.
   26  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
   27  * Copyright 2017 RackTop Systems.
   28  * Copyright (c) 2018 Datto Inc.
   29  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
   30  */
   31 
   32 #include <dirent.h>
   33 #include <dlfcn.h>
   34 #include <errno.h>
   35 #include <fcntl.h>
   36 #include <libgen.h>
   37 #include <libintl.h>
   38 #include <stdio.h>
   39 #include <stdlib.h>
   40 #include <string.h>
   41 #include <unistd.h>
   42 #include <zone.h>
   43 #include <sys/mntent.h>
   44 #include <sys/mount.h>
   45 #include <sys/stat.h>
   46 #include <sys/vfs.h>
   47 #include <sys/dsl_crypt.h>
   48 #include <libzfs.h>
   49 
   50 #include "../../libzfs_impl.h"
   51 #include <thread_pool.h>
   52 
   53 #define ZS_COMMENT      0x00000000      /* comment */
   54 #define ZS_ZFSUTIL      0x00000001      /* caller is zfs(8) */
   55 
   56 typedef struct option_map {
   57         const char *name;
   58         unsigned long mntmask;
   59         unsigned long zfsmask;
   60 } option_map_t;
   61 
   62 static const option_map_t option_map[] = {
   63         /* Canonicalized filesystem independent options from mount(8) */
   64         { MNTOPT_NOAUTO,        MS_COMMENT,     ZS_COMMENT      },
   65         { MNTOPT_DEFAULTS,      MS_COMMENT,     ZS_COMMENT      },
   66         { MNTOPT_NODEVICES,     MS_NODEV,       ZS_COMMENT      },
   67         { MNTOPT_DEVICES,       MS_COMMENT,     ZS_COMMENT      },
   68         { MNTOPT_DIRSYNC,       MS_DIRSYNC,     ZS_COMMENT      },
   69         { MNTOPT_NOEXEC,        MS_NOEXEC,      ZS_COMMENT      },
   70         { MNTOPT_EXEC,          MS_COMMENT,     ZS_COMMENT      },
   71         { MNTOPT_GROUP,         MS_GROUP,       ZS_COMMENT      },
   72         { MNTOPT_NETDEV,        MS_COMMENT,     ZS_COMMENT      },
   73         { MNTOPT_NOFAIL,        MS_COMMENT,     ZS_COMMENT      },
   74         { MNTOPT_NOSUID,        MS_NOSUID,      ZS_COMMENT      },
   75         { MNTOPT_SUID,          MS_COMMENT,     ZS_COMMENT      },
   76         { MNTOPT_OWNER,         MS_OWNER,       ZS_COMMENT      },
   77         { MNTOPT_REMOUNT,       MS_REMOUNT,     ZS_COMMENT      },
   78         { MNTOPT_RO,            MS_RDONLY,      ZS_COMMENT      },
   79         { MNTOPT_RW,            MS_COMMENT,     ZS_COMMENT      },
   80         { MNTOPT_SYNC,          MS_SYNCHRONOUS, ZS_COMMENT      },
   81         { MNTOPT_USER,          MS_USERS,       ZS_COMMENT      },
   82         { MNTOPT_USERS,         MS_USERS,       ZS_COMMENT      },
   83         /* acl flags passed with util-linux-2.24 mount command */
   84         { MNTOPT_ACL,           MS_POSIXACL,    ZS_COMMENT      },
   85         { MNTOPT_NOACL,         MS_COMMENT,     ZS_COMMENT      },
   86         { MNTOPT_POSIXACL,      MS_POSIXACL,    ZS_COMMENT      },
   87         /*
   88          * Case sensitive options are just listed here to silently
   89          * ignore the error if passed with zfs mount command.
   90          */
   91         { MNTOPT_CASESENSITIVE,         MS_COMMENT,     ZS_COMMENT      },
   92         { MNTOPT_CASEINSENSITIVE,       MS_COMMENT,     ZS_COMMENT      },
   93         { MNTOPT_CASEMIXED,             MS_COMMENT,     ZS_COMMENT      },
   94 #ifdef MS_NOATIME
   95         { MNTOPT_NOATIME,       MS_NOATIME,     ZS_COMMENT      },
   96         { MNTOPT_ATIME,         MS_COMMENT,     ZS_COMMENT      },
   97 #endif
   98 #ifdef MS_NODIRATIME
   99         { MNTOPT_NODIRATIME,    MS_NODIRATIME,  ZS_COMMENT      },
  100         { MNTOPT_DIRATIME,      MS_COMMENT,     ZS_COMMENT      },
  101 #endif
  102 #ifdef MS_RELATIME
  103         { MNTOPT_RELATIME,      MS_RELATIME,    ZS_COMMENT      },
  104         { MNTOPT_NORELATIME,    MS_COMMENT,     ZS_COMMENT      },
  105 #endif
  106 #ifdef MS_STRICTATIME
  107         { MNTOPT_STRICTATIME,   MS_STRICTATIME, ZS_COMMENT      },
  108         { MNTOPT_NOSTRICTATIME, MS_COMMENT,     ZS_COMMENT      },
  109 #endif
  110 #ifdef MS_LAZYTIME
  111         { MNTOPT_LAZYTIME,      MS_LAZYTIME,    ZS_COMMENT      },
  112 #endif
  113         { MNTOPT_CONTEXT,       MS_COMMENT,     ZS_COMMENT      },
  114         { MNTOPT_FSCONTEXT,     MS_COMMENT,     ZS_COMMENT      },
  115         { MNTOPT_DEFCONTEXT,    MS_COMMENT,     ZS_COMMENT      },
  116         { MNTOPT_ROOTCONTEXT,   MS_COMMENT,     ZS_COMMENT      },
  117 #ifdef MS_I_VERSION
  118         { MNTOPT_IVERSION,      MS_I_VERSION,   ZS_COMMENT      },
  119 #endif
  120 #ifdef MS_MANDLOCK
  121         { MNTOPT_NBMAND,        MS_MANDLOCK,    ZS_COMMENT      },
  122         { MNTOPT_NONBMAND,      MS_COMMENT,     ZS_COMMENT      },
  123 #endif
  124         /* Valid options not found in mount(8) */
  125         { MNTOPT_BIND,          MS_BIND,        ZS_COMMENT      },
  126 #ifdef MS_REC
  127         { MNTOPT_RBIND,         MS_BIND|MS_REC, ZS_COMMENT      },
  128 #endif
  129         { MNTOPT_COMMENT,       MS_COMMENT,     ZS_COMMENT      },
  130 #ifdef MS_NOSUB
  131         { MNTOPT_NOSUB,         MS_NOSUB,       ZS_COMMENT      },
  132 #endif
  133 #ifdef MS_SILENT
  134         { MNTOPT_QUIET,         MS_SILENT,      ZS_COMMENT      },
  135 #endif
  136         /* Custom zfs options */
  137         { MNTOPT_XATTR,         MS_COMMENT,     ZS_COMMENT      },
  138         { MNTOPT_NOXATTR,       MS_COMMENT,     ZS_COMMENT      },
  139         { MNTOPT_ZFSUTIL,       MS_COMMENT,     ZS_ZFSUTIL      },
  140         { NULL,                 0,              0               } };
  141 
  142 /*
  143  * Break the mount option in to a name/value pair.  The name is
  144  * validated against the option map and mount flags set accordingly.
  145  */
  146 static int
  147 parse_option(char *mntopt, unsigned long *mntflags,
  148     unsigned long *zfsflags, int sloppy)
  149 {
  150         const option_map_t *opt;
  151         char *ptr, *name, *value = NULL;
  152         int error = 0;
  153 
  154         name = strdup(mntopt);
  155         if (name == NULL)
  156                 return (ENOMEM);
  157 
  158         for (ptr = name; ptr && *ptr; ptr++) {
  159                 if (*ptr == '=') {
  160                         *ptr = '\0';
  161                         value = ptr+1;
  162                         VERIFY3P(value, !=, NULL);
  163                         break;
  164                 }
  165         }
  166 
  167         for (opt = option_map; opt->name != NULL; opt++) {
  168                 if (strncmp(name, opt->name, strlen(name)) == 0) {
  169                         *mntflags |= opt->mntmask;
  170                         *zfsflags |= opt->zfsmask;
  171                         error = 0;
  172                         goto out;
  173                 }
  174         }
  175 
  176         if (!sloppy)
  177                 error = ENOENT;
  178 out:
  179         /* If required further process on the value may be done here */
  180         free(name);
  181         return (error);
  182 }
  183 
  184 /*
  185  * Translate the mount option string in to MS_* mount flags for the
  186  * kernel vfs.  When sloppy is non-zero unknown options will be ignored
  187  * otherwise they are considered fatal are copied in to badopt.
  188  */
  189 int
  190 zfs_parse_mount_options(const char *mntopts, unsigned long *mntflags,
  191     unsigned long *zfsflags, int sloppy, char *badopt, char *mtabopt)
  192 {
  193         int error = 0, quote = 0, flag = 0, count = 0;
  194         char *ptr, *opt, *opts;
  195 
  196         opts = strdup(mntopts);
  197         if (opts == NULL)
  198                 return (ENOMEM);
  199 
  200         *mntflags = 0;
  201         opt = NULL;
  202 
  203         /*
  204          * Scan through all mount options which must be comma delimited.
  205          * We must be careful to notice regions which are double quoted
  206          * and skip commas in these regions.  Each option is then checked
  207          * to determine if it is a known option.
  208          */
  209         for (ptr = opts; ptr && !flag; ptr++) {
  210                 if (opt == NULL)
  211                         opt = ptr;
  212 
  213                 if (*ptr == '"')
  214                         quote = !quote;
  215 
  216                 if (quote)
  217                         continue;
  218 
  219                 if (*ptr == '\0')
  220                         flag = 1;
  221 
  222                 if ((*ptr == ',') || (*ptr == '\0')) {
  223                         *ptr = '\0';
  224 
  225                         error = parse_option(opt, mntflags, zfsflags, sloppy);
  226                         if (error) {
  227                                 strcpy(badopt, opt);
  228                                 goto out;
  229 
  230                         }
  231 
  232                         if (!(*mntflags & MS_REMOUNT) &&
  233                             !(*zfsflags & ZS_ZFSUTIL) &&
  234                             mtabopt != NULL) {
  235                                 if (count > 0)
  236                                         strlcat(mtabopt, ",", MNT_LINE_MAX);
  237 
  238                                 strlcat(mtabopt, opt, MNT_LINE_MAX);
  239                                 count++;
  240                         }
  241 
  242                         opt = NULL;
  243                 }
  244         }
  245 
  246 out:
  247         free(opts);
  248         return (error);
  249 }
  250 
  251 static void
  252 append_mntopt(const char *name, const char *val, char *mntopts,
  253     char *mtabopt, boolean_t quote)
  254 {
  255         char tmp[MNT_LINE_MAX];
  256 
  257         snprintf(tmp, MNT_LINE_MAX, quote ? ",%s=\"%s\"" : ",%s=%s", name, val);
  258 
  259         if (mntopts)
  260                 strlcat(mntopts, tmp, MNT_LINE_MAX);
  261 
  262         if (mtabopt)
  263                 strlcat(mtabopt, tmp, MNT_LINE_MAX);
  264 }
  265 
  266 static void
  267 zfs_selinux_setcontext(zfs_handle_t *zhp, zfs_prop_t zpt, const char *name,
  268     char *mntopts, char *mtabopt)
  269 {
  270         char context[ZFS_MAXPROPLEN];
  271 
  272         if (zfs_prop_get(zhp, zpt, context, sizeof (context),
  273             NULL, NULL, 0, B_FALSE) == 0) {
  274                 if (strcmp(context, "none") != 0)
  275                         append_mntopt(name, context, mntopts, mtabopt, B_TRUE);
  276         }
  277 }
  278 
  279 void
  280 zfs_adjust_mount_options(zfs_handle_t *zhp, const char *mntpoint,
  281     char *mntopts, char *mtabopt)
  282 {
  283         char prop[ZFS_MAXPROPLEN];
  284 
  285         /*
  286          * Checks to see if the ZFS_PROP_SELINUX_CONTEXT exists
  287          * if it does, create a tmp variable in case it's needed
  288          * checks to see if the selinux context is set to the default
  289          * if it is, allow the setting of the other context properties
  290          * this is needed because the 'context' property overrides others
  291          * if it is not the default, set the 'context' property
  292          */
  293         if (zfs_prop_get(zhp, ZFS_PROP_SELINUX_CONTEXT, prop, sizeof (prop),
  294             NULL, NULL, 0, B_FALSE) == 0) {
  295                 if (strcmp(prop, "none") == 0) {
  296                         zfs_selinux_setcontext(zhp, ZFS_PROP_SELINUX_FSCONTEXT,
  297                             MNTOPT_FSCONTEXT, mntopts, mtabopt);
  298                         zfs_selinux_setcontext(zhp, ZFS_PROP_SELINUX_DEFCONTEXT,
  299                             MNTOPT_DEFCONTEXT, mntopts, mtabopt);
  300                         zfs_selinux_setcontext(zhp,
  301                             ZFS_PROP_SELINUX_ROOTCONTEXT, MNTOPT_ROOTCONTEXT,
  302                             mntopts, mtabopt);
  303                 } else {
  304                         append_mntopt(MNTOPT_CONTEXT, prop,
  305                             mntopts, mtabopt, B_TRUE);
  306                 }
  307         }
  308 
  309         /* A hint used to determine an auto-mounted snapshot mount point */
  310         append_mntopt(MNTOPT_MNTPOINT, mntpoint, mntopts, NULL, B_FALSE);
  311 }
  312 
  313 /*
  314  * By default the filesystem by preparing the mount options (i.e. parsing
  315  * some flags from the "opts" parameter into the "flags" parameter) and then
  316  * directly calling the system call mount(2). We don't need the mount utility
  317  * or update /etc/mtab, because this is a symlink on all modern systems.
  318  *
  319  * If the environment variable ZFS_MOUNT_HELPER is set, we fall back to the
  320  * previous behavior:
  321  * The filesystem is mounted by invoking the system mount utility rather
  322  * than by the system call mount(2).  This ensures that the /etc/mtab
  323  * file is correctly locked for the update.  Performing our own locking
  324  * and /etc/mtab update requires making an unsafe assumption about how
  325  * the mount utility performs its locking.  Unfortunately, this also means
  326  * in the case of a mount failure we do not have the exact errno.  We must
  327  * make due with return value from the mount process.
  328  */
  329 int
  330 do_mount(zfs_handle_t *zhp, const char *mntpt, const char *opts, int flags)
  331 {
  332         const char *src = zfs_get_name(zhp);
  333         int error = 0;
  334 
  335         if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
  336                 char badopt[MNT_LINE_MAX] = {0};
  337                 unsigned long mntflags = flags, zfsflags = 0;
  338                 char myopts[MNT_LINE_MAX] = {0};
  339 
  340                 if (zfs_parse_mount_options(opts, &mntflags,
  341                     &zfsflags, 0, badopt, NULL)) {
  342                         return (EINVAL);
  343                 }
  344                 strlcat(myopts, opts, MNT_LINE_MAX);
  345                 zfs_adjust_mount_options(zhp, mntpt, myopts, NULL);
  346                 if (mount(src, mntpt, MNTTYPE_ZFS, mntflags, myopts)) {
  347                         return (errno);
  348                 }
  349         } else {
  350                 char *argv[9] = {
  351                     (char *)"/bin/mount",
  352                     (char *)"--no-canonicalize",
  353                     (char *)"-t", (char *)MNTTYPE_ZFS,
  354                     (char *)"-o", (char *)opts,
  355                     (char *)src,
  356                     (char *)mntpt,
  357                     (char *)NULL };
  358 
  359                 /* Return only the most critical mount error */
  360                 error = libzfs_run_process(argv[0], argv,
  361                     STDOUT_VERBOSE|STDERR_VERBOSE);
  362                 if (error) {
  363                         if (error & MOUNT_FILEIO) {
  364                                 error = EIO;
  365                         } else if (error & MOUNT_USER) {
  366                                 error = EINTR;
  367                         } else if (error & MOUNT_SOFTWARE) {
  368                                 error = EPIPE;
  369                         } else if (error & MOUNT_BUSY) {
  370                                 error = EBUSY;
  371                         } else if (error & MOUNT_SYSERR) {
  372                                 error = EAGAIN;
  373                         } else if (error & MOUNT_USAGE) {
  374                                 error = EINVAL;
  375                         } else
  376                                 error = ENXIO; /* Generic error */
  377                 }
  378         }
  379 
  380         return (error);
  381 }
  382 
  383 int
  384 do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags)
  385 {
  386         (void) zhp;
  387 
  388         if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
  389                 int rv = umount2(mntpt, flags);
  390 
  391                 return (rv < 0 ? errno : 0);
  392         }
  393 
  394         char *argv[7] = {
  395             (char *)"/bin/umount",
  396             (char *)"-t", (char *)MNTTYPE_ZFS,
  397             NULL, NULL, NULL, NULL };
  398         int rc, count = 3;
  399 
  400         if (flags & MS_FORCE)
  401                 argv[count++] = (char *)"-f";
  402 
  403         if (flags & MS_DETACH)
  404                 argv[count++] = (char *)"-l";
  405 
  406         argv[count] = (char *)mntpt;
  407         rc = libzfs_run_process(argv[0], argv, STDOUT_VERBOSE|STDERR_VERBOSE);
  408 
  409         return (rc ? EINVAL : 0);
  410 }
  411 
  412 int
  413 zfs_mount_delegation_check(void)
  414 {
  415         return ((geteuid() != 0) ? EACCES : 0);
  416 }
  417 
  418 /* Called from the tail end of zpool_disable_datasets() */
  419 void
  420 zpool_disable_datasets_os(zpool_handle_t *zhp, boolean_t force)
  421 {
  422         (void) zhp, (void) force;
  423 }
  424 
  425 /* Called from the tail end of zfs_unmount() */
  426 void
  427 zpool_disable_volume_os(const char *name)
  428 {
  429         (void) name;
  430 }

Cache object: d201c86d79922b68fd1dafbfffe9ef80


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.