Skip to content
Merged
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
9 changes: 8 additions & 1 deletion bin/omarchy-drive-password
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ root_luks_device() {
fi
}

# Every LUKS device, from udev's probe as root_luks_device reads it. An
# unprivileged blkid only reads /run/blkid, empty until root runs blkid. lsblk
# repeats a device under each parent (RAID members), so each is listed once.
luks_drives() {
lsblk -nrpo NAME,FSTYPE | awk '$2 == "crypto_LUKS" && !seen[$1]++ { print $1 }'
}

# Every cryptsetup call holds the disk lock, so one left running by a run that
# was killed finishes before the next run looks at the drive.

Expand Down Expand Up @@ -253,7 +260,7 @@ finish_interrupted_change() {
change_selected_drive() {
local encrypted_drives drive login current old_slot new_password confirmation status=0 system_drive=false

encrypted_drives=$(blkid -t TYPE=crypto_LUKS -o device)
encrypted_drives=$(luks_drives)
if [[ -z $encrypted_drives ]]; then
echo "No encrypted drives available."
return 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ Type=oneshot
RemainAfterExit=yes
TimeoutStartSec=infinity
ExecStart=/usr/lib/omarchy/initcpio/omarchy-mac-encrypt
# Progress goes to the journal and the kernel log, never straight to the
# console: on a Mac loglevel=0 keeps the splash clean, while a serial console
# without "quiet" (the VM harness) still sees every line. A failure is shown
# Progress goes to the journal and on to the kernel log (kmsg), never straight
# to the console: on a Mac loglevel=0 keeps the splash clean, while a serial
# console without "quiet" (the VM harness) still sees every line. journald
# passes only notice and above to kmsg (MaxLevelKMsg=). A failure is shown
# through Plymouth and left in /run/omarchy-mac-encrypt.failed.
StandardOutput=journal+kmsg
StandardError=journal+kmsg
StandardOutput=kmsg
StandardError=kmsg
SyslogLevel=notice
30 changes: 28 additions & 2 deletions packages/omarchy-mac/boot/test/mac-encrypt-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ grep -Fq 'After=systemd-udevd.service systemd-udev-trigger.service systemd-udev-
grep -Fq 'TimeoutStartSec=infinity' "$UNIT" &&
grep -Fxq 'ExecStart=/usr/lib/omarchy/initcpio/omarchy-mac-encrypt' "$UNIT" ||
fail "the initrd unit matches v3 ordering (udev settle + vendorfw-initrd, before cryptsetup-pre/sysroot)"
grep -Fxq 'StandardOutput=journal+kmsg' "$UNIT" && grep -Fxq 'StandardError=journal+kmsg' "$UNIT" &&
! grep -Eq '^(TTYPath|StandardInput)=' "$UNIT" ||
grep -Fxq 'StandardOutput=kmsg' "$UNIT" && grep -Fxq 'StandardError=kmsg' "$UNIT" &&
grep -Fxq 'SyslogLevel=notice' "$UNIT" && ! grep -Eq '^(TTYPath|StandardInput)=' "$UNIT" ||
fail "the initrd unit logs to the journal and kmsg (serial harness), never the console"
for binary in chroot grep mv cat mkdir chmod readlink stat sync date; do
grep -Eq "\b$binary\b" "$INSTALL" || fail "the install hook adds $binary (busybox is not guaranteed)"
Expand Down Expand Up @@ -137,6 +137,32 @@ grep -Fq 'dir=$mnt/var/lib/omarchy/mac-first-boot' "$SCRIPT" &&
fail "a fresh image is the first-boot marker with its conversion token, never the image hardware queue a reset restores"
echo 'ok - script, unit and drop-in match INTERFACES §5 T4a v3'

# systemd ignores a setting it cannot parse and still exits 0, so any output
# fails. Emulated containers cannot verify even a trivial unit; skip there.
if command -v systemd-analyze >/dev/null; then
verify_root=$(mktemp -d)
verify_units=$verify_root/usr/lib/systemd/system
install -D -m 755 "$SCRIPT" "$verify_root/usr/lib/omarchy/initcpio/omarchy-mac-encrypt"
install -D -m 644 "$UNIT" "$verify_units/omarchy-mac-encrypt.service"
printf '[Unit]\nDefaultDependencies=no\n[Service]\nType=oneshot\nExecStart=/usr/lib/omarchy/initcpio/omarchy-mac-encrypt\n' \
>"$verify_units/probe.service"
verify_out=""
if probe_out=$(systemd-analyze verify --man=no --root="$verify_root" "$verify_units/probe.service" 2>&1) && [[ -z $probe_out ]]; then
verify_out=$(systemd-analyze verify --man=no --root="$verify_root" "$verify_units/omarchy-mac-encrypt.service" 2>&1) ||
verify_out+=$'\n'"exit $?"
verified=true
else
verified=false
fi
rm -rf "$verify_root"
if [[ $verified == "true" ]]; then
[[ -z $verify_out ]] || fail "systemd-analyze verify accepts the initrd unit: $verify_out"
echo 'ok - systemd-analyze verify accepts the initrd unit'
else
echo 'ok - systemd-analyze cannot verify units here; unit verification not run'
fi
fi

if [[ ${OMARCHY_DISPOSABLE_BOOT_TESTS:-0} != "1" && ${OMARCHY_MAC_ENCRYPT_TEST_INNER:-0} != "1" ]]; then
echo 'ok - source checks passed; disposable initramfs/block tests not run (OMARCHY_DISPOSABLE_BOOT_TESTS=1 opts in)'
exit 0
Expand Down
25 changes: 20 additions & 5 deletions test/shell.d/drive-password-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

# omarchy-drive-password against fake drives. blkid, findmnt and lsblk describe
# a system drive under / and a data drive; cryptsetup is either a slot-table fake
# omarchy-drive-password against fake drives. findmnt and lsblk describe a
# system drive under / and a data drive, and blkid has the empty cache a user
# sees until root runs blkid in that boot; cryptsetup is either a slot-table fake
# or the real binary on file-backed volumes; chpasswd records the accounts. Each
# cryptsetup and chpasswd call is a crash point, so a run can be killed after
# every step and rerun, like a power loss. The runs repeat on an Apple fixture,
Expand Down Expand Up @@ -48,8 +49,7 @@ SH

cat >"$tmp/bin/blkid" <<'SH'
#!/bin/bash
[[ $* == "-t TYPE=crypto_LUKS -o device" ]] || exit 99
cat "$TEST_TMP/drives"
exit 2
SH

cat >"$tmp/bin/findmnt" <<'SH'
Expand All @@ -64,12 +64,20 @@ if [[ $1 == "-dno" && $2 == "UUID" ]]; then
cat "$3.uuid"
exit
fi
if [[ $* == "-nrpo NAME,FSTYPE" ]]; then
echo "/dev/fake-disk "
while IFS= read -r drive; do
printf '%s crypto_LUKS\n/dev/mapper/%s btrfs\n' "$drive" "${drive##*/}"
done <"$TEST_TMP/drives"
exit
fi
[[ $* == "-nsrpo NAME,TYPE,FSTYPE /dev/mapper/root" ]] || exit 98
cat "$TEST_TMP/root-ancestry"
SH

cat >"$tmp/bin/omarchy-drive-select" <<'SH'
#!/bin/bash
printf '%s\n' "$@" >"$TEST_TMP/offered"
cat "$TEST_TMP/select"
SH

Expand Down Expand Up @@ -287,7 +295,7 @@ volume() {

# / on the system drive, which also holds a recovery key; a data drive beside it.
fixture() {
rm -rf "$tmp/state" "$tmp/output" "$tmp/trace" "$tmp"/dev/* "$tmp/slot-record" "$tmp/record-fail"
rm -rf "$tmp/state" "$tmp/output" "$tmp/trace" "$tmp/offered" "$tmp"/dev/* "$tmp/slot-record" "$tmp/record-fail"
unset TEST_OPEN_FAIL TEST_CHPASSWD_FAIL TEST_CHANGE_FAIL TEST_CHANGE_PARTIAL TEST_KILL_FAIL TEST_FINDMNT_FAIL TEST_TOKEN_SLOT CRASH_ORPHAN
system=$tmp/dev/system
recovery=${1-$recovery_key}
Expand Down Expand Up @@ -491,6 +499,13 @@ done

use fake x86

fixture
printf '%s\n%s\n%s\n' "$system" "$data" "$data" >"$tmp/drives"
attempt 0 "$old_password" "$new_password" "$new_password" || fail "a fresh boot finds the system disk without a blkid cache" "$(cat "$tmp/output")"
[[ $(cat "$tmp/offered") == "$system"$'\n'"$data" ]] || fail "each LUKS drive lsblk names is offered once" "$(cat "$tmp/offered")"
consistent "fresh boot" "$new_password"
pass "before root has run blkid, every LUKS drive is offered once and the system disk changes"

fixture
printf '5\t%s\n' tpm-sealed-key >>"$system.slots"
export TEST_TOKEN_SLOT=5
Expand Down
Loading