diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 14:01:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 14:01:36 +0000 |
commit | 70de5d4041249c1a0f597714398cc245f59495c6 (patch) | |
tree | ff491e31b95b662ca6c481ac49d1ca8a94c0226b /modules.d/90systemd-cryptsetup/module-setup.sh | |
parent | Adding debian version 060+5-8. (diff) | |
download | dracut-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-x | modules.d/90systemd-cryptsetup/module-setup.sh | 120 |
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 +} |