Fix encryption logic in systemd mount generator

Previously the generator would skip a dataset if it wasn't mountable by
'zfs mount -a' (legacy/none mountpoint, canmount off/noauto). This also
skipped the generation of key-load units for such datasets, breaking
the dependency handling for mountable child datasets.

Reviewed-by: Antonio Russo <antonio.e.russo@gmail.com>
Reviewed-by: Richard Laager <rlaager@wiktel.com>
Signed-off-by: InsanePrawn <insane.prawny@gmail.com>
Closes #9611
This commit is contained in:
InsanePrawn 2019-11-22 18:53:51 +01:00 committed by Brian Behlendorf
parent 70d2dd922b
commit c940bf0c37
1 changed files with 57 additions and 50 deletions

View File

@ -74,6 +74,62 @@ process_line() {
p_encroot="${11}" p_encroot="${11}"
p_keyloc="${12}" p_keyloc="${12}"
# Minimal pre-requisites to mount a ZFS dataset
wants="zfs-import.target"
# Handle encryption
if [ -n "${p_encroot}" ] &&
[ "${p_encroot}" != "-" ] ; then
keyloadunit="zfs-load-key-$(systemd-escape "${p_encroot}").service"
if [ "${p_encroot}" = "${dataset}" ] ; then
pathdep=""
if [ "${p_keyloc%%://*}" = "file" ] ; then
pathdep="RequiresMountsFor='${p_keyloc#file://}'"
keyloadcmd="@sbindir@/zfs load-key '${dataset}'"
elif [ "${p_keyloc}" = "prompt" ] ; then
keyloadcmd="/bin/sh -c 'set -eu;"\
"keystatus=\"\$\$(@sbindir@/zfs get -H -o value keystatus \"${dataset}\")\";"\
"[ \"\$\$keystatus\" = \"unavailable\" ] || exit 0;"\
"count=0;"\
"while [ \$\$count -lt 3 ];do"\
" systemd-ask-password --id=\"zfs:${dataset}\""\
" \"Enter passphrase for ${dataset}:\"|"\
" @sbindir@/zfs load-key \"${dataset}\" && exit 0;"\
" count=\$\$((count + 1));"\
"done;"\
"exit 1'"
else
printf 'zfs-mount-generator: (%s) invalid keylocation\n' \
"${dataset}" >/dev/kmsg
fi
# Generate the key-load .service unit
cat > "${dest_norm}/${keyloadunit}" << EOF
# Automatically generated by zfs-mount-generator
[Unit]
Description=Load ZFS key for ${dataset}
SourcePath=${cachefile}
Documentation=man:zfs-mount-generator(8)
DefaultDependencies=no
Wants=${wants}
After=${wants}
${pathdep}
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=${keyloadcmd}
ExecStop=@sbindir@/zfs unload-key '${dataset}'
EOF
fi
# Update the dependencies for the mount file to require the
# key-loading unit.
wants="${wants} ${keyloadunit}"
fi
# Prepare the .mount unit
# Check for canmount=off . # Check for canmount=off .
if [ "${p_canmount}" = "off" ] ; then if [ "${p_canmount}" = "off" ] ; then
return return
@ -170,56 +226,6 @@ process_line() {
"${dataset}" >/dev/kmsg "${dataset}" >/dev/kmsg
fi fi
# Minimal pre-requisites to mount a ZFS dataset
wants="zfs-import.target"
if [ -n "${p_encroot}" ] &&
[ "${p_encroot}" != "-" ] ; then
keyloadunit="zfs-load-key-$(systemd-escape "${p_encroot}").service"
if [ "${p_encroot}" = "${dataset}" ] ; then
pathdep=""
if [ "${p_keyloc%%://*}" = "file" ] ; then
pathdep="RequiresMountsFor='${p_keyloc#file://}'"
keyloadcmd="@sbindir@/zfs load-key '${dataset}'"
elif [ "${p_keyloc}" = "prompt" ] ; then
keyloadcmd="/bin/sh -c 'set -eu;"\
"keystatus=\"\$\$(@sbindir@/zfs get -H -o value keystatus \"${dataset}\")\";"\
"[ \"\$\$keystatus\" = \"unavailable\" ] || exit 0;"\
"count=0;"\
"while [ \$\$count -lt 3 ];do"\
" systemd-ask-password --id=\"zfs:${dataset}\""\
" \"Enter passphrase for ${dataset}:\"|"\
" @sbindir@/zfs load-key \"${dataset}\" && exit 0;"\
" count=\$\$((count + 1));"\
"done;"\
"exit 1'"
else
printf 'zfs-mount-generator: (%s) invalid keylocation\n' \
"${dataset}" >/dev/kmsg
fi
cat > "${dest_norm}/${keyloadunit}" << EOF
# Automatically generated by zfs-mount-generator
[Unit]
Description=Load ZFS key for ${dataset}
SourcePath=${cachefile}
Documentation=man:zfs-mount-generator(8)
DefaultDependencies=no
Wants=${wants}
After=${wants}
${pathdep}
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=${keyloadcmd}
ExecStop=@sbindir@/zfs unload-key '${dataset}'
EOF
fi
# Update the dependencies for the mount file to require the
# key-loading unit.
wants="${wants} ${keyloadunit}"
fi
# If the mountpoint has already been created, give it precedence. # If the mountpoint has already been created, give it precedence.
if [ -e "${dest_norm}/${mountfile}" ] ; then if [ -e "${dest_norm}/${mountfile}" ] ; then
printf 'zfs-mount-generator: %s already exists\n' "${mountfile}" \ printf 'zfs-mount-generator: %s already exists\n' "${mountfile}" \
@ -227,6 +233,7 @@ EOF
return return
fi fi
# Create the .mount unit file.
# By ordering before zfs-mount.service, we avoid race conditions. # By ordering before zfs-mount.service, we avoid race conditions.
cat > "${dest_norm}/${mountfile}" << EOF cat > "${dest_norm}/${mountfile}" << EOF
# Automatically generated by zfs-mount-generator # Automatically generated by zfs-mount-generator