diff options
author | наб <[email protected]> | 2021-04-13 06:26:55 +0200 |
---|---|---|
committer | Tony Hutter <[email protected]> | 2021-06-23 13:22:14 -0700 |
commit | 3430eced806fc5a8be24900f217898a0ae2dfe69 (patch) | |
tree | 29a1f86ed4880e4d83ff0b6cd61fad29a3f8cf46 | |
parent | 0839934d84adbd295e767808a7debbbea171bdb0 (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 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 { |