diff options
Diffstat (limited to 'usr/src/lib/libzfs/common/libzfs_mount.c')
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_mount.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_mount.c b/usr/src/lib/libzfs/common/libzfs_mount.c index 9bbf4d2233..44c0ec89e9 100644 --- a/usr/src/lib/libzfs/common/libzfs_mount.c +++ b/usr/src/lib/libzfs/common/libzfs_mount.c @@ -80,6 +80,7 @@ #include <sys/mount.h> #include <sys/stat.h> #include <sys/statvfs.h> +#include <sys/dsl_crypt.h> #include <libzfs.h> @@ -339,6 +340,8 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) char mountpoint[ZFS_MAXPROPLEN]; char mntopts[MNT_LINE_MAX]; libzfs_handle_t *hdl = zhp->zfs_hdl; + uint64_t keystatus; + int rc; if (options == NULL) mntopts[0] = '\0'; @@ -354,6 +357,39 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL)) return (0); + /* + * If the filesystem is encrypted the key must be loaded in order to + * mount. If the key isn't loaded, the MS_CRYPT flag decides whether + * or not we attempt to load the keys. Note: we must call + * zfs_refresh_properties() here since some callers of this function + * (most notably zpool_enable_datasets()) may implicitly load our key + * by loading the parent's key first. + */ + if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) { + zfs_refresh_properties(zhp); + keystatus = zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS); + + /* + * If the key is unavailable and MS_CRYPT is set give the + * user a chance to enter the key. Otherwise just fail + * immediately. + */ + if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) { + if (flags & MS_CRYPT) { + rc = zfs_crypto_load_key(zhp, B_FALSE, NULL); + if (rc != 0) + return (rc); + } else { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "encryption key not loaded")); + return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, + dgettext(TEXT_DOMAIN, "cannot mount '%s'"), + mountpoint)); + } + } + + } + /* Create the directory if it doesn't already exist */ if (lstat(mountpoint, &buf) != 0) { if (mkdirp(mountpoint, 0755) != 0) { @@ -1121,6 +1157,12 @@ zfs_iter_cb(zfs_handle_t *zhp, void *data) return (0); } + if (zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) == + ZFS_KEYSTATUS_UNAVAILABLE) { + zfs_close(zhp); + return (0); + } + /* * If this filesystem is inconsistent and has a receive resume * token, we can not mount it. @@ -1313,6 +1355,10 @@ zfs_mount_one(zfs_handle_t *zhp, void *arg) mount_state_t *ms = arg; int ret = 0; + if (zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) == + ZFS_KEYSTATUS_UNAVAILABLE) + return (0); + if (zfs_mount(zhp, ms->ms_mntopts, ms->ms_mntflags) != 0) ret = ms->ms_mntstatus = -1; return (ret); |