diff --git a/contrib/dracut/90zfs/mount-zfs.sh.in b/contrib/dracut/90zfs/mount-zfs.sh.in index 5d02a8d74501..fa9f1bb767b8 100755 --- a/contrib/dracut/90zfs/mount-zfs.sh.in +++ b/contrib/dracut/90zfs/mount-zfs.sh.in @@ -1,119 +1,120 @@ #!/bin/sh # shellcheck disable=SC2034,SC2154 . /lib/dracut-zfs-lib.sh decode_root_args || return 0 GENERATOR_FILE=/run/systemd/generator/sysroot.mount GENERATOR_EXTENSION=/run/systemd/generator/sysroot.mount.d/zfs-enhancement.conf if [ -e "$GENERATOR_FILE" ] && [ -e "$GENERATOR_EXTENSION" ]; then # We're under systemd and dracut-zfs-generator ran to completion. info "ZFS: Delegating root mount to sysroot.mount at al." # We now prevent Dracut from running this thing again. rm -f "$hookdir"/mount/*zfs* return fi info "ZFS: No sysroot.mount exists or zfs-generator did not extend it." info "ZFS: Mounting root with the traditional mount-zfs.sh instead." # ask_for_password tries prompt cmd # # Wraps around plymouth ask-for-password and adds fallback to tty password ask # if plymouth is not present. ask_for_password() { tries="$1" prompt="$2" cmd="$3" { flock -s 9 # Prompt for password with plymouth, if installed and running. if plymouth --ping 2>/dev/null; then plymouth ask-for-password \ --prompt "$prompt" --number-of-tries="$tries" | \ eval "$cmd" ret=$? else i=1 while [ "$i" -le "$tries" ]; do printf "%s [%i/%i]:" "$prompt" "$i" "$tries" >&2 eval "$cmd" && ret=0 && break ret=$? i=$((i+1)) printf '\n' >&2 done unset i fi } 9>/.console_lock [ "$ret" -ne 0 ] && echo "Wrong password" >&2 return "$ret" } # Delay until all required block devices are present. modprobe zfs 2>/dev/null udevadm settle ZFS_DATASET= ZFS_POOL= if [ "${root}" = "zfs:AUTO" ] ; then if ! ZFS_DATASET="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"; then # shellcheck disable=SC2086 zpool import -N -a ${ZPOOL_IMPORT_OPTS} if ! ZFS_DATASET="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"; then warn "ZFS: No bootfs attribute found in importable pools." zpool export -aF rootok=0 return 1 fi fi info "ZFS: Using ${ZFS_DATASET} as root." fi ZFS_DATASET="${ZFS_DATASET:-${root}}" ZFS_POOL="${ZFS_DATASET%%/*}" if ! zpool get -Ho name "${ZFS_POOL}" > /dev/null 2>&1; then info "ZFS: Importing pool ${ZFS_POOL}..." # shellcheck disable=SC2086 if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${ZFS_POOL}"; then warn "ZFS: Unable to import pool ${ZFS_POOL}" rootok=0 return 1 fi fi # Load keys if we can or if we need to +# TODO: for_relevant_root_children like in zfs-load-key.sh.in if [ "$(zpool get -Ho value feature@encryption "${ZFS_POOL}")" = 'active' ]; then # if the root dataset has encryption enabled ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${ZFS_DATASET}")" if ! [ "${ENCRYPTIONROOT}" = "-" ]; then KEYSTATUS="$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")" # if the key needs to be loaded if [ "$KEYSTATUS" = "unavailable" ]; then # decrypt them ask_for_password \ 5 \ "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \ "zfs load-key '${ENCRYPTIONROOT}'" fi fi fi # Let us tell the initrd to run on shutdown. # We have a shutdown hook to run # because we imported the pool. info "ZFS: Mounting dataset ${ZFS_DATASET}..." if ! mount_dataset "${ZFS_DATASET}"; then rootok=0 return 1 fi diff --git a/contrib/dracut/90zfs/zfs-load-key.sh.in b/contrib/dracut/90zfs/zfs-load-key.sh.in index 97e9246d4644..d916f43b4e95 100755 --- a/contrib/dracut/90zfs/zfs-load-key.sh.in +++ b/contrib/dracut/90zfs/zfs-load-key.sh.in @@ -1,57 +1,64 @@ #!/bin/sh # shellcheck disable=SC2154 # only run this on systemd systems, we handle the decrypt in mount-zfs.sh in the mount hook otherwise [ -e /bin/systemctl ] || [ -e /usr/bin/systemctl ] || return 0 # shellcheck source=zfs-lib.sh.in . /lib/dracut-zfs-lib.sh decode_root_args || return 0 # There is a race between the zpool import and the pre-mount hooks, so we wait for a pool to be imported while ! systemctl is-active --quiet zfs-import.target; do systemctl is-failed --quiet zfs-import-cache.service zfs-import-scan.service && return 1 sleep 0.1s done BOOTFS="$root" if [ "$BOOTFS" = "zfs:AUTO" ]; then BOOTFS="$(zpool get -Ho value bootfs | grep -m1 -vFx -)" fi [ "$(zpool get -Ho value feature@encryption "${BOOTFS%%/*}")" = 'active' ] || return 0 -ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${BOOTFS}")" -[ "${ENCRYPTIONROOT}" = "-" ] && return 0 - -[ "$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")" = "unavailable" ] || return 0 - -KEYLOCATION="$(zfs get -H -o value keylocation "${ENCRYPTIONROOT}")" -case "${KEYLOCATION%%://*}" in - prompt) - for _ in 1 2 3; do - systemd-ask-password --no-tty "Encrypted ZFS password for ${BOOTFS}" | zfs load-key "${ENCRYPTIONROOT}" && break - done - ;; - http*) - systemctl start network-online.target - zfs load-key "${ENCRYPTIONROOT}" - ;; - file) - KEYFILE="${KEYLOCATION#file://}" - [ -r "${KEYFILE}" ] || udevadm settle - [ -r "${KEYFILE}" ] || { - info "ZFS: Waiting for key ${KEYFILE} for ${ENCRYPTIONROOT}..." - for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do - sleep 0.5s - [ -r "${KEYFILE}" ] && break +_load_key_cb() { + dataset="$1" + + ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${dataset}")" + [ "${ENCRYPTIONROOT}" = "-" ] && return 0 + + [ "$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")" = "unavailable" ] || return 0 + + KEYLOCATION="$(zfs get -Ho value keylocation "${ENCRYPTIONROOT}")" + case "${KEYLOCATION%%://*}" in + prompt) + for _ in 1 2 3; do + systemd-ask-password --no-tty "Encrypted ZFS password for ${dataset}" | zfs load-key "${ENCRYPTIONROOT}" && break done - } - [ -r "${KEYFILE}" ] || warn "ZFS: Key ${KEYFILE} for ${ENCRYPTIONROOT} hasn't appeared. Trying anyway." - zfs load-key "${ENCRYPTIONROOT}" - ;; - *) - zfs load-key "${ENCRYPTIONROOT}" - ;; -esac + ;; + http*) + systemctl start network-online.target + zfs load-key "${ENCRYPTIONROOT}" + ;; + file) + KEYFILE="${KEYLOCATION#file://}" + [ -r "${KEYFILE}" ] || udevadm settle + [ -r "${KEYFILE}" ] || { + info "ZFS: Waiting for key ${KEYFILE} for ${ENCRYPTIONROOT}..." + for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + sleep 0.5s + [ -r "${KEYFILE}" ] && break + done + } + [ -r "${KEYFILE}" ] || warn "ZFS: Key ${KEYFILE} for ${ENCRYPTIONROOT} hasn't appeared. Trying anyway." + zfs load-key "${ENCRYPTIONROOT}" + ;; + *) + zfs load-key "${ENCRYPTIONROOT}" + ;; + esac +} + +_load_key_cb "$BOOTFS" +for_relevant_root_children "$BOOTFS" _load_key_cb