heads/qubes/boot.sh

108 lines
3.1 KiB
Bash

#!/bin/sh
# /boot/boot.sh -- Startup Qubes
#
# The signature on this script will be verified by the ROM,
# and this script lives on the /boot partition to allow
# the system owner to change the specific Qubes boot parameters
#
# This depends on the PCR 4 being "normal-boot":
# f8fa3b6e32e7c6fe04c366e74636e505b28f3b0d
# which is only set if the top level /init script has started
# without user intervention or dropping into a recovery shell.
#
# To sign this script and the other bootable components:
#
# gpg -a --sign --detach-sign boot.sh
#
XEN=/boot/xen-4.6.4.heads
INITRD=/boot/initramfs-4.4.14-11.pvops.qubes.x86_64.img
KERNEL=/boot/vmlinuz-4.4.14-11.pvops.qubes.x86_64
recovery() {
echo >&2 "!!!!! $@"
rm -f /tmp/secret.key /initrd.gz
tpm extend -ix 4 -ic recovery
echo >&2 "!!!!! Starting recovery shell"
exec /bin/ash
}
. /config
echo "+++ Checking $XEN"
gpgv "${XEN}.asc" "${XEN}" \
|| recovery 'Xen signature failed'
echo "+++ Checking $INITRD"
gpgv "${INITRD}.asc" "${INITRD}" \
|| recovery 'Initrd signature failed'
echo "+++ Checking $KERNEL"
gpgv "${KERNEL}.asc" "${KERNEL}" \
|| recovery 'Kernel signature failed'
# Activate the dom0 group
lvm vgchange -a y "$CONFIG_QUBES_VG" \
|| recovery "$CONFIG_QUBES_VG: LVM volume group activate failed"
# Measure the LUKS headers before we unseal the disk key
qubes-measure-luks /dev/$CONFIG_QUBES_VG/* \
|| recovery "LUKS measure failed"
# get the UUID of the root file system
# busybox blkid doesn't have a "just the UUID" option
ROOT_UUID=`blkid /dev/$CONFIG_QUBES_VG/00 | cut -d\" -f2`
if [ -z "$ROOT_UUID" ]; then
recovery "$CONFIG_QUBES_VG/00: No UUID for /"
fi
echo "$CONFIG_QUBES_VG/00: UUID=$ROOT_UUID"
# Attempt to unseal the disk key from the TPM
# should we give this some number of tries?
unseal-key \
|| recovery 'Unseal disk key failed. Starting recovery shell'
# Unpack the initrd and fixup the /etc/crypttab
# this is a hack to split it into two parts since
# we know that the first 0x3400 bytes are the microcode
INITRD_DIR=/tmp/initrd
echo '+++ Unpacking initrd'
mkdir -p $INITRD_DIR/etc
#dd if="$INITRD" bs=256 count=52 | ( cd $INITRD_DIR ; cpio -i )
#dd if="$INITRD" bs=256 skip=52 | zcat | ( cd $INITRD_DIR ; cpio -i )
mv /tmp/secret.key $INITRD_DIR/
## Update the /etc/crypttab in the initrd and install our key
## This is no longer required, now that dom0 /etc/crypttab has
## the /secret.key specified.
#for dev in /dev/$CONFIG_QUBES_VG/*; do
# uuid=`blkid $dev | cut -d\" -f2`
# echo luks-$uuid /dev/disk/by-uuid/$uuid /secret.key
#done > $INITRD_DIR/etc/crypttab
echo '+++ Repacking initrd'
( cd $INITRD_DIR ; find . | cpio -H newc -o ) > /initrd.cpio
cat "$INITRD" >> /initrd.cpio
# command line arguments are include in the signature on this script,
echo '+++ Loading kernel and initrd'
kexec \
-l \
--module "${KERNEL} root=/dev/mapper/luks-$ROOT_UUID ro rd.qubes.hide_all_usb" \
--module /initrd.cpio \
--command-line "no-real-mode reboot=no" \
"${XEN}" \
|| recovery "kexec load failed"
# Last step is to override PCR 4 so that user can't read the key
tpm extend -ix 4 -ic qubes \
|| recovery 'Unable to scramble PCR'
echo "+++ Starting Qubes..."
sleep 2
exec kexec -e