aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKash Pande <[email protected]>2018-02-20 13:13:20 -0500
committerBrian Behlendorf <[email protected]>2018-02-23 12:57:28 -0800
commit7280d581973e923c6492b59803246a94347a47b8 (patch)
treeb69fe52d69d526ba08e1d4eb809901988f657290
parentbf95a000c432dc92591432bfd2b7943cbbfb6708 (diff)
Enable booting from nested encrypted datasets
- enable booting from nested encrypted datasets - fix plymouth boot splash passphrase entry - optimize unlock process Co-authored-by: Kash Pande <[email protected]> Co-authored-by: Matthew Thode <[email protected]> Signed-off-by: Kash Pande <[email protected]> Signed-off-by: Matthew Thode <[email protected]> Closes #7214
-rwxr-xr-xcontrib/dracut/90zfs/mount-zfs.sh.in27
-rwxr-xr-xcontrib/dracut/90zfs/zfs-lib.sh.in72
-rwxr-xr-xcontrib/dracut/90zfs/zfs-load-key.sh.in16
3 files changed, 82 insertions, 33 deletions
diff --git a/contrib/dracut/90zfs/mount-zfs.sh.in b/contrib/dracut/90zfs/mount-zfs.sh.in
index 36f07d667..5b6998b74 100755
--- a/contrib/dracut/90zfs/mount-zfs.sh.in
+++ b/contrib/dracut/90zfs/mount-zfs.sh.in
@@ -59,28 +59,13 @@ if import_pool "${ZFS_POOL}" ; then
# Load keys if we can or if we need to
if [ $(zpool list -H -o feature@encryption $(echo "${ZFS_POOL}" | awk -F\/ '{print $1}')) == 'active' ]; then
# if the root dataset has encryption enabled
- if $(zfs list -H -o encryption "${ZFS_DATASET}" | grep -q -v off); then
- # figure out where the root dataset has its key, the keylocation should not be none
- while true; do
- if [[ $(zfs list -H -o keylocation "${ZFS_DATASET}") == 'none' ]]; then
- ZFS_DATASET=$(echo -n "${ZFS_DATASET}" | awk 'BEGIN{FS=OFS="/"}{NF--; print}')
- if [[ "${ZFS_DATASET}" == '' ]]; then
- rootok=0
- break
- fi
- else
- rootok=1
- break
- fi
- done
- [[ "${rootok}" -eq 0 ]]&& return 1
+ ENCRYPTIONROOT=$(zfs get -H -o value encryptionroot ${ZFS_DATASET})
+ if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
# decrypt them
- TRY_COUNT=5
- while [ $TRY_COUNT != 0 ]; do
- zfs load-key "${ZFS_DATASET}"
- [ $? == 0 ] && break
- ((TRY_COUNT-=1))
- done
+ ask_for_password \
+ --tries 5 \
+ --prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \
+ --cmd "zfs load-key ${ENCRYPTIONROOT}"
fi
fi
# Let us tell the initrd to run on shutdown.
diff --git a/contrib/dracut/90zfs/zfs-lib.sh.in b/contrib/dracut/90zfs/zfs-lib.sh.in
index c988dfe60..82666afd0 100755
--- a/contrib/dracut/90zfs/zfs-lib.sh.in
+++ b/contrib/dracut/90zfs/zfs-lib.sh.in
@@ -103,3 +103,75 @@ export_all() {
return ${ret}
}
+
+# ask_for_password
+#
+# Wraps around plymouth ask-for-password and adds fallback to tty password ask
+# if plymouth is not present.
+#
+# --cmd command
+# Command to execute. Required.
+# --prompt prompt
+# Password prompt. Note that function already adds ':' at the end.
+# Recommended.
+# --tries n
+# How many times repeat command on its failure. Default is 3.
+# --ply-[cmd|prompt|tries]
+# Command/prompt/tries specific for plymouth password ask only.
+# --tty-[cmd|prompt|tries]
+# Command/prompt/tries specific for tty password ask only.
+# --tty-echo-off
+# Turn off input echo before tty command is executed and turn on after.
+# It's useful when password is read from stdin.
+ask_for_password() {
+ local cmd; local prompt; local tries=3
+ local ply_cmd; local ply_prompt; local ply_tries=3
+ local tty_cmd; local tty_prompt; local tty_tries=3
+ local ret
+
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ --cmd) ply_cmd="$2"; tty_cmd="$2"; shift;;
+ --ply-cmd) ply_cmd="$2"; shift;;
+ --tty-cmd) tty_cmd="$2"; shift;;
+ --prompt) ply_prompt="$2"; tty_prompt="$2"; shift;;
+ --ply-prompt) ply_prompt="$2"; shift;;
+ --tty-prompt) tty_prompt="$2"; shift;;
+ --tries) ply_tries="$2"; tty_tries="$2"; shift;;
+ --ply-tries) ply_tries="$2"; shift;;
+ --tty-tries) tty_tries="$2"; shift;;
+ --tty-echo-off) tty_echo_off=yes;;
+ esac
+ shift
+ done
+
+ { flock -s 9;
+ # Prompt for password with plymouth, if installed and running.
+ if type plymouth >/dev/null 2>&1 && plymouth --ping 2>/dev/null; then
+ plymouth ask-for-password \
+ --prompt "$ply_prompt" --number-of-tries=$ply_tries \
+ --command="$ply_cmd"
+ ret=$?
+ else
+ if [ "$tty_echo_off" = yes ]; then
+ stty_orig="$(stty -g)"
+ stty -echo
+ fi
+
+ local i=1
+ while [ $i -le $tty_tries ]; do
+ [ -n "$tty_prompt" ] && \
+ printf "$tty_prompt [$i/$tty_tries]:" >&2
+ eval "$tty_cmd" && ret=0 && break
+ ret=$?
+ i=$(($i+1))
+ [ -n "$tty_prompt" ] && printf '\n' >&2
+ done
+
+ [ "$tty_echo_off" = yes ] && stty $stty_orig
+ fi
+ } 9>/.console_lock
+
+ [ $ret -ne 0 ] && echo "Wrong password" >&2
+ return $ret
+}
diff --git a/contrib/dracut/90zfs/zfs-load-key.sh.in b/contrib/dracut/90zfs/zfs-load-key.sh.in
index 9a6241bd7..6c1f423ae 100755
--- a/contrib/dracut/90zfs/zfs-load-key.sh.in
+++ b/contrib/dracut/90zfs/zfs-load-key.sh.in
@@ -33,21 +33,13 @@ fi
# if pool encryption is active and the zfs command understands '-o encryption'
if [[ $(zpool list -H -o feature@encryption $(echo "${root}" | awk -F\/ '{print $1}')) == 'active' ]]; then
- # check if root dataset has encryption enabled
- if $(zfs list -H -o encryption "${root}" | grep -q -v off); then
- # figure out where the root dataset has its key, the keylocation should not be none
- while true; do
- if [[ $(zfs list -H -o keylocation "${root}") == 'none' ]]; then
- root=$(echo -n "${root}" | awk 'BEGIN{FS=OFS="/"}{NF--; print}')
- [[ "${root}" == '' ]] && exit 1
- else
- break
- fi
- done
+ # if the root dataset has encryption enabled
+ ENCRYPTIONROOT=$(zfs get -H -o value encryptionroot ${ZFS_DATASET})
+ if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
# decrypt them
TRY_COUNT=5
while [ $TRY_COUNT != 0 ]; do
- zfs load-key "$root" <<< $(systemd-ask-password "Encrypted ZFS password for ${root}: ")
+ zfs load-key "${ENCRYPTIONROOT}" <<< $(systemd-ask-password "Encrypted ZFS password for ${root}: ")
[[ $? == 0 ]] && break
((TRY_COUNT-=1))
done