mirror of
https://github.com/linuxboot/heads.git
synced 2025-04-06 19:06:49 +00:00
Added a generic boot config and persistent params
Refactored boot parsing code and applied that in local-init to scan /boot for grub options and allow the user to unsafely boot anything. This goes a long way to addressing #196. Optionally the user can customize those boot parameters or enforce arbitrary hashes on the boot device by creating and signing config files in /boot/ or /media/ or /media/kexec_iso/ISO_FILENAME/.
This commit is contained in:
parent
76a20288a3
commit
3614044fff
24
config/x230-generic.config
Normal file
24
config/x230-generic.config
Normal file
@ -0,0 +1,24 @@
|
||||
# Configuration for a x230 running non-Qubes
|
||||
BOARD=x230
|
||||
|
||||
CONFIG_CRYPTSETUP=y
|
||||
CONFIG_FLASHROM=y
|
||||
CONFIG_GPG=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_UTIL_LINUX=y
|
||||
CONFIG_LVM2=y
|
||||
CONFIG_MBEDTLS=y
|
||||
CONFIG_PCIUTILS=y
|
||||
CONFIG_POPT=y
|
||||
CONFIG_QRENCODE=y
|
||||
CONFIG_TPMTOTP=y
|
||||
CONFIG_XEN=y
|
||||
CONFIG_DROPBEAR=y
|
||||
|
||||
CONFIG_LINUX_USB=y
|
||||
CONFIG_LINUX_E1000E=y
|
||||
|
||||
CONFIG_BOOTSCRIPT=/bin/local-init
|
||||
|
||||
CONFIG_BOOT_DEV="/dev/sda1"
|
||||
CONFIG_USB_BOOT_DEV="/dev/sdb1"
|
@ -14,6 +14,10 @@ kexectype=`echo $entry | cut -d\| -f2`
|
||||
kexecparams=`echo $entry | cut -d\| -f3- | tr '|' '\n'`
|
||||
kexeccmd="kexec"
|
||||
|
||||
# TODO: make this configurable
|
||||
cmdadd="intel_iommu=on $cmdadd"
|
||||
cmdremove="quiet $cmdremove"
|
||||
|
||||
fix_file_path() {
|
||||
filepath=`find $bootdir -path "*$firstval" | tail -1`
|
||||
if ! [ -r $filepath ]; then
|
22
initrd/bin/kexec-check-config
Executable file
22
initrd/bin/kexec-check-config
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
# Check for valid kexec params and copy to tmp
|
||||
. /etc/functions
|
||||
|
||||
MEDIA="$1"
|
||||
if [ ! -d /tmp/kexec ]; then
|
||||
mkdir /tmp/kexec \
|
||||
|| recovery 'failed to make kexec tmp dir'
|
||||
fi
|
||||
|
||||
if [ ! -r $MEDIA/kexec.sig ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z `find $MEDIA/kexec*.txt` ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if sha256sum `find $MEDIA/kexec*.txt` | gpg --verify $MEDIA/kexec.sig - ; then
|
||||
echo "+++ Found verified kexec boot params"
|
||||
cp $MEDIA/kexec*.txt /tmp/kexec
|
||||
fi
|
42
initrd/bin/kexec-iso-init
Executable file
42
initrd/bin/kexec-iso-init
Executable file
@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
# Boot from signed ISO
|
||||
|
||||
. /etc/functions
|
||||
. /etc/config
|
||||
|
||||
MOUNTED_ISO_PATH="$1"
|
||||
ISO_PATH="$2"
|
||||
DEV="$3"
|
||||
|
||||
echo '+++ Verifying ISO'
|
||||
# Verify the signature on the hashes
|
||||
ISOSIG="$MOUNTED_ISO_PATH.sig"
|
||||
if ! [ -r "$ISOSIG" ]; then
|
||||
ISOSIG="$MOUNTED_ISO_PATH.asc"
|
||||
fi
|
||||
|
||||
gpgv "$ISOSIG" "$MOUNTED_ISO_PATH" \
|
||||
|| recovery 'ISO signature failed'
|
||||
|
||||
echo '+++ Mounting ISO and booting'
|
||||
mount -t iso9660 -o loop $MOUNTED_ISO_PATH /boot \
|
||||
|| recovery '$MOUNTED_ISO_PATH: Unable to mount /boot'
|
||||
|
||||
DEV_UUID=`blkid $DEV | tail -1 | tr " " "\n" | grep UUID | cut -d\" -f2`
|
||||
ADD="fromiso=/dev/disk/by-uuid/$DEV_UUID/$ISO_PATH"
|
||||
REMOVE=""
|
||||
|
||||
ADD_FILE=/tmp/kexec/kexec_iso_add.txt
|
||||
if [ -r $ADD_FILE ]; then
|
||||
NEW_ADD=`cat $ADD_FILE`
|
||||
ADD=$(eval "echo \"$NEW_ADD\"")
|
||||
echo "+++ Overriding standard ISO kernel add arguments: $ADD"
|
||||
fi
|
||||
REMOVE_FILE=/tmp/kexec/kexec_iso_remove.txt
|
||||
if [ -r $REMOVE_FILE ]; then
|
||||
NEW_REMOVE=`cat $REMOVE_FILE`
|
||||
REMOVE=$(eval "echo \"$NEW_REMOVE\"")
|
||||
echo "+++ Overriding standard ISO kernel remove arguments: $REMOVE"x
|
||||
fi
|
||||
|
||||
kexec-select-boot /boot "$ADD" "$REMOVE"
|
82
initrd/bin/kexec-select-boot
Executable file
82
initrd/bin/kexec-select-boot
Executable file
@ -0,0 +1,82 @@
|
||||
#!/bin/sh
|
||||
. /etc/functions
|
||||
|
||||
bootdir=$1
|
||||
add=$2
|
||||
remove=$3
|
||||
|
||||
MENU_NAME="kexec_menu.txt"
|
||||
HASH_NAME="kexec_hashes.txt"
|
||||
TMP_MENU_FILE=/tmp/kexec/$MENU_NAME
|
||||
TMP_HASH_FILE=/tmp/kexec/$HASH_NAME
|
||||
|
||||
get_menu_option() {
|
||||
echo "+++ Select your boot option:"
|
||||
n=0
|
||||
while read option
|
||||
do
|
||||
parse_option
|
||||
n=`expr $n + 1`
|
||||
echo "$n. $name [$kernel]"
|
||||
done < $TMP_MENU_FILE
|
||||
|
||||
read \
|
||||
-p "Choose the boot option [1-$n, a to abort]: " \
|
||||
option_index
|
||||
|
||||
if [ "$option_index" = "a" ]; then
|
||||
recovery "Aborting boot attempt"
|
||||
fi
|
||||
|
||||
option=`head -n $option_index $TMP_MENU_FILE | tail -1`
|
||||
parse_option
|
||||
}
|
||||
|
||||
confirm_menu_option() {
|
||||
echo "+++ Please confirm the boot details for $name:"
|
||||
echo $option
|
||||
|
||||
read \
|
||||
-n 1 \
|
||||
-p "Confirm selection by pressing 'y': " \
|
||||
option_confirm
|
||||
echo
|
||||
}
|
||||
|
||||
parse_option() {
|
||||
name=`echo $option | cut -d\| -f1`
|
||||
kernel=`echo $option | cut -d\| -f3`
|
||||
}
|
||||
|
||||
# optionally enforce file hashes
|
||||
if [ -r $TMP_HASH_FILE ]; then
|
||||
echo "+++ Checking verified boot hash file "
|
||||
# Check the hashes of all the files
|
||||
if cd $bootdir && sha256sum -c "$TMP_HASH_FILE" ; then
|
||||
echo "+++ Verified boot hashes "
|
||||
else
|
||||
recovery "$TMP_HASH_FILE: boot hash mismatch"
|
||||
fi
|
||||
fi
|
||||
|
||||
# otherwise scan the boot directory and generate options
|
||||
if [ ! -r $TMP_MENU_FILE ]; then
|
||||
echo "+++ Scanning for unsigned boot options"
|
||||
option_file="/tmp/kexec_options.txt"
|
||||
for i in `find $bootdir -name "*.cfg"`; do
|
||||
kexec-parse-boot $i >> $option_file
|
||||
done
|
||||
if [ ! -r $option_file ]; then
|
||||
recovery "Failed to parse any boot options"
|
||||
fi
|
||||
sort $option_file | uniq > $TMP_MENU_FILE
|
||||
fi
|
||||
|
||||
option_confirm=""
|
||||
while [ "$option_confirm" != "y" ]
|
||||
do
|
||||
get_menu_option
|
||||
confirm_menu_option
|
||||
done
|
||||
|
||||
kexec-boot -b $bootdir -e "$option" -a "$add" -r "$remove"
|
45
initrd/bin/kexec-sign-config
Executable file
45
initrd/bin/kexec-sign-config
Executable file
@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
# Sign a valid directory of kexec params
|
||||
. /etc/functions
|
||||
|
||||
MEDIA="$1"
|
||||
|
||||
if [ -z "$MEDIA" ]; then
|
||||
die "Usage: $0 /boot "
|
||||
fi
|
||||
|
||||
# setup the USB so we can reach the GPG card
|
||||
if ! lsmod | grep -q ehci_hcd; then
|
||||
insmod /lib/modules/ehci-hcd.ko \
|
||||
|| die "ehci_hcd: module load failed"
|
||||
fi
|
||||
if ! lsmod | grep -q ehci_pci; then
|
||||
insmod /lib/modules/ehci-pci.ko \
|
||||
|| die "ehci_pci: module load failed"
|
||||
fi
|
||||
if ! lsmod | grep -q xhci_hcd; then
|
||||
insmod /lib/modules/xhci-hcd.ko \
|
||||
|| die "ehci_hcd: module load failed"
|
||||
fi
|
||||
if ! lsmod | grep -q xhci_pci; then
|
||||
insmod /lib/modules/xhci-pci.ko \
|
||||
|| die "ehci_pci: module load failed"
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
gpg --card-status \
|
||||
|| die "gpg card read failed"
|
||||
|
||||
for tries in 1 2 3; do
|
||||
if sha256sum `find $MEDIA/kexec*.txt` | gpg \
|
||||
--digest-algo SHA256 \
|
||||
--detach-sign \
|
||||
-a \
|
||||
> $MEDIA/kexec.sig \
|
||||
; then
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
warn "$MEDIA: Unable to sign boot hashes"
|
||||
exit 1
|
29
initrd/bin/local-init
Executable file
29
initrd/bin/local-init
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
# Boot from a local disk installation
|
||||
|
||||
. /etc/functions
|
||||
. /etc/config
|
||||
|
||||
# Confirm we have a good TOTP unseal
|
||||
if ! confirm_totp ; then
|
||||
recovery 'Failed to unseal TOTP'
|
||||
fi
|
||||
|
||||
# Extend PCR4 as soon as possible
|
||||
tpm extend -ix 4 -ic local
|
||||
|
||||
if [ ! "$totp_confirm" = "y" ]; then
|
||||
recovery "Failed to confirm validity of TOTP"
|
||||
fi
|
||||
|
||||
# Mount local disk
|
||||
if ! grep -q /boot /proc/mounts ; then
|
||||
mount -o ro "$CONFIG_BOOT_DEV" /boot \
|
||||
|| recovery '$CONFIG_BOOT_DEV: Unable to mount /boot'
|
||||
fi
|
||||
|
||||
# Attempt to pull verified config from device
|
||||
kexec-check-config /boot
|
||||
exec kexec-select-boot /boot
|
||||
|
||||
recovery "Something failed..."
|
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Boot a Tails installation
|
||||
# Boot a USB installation
|
||||
|
||||
. /etc/functions
|
||||
. /etc/config
|
||||
@ -16,8 +16,9 @@ if [ ! "$totp_confirm" = "y" ]; then
|
||||
recovery "Failed to confirm validity of TOTP"
|
||||
fi
|
||||
|
||||
# TODO: Do a scan of USB devices to detect the Tails USB
|
||||
mount-usb "$CONFIG_USB_BOOT_DEV"
|
||||
# Mount the USB boot device
|
||||
mount-usb "$CONFIG_USB_BOOT_DEV" \
|
||||
|| recovery '$CONFIG_USB_BOOT_DEV: Unable to mount /media'
|
||||
|
||||
# Check for ISO first
|
||||
get_menu_option() {
|
||||
@ -55,11 +56,16 @@ if [ `wc -l /tmp/iso_menu.txt | cut -d\ -f1` -gt 0 ]; then
|
||||
done
|
||||
|
||||
if [ -n "$option" ]; then
|
||||
exec usb-iso-init $option
|
||||
MOUNTED_ISO=$option
|
||||
ISO=${option:7} # remove /media/ to get device relative path
|
||||
kexec-check-config /media/kexec_iso/$ISO
|
||||
exec kexec-iso-init $MOUNTED_ISO $ISO $CONFIG_USB_BOOT_DEV
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "!!! Could not find any ISO, trying bootable USB"
|
||||
exec usb-select-boot /media
|
||||
# Attempt to pull verified config from device
|
||||
kexec-check-config /media
|
||||
exec kexec-select-boot /media
|
||||
|
||||
recovery "Something failed..."
|
||||
|
@ -1,27 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Boot from signed ISO
|
||||
|
||||
. /etc/functions
|
||||
. /etc/config
|
||||
|
||||
ISO="$1"
|
||||
|
||||
echo '+++ Verifying ISO'
|
||||
# Verify the signature on the hashes
|
||||
ISOSIG="$ISO.sig"
|
||||
if ! [ -r "$ISOSIG" ]; then
|
||||
ISOSIG="$ISO.asc"
|
||||
fi
|
||||
|
||||
gpgv "$ISOSIG" "$ISO" \
|
||||
|| recovery 'ISO signature failed'
|
||||
|
||||
echo '+++ Mounting ISO and booting'
|
||||
mount -t iso9660 -o loop $ISO /boot
|
||||
|
||||
ISO_FILE=${ISO:7}
|
||||
DEV=$CONFIG_USB_BOOT_DEV
|
||||
DEV_UUID=`blkid $DEV | tail -1 | tr " " "\n" | grep UUID | cut -d\" -f2`
|
||||
ADD="fromiso=/dev/disk/by-uuid/$DEV_UUID/$ISO_FILE"
|
||||
|
||||
/bin/usb-select-boot /boot "$ADD"
|
@ -1,59 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /etc/functions
|
||||
|
||||
bootdir=$1
|
||||
add=$2
|
||||
|
||||
get_menu_option() {
|
||||
echo "+++ Select your boot option:"
|
||||
n=0
|
||||
while read option
|
||||
do
|
||||
parse_option
|
||||
n=`expr $n + 1`
|
||||
echo "$n. $name [$kernel]"
|
||||
done < /tmp/usb_menu.txt
|
||||
|
||||
read \
|
||||
-p "Choose the boot option [1-$n, a to abort]: " \
|
||||
option_index
|
||||
|
||||
if [ "$option_index" = "a" ]; then
|
||||
recovery "Aborting boot attempt"
|
||||
fi
|
||||
|
||||
option=`head -n $option_index /tmp/usb_menu.txt | tail -1`
|
||||
parse_option
|
||||
}
|
||||
|
||||
confirm_menu_option() {
|
||||
echo "+++ Please confirm the boot details for $name:"
|
||||
echo $option
|
||||
|
||||
read \
|
||||
-n 1 \
|
||||
-p "Confirm selection by pressing 'y': " \
|
||||
option_confirm
|
||||
echo
|
||||
}
|
||||
|
||||
parse_option() {
|
||||
name=`echo $option | cut -d\| -f1`
|
||||
kernel=`echo $option | cut -d\| -f3`
|
||||
}
|
||||
|
||||
echo "+++ Scanning USB media boot options"
|
||||
for i in `find $bootdir -name "*.cfg"`; do usb-parse-boot $i >> /tmp/usb_options.txt; done
|
||||
if [ ! -r /tmp/usb_options.txt ]; then
|
||||
recovery "Failed to parse any boot options"
|
||||
fi
|
||||
sort /tmp/usb_options.txt | uniq > /tmp/usb_menu.txt
|
||||
|
||||
option_confirm=""
|
||||
while [ "$option_confirm" != "y" ]
|
||||
do
|
||||
get_menu_option
|
||||
confirm_menu_option
|
||||
done
|
||||
|
||||
usb-boot -b $bootdir -e "$option" -a "intel_iommu=on $add" -r "quiet"
|
Loading…
x
Reference in New Issue
Block a user