summaryrefslogtreecommitdiffstats
path: root/modules.d/90systemd-cryptsetup/module-setup.sh
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 14:01:36 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 14:01:36 +0000
commit70de5d4041249c1a0f597714398cc245f59495c6 (patch)
treeff491e31b95b662ca6c481ac49d1ca8a94c0226b /modules.d/90systemd-cryptsetup/module-setup.sh
parentAdding debian version 060+5-8. (diff)
downloaddracut-70de5d4041249c1a0f597714398cc245f59495c6.tar.xz
dracut-70de5d4041249c1a0f597714398cc245f59495c6.zip
Merging upstream version 102.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules.d/90systemd-cryptsetup/module-setup.sh')
-rwxr-xr-xmodules.d/90systemd-cryptsetup/module-setup.sh120
1 files changed, 120 insertions, 0 deletions
diff --git a/modules.d/90systemd-cryptsetup/module-setup.sh b/modules.d/90systemd-cryptsetup/module-setup.sh
new file mode 100755
index 0000000..da37bde
--- /dev/null
+++ b/modules.d/90systemd-cryptsetup/module-setup.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local fs
+ # if cryptsetup is not installed, then we cannot support encrypted devices.
+ require_any_binary "$systemdutildir"/systemd-cryptsetup || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == "crypto_LUKS" ]] && return 0
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ local deps
+ deps="dm rootfs-block crypt systemd-ask-password"
+ if [[ $hostonly && -f "$dracutsysrootdir"/etc/crypttab ]]; then
+ if grep -q -e "fido2-device=" -e "fido2-cid=" "$dracutsysrootdir"/etc/crypttab; then
+ deps+=" fido2"
+ fi
+ if grep -q "pkcs11-uri" "$dracutsysrootdir"/etc/crypttab; then
+ deps+=" pkcs11"
+ fi
+ if grep -q "tpm2-device=" "$dracutsysrootdir"/etc/crypttab; then
+ deps+=" tpm2-tss"
+ fi
+ elif [[ ! $hostonly ]]; then
+ for module in fido2 pkcs11 tpm2-tss; do
+ module_check $module > /dev/null 2>&1
+ if [[ $? == 255 ]]; then
+ deps+=" $module"
+ fi
+ done
+ fi
+ echo "$deps"
+ return 0
+}
+
+# called by dracut
+install() {
+ # the cryptsetup targets are already pulled in by 00systemd, but not
+ # the enablement symlinks
+ inst_multiple -o \
+ "$tmpfilesdir"/cryptsetup.conf \
+ "$systemdutildir"/system-generators/systemd-cryptsetup-generator \
+ "$systemdutildir"/systemd-cryptsetup \
+ "$systemdsystemunitdir"/cryptsetup.target \
+ "$systemdsystemunitdir"/sysinit.target.wants/cryptsetup.target \
+ "$systemdsystemunitdir"/remote-cryptsetup.target \
+ "$systemdsystemunitdir"/initrd-root-device.target.wants/remote-cryptsetup.target
+
+ if [[ $hostonly ]] && [[ -f $initdir/etc/crypttab ]]; then
+ # for each entry in /etc/crypttab check if the key file is backed by a socket unit and if so,
+ # include it along with its corresponding service unit.
+ while read -r _mapper _dev _luksfile _luksoptions || [[ -n $_mapper ]]; do
+ # ignore paths followed by a device specification
+ if [[ $_luksfile == *":"* ]]; then
+ return
+ fi
+
+ # if no explicit path is provided, try to include units for auto-discoverable keys
+ if [[ -z $_luksfile ]] || [[ $_luksfile == "-" ]] || [[ $_luksfile == "none" ]]; then
+ _luksfile="/run/cryptsetup-keys.d/$_mapper.key"
+ fi
+
+ find "$systemdsystemunitdir" "$systemdsystemconfdir" -type f -name "*.socket" | while read -r socket_unit; do
+ # systemd-cryptsetup utility only supports SOCK_STREAM (ListenStream) sockets, so we ignore
+ # other types like SOCK_DGRAM (ListenDatagram), SOCK_SEQPACKET (ListenSequentialPacket), etc.
+ if ! grep -E -q "^ListenStream\s*=\s*$_luksfile$" "$socket_unit"; then
+ continue
+ fi
+
+ service_name=$(grep -E "^Service\s*=\s*" "$socket_unit" | cut -d= -f2)
+
+ if [ -z "$service_name" ]; then
+ # if no explicit Service= is defined, construct the service name based on the socket unit's name
+ if grep -P -q "^Accept\s*=\s*(?i)(1|yes|y|true|t|on)$" "$socket_unit"; then
+ # if Accept is truthy, assemble a service template
+ service_name=$(basename "$socket_unit" .socket)"@.service"
+ else
+ # otherwise, just replace .socket with .service
+ service_name=$(basename "$socket_unit" .socket)".service"
+ fi
+ fi
+
+ # this assumes the service file is in the same directory as the socket file,
+ # which is a common configuration but not guaranteed.
+ if ! inst_multiple -H "${socket_unit%/*}/$service_name" "$socket_unit"; then
+ continue
+ fi
+
+ # sanity check - all units which use default dependencies will depend on sysinit.target,
+ # which itself depends on cryptsetup.target. This could lead to either:
+ # a) systemd-cryptsetup falling back to a passphrase prompt due to a missing socket file
+ # b) a deadlock caused by a circular dependency (service unit -> sysinit.target -> cryptsetup.target -> service unit)
+ if ! grep -P -q "^DefaultDependencies\s*=\s*(?i)(0|no|n|false|f|off)" "$socket_unit"; then
+ dwarning "crypt: $socket_unit: default dependencies are not disabled," \
+ "the socket file may not exist by the time systemd-cryptsetup gets executed"
+ fi
+
+ if ! grep -P -q "^DefaultDependencies\s*=\s*(?i)(0|no|n|false|f|off)" "${socket_unit%/*}/$service_name"; then
+ dwarning "crypt: ${socket_unit%/*}/$service_name: default dependencies are not disabled," \
+ "the service unit may encounter a deadlock due to a circular dependency"
+ fi
+
+ socket_unit_basename=$(basename "$socket_unit")
+ inst_multiple -H -o \
+ "$systemdsystemunitdir"/sockets.target.wants/"$socket_unit_basename" \
+ "$systemdsystemconfdir"/sockets.target.wants/"$socket_unit_basename"
+ break
+ done
+ done < "$initdir"/etc/crypttab
+ fi
+}