diff --git a/Makefile b/Makefile index a9f4aae..71eb9df 100644 --- a/Makefile +++ b/Makefile @@ -62,10 +62,12 @@ $(OUTDIR)man/index.txt : $(MANDIR)index.txt $(patsubst $(MANDIR)%.pp,$(OUTDIR)ma $(OUTDIR)initramfs-tools/usr/share/initramfs-tools/hooks/tzpfms: $(INITRDDIR)initramfs-tools/hook $(INITRD_HEADERS) @mkdir -p $(dir $@) $(AWK) -f pp.awk $< > $@ + chmod --reference $< $@ $(OUTDIR)initramfs-tools/usr/share/tzpfms/initramfs-tools-zfs-patch.sh: $(INITRDDIR)initramfs-tools/zfs-patch.sh $(INITRD_HEADERS) @mkdir -p $(dir $@) $(AWK) -f pp.awk $< > $@ + chmod --reference $< $@ $(OUTDIR)%$(EXE) : $(subst $(SRCDIR),$(OBJDIR),$(subst .cpp,$(OBJ),$(SRCDIR)bin/%.cpp $(COMMON_SOURCES))) @@ -88,3 +90,4 @@ $(OUTDIR)man/%.md : $(MANDIR)%.md.pp $(MANPAGE_HEADERS) $(OUTDIR)dracut/usr/lib/dracut/modules.d/91tzpfms/% : $(INITRDDIR)dracut/% $(INITRD_HEADERS) @mkdir -p $(dir $@) $(AWK) -f pp.awk $< > $@ + chmod --reference $< $@ diff --git a/initrd/dracut/module-setup.sh b/initrd/dracut/module-setup.sh index c0e0180..cebfff9 100755 --- a/initrd/dracut/module-setup.sh +++ b/initrd/dracut/module-setup.sh @@ -2,6 +2,9 @@ # SPDX-License-Identifier: MIT +#include "../install.h" + + _get_backend() { rootfs="$(awk '$2 == "/" && $3 == "zfs" {print $1; exit 1}' /etc/mtab)" [ -z "$rootfs" ] && return 1 @@ -11,17 +14,20 @@ _get_backend() { backend="$(zfs-tpm-list -H "$eroot" | awk -F'\t' '{print $2}')" - [ -z "$backend" ] && return 1 + [ -n "$backend" ] + return } _install_tpm2() { + inst_binary zfs-tpm2-load-key # shellcheck disable=SC2046 - dracut_install zfs-tpm2-load-key $(find /usr/lib -name 'libtss2-tcti*.so*') # TODO: there's got to be a better way™! + inst_library $(find /usr/lib -name 'libtss2-tcti*.so*') # TODO: there's got to be a better way™! } _install_tpm1x() { - dracut_install zfs-tpm1x-load-key - command -v tcsd > /dev/null && dracut_install tcsd + inst_binary zfs-tpm1x-load-key + INSTALL_TPM1X{inst_binary tcsd; inst_binary ip; inst_binary ss, initdir, inst_simple, inst_simple, inst_simple, inst_library} + command -v tpm_resetdalock > /dev/null && inst_binary tpm_resetdalock } @@ -29,16 +35,16 @@ check() { command -v zfs-tpm-list > /dev/null || return 1 # shellcheck disable=SC2154 - if [ -n "$hostonly" ]; then + if [ -n "$hostonly" ]; then _get_backend || return [ "$backend" = "TPM2" ] && command -v zfs-tpm2-load-key > /dev/null && return 0 [ "$backend" = "TPM1.X" ] && command -v zfs-tpm1x-load-key > /dev/null && return 0 return 1 - fi + fi - return 0 + return 0 } @@ -53,7 +59,7 @@ installkernel() { install() { - dracut_install zfs-tpm-list + inst_binary zfs-tpm-list if [ -n "${hostonly}" ]; then _get_backend diff --git a/initrd/dracut/tzpfms-load-key.sh b/initrd/dracut/tzpfms-load-key.sh index 21e2c33..adb27ec 100755 --- a/initrd/dracut/tzpfms-load-key.sh +++ b/initrd/dracut/tzpfms-load-key.sh @@ -17,6 +17,11 @@ root="${root:=$(getarg root=)}" rootfstype="${rootfstype:=$(getarg rootfstype=)}" [ "${root##zfs:}" = "$root" ] && [ "${root##ZFS=}" = "$root" ] && [ "$rootfstype" != "zfs" ] && exit 0 +TZPFMS_TPM1X="$(getarg TZPFMS_TPM1X=)" +[ -z "$TZPFMS_TPM1X" ] || export TZPFMS_TPM1X + +getarg 0 quiet && quiet=y + # There is a race between the zpool import and the pre-mount hooks, so we wait for a pool to be imported while [ "$(zpool list -H)" = "" ]; do @@ -48,7 +53,7 @@ if [ "$(zpool list -H -o feature@encryption "$(echo "$BOOTFS" | awk -F/ '{print fi if command -v zfs-tpm1x-load-key > /dev/null && ! [ "$(zfs-tpm-list -Hub TPM1.X "$ENCRYPTIONROOT")" = "" ]; then - POTENTIALLY_START_TCSD{} + POTENTIALLY_START_TCSD{ss -ltO, > /dev/console 2>&1} with_promptable_tty zfs-tpm1x-load-key "$ENCRYPTIONROOT"; err="$?" POTENTIALLY_KILL_TCSD{} exit "$err" diff --git a/initrd/initramfs-tools/hook b/initrd/initramfs-tools/hook index fabe150..e55b734 100755 --- a/initrd/initramfs-tools/hook +++ b/initrd/initramfs-tools/hook @@ -1,6 +1,10 @@ #!/bin/sh # SPDX-License-Identifier: MIT + +#include "../install.h" + + PREREQ="zfs" [ "$1" = "prereqs" ] && exec echo "$PREREQ" . /usr/share/initramfs-tools/hook-functions @@ -13,44 +17,12 @@ sed -Ei 's/^decrypt_fs\(\)/__tzpfms__&/' "$DESTDIR/scripts/zfs" cat /usr/share/tzpfms/initramfs-tools-zfs-patch.sh >> "$DESTDIR/scripts/zfs" -for x in tpm_resetdalock zfs-tpm-list zfs-tpm2-load-key zfs-tpm1x-load-key tcsd $(find /usr/lib -name 'libtss2-tcti*.so*'); do # TODO: there's got to be a better way™! +for x in zfs-tpm-list zfs-tpm2-load-key zfs-tpm1x-load-key tpm_resetdalock tcsd $(find /usr/lib -name 'libtss2-tcti*.so*'); do # TODO: there's got to be a better way™! xloc="$(command -v "$x")" [ "$xloc" = "" ] || copy_exec "$xloc" done -if command -v tcsd > /dev/null; then - # tcsd exits if it doesn't have tss group and user - grep tss /etc/group >> "$DESTDIR/etc/group" - grep tss /etc/passwd >> "$DESTDIR/etc/passwd" - - for f in /lib/udev/rules.d/*tpm*; do - copy_file rule $f - done - - if [ -e /etc/tcsd.conf ]; then - copy_file config /etc/tcsd.conf - system_ps_file="$(awk -F '[[:space:]]*=[[:space:]]*' '!/^[[:space:]]*#/ && !/^$/ && $1 ~ /system_ps_file$/ {gsub(/[[:space:]]*$/, "", $2); print $2}' /etc/tcsd.conf)" - system_ps_file="${system_ps_file:-/var/lib/tpm/system.data}" - fi - - # tcsd can't find SRK if state not present, refuses to start if it doesn't have parent to tss dir - mkdir -p "$DESTDIR/$(dirname "$(dirname "$system_ps_file")")" - [ -f "$system_ps_file" ] && copy_file state "$system_ps_file" -fi - -# localhost needs to resolve at the very least -for f in /etc/hosts /etc/resolv.conf /etc/host.conf /etc/gai.conf; do - [ -e $f ] && copy_file config $f -done -if [ -e /etc/nsswitch.conf ]; then - copy_file config /etc/nsswitch.conf - databases="$(awk '/^group|hosts/ {for(i = 2; i <= NF; ++i) print $i}' /etc/nsswitch.conf | sort | uniq)" - for db in $databases; do - for f in /lib/*/"libnss_$db"*; do - copy_exec "$f" - done - done -fi +INSTALL_TPM1X{, DESTDIR, copy_file rule, copy_file config, copy_file state, copy_exec} copy_modules_dir 'kernel/drivers/char/tpm' diff --git a/initrd/initramfs-tools/zfs-patch.sh b/initrd/initramfs-tools/zfs-patch.sh index 37faaeb..929b200 100644 --- a/initrd/initramfs-tools/zfs-patch.sh +++ b/initrd/initramfs-tools/zfs-patch.sh @@ -28,7 +28,7 @@ decrypt_fs() { fi if command -v zfs-tpm1x-load-key > /dev/null && ! [ "$(zfs-tpm-list -Hub TPM1.X "$ENCRYPTIONROOT")" = "" ]; then - POTENTIALLY_START_TCSD{} + POTENTIALLY_START_TCSD{netstat -lt, } with_promptable_tty zfs-tpm1x-load-key "$ENCRYPTIONROOT"; err="$?" POTENTIALLY_KILL_TCSD{} return "$err" diff --git a/initrd/install.h b/initrd/install.h new file mode 100644 index 0000000..46579ae --- /dev/null +++ b/initrd/install.h @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: MIT + + +#define INSTALL_TPM1X(PREREQ, TARGET_DIR, INST_UDEV, INST_CFG, INST_STATE, INST_LIB) + command -v tcsd > /dev/null && { + PREREQ + + # tcsd exits if it doesn't have tss group and user + grep tss /etc/group >> "${TARGET_DIR:-MUST_EXIST}/etc/group" + grep tss /etc/passwd >> "${TARGET_DIR:-MUST_EXIST}/etc/passwd" + + for f in /lib/udev/rules.d/*tpm*; do + INST_UDEV "$f" + done + + if [ -e /etc/tcsd.conf ]; then + INST_CFG /etc/tcsd.conf + chown tss:tss "${TARGET_DIR:-MUST_EXIST}/etc/tcsd.conf" + system_ps_file="$(awk -F '[[:space:]]*=[[:space:]]*' '!/^[[:space:]]*#/ && !/^$/ && $1 ~ /system_ps_file$/ {gsub(/[[:space:]]*$/, "", $2); print $2}' /etc/tcsd.conf)" + system_ps_file="${system_ps_file:-/var/lib/tpm/system.data}" + fi + + # tcsd can't find SRK if state not present, refuses to start if it doesn't have parent to tss dir + mkdir -p "${TARGET_DIR:-MUST_EXIST}/$(dirname "$(dirname "$system_ps_file")")" + [ -f "$system_ps_file" ] && INST_STATE "$system_ps_file" + } + + # localhost needs to resolve at the very least + for f in /etc/hosts /etc/resolv.conf /etc/host.conf /etc/gai.conf; do + [ -e "$f" ] && INST_CFG "$f" + done + + if [ -e /etc/nsswitch.conf ]; then + INST_CFG /etc/nsswitch.conf + databases="$(awk '/^group|hosts/ {for(i = 2; i <= NF; ++i) print $i}' /etc/nsswitch.conf | sort | uniq)" + for db in $databases; do + for f in /lib/*/"libnss_$db"*; do + INST_LIB "$f" + done + done + fi +#endefine diff --git a/initrd/mount.h b/initrd/mount.h old mode 100755 new mode 100644 index d414d81..0ce8182 --- a/initrd/mount.h +++ b/initrd/mount.h @@ -11,7 +11,8 @@ with_promptable_tty() { if command -v plymouth > /dev/null && plymouth --ping; then plymouth hide-splash - [ "${quiet:-n}" = "y" ] && printf '\033c' + # shellcheck disable=SC2217 + [ "${quiet:-n}" = "y" ] && printf '\033c' REDIREXIONS "$@" REDIREXIONS; ret="$?" @@ -30,7 +31,7 @@ #endefine -#define POTENTIALLY_START_TCSD() +#define POTENTIALLY_START_TCSD(LISTENING_TCP, REDIREXIONS) [ -z "$TZPFMS_TPM1X" ] && command -v tcsd > /dev/null && { ip l | awk -F '[[:space:]]*:[[:space:]]*' '{if($2 == "lo") exit $3 ~ /UP/}' lo_was_up="$?" @@ -42,10 +43,10 @@ if [ "${quiet:-n}" = "y" ]; then tcsd -f > /tcsd.log 2>&1 & else - tcsd -f & + tcsd -f REDIREXIONS & fi tcsd_port="$(awk -F '[[:space:]]*=[[:space:]]*' '!/^[[:space:]]*#/ && !/^$/ && $1 ~ /port$/ {gsub(/[[:space:]]/, "", $2); print $2}' /etc/tcsd.conf)" - i=0; while [ "$i" -lt 100 ] && ! netstat -lt | grep -q "${tcsd_port:-30003}"; do sleep 0.1; i="$((i + 1))"; done + i=0; while [ "$i" -lt 100 ] && ! LISTENING_TCP | grep -q "${tcsd_port:-30003}"; do sleep 0.1; i="$((i + 1))"; done [ "$i" = 100 ] && echo "Couldn't start tcsd!" >&2 } #endefine diff --git a/pp.awk b/pp.awk old mode 100755 new mode 100644 index 98dd781..28435e5 --- a/pp.awk +++ b/pp.awk @@ -41,7 +41,7 @@ function input() { last = $i ~ /\)$/ sub(/[,\)]/, "", $i) - macro_args[macroname,i - 2] = $i + macro_args[macroname,i - 1] = $i } }