From 138bbc034a709904e10808c2ea3c85fa63c885c5 Mon Sep 17 00:00:00 2001 From: DevomB Date: Mon, 5 Oct 2026 08:43:25 -0700 Subject: [PATCH] Every ESP and control disk is mounted as FAT and nothing else: on another filesystem under the partition's label, a link at a name root writes would carry the write to a disk or a file of the machine --- build/service-scripts/boot-success.sh | 4 ++-- build/service-scripts/installer-run.sh | 4 ++-- build/service-scripts/testctl.sh | 2 +- tools/install/kryptik-install.sh | 6 +++--- tools/tests/boot-success.sh | 4 ++-- tools/tests/mount-types.sh | 26 ++++++++++++++++++++++++++ tools/update/kryptik-recover | 12 ++++++------ tools/update/kryptik-update | 2 +- 8 files changed, 43 insertions(+), 17 deletions(-) create mode 100755 tools/tests/mount-types.sh diff --git a/build/service-scripts/boot-success.sh b/build/service-scripts/boot-success.sh index abb18438..1fb61a25 100755 --- a/build/service-scripts/boot-success.sh +++ b/build/service-scripts/boot-success.sh @@ -69,7 +69,7 @@ commit_slot() { # commit_slot : make BOOTX64.EFI this slot's kernel esp="$(kryptik_part kryptik-esp 2>/dev/null)" [ -n "$esp" ] || { say "no unambiguous ESP on this installation's disk; cannot commit"; return 1; } mkdir -p "$ESP_MNT" - mount -o rw,nosuid,nodev,noexec "$esp" "$ESP_MNT" || { say "cannot mount ESP $esp"; return 1; } + mount -t vfat -o rw,nosuid,nodev,noexec "$esp" "$ESP_MNT" || { say "cannot mount ESP $esp"; return 1; } src="$ESP_MNT/EFI/kryptik/kryptik-$1.efi" dst="$ESP_MNT/EFI/BOOT/BOOTX64.EFI" rc=1 @@ -113,7 +113,7 @@ forget_entries() { # forget_entries COMMITTED-SLOT esp_committed() { e="$(kryptik_part kryptik-esp 2>/dev/null)" && [ -n "$e" ] || return 0 mkdir -p "$ESP_MNT" - mount -o ro,nosuid,nodev,noexec "$e" "$ESP_MNT" 2>/dev/null || return 0 + mount -t vfat -o ro,nosuid,nodev,noexec "$e" "$ESP_MNT" 2>/dev/null || return 0 sed -n 1p "$ESP_MNT/kryptik/committed-slot" 2>/dev/null umount "$ESP_MNT" } diff --git a/build/service-scripts/installer-run.sh b/build/service-scripts/installer-run.sh index a4a9230a..e94a0c1c 100755 --- a/build/service-scripts/installer-run.sh +++ b/build/service-scripts/installer-run.sh @@ -82,7 +82,7 @@ if [ "$rc" -eq 0 ]; then done esp="$(blkid -t PARTLABEL=kryptik-esp -o device 2>/dev/null | grep "^${target}" | head -1)" mkdir -p /run/verify - if [ -n "$esp" ] && mount -o ro "$esp" /run/verify 2>/dev/null; then + if [ -n "$esp" ] && mount -t vfat -o ro "$esp" /run/verify 2>/dev/null; then say "verify: esp_files=$(cd /run/verify && find . -type f | sort | tr '\n' ' ')" say "verify: bootx64_sha256=$(sha256sum /run/verify/EFI/BOOT/BOOTX64.EFI 2>/dev/null | cut -c1-64)" say "verify: version_a=$(cat /run/verify/kryptik/version-a 2>/dev/null || echo none)" @@ -92,7 +92,7 @@ if [ "$rc" -eq 0 ]; then fi st="$(blkid -t PARTLABEL=kryptik-state -o device 2>/dev/null | grep "^${target}" | head -1)" if [ -n "$st" ] && printf '%s' "$sp" | cryptsetup open --readonly --type luks2 --key-file=- "$st" kryptik-verify-state 2>/dev/null \ - && mount -o ro /dev/mapper/kryptik-verify-state /run/verify 2>/dev/null; then + && mount -t ext4 -o ro /dev/mapper/kryptik-verify-state /run/verify 2>/dev/null; then say "verify: state_marker=$([ -e /run/verify/.kryptik-state ] && echo yes || echo no)" say "verify: install_json=$([ -r /run/verify/lib/kryptik/install.json ] && echo yes || echo no)" say "verify: preseed=$([ -r /run/verify/lib/kryptik/firstboot.preseed ] && echo present || echo none)" diff --git a/build/service-scripts/testctl.sh b/build/service-scripts/testctl.sh index eb739a18..70c6764d 100755 --- a/build/service-scripts/testctl.sh +++ b/build/service-scripts/testctl.sh @@ -35,7 +35,7 @@ testctl_load() { [ -n "$dev" ] && [ -b "$dev" ] || return 1 mkdir -p "$TESTCTL_MNT" if ! mountpoint -q "$TESTCTL_MNT"; then - mount -o ro,nosuid,nodev,noexec "$dev" "$TESTCTL_MNT" 2>/dev/null || return 1 + mount -t vfat -o ro,nosuid,nodev,noexec "$dev" "$TESTCTL_MNT" 2>/dev/null || return 1 fi [ -r "$TESTCTL_MNT/kryptik-test.conf" ] || return 1 if ! testctl_signed "$TESTCTL_MNT/kryptik-test.conf"; then diff --git a/tools/install/kryptik-install.sh b/tools/install/kryptik-install.sh index d802adaf..547d0f70 100755 --- a/tools/install/kryptik-install.sh +++ b/tools/install/kryptik-install.sh @@ -162,7 +162,7 @@ case "$media" in [ -b "$ROOT_SRC" ] || die "no single kryptik-media partition on the medium this system booted from" ESP_SRC="$(kryptik_part kryptik-esp)" || true [ -b "$ESP_SRC" ] || die "no single kryptik-esp partition on the medium this system booted from" - mount -o ro "$ESP_SRC" "$MNT_BASE/esp" || die "could not mount the medium's ESP" + mount -t vfat -o ro "$ESP_SRC" "$MNT_BASE/esp" || die "could not mount the medium's ESP" ROOT_JSON="$MNT_BASE/esp/kryptik/root.json" ;; iso) @@ -305,7 +305,7 @@ STATE_PASS="" mkfs.ext4 -q -F -L kryptik-state "/dev/mapper/$MAPPING" || die "mkfs.ext4 inside ${P4} failed" # --- the target ESP: slot A is the committed boot file ---------------------- -mount -o rw "$P1" "$MNT_BASE/tesp" || die "could not mount the new ESP" +mount -t vfat -o rw "$P1" "$MNT_BASE/tesp" || die "could not mount the new ESP" [ -f "$MNT_BASE/tesp/EFI/kryptik/kryptik-a.efi" ] || die "the copied ESP has no slot A kernel" cp "$MNT_BASE/tesp/EFI/kryptik/kryptik-a.efi" "$MNT_BASE/tesp/EFI/BOOT/BOOTX64.EFI.new" || die "could not stage BOOTX64.EFI" sync -f "$MNT_BASE/tesp/EFI/BOOT/BOOTX64.EFI.new" @@ -317,7 +317,7 @@ sync umount "$MNT_BASE/tesp" || die "could not unmount the new ESP" # --- the state partition: what installed this, and the first-boot preseed -- -mount -o rw "/dev/mapper/$MAPPING" "$MNT_BASE/state" || die "could not mount kryptik-state" +mount -t ext4 -o rw "/dev/mapper/$MAPPING" "$MNT_BASE/state" || die "could not mount kryptik-state" mkdir -p "$MNT_BASE/state/lib/kryptik" cat > "$MNT_BASE/state/lib/kryptik/install.json" < "$KTEST/efiboot_fai check "... and reboots if they stay: its record, now trial.failed, keeps it from coming back" "$(reboots)" "1" # On a degraded state /var is a tmpfs, so the trial record is out of reach. run_case degraded b "" degraded "" $ALL; go -check "trial on a degraded state: known from the ESP, not committed, forgotten, rebooted" "${RESULT%%:*}|$(cat "$KTEST/esp/EFI/BOOT/BOOTX64.EFI")|$CALLS" "trial-unhealthy b|kernel-a|mount -o ro,nosuid,nodev,noexec /dev/vda1 $KTEST/run/esp umount $KTEST/run/esp efiboot forget efiboot ensure a reboot " +check "trial on a degraded state: known from the ESP, not committed, forgotten, rebooted" "${RESULT%%:*}|$(cat "$KTEST/esp/EFI/BOOT/BOOTX64.EFI")|$CALLS" "trial-unhealthy b|kernel-a|mount -t vfat -o ro,nosuid,nodev,noexec /dev/vda1 $KTEST/run/esp umount $KTEST/run/esp efiboot forget efiboot ensure a reboot " run_case degraded2 b "" degraded "" $ALL; : > "$KTEST/efiboot_fails"; go check "... not rebooted while its entries stay: nothing else keeps the next boot from being it" "$(reboots)" "0" run_case degraded3 a "" degraded "" $ALL; go diff --git a/tools/tests/mount-types.sh b/tools/tests/mount-types.sh new file mode 100755 index 00000000..d2b75961 --- /dev/null +++ b/tools/tests/mount-types.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Every mount of a device the on-system tools make names its filesystem. An +# ESP and a control disk are FAT, and FAT holds no links: on another +# filesystem carrying the partition's label, a link at a name root writes +# would send the write to a disk or a file of the machine. Offline. +set -uo pipefail +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" + +PASS=0; FAIL=0 +green() { printf ' PASS %s\n' "$1"; PASS=$((PASS + 1)); } +red() { printf ' FAIL %s\n' "$1"; FAIL=$((FAIL + 1)); } + +# A mount that opens with its options has left the filesystem to be guessed. +LOOSE='(^|[^a-zA-Z_./-])mount +-o ' +grep -qE "$LOOSE" <<<' mount -o ro "$dev" /mnt || exit 1' && ! grep -qE "$LOOSE" <<<' mount -t vfat -o ro "$dev" /mnt; umount -o x /mnt' \ + && green "the check sees a mount that names no filesystem, and passes one that does" || red "the check cannot tell the two apart" + +cd "$ROOT" || exit 1 +for f in build/service-scripts/*.sh tools/install/*.sh tools/update/kryptik-update tools/update/kryptik-recover; do + loose="$(grep -nE "$LOOSE" "$f" | cut -d: -f1 | tr '\n' ' ')" + [[ -z "$loose" ]] && green "${f}: every mount names its filesystem" || red "${f}: line(s) ${loose% } leave the filesystem to be guessed" +done + +echo +echo "${PASS} passed, ${FAIL} failed" +[[ "$FAIL" -eq 0 ]] diff --git a/tools/update/kryptik-recover b/tools/update/kryptik-recover index 944aeca3..73bccf5c 100755 --- a/tools/update/kryptik-recover +++ b/tools/update/kryptik-recover @@ -55,7 +55,7 @@ has_fs() { [ "$(dd if="$1" bs=1 skip=1080 count=2 status=none | od -An -tx1 | tr put() { printf '%s\n' "$2" > "$1.new" && sync -f "$1.new" && mv -f "$1.new" "$1"; } # put FILE LINE if [ "$STATUS" = 1 ]; then - mount -o ro "$ESP" /run/kryptik-recover || die "cannot mount the ESP" + mount -t vfat -o ro "$ESP" /run/kryptik-recover || die "cannot mount the ESP" echo "disk $DISK" echo "committed slot $(cat /run/kryptik-recover/kryptik/committed-slot 2>/dev/null || echo unknown)" for s in a b; do @@ -108,13 +108,13 @@ if [ -n "$RESTORE" ]; then . /usr/libexec/kryptik/devices.sh src="$(kryptik_part kryptik-media)" || die "no single kryptik-media partition on this medium"; off=0 mesp="$(kryptik_part kryptik-esp)" || die "no single kryptik-esp partition on this medium" - mount -o ro "$mesp" /run/kryptik-recover-media || die "cannot mount the medium's ESP" + mount -t vfat -o ro "$mesp" /run/kryptik-recover-media || die "cannot mount the medium's ESP" rj=/run/kryptik-recover-media/kryptik/root.json; kdir=/run/kryptik-recover-media/EFI/kryptik ;; iso) mount -t iso9660 -o ro /dev/sr0 /run/kryptik-recover-media || die "cannot mount the medium" src=/dev/sr0; off="$(sed -n 's/.*linear \/dev\/sr0 \([0-9]*\).*/\1/p' /proc/cmdline | head -1)"; off=$(( off * 512 )) rj=/run/kryptik-recover-media/root.json - mkdir -p /run/kryptik-recover-esp && mount -o ro,loop /run/kryptik-recover-media/esp.img /run/kryptik-recover-esp || die "cannot mount the medium's ESP image" + mkdir -p /run/kryptik-recover-esp && mount -t vfat -o ro,loop /run/kryptik-recover-media/esp.img /run/kryptik-recover-esp || die "cannot mount the medium's ESP image" kdir=/run/kryptik-recover-esp/EFI/kryptik ;; esac bytes="$(sed -n 's/^ "total_bytes": \([0-9]*\).*/\1/p' "$rj")"; sha="$(sed -n 's/^ "sha256": "\([0-9a-f]*\)".*/\1/p' "$rj")"; ver="$(sed -n 's/^ "version": "\([^"]*\)".*/\1/p' "$rj")" @@ -122,7 +122,7 @@ if [ -n "$RESTORE" ]; then # As kryptik-update does, the ESP stops naming the slot before it is # rewritten, and is unmounted meanwhile: a restore cut short leaves nothing # --commit-slot would take, on a clean FAT. - mount -o rw "$ESP" /run/kryptik-recover || die "cannot mount the target ESP" + mount -t vfat -o rw "$ESP" /run/kryptik-recover || die "cannot mount the target ESP" rm -f "/run/kryptik-recover/EFI/kryptik/kryptik-$RESTORE.efi" "/run/kryptik-recover/kryptik/version-$RESTORE" umount /run/kryptik-recover || die "cannot unmount the target ESP" say "restoring slot $RESTORE from this medium (${ver}, ${bytes} bytes); the state partition is untouched" @@ -132,7 +132,7 @@ if [ -n "$RESTORE" ]; then got="$(dd if="$sd" bs=4M iflag=count_bytes count="$bytes" status=none | sha256sum | cut -c1-64)" [ "$got" = "$sha" ] || die "slot $RESTORE reads back as $got, expected $sha" say "slot $RESTORE verifies" - mount -o rw "$ESP" /run/kryptik-recover || die "cannot mount the target ESP" + mount -t vfat -o rw "$ESP" /run/kryptik-recover || die "cannot mount the target ESP" cp "$kdir/kryptik-$RESTORE.efi" "/run/kryptik-recover/EFI/kryptik/kryptik-$RESTORE.efi.new" sync -f "/run/kryptik-recover/EFI/kryptik/kryptik-$RESTORE.efi.new" mv -f "/run/kryptik-recover/EFI/kryptik/kryptik-$RESTORE.efi.new" "/run/kryptik-recover/EFI/kryptik/kryptik-$RESTORE.efi" @@ -146,7 +146,7 @@ if [ -n "$RESTORE" ]; then fi if [ -n "$COMMIT" ]; then - mount -o rw "$ESP" /run/kryptik-recover || die "cannot mount the target ESP" + mount -t vfat -o rw "$ESP" /run/kryptik-recover || die "cannot mount the target ESP" commit_slot "$COMMIT" umount /run/kryptik-recover exit 0 diff --git a/tools/update/kryptik-update b/tools/update/kryptik-update index 7204456d..310634cb 100755 --- a/tools/update/kryptik-update +++ b/tools/update/kryptik-update @@ -76,7 +76,7 @@ mount_esp() { dev="$(esp_dev)" || exit 1 mkdir -p "$ESP_MNT" if ! mountpoint -q "$ESP_MNT"; then - mount -o rw,nosuid,nodev,noexec "$dev" "$ESP_MNT" || die "cannot mount the ESP" + mount -t vfat -o rw,nosuid,nodev,noexec "$dev" "$ESP_MNT" || die "cannot mount the ESP" ESP_MINE=1 fi }