summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzfs/common/libzfs_mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libzfs/common/libzfs_mount.c')
-rw-r--r--usr/src/lib/libzfs/common/libzfs_mount.c46
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);