Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions modules.d/70crypt/crypt-needshutdown.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

command -v getarg > /dev/null || . /lib/dracut-lib.sh

# The legacy crypt path calls need_shutdown from cryptroot-ask.sh, but
# systemd-cryptsetup does not, so ensure the flag is set here whenever a LUKS
# mapping is active. Otherwise dracut-initramfs-restore exits early and
# dm-shutdown.sh never runs, leaving LUKS stacks busy at shutdown
for _dev in /sys/block/dm-*; do
[ -e "${_dev}/dm/uuid" ] || continue
case $(cat "${_dev}/dm/uuid") in
CRYPT-LUKS*)
need_shutdown
break
;;
esac
done
unset _dev
1 change: 1 addition & 0 deletions modules.d/70crypt/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ install() {
fi

inst_hook cmdline 30 "$moddir/parse-crypt.sh"
inst_hook cleanup 29 "$moddir/crypt-needshutdown.sh"
if dracut_module_included "systemd"; then
inst_script "$moddir/crypt-generator.sh" "$systemdutildir"/system-generators/dracut-crypt-generator
else
Expand Down
11 changes: 11 additions & 0 deletions test/TEST-26-ENC-RAID-LVM/assertion.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh

# required binaries: test

# Verify that dracut flagged .need_shutdown during boot. Without the flag,
# dracut-initramfs-restore exits early on shutdown, the initramfs is not
# pivoted to, and dm-shutdown.sh never runs leaving LUKS stacks
# (e.g. LVM-on-LUKS) busy and blocking poweroff
if [ ! -e /run/initramfs/.need_shutdown ]; then
echo "/run/initramfs/.need_shutdown was not created during boot" >> /run/failed
fi
32 changes: 32 additions & 0 deletions test/TEST-26-ENC-RAID-LVM/setup-shutdown-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

# Creates a single-disk LVM-on-LUKS root filesystem for the shutdown test

trap 'poweroff -f' EXIT
set -ex

printf verySecurePassword > keyfile
cryptsetup --pbkdf pbkdf2 -q luksFormat /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_disk1 /keyfile
cryptsetup luksOpen /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_disk1 vault < /keyfile

lvm pvcreate -ff -y /dev/mapper/vault
lvm vgcreate dracut /dev/mapper/vault
lvm lvcreate --yes -l 100%FREE -n root dracut
lvm vgchange -ay

mkfs.ext4 -q /dev/dracut/root
mkdir -p /sysroot
mount -t ext4 /dev/dracut/root /sysroot
cp -a -t /sysroot /source/*
umount /sysroot

lvm lvchange -a n /dev/dracut/root
lvm vgchange -an
cryptsetup luksClose vault

{
echo "dracut-root-block-created"
udevadm info --query=property --name=/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_disk1 \
| grep 'ID_FS_UUID='
} | dd oflag=direct of=/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_marker status=none
sync
73 changes: 69 additions & 4 deletions test/TEST-26-ENC-RAID-LVM/test.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -eu
# shellcheck disable=SC2034
TEST_DESCRIPTION="root filesystem on LVM on encrypted partitions of a RAID"
TEST_DESCRIPTION="root filesystem on LVM on encrypted partitions (with and without RAID)"

# Uncomment this to debug failures
#DEBUGFAIL="rd.shell rd.break" # udev.log-priority=debug
Expand All @@ -14,6 +14,11 @@ test_check() {
return 1
fi

if ! type -p lvm &> /dev/null; then
echo "Test needs lvm for lvm module... Skipping"
return 1
fi

if ! type -p mdadm &> /dev/null; then
echo "Test needs mdadm for mdraid module ... Skipping"
return 1
Expand Down Expand Up @@ -44,9 +49,47 @@ test_run() {
check_qemu_log
client_test_end

if [ -f "$TESTDIR"/initramfs.testing.enc-lvm ]; then
client_test_start "LVM-on-LUKS with systemd (need_shutdown set)"

declare -a enc_lvm_disk_args=()
qemu_add_drive enc_lvm_disk_args "$TESTDIR"/disk-enc-lvm.img disk1

LUKSARGS_ENC_LVM=$(cat "$TESTDIR"/luks-enc-lvm.txt)
"$testdir"/run-qemu \
"${enc_lvm_disk_args[@]}" \
-append "$TEST_KERNEL_CMDLINE root=/dev/dracut/root ro rd.auto rootwait $LUKSARGS_ENC_LVM" \
-initrd "$TESTDIR"/initramfs.testing.enc-lvm
check_qemu_log
client_test_end
fi

return 0
}

make_enc_lvm_rootfs() {
# Build a root filesystem on a single encrypted disk (LVM-on-LUKS, no RAID)
build_client_rootfs "$TESTDIR/overlay-enc-lvm/source" ./assertion.sh

call_dracut -i "$TESTDIR/overlay-enc-lvm" / \
--add-confdir test-makeroot \
-a "bash crypt lvm" \
-I "grep cryptsetup" \
-i ./setup-shutdown-env.sh /usr/lib/dracut/hooks/initqueue/01-create-root.sh \
-f "$TESTDIR"/initramfs.makeroot-enc-lvm

declare -a disk_args=()
qemu_add_drive disk_args "$TESTDIR"/marker-enc-lvm.img marker 1
qemu_add_drive disk_args "$TESTDIR"/disk-enc-lvm.img disk1 1

"$testdir"/run-qemu \
"${disk_args[@]}" \
-append "root=/dev/fakeroot quiet" \
-initrd "$TESTDIR"/initramfs.makeroot-enc-lvm
test_marker_check dracut-root-block-created marker-enc-lvm.img
rm -rf "$TESTDIR/overlay-enc-lvm"
}

make_test_rootfs() {
# Create what will eventually be our root filesystem onto an overlay
build_client_rootfs "$TESTDIR/overlay/source"
Expand Down Expand Up @@ -76,6 +119,30 @@ make_test_rootfs() {
}

test_setup() {
echo -n verySecurePassword > /tmp/key
chmod 0600 /tmp/key

# The LVM-on-LUKS systemd case needs the systemd-cryptsetup binary. Skip
# that case on hosts without it
if [ -x /usr/lib/systemd/systemd-cryptsetup ] || [ -x /lib/systemd/systemd-cryptsetup ]; then
# Build the no-RAID rootfs and systemd-based initramfs first, then
# rename it aside, the RAID build reuses $TESTDIR/initramfs.testing
make_enc_lvm_rootfs

luks_uuid=$(grep -F -a -m 1 ID_FS_UUID "$TESTDIR"/marker-enc-lvm.img | cut -d= -f2)
printf 'rd.luks.uuid=luks-%s' "$luks_uuid" > "$TESTDIR"/luks-enc-lvm.txt
printf 'luks-%s /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_disk1 /etc/key timeout=0\n' "$luks_uuid" > /tmp/crypttab-enc-lvm

test_dracut -f \
Comment thread
nadzyah marked this conversation as resolved.
-a "crypt lvm" \
--add "systemd systemd-cryptsetup" \
-i "/tmp/crypttab-enc-lvm" "/etc/crypttab" \
-i "/tmp/key" "/etc/key"
mv "$TESTDIR/initramfs.testing" "$TESTDIR/initramfs.testing.enc-lvm"
else
echo "systemd-cryptsetup not found, skipping LVM-on-LUKS systemd build"
fi

make_test_rootfs

cryptoUUIDS=$(grep -F -a -m 3 ID_FS_UUID "$TESTDIR"/marker.img)
Expand All @@ -90,10 +157,8 @@ test_setup() {
printf 'luks-%s /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_disk%s /etc/key timeout=0\n' "$ID_FS_UUID" $i
((i += 1))
done > /tmp/crypttab
echo -n verySecurePassword > /tmp/key
chmod 0600 /tmp/key

test_dracut \
test_dracut -f \
-a "crypt lvm mdraid" \
-i "/tmp/crypttab" "/etc/crypttab" \
-i "/tmp/key" "/etc/key"
Expand Down
Loading