diff options
author | наб <[email protected]> | 2021-04-13 06:26:55 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2021-04-12 21:26:55 -0700 |
commit | b3530c4262275d6a6419a259b2f58c3c12664ea6 (patch) | |
tree | 51cce8be10281778969304afc4318da277d0e9e2 | |
parent | 93f81eb7211becfa2acccac640e7f8c92fd76e0d (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 <[email protected]>
Signed-off-by: Ahelenia Ziemiańska <[email protected]>
Closes #11870
Closes #11875
-rw-r--r-- | lib/libzfs/libzfs_mount.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index 45dccccd4..d3f7e6106 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 { |