openzfs / zfs

OpenZFS on Linux and FreeBSD
https://openzfs.github.io/openzfs-docs
Other
10.61k stars 1.75k forks source link

LUKS based encryption keys fail to load from ZFS during encrypted root filesystem boot #15808

Open antevens opened 9 months ago

antevens commented 9 months ago

Type | 2.2.2-1/Name

--- --- Linux Mint 21.3 Virginia 6.6.11-zabbly+ x86_64 2.2.2-1

Describe the problem you're observing

Default initramfs scripts don't check for a LUKS based ZFS keystore during boot.

Describe how to reproduce the problem

Install Ubuntu/Mint linux with full disk encryption and ZFS. Upgrade kernel and ZFS with packages from https://github.com/zabbly/linux/ https://github.com/zabbly/zfs Reboot

Key load error: Failed to open key material file: No such file or directory

Command: mount -o zfsutil -t zfs rpool/ROOT/ubuntu_xxxxx /root//
Message: zfs_mount_at() failed: encryption key not loadedzfsmount_at() failed: encryption key not loadedmount: mounting rpool/ROOT/ubuntu_xxxxx on /root\\ failed: Permisssion denied
Error 2

Failed to mount rpool/ROOT/ubuntu_xxxxxx on /root//.
Manually mount the filesyste and exit.

BusyBox v1.3.0.1 (Ubuntu 1:1.30.1-7ubuntu3) built-in shell (ash)
Enter 'help' for a list of built-in commands.

(initramfs)

The Cannonical package version of /usr/share/initramfs-tools/scripts/zfs includes the following snipped on line 914 (currently), after finding and importing the correct pool and before preparing the root filesystem

# Open and mount luks keystore for any pools using one
CRYPTROOT=/scripts/local-top/cryptroot
# We already processed original crypttab by calling local-top. Only add zvol related ones now.
if [ -x "${CRYPTROOT}" ]; then
        TABFILE=/cryptroot/crypttab
        :>"${TABFILE}"
    # Wait for all keystore devices in /dev/zvol to appear with a 5s timeout
    timeout=50
    NUMKS=$(zfs list -H -o name | grep '/keystore$' | wc -l)
    while [ ${NUMKS} -ne $(find /dev/zvol/ -name 'keystore' | wc -l) ]; do
        if [ $timeout -le 0 ]; then
            break
        fi
        sleep .1
        timeout=$((timeout - 1))
    done
    # Locate, then mount the keystore volumes
    for ks in $(find /dev/zvol/ -name 'keystore'); do
        [ ! -e "${ks}" ] && continue
        pool="$(basename $(dirname ${ks}))"
        echo "keystore-${pool} ${ks} none luks,discard" >> "${TABFILE}"
    done
    ${CRYPTROOT}
    for dev in $(find /dev/mapper -name 'keystore-*'); do
        # Translate filename to path
        storepath="/run/$(echo $(basename ${dev})|sed -e 's,-,/,')"
        mkdir -p "${storepath}"
        mount "${dev}" "${storepath}"
    done
fi
antevens commented 9 months ago

https://github.com/zabbly/zfs/issues/1