summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorнаб <nabijaczleweli@nabijaczleweli.xyz>2021-04-13 06:26:55 +0200
committerBrian Behlendorf <behlendorf1@llnl.gov>2021-05-19 20:00:08 -0700
commite684da8f5211e63971603fc2a9ec69189b17983c (patch)
tree29a1f86ed4880e4d83ff0b6cd61fad29a3f8cf46
parentb5c3844218387d82dc39189d389bf45aed7a6cb2 (diff)
libzfs: zfs_mount_at(): load key for encryption root if MS_CRYPT
zfs_crypto_load_key() only works on encryption roots, and zfs mount -la would fail if it encounters a datasets that is sorted before their encroots. To trigger: truncate -s 40G /tmp/test dd if=/dev/urandom of=/tmp/k bs=128 count=1 status=none zpool create -O encryption=on -O keylocation=file:///tmp/k \ -O keyformat=passphrase test /tmp/test zfs create -o mountpoint=/a test/a zfs create -o mountpoint=/b test/b zfs umount test zfs unload-key test zfs mount -la The final mount errored out with: Key load error: Keys must be loaded for encryption root of 'test/a' (test). Key load error: Keys must be loaded for encryption root of 'test/b' (test). And only /test was mounted This technically breaks the libzfs API, but the previous behavior was decidedly a bug. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz> Closes #11870 Closes #11875
-rw-r--r--lib/libzfs/libzfs_mount.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c
index d4efb0908..4a5335d71 100644
--- a/lib/libzfs/libzfs_mount.c
+++ b/lib/libzfs/libzfs_mount.c
@@ -385,6 +385,9 @@ zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags,
struct stat buf;
char mntopts[MNT_LINE_MAX];
char overlay[ZFS_MAXPROPLEN];
+ char prop_encroot[MAXNAMELEN];
+ boolean_t is_encroot;
+ zfs_handle_t *encroot_hp = zhp;
libzfs_handle_t *hdl = zhp->zfs_hdl;
uint64_t keystatus;
int remount = 0, rc;
@@ -443,7 +446,27 @@ zfs_mount_at(zfs_handle_t *zhp, const char *options, int flags,
*/
if (keystatus == ZFS_KEYSTATUS_UNAVAILABLE) {
if (flags & MS_CRYPT) {
- rc = zfs_crypto_load_key(zhp, B_FALSE, NULL);
+ rc = zfs_crypto_get_encryption_root(zhp,
+ &is_encroot, prop_encroot);
+ if (rc) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Failed to get encryption root for "
+ "'%s'."), zfs_get_name(zhp));
+ return (rc);
+ }
+
+ if (!is_encroot) {
+ encroot_hp = zfs_open(hdl, prop_encroot,
+ ZFS_TYPE_DATASET);
+ if (encroot_hp == NULL)
+ return (hdl->libzfs_error);
+ }
+
+ rc = zfs_crypto_load_key(encroot_hp,
+ B_FALSE, NULL);
+
+ if (!is_encroot)
+ zfs_close(encroot_hp);
if (rc)
return (rc);
} else {