1#!/bin/bash 2 3# only run this on systemd systems, we handle the decrypt in mount-zfs.sh in the mount hook otherwise 4[ -e /bin/systemctl ] || return 0 5 6# This script only gets executed on systemd systems, see mount-zfs.sh for non-systemd systems 7 8# import the libs now that we know the pool imported 9[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh 10[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh 11# shellcheck source=./lib-zfs.sh.in 12. "$dracutlib" 13 14# load the kernel command line vars 15[ -z "$root" ] && root="$(getarg root=)" 16# If root is not ZFS= or zfs: or rootfstype is not zfs then we are not supposed to handle it. 17[ "${root##zfs:}" = "${root}" ] && [ "${root##ZFS=}" = "${root}" ] && [ "$rootfstype" != "zfs" ] && exit 0 18 19# There is a race between the zpool import and the pre-mount hooks, so we wait for a pool to be imported 20while true; do 21 zpool list -H | grep -q -v '^$' && break 22 [ "$(systemctl is-failed zfs-import-cache.service)" = 'failed' ] && exit 1 23 [ "$(systemctl is-failed zfs-import-scan.service)" = 'failed' ] && exit 1 24 sleep 0.1s 25done 26 27# run this after import as zfs-import-cache/scan service is confirmed good 28# we do not overwrite the ${root} variable, but create a new one, BOOTFS, to hold the dataset 29if [ "${root}" = "zfs:AUTO" ] ; then 30 BOOTFS="$(zpool list -H -o bootfs | awk '$1 != "-" {print; exit}')" 31else 32 BOOTFS="${root##zfs:}" 33 BOOTFS="${BOOTFS##ZFS=}" 34fi 35 36# if pool encryption is active and the zfs command understands '-o encryption' 37if [ "$(zpool list -H -o feature@encryption $(echo "${BOOTFS}" | awk -F\/ '{print $1}'))" = 'active' ]; then 38 # if the root dataset has encryption enabled 39 ENCRYPTIONROOT=$(zfs get -H -o value encryptionroot "${BOOTFS}") 40 # where the key is stored (in a file or loaded via prompt) 41 KEYLOCATION=$(zfs get -H -o value keylocation "${ENCRYPTIONROOT}") 42 if ! [ "${ENCRYPTIONROOT}" = "-" ]; then 43 KEYSTATUS="$(zfs get -H -o value keystatus "${ENCRYPTIONROOT}")" 44 # continue only if the key needs to be loaded 45 [ "$KEYSTATUS" = "unavailable" ] || exit 0 46 # if key is stored in a file, do not prompt 47 if ! [ "${KEYLOCATION}" = "prompt" ]; then 48 zfs load-key "${ENCRYPTIONROOT}" 49 else 50 # decrypt them 51 TRY_COUNT=5 52 while [ $TRY_COUNT -gt 0 ]; do 53 systemd-ask-password "Encrypted ZFS password for ${BOOTFS}" --no-tty | zfs load-key "${ENCRYPTIONROOT}" && break 54 TRY_COUNT=$((TRY_COUNT - 1)) 55 done 56 fi 57 fi 58fi 59