From c40748aa255f96067076bedf3a88d2dd70b3cb1b Mon Sep 17 00:00:00 2001 From: Trammell Hudson Date: Fri, 31 Mar 2017 11:18:46 -0400 Subject: [PATCH] Build time configuration for startup scripts and modules. This addresses multiple issues: * Issue #63: initrd is build fresh each time, so tracked files do not matter. * Issue #144: build time configuration * Issue #123: allows us to customize the startup experience * Issue #122: manual start-xen will go away * Issue #25: tpmtotp PCRs are updated after reading the secret * Issue #16: insmod now meaures modules --- Makefile | 35 +++++++++++------ config/qemu-moc.config | 18 +++++++++ config/x230-moc.config | 20 ++++++++++ config/x230-qubes.config | 17 +++++++++ initrd/etc/keylime-init | 17 +++++++++ initrd/etc/motd | 8 ++++ initrd/init | 72 +++++++++++++++++++++++++---------- initrd/sbin/insmod | 37 ++++++++++++++++++ initrd/sbin/insmod-measure.sh | 29 -------------- modules/busybox | 4 +- modules/coreboot | 4 +- modules/cryptsetup | 2 +- modules/flashrom | 2 +- modules/gpg | 2 +- modules/kernel-headers | 2 +- modules/libuuid | 2 +- modules/linux | 19 +++++---- modules/lvm2 | 2 +- modules/mbedtls | 2 +- modules/musl | 2 +- modules/musl-cross | 2 +- modules/pciutils | 2 +- modules/popt | 2 +- modules/qrencode | 2 +- modules/tpmtotp | 2 +- modules/xen | 4 +- 26 files changed, 221 insertions(+), 89 deletions(-) create mode 100644 config/qemu-moc.config create mode 100644 config/x230-moc.config create mode 100644 config/x230-qubes.config create mode 100755 initrd/etc/keylime-init create mode 100644 initrd/etc/motd create mode 100755 initrd/sbin/insmod delete mode 100755 initrd/sbin/insmod-measure.sh diff --git a/Makefile b/Makefile index a411d1a2..5e2eb9fe 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,10 @@ -modules := +modules-y := pwd := $(shell pwd) packages := $(pwd)/packages build := $(pwd)/build config := $(pwd)/build INSTALL := $(pwd)/install log_dir := $(build)/log -initrd_lib_dir := initrd/lib -initrd_bin_dir := initrd/bin # Controls how many parallel jobs are invoked in subshells MAKE_JOBS ?= -j8 --max-load 24 @@ -37,6 +35,17 @@ LOCAL_MAKE_VERSION := $(shell $(MAKE) --version | head -1 | cut -d' ' -f3) include modules/make ifeq "$(LOCAL_MAKE_VERSION)" "$(make_version)" + +# Create a temporary directory for the initrd +initrd_dir := $(shell mktemp -d) +initrd_lib_dir := $(initrd_dir)/lib +initrd_bin_dir := $(initrd_dir)/bin + +$(shell mkdir -p "$(initrd_lib_dir)" "$(initrd_bin_dir)") +$(shell echo "Initrd: $initrd_dir") + +include $(CONFIG) + # We are running our own version of make, # proceed with the build. @@ -81,7 +90,7 @@ include modules/* # These will be built via their intermediate targets # This increases the build time, so it is commented out for now -#all: $(foreach m,$(modules),$m.intermediate) +#all: $(foreach m,$(modules-y),$m.intermediate) define bins = $(foreach m,$1,$(call prefix,$(build)/$($m_dir)/,$($m_output))) @@ -197,7 +206,7 @@ define define_module = endef -$(call map, define_module, $(modules)) +$(call map, define_module, $(modules-y)) # @@ -223,7 +232,6 @@ endef define initrd_lib_add = $(initrd_lib_dir)/$(notdir $1): $1 - @-mkdir -p "$(dir $$@)" $(call do,INSTALL-LIB,$$@,$(CROSS)strip -o "$$@" "$$<") initrd_libs += $(initrd_lib_dir)/$(notdir $1) endef @@ -242,7 +250,7 @@ $(foreach m, $(bin_modules), \ ) # Install the libraries for every module that we have built -$(foreach m, $(modules), \ +$(foreach m, $(modules-y), \ $(call map,initrd_lib_add,$(call libs,$m)) \ ) @@ -289,7 +297,7 @@ $(initrd_lib_dir)/modules/$(notdir $1): $(build)/$(linux_dir)/$1 @-mkdir -p "$(initrd_lib_dir)/modules" $(call do,INSTALL-MODULE,$$@,$(CROSS)strip --strip-debug -o "$$@" "$$<") endef -$(call map,linux_module,$(linux_modules)) +$(call map,linux_module,$(linux_modules-y)) # @@ -307,13 +315,18 @@ $(call map,linux_module,$(linux_modules)) # # initrd.cpio: $(initrd_bins) $(initrd_libs) dev.cpio FORCE + $(call do,OVERLAY,initrd,\ + tar -C ./initrd -cf - . | tar -C "$(initrd_dir)" -xf - \ + ) + $(call do,INSTALL,$(CONFIG),cp "$(CONFIG)" "$(initrd_dir)/config") $(call do,CPIO,$@, \ - cd ./initrd ; \ + cd "$(initrd_dir)"; \ find . \ | cpio --quiet -H newc -o \ - | ../cpio-clean ../dev.cpio - \ - > "../$@" \ + | $(pwd)/cpio-clean $(pwd)/dev.cpio - \ + > "$(pwd)/$@" \ ) + echo should $(RM) -rf "$(initrd_dir)" initrd.intermediate: initrd.cpio diff --git a/config/qemu-moc.config b/config/qemu-moc.config new file mode 100644 index 00000000..177a7566 --- /dev/null +++ b/config/qemu-moc.config @@ -0,0 +1,18 @@ +# Configuration for building the MOC "server" build on the x230 +# thinkpad prototypes. +BOARD=qemu +CONFIG_CRYPTSETUP=y +CONFIG_FLASHROM=y +CONFIG_GPG=y +CONFIG_KEXEC=y +CONFIG_LIBUUID=y +CONFIG_LVM2=y +CONFIG_MBEDTLS=y +CONFIG_PCIUTILS=y +CONFIG_POPT=y +CONFIG_QRENCODE=y +CONFIG_TPMTOTP=y +CONFIG_XEN=n + +CONFIG_LINUX_USB=y +CONFIG_LINUX_E1000=y diff --git a/config/x230-moc.config b/config/x230-moc.config new file mode 100644 index 00000000..0543a4c5 --- /dev/null +++ b/config/x230-moc.config @@ -0,0 +1,20 @@ +# Configuration for building the MOC "server" build on the x230 +# thinkpad prototypes. +BOARD=x230 +CONFIG_CRYPTSETUP=y +CONFIG_FLASHROM=y +CONFIG_GPG=y +CONFIG_KEXEC=y +CONFIG_LIBUUID=y +CONFIG_LVM2=y +CONFIG_MBEDTLS=y +CONFIG_PCIUTILS=y +CONFIG_POPT=y +CONFIG_QRENCODE=y +CONFIG_TPMTOTP=y +CONFIG_XEN=n + +CONFIG_LINUX_USB=y +CONFIG_LINUX_E1000E=y + +CONFIG_BOOTSCRIPT=/etc/keylime-init diff --git a/config/x230-qubes.config b/config/x230-qubes.config new file mode 100644 index 00000000..eac343d1 --- /dev/null +++ b/config/x230-qubes.config @@ -0,0 +1,17 @@ +# Configuration for a x230 running Qubes OS +BOARD=x230 +CONFIG_CRYPTSETUP=y +CONFIG_FLASHROM=y +CONFIG_GPG=y +CONFIG_KEXEC=y +CONFIG_LIBUUID=y +CONFIG_LVM2=y +CONFIG_MBEDTLS=y +CONFIG_PCIUTILS=y +CONFIG_POPT=y +CONFIG_QRENCODE=y +CONFIG_TPMTOTP=y +CONFIG_XEN=y + +CONFIG_LINUX_USB=y +CONFIG_LINUX_E1000E=y diff --git a/initrd/etc/keylime-init b/initrd/etc/keylime-init new file mode 100755 index 00000000..e0974e96 --- /dev/null +++ b/initrd/etc/keylime-init @@ -0,0 +1,17 @@ +#!/bin/sh +# Bring up the x230's NIC, get a DHCP address and invoke keylime + +insmod /lib/modules/e1000e.ko +udhcpc -n + +cd / +wget-measure.sh 6 http://192.168.1.5/keylime.tar.gz +tar xf keylime.tar.gz + +if [ ! -x /keylime-node ]; then + echo '!!!! Keylime overlay not found?' + tpm extend -ix 4 -ic "recovery" + exec /bin/ash +fi + +exec /keylime-node diff --git a/initrd/etc/motd b/initrd/etc/motd new file mode 100644 index 00000000..13130a0a --- /dev/null +++ b/initrd/etc/motd @@ -0,0 +1,8 @@ +===================================================== + _ _ _ ____ ___ __ __ +| | | | ___ __ _ __| |___ _ | _ \ / _ \| \/ | +| |_| |/ _ \/ _` |/ _` / __| (_) | |_) | | | | |\/| | +| _ | __/ (_| | (_| \__ \ _ | _ <| |_| | | | | +|_| |_|\___|\__,_|\__,_|___/ (_) |_| \_\\___/|_| |_| + +===================================================== diff --git a/initrd/init b/initrd/init index 5d381e26..0fca961a 100755 --- a/initrd/init +++ b/initrd/init @@ -5,29 +5,61 @@ mount -t devtmpfs none /dev mount -t proc none /proc mount -t sysfs none /sys +# Setup our path +export PATH=/sbin:/bin + # Now it is safe to print a banner -echo '=====================================================' -echo ' _ _ _ ____ ___ __ __ ' -echo '| | | | ___ __ _ __| |___ _ | _ \ / _ \| \/ |' -echo '| |_| |/ _ \/ _` |/ _` / __| (_) | |_) | | | | |\/| |' -echo '| _ | __/ (_| | (_| \__ \ _ | _ <| |_| | | | |' -echo '|_| |_|\___|\__,_|\__,_|___/ (_) |_| \_\\___/|_| |_|' -echo '' -echo '=====================================================' +if [ -r /etc/motd ]; then + cat /etc/motd +fi # Load the date from the hardware clock, setting it in local time hwclock -l -s -# Verify the user's TPM secret -echo "TPM TOTP:" -if ! unsealtotp.sh ; then - echo '!!!!!' - echo '!!!!! TPM TOTP secret not found.' - echo '!!!!! This firmware can not be trusted.' - echo '!!!!!' -fi -echo +# Read the system configuration parameters +. /config -# Start an interactive shell -export PATH=/sbin:/usr/sbin:/bin:/usr/bin -exec /bin/ash +if [ -z "$CONFIG_TIMEOUT" ]; then + CONFIG_TIMEOUT=10 +fi + +while true; do + # Verify the user's TPM secret + echo "TPM TOTP:" + if ! unsealtotp.sh ; then + echo '!!!!!' + echo '!!!!! TPM TOTP secret not found.' + echo '!!!!! This firmware can not be trusted.' + echo '!!!!! Entering recovery shell' + echo '!!!!!' + tpm extend -ix 4 -ic "tpm-failure" + exec /bin/ash + fi + + # Secret decrypted ok, so prompt for a next step + + read \ + -t "$CONFIG_TIMEOUT" \ + -p "Enter for normal boot or 'r' for recovery shell: " \ + -n 1 \ + boot_option + + if [ "$boot_option" = "r" ]; then + # Start an interactive shell + echo '***** Starting recovery shell' + tpm extend -ix 4 -ic "recovery" + exec /bin/ash + fi + + if [ "$boot_option" = "" ]; then + if [ ! -x "$CONFIG_BOOTSCRIPT" ]; then + echo '!!!!! Boot script missing? Entering recovery shell' + tpm extend -ix 4 -ic "boot-failure" + exec /bin/ash + fi + + echo '***** Normal boot' + tpm extend -ix 4 -ic "normal-boot" + exec "$CONFIG_BOOTSCRIPT" + fi +done diff --git a/initrd/sbin/insmod b/initrd/sbin/insmod new file mode 100755 index 00000000..ac623e2f --- /dev/null +++ b/initrd/sbin/insmod @@ -0,0 +1,37 @@ +#!/bin/sh +# extend a TPM PCR with a module and then load it +# any arguments will also be measured. +# The default PCR to be extended is 5, but can be +# overridden with the MODULE_PCR environment variable + +die() { + echo >&2 "$@" + exit 1 +} + +MODULE="$1"; shift + +if [ -z "$MODULE_PCR" ]; then + MODULE_PCR=5 +fi + + +if [ -z "$MODULE" ]; then + die "Usage: $0 module [args...]" +fi + +if [ ! -r "$MODULE" ]; then + die "$MODULE: not found?" +fi + +tpm extend -ix "$MODULE_PCR" -if "$MODULE" || die "$MODULE: tpm extend failed" + +if [ ! -z "$@" ]; then + TMPFILE=/tmp/insmod.$$ + echo "$@" > $TMPFILE + tpm extend -ix "$MODULE_PCR" -if $TMPFILE || die "$MODULE: tpm extend on arguments failed" +fi + +# Since we have replaced the real insmod, we must invoke +# the busybox insmod via the original executable +busybox insmod "$MODULE" "$@" || die "$MODULE: insmod failed" diff --git a/initrd/sbin/insmod-measure.sh b/initrd/sbin/insmod-measure.sh deleted file mode 100755 index 53cb3e52..00000000 --- a/initrd/sbin/insmod-measure.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -# extend a TPM PCR with a module and then load it -# any arguments will also be measured - -die() { - echo >&2 "$@" - exit 1 -} - -INDEX="$1"; shift -MODULE="$1"; shift - -if [ -z "$INDEX" -o -z "$MODULE" ]; then - die "Usage: $0 pcr-index module [args...]" -fi - -if [ ! -r "$MODULE" ]; then - die "$MODULE: not found?" -fi - -tpm extend -ix "$INDEX" -if "$MODULE" || die "$MODULE: tpm extend failed" - -if [ ! -z "$@" ]; then - TMPFILE=/tmp/insmod.$$ - echo "$@" > $TMPFILE - tpm extend -ix "$INDEX" -if $TMPFILE || die "$MODULE: tpm extend on arguments failed" -fi - -insmod "$MODULE" "$@" || die "$MODULE: insmod failed" diff --git a/modules/busybox b/modules/busybox index ae9a5f0f..4348d7ea 100644 --- a/modules/busybox +++ b/modules/busybox @@ -1,4 +1,4 @@ -modules += busybox +modules-y += busybox busybox_version := 1.25.0 busybox_dir := busybox-$(busybox_version) @@ -11,7 +11,7 @@ busybox_config := busybox.config busybox_output := busybox busybox_target := \ CC="$(heads_cc)" \ - CONFIG_PREFIX="../../initrd/" \ + CONFIG_PREFIX="$(initrd_dir)" \ $(MAKE_JOBS) \ install diff --git a/modules/coreboot b/modules/coreboot index 2f94f422..65a36b1f 100644 --- a/modules/coreboot +++ b/modules/coreboot @@ -1,4 +1,4 @@ -modules += coreboot +modules-y += coreboot #coreboot_version := git #coreboot_repo := https://github.com/osresearch/coreboot @@ -52,7 +52,7 @@ ifneq "$(coreboot_version)" "git" # if we are not building from a git checkout, # we must also download the coreboot-blobs tree coreboot_depends += coreboot-blobs -modules += coreboot-blobs +modules-y += coreboot-blobs coreboot-blobs_version := $(coreboot_version) coreboot-blobs_tar := coreboot-blobs-$(coreboot-blobs_version).tar.xz diff --git a/modules/cryptsetup b/modules/cryptsetup index b957eec4..e582bbeb 100644 --- a/modules/cryptsetup +++ b/modules/cryptsetup @@ -1,4 +1,4 @@ -modules += cryptsetup +modules-$(CONFIG_CRYPTSETUP) += cryptsetup cryptsetup_depends := libuuid popt lvm2 $(musl_dep) diff --git a/modules/flashrom b/modules/flashrom index 88b2285e..d14902b6 100644 --- a/modules/flashrom +++ b/modules/flashrom @@ -1,4 +1,4 @@ -modules += flashrom +modules-$(CONFIG_FLASHROM) += flashrom flashrom_depends := pciutils $(musl_dep) diff --git a/modules/gpg b/modules/gpg index fad79334..0e066572 100644 --- a/modules/gpg +++ b/modules/gpg @@ -1,4 +1,4 @@ -modules += gpg +modules-$(CONFIG_GPG) += gpg # we install gpgv 1.4, which is an older version that has fewer # dependencies. This may need to be revisted later. diff --git a/modules/kernel-headers b/modules/kernel-headers index 512dc86d..44f6853e 100644 --- a/modules/kernel-headers +++ b/modules/kernel-headers @@ -1,4 +1,4 @@ -modules += kernel-headers +modules-y += kernel-headers # we install kernel-headers from sabotage linux, a musl-libc based # distribution, that works well with busybox and other tools. diff --git a/modules/libuuid b/modules/libuuid index 487463d2..5e9fed57 100644 --- a/modules/libuuid +++ b/modules/libuuid @@ -1,4 +1,4 @@ -modules += libuuid +modules-$(CONFIG_LIBUUID) += libuuid libuuid_version := 1.0.3 libuuid_dir := libuuid-$(libuuid_version) diff --git a/modules/linux b/modules/linux index e94b1f76..482f834b 100644 --- a/modules/linux +++ b/modules/linux @@ -1,4 +1,4 @@ -modules += linux +modules-y += linux linux_version := 4.9.7 linux_dir := linux-$(linux_version) @@ -17,15 +17,14 @@ linux_configure := \ linux_output := arch/x86/boot/bzImage linux_config := linux.config -linux_modules := \ - drivers/net/ethernet/intel/e1000/e1000.ko \ - drivers/net/ethernet/intel/e1000e/e1000e.ko \ - drivers/usb/host/xhci-hcd.ko \ - drivers/usb/host/ehci-platform.ko \ - drivers/usb/host/ehci-hcd.ko \ - drivers/usb/host/xhci-plat-hcd.ko \ - drivers/usb/host/xhci-pci.ko \ - drivers/usb/host/ehci-pci.ko \ +linux_modules-$(CONFIG_LINUX_E1000) += drivers/net/ethernet/intel/e1000/e1000.ko +linux_modules-$(CONFIG_LINUX_E1000E) += drivers/net/ethernet/intel/e1000e/e1000e.ko +#linux_modules-$(CONFIG_LINUX_USB) += drivers/usb/host/ehci-platform.ko +linux_modules-$(CONFIG_LINUX_USB) += drivers/usb/host/ehci-hcd.ko +linux_modules-$(CONFIG_LINUX_USB) += drivers/usb/host/ehci-pci.ko +linux_modules-$(CONFIG_LINUX_USB) += drivers/usb/host/xhci-hcd.ko +#linux_modules-$(CONFIG_LINUX_USB) += drivers/usb/host/xhci-plat-hcd.ko +linux_modules-$(CONFIG_LINUX_USB) += drivers/usb/host/xhci-pci.ko EXTRA_FLAGS := -fdebug-prefix-map=$(pwd)=heads -gno-record-gcc-switches diff --git a/modules/lvm2 b/modules/lvm2 index 7972456a..a2afe265 100644 --- a/modules/lvm2 +++ b/modules/lvm2 @@ -1,4 +1,4 @@ -modules += lvm2 +modules-$(CONFIG_LVM2) += lvm2 lvm2_version := 2.02.168 lvm2_dir := LVM2.$(lvm2_version) diff --git a/modules/mbedtls b/modules/mbedtls index 8336ed1c..d2442b33 100644 --- a/modules/mbedtls +++ b/modules/mbedtls @@ -1,4 +1,4 @@ -modules += mbedtls +modules-$(CONFIG_MBEDTLS) += mbedtls mbedtls_version := 2.4.2 mbedtls_dir := mbedtls-$(mbedtls_version) diff --git a/modules/musl b/modules/musl index 23ad4a1d..05db6f26 100644 --- a/modules/musl +++ b/modules/musl @@ -1,4 +1,4 @@ -modules += musl +modules-y += musl musl_version := 1.1.15 musl_dir := musl-$(musl_version) diff --git a/modules/musl-cross b/modules/musl-cross index 30375f00..4107df88 100644 --- a/modules/musl-cross +++ b/modules/musl-cross @@ -1,4 +1,4 @@ -modules += musl-cross +modules-y += musl-cross musl-cross_version := git musl-cross_dir := musl-cross-$(musl-cross_version) diff --git a/modules/pciutils b/modules/pciutils index 1b561a52..83e320f2 100644 --- a/modules/pciutils +++ b/modules/pciutils @@ -1,4 +1,4 @@ -modules += pciutils +modules-$(CONFIG_PCIUTILS) += pciutils pciutils_depends := $(musl_dep) diff --git a/modules/popt b/modules/popt index 25c5be2c..4f47bcf5 100644 --- a/modules/popt +++ b/modules/popt @@ -1,4 +1,4 @@ -modules += popt +modules-$(CONFIG_POPT) += popt popt_version := 1.16 popt_dir := popt-$(popt_version) diff --git a/modules/qrencode b/modules/qrencode index 91d9d561..36e23a8f 100644 --- a/modules/qrencode +++ b/modules/qrencode @@ -1,4 +1,4 @@ -modules += qrencode +modules-$(CONFIG_QRENCODE) += qrencode qrencode_version := 3.4.4 qrencode_dir := qrencode-$(qrencode_version) diff --git a/modules/tpmtotp b/modules/tpmtotp index 2b2c2ba3..f644f082 100644 --- a/modules/tpmtotp +++ b/modules/tpmtotp @@ -1,4 +1,4 @@ -modules += tpmtotp +modules-$(CONFIG_TPMTOTP) += tpmtotp tpmtotp_depends := mbedtls qrencode $(musl_dep) diff --git a/modules/xen b/modules/xen index ec3211d2..10bd01ce 100644 --- a/modules/xen +++ b/modules/xen @@ -1,4 +1,4 @@ -modules += xen +modules-$(CONFIG_XEN) += xen # We extract the entire Xen tree, but only use the xen/xen hypervisor # portion since Qubes provides the rest of it. @@ -8,6 +8,6 @@ xen_tar := xen-$(xen_version).tar.gz xen_url := http://bits.xensource.com/oss-xen/release/4.6.3/xen-4.6.3.tar.gz xen_hash := 02badfce9a037bd1bd4a94210c1f6b85467746216c71795805102b514bcf1fc4 -xen_output := xen.gz +xen_output := xen_configure := xen_target := $(MAKE_JOBS)