From 2ff6ac718c182ae2f8cd88ace4d6d67dc46e6184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Fri, 9 Apr 2021 19:53:25 +0200 Subject: [PATCH] libzfs: zfs_mount_at(): load key for encryption root if MS_CRYPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit zfs_crypto_load_key() only works on encryption roots, and zfs mount -la would fail if it encounted datasets that 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 behaviour was decidedly a bug, so Signed-off-by: Ahelenia ZiemiaƄska Closes #11870 --- lib/libzfs/libzfs_mount.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index 45dccccd4e29..d3f7e6106c6b 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 {