Skip to content

initrd: add boot partition preflight check and documentation#2073

Open
MarkAtwood wants to merge 1 commit intolinuxboot:masterfrom
MarkAtwood:fix/add-boot-partition-preflight-check
Open

initrd: add boot partition preflight check and documentation#2073
MarkAtwood wants to merge 1 commit intolinuxboot:masterfrom
MarkAtwood:fix/add-boot-partition-preflight-check

Conversation

@MarkAtwood
Copy link

Problem

Heads has always required /boot to be a separate, unencrypted partition (CONFIG_BOOT_DEV). This is the foundation of the entire integrity model — Heads runs from ROM, measures /boot before the OS runs, and kexec's the kernel only after GPG signature and TPM PCR verification pass. If /boot is encrypted or merged into /, none of that is possible.

The failure mode was silent degradation. A wrong layout produced whiptail dialogs asking "would you like to configure the /boot device now?" — identical to normal first-boot prompts — with no indication the disk layout was fundamentally incompatible. Execution continued with /boot unmounted.

Noted without enforcement in issue #959:

"Heads has always used/required a dedicated, unencrypted /boot partition AFAIK"

Changes

initrd/bin/check-boot-partition (new, executable)
Preflight validator with five checks: CONFIG_BOOT_DEV is set; device exists; it is a block device; it is not the same device as /; it is not crypto_LUKS per blkid. Hard failures call die(). Warnings for soft mismatches (already-mounted device mismatch).

initrd/bin/gui-init (modified)
Call check-boot-partition as the first substantive action, before any whiptail dialogs. If it fails, the user drops to the recovery shell with a clear error rather than a misleading setup prompt.

initrd/bin/init (not modified)
Does not exist in the current tree. If a non-GUI init path is added in the future, it should also call check-boot-partition.

doc/boot-partition-requirements.md (new)
First-class in-repo documentation: why the requirement exists, correct vs incorrect layouts, OS-specific notes (Debian, Fedora, Qubes, NixOS, Guix), how to set CONFIG_BOOT_DEV, what the new errors mean, how to recover.

Testing checklist

  • QEMU correct layout (separate ext4 /boot): boots normally
  • QEMU with CONFIG_BOOT_DEV unset: recovery shell with clear error
  • QEMU with CONFIG_BOOT_DEV pointing to nonexistent device: clear error
  • QEMU with CONFIG_BOOT_DEV pointing to LUKS partition: clear error
  • x230 hardware with standard Qubes layout: boots normally

Related

Fixes silent failure noted in #959. Related: #753, #1620, #531

Heads requires /boot to be a separate, unencrypted block device
partition (CONFIG_BOOT_DEV). This has always been true but was never
enforced at runtime. A missing or wrong CONFIG_BOOT_DEV produced
confusing first-boot-style whiptail dialogs instead of a clear error.

Add check-boot-partition, a preflight script called at the top of
gui-init before mount_boot(). It validates:

  - CONFIG_BOOT_DEV is set
  - CONFIG_BOOT_DEV exists and is a block device
  - CONFIG_BOOT_DEV is not the same device as /
  - CONFIG_BOOT_DEV is not LUKS-encrypted (via blkid)

On any hard failure it calls die() with a human-readable explanation,
dropping to the recovery shell with the error visible in scrollback.

Also add doc/boot-partition-requirements.md — first-class in-repo
documentation of the requirement, including correct/incorrect layout
examples, OS-specific notes (Debian, Fedora, Qubes, NixOS, Guix),
and recovery instructions.

Note: initrd/bin/init does not exist in the current tree, so the
preflight check is only added to gui-init. If a non-GUI init path
is added in the future, it should also call check-boot-partition.

Fixes the silent-failure mode reported in passing in issue linuxboot#959.
Related: linuxboot#753, linuxboot#1620, linuxboot#531

Signed-off-by: Mark Atwood <mark.atwood@gmail.com>

### Debian / Ubuntu

The default installer in recent versions creates a single encrypted
Copy link
Collaborator

@tlaurion tlaurion Mar 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not true if using dvd live install, which detects legacy bios and creates unencrypted /boot

@tlaurion
Copy link
Collaborator

tlaurion commented Mar 15, 2026

Will test later but unsure why initrd/etc/detect_boot_device not enough/not the place to implement those improvements. We might force check earlier, but unsure of redundancy and addition of other scripts

as of origin/master, initrd/etc/functions: detect_boot_device looks like:


# detect and set /boot device
# mount /boot if successful
detect_boot_device() {
	TRACE_FUNC
	local devname mounted_boot_dev
	DEBUG "CONFIG_BOOT_DEV=$CONFIG_BOOT_DEV"
	# If /boot is already mounted and appears to be a valid boot tree, just
	# use its device.  This avoids remount churn and makes the later lookup
	# fast.
	mounted_boot_dev="$(awk '$2=="/boot" {print $1; exit}' /proc/mounts)"
	if [ -n "$mounted_boot_dev" ] && ls -d /boot/grub* >/dev/null 2>&1; then
		CONFIG_BOOT_DEV="$mounted_boot_dev"
		DEBUG "Using already-mounted /boot device as CONFIG_BOOT_DEV=$CONFIG_BOOT_DEV"
		return 0
	fi
	# unmount /boot to be safe
	cd / && umount /boot 2>/dev/null

	# check $CONFIG_BOOT_DEV if set/valid
	if [ -e "$CONFIG_BOOT_DEV" ] && mount_possible_boot_device "$CONFIG_BOOT_DEV"; then
		# CONFIG_BOOT_DEV is valid device and contains an installed OS
		return 0
	fi

	# generate list of possible boot devices
	fdisk -l 2>/dev/null | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" >/tmp/disklist

	# Check each possible boot device
	for i in $(cat /tmp/disklist); do
		# If the device has partitions, check the partitions instead
		if device_has_partitions "$i"; then
			devname="$(basename "$i")"
			partitions=("/sys/class/block/$devname/$devname"?*)
		else
			partitions=("$i") # Use the device itself
		fi
		for partition in "${partitions[@]}"; do
			partition_dev=/dev/"$(basename "$partition")"
			# No sense trying something we already tried above
			if [ "$partition_dev" = "$CONFIG_BOOT_DEV" ]; then
				continue
			fi
			# If this is a reasonable boot device, select it and finish
			if mount_possible_boot_device "$partition_dev"; then
				CONFIG_BOOT_DEV="$partition_dev"
				return 0
			fi
		done
	done

	# no valid boot device found
	echo "Unable to locate /boot files on any mounted disk"
	DEBUG "detect_boot_device: failed to find a bootable device"
	return 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants