diff mbox series

[isar-cip-core,RFC,3/7] secure-boot: select boot partition in initramfs

Message ID 20200625141015.31719-4-Quirin.Gylstorff@siemens.com (mailing list archive)
State Accepted
Headers show
Series None | expand

Commit Message

Quirin Gylstorff June 25, 2020, 2:10 p.m. UTC
From: Quirin Gylstorff <quirin.gylstorff@siemens.com>

As the usage of a unified kernel image freeze the kernel commmandline
during build time the rootfs selection for swupdate can no longer be
done with the kernel commandline and must be done later in the boot
process. Read the root filesystem /etc/os-release and check if it contains
the same uuid as stored in the initramfs . If the uuids are the same
boot the root file system.

Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com>
---
 classes/image_uuid.bbclass                    | 29 +++++++
 .../files/initramfs.image_uuid.hook           | 33 ++++++++
 .../files/initramfs.lsblk.hook                | 29 +++++++
 .../initramfs-config/files/postinst.tmpl      | 31 ++++++++
 .../files/secure-boot-debian-local-patch      | 77 +++++++++++++++++++
 .../initramfs-config_0.1-cip.bb               | 35 +++++++++
 6 files changed, 234 insertions(+)
 create mode 100644 classes/image_uuid.bbclass
 create mode 100644 recipes-support/initramfs-config/files/initramfs.image_uuid.hook
 create mode 100644 recipes-support/initramfs-config/files/initramfs.lsblk.hook
 create mode 100644 recipes-support/initramfs-config/files/postinst.tmpl
 create mode 100644 recipes-support/initramfs-config/files/secure-boot-debian-local-patch
 create mode 100644 recipes-support/initramfs-config/initramfs-config_0.1-cip.bb
diff mbox series

Patch

diff --git a/classes/image_uuid.bbclass b/classes/image_uuid.bbclass
new file mode 100644
index 0000000..3bd03d5
--- /dev/null
+++ b/classes/image_uuid.bbclass
@@ -0,0 +1,29 @@ 
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+def generate_image_uuid():
+    import uuid
+    return str(uuid.uuid4())
+
+
+IMAGE_UUID ?= "${@generate_image_uuid()}"
+
+
+do_generate_image_uuid() {
+    sudo sed -i '/^IMAGE_UUID=.*/d' '${IMAGE_ROOTFS}/etc/os-release'
+    echo "IMAGE_UUID=\"${IMAGE_UUID}\"" | \
+        sudo tee -a '${IMAGE_ROOTFS}/etc/os-release'
+    image_do_mounts
+
+    # update initramfs to add uuid
+    sudo chroot '${IMAGE_ROOTFS}' update-initramfs -u
+}
+addtask generate_image_uuid before do_copy_boot_files after do_rootfs_install
diff --git a/recipes-support/initramfs-config/files/initramfs.image_uuid.hook b/recipes-support/initramfs-config/files/initramfs.image_uuid.hook
new file mode 100644
index 0000000..910ce84
--- /dev/null
+++ b/recipes-support/initramfs-config/files/initramfs.image_uuid.hook
@@ -0,0 +1,33 @@ 
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2020
+#
+# SPDX-License-Identifier: MIT
+
+#!/bin/sh
+set -x
+PREREQ=""
+
+prereqs()
+{
+     echo "$PREREQ"
+}
+
+case $1 in
+prereqs)
+     prereqs
+     exit 0
+     ;;
+esac
+
+. /usr/share/initramfs-tools/scripts/functions
+. /usr/share/initramfs-tools/hook-functions
+
+if [ ! -e /etc/os-release ]; then
+	echo "Warning: couldn't find /etc/os-release!"
+	exit 0
+fi
+
+IMAGE_UUID=$(sed -n 's/^IMAGE_UUID="\(.*\)"/\1/p' /etc/os-release)
+echo "${IMAGE_UUID}" > "${DESTDIR}/conf/image_uuid"
+
+exit 0
\ No newline at end of file
diff --git a/recipes-support/initramfs-config/files/initramfs.lsblk.hook b/recipes-support/initramfs-config/files/initramfs.lsblk.hook
new file mode 100644
index 0000000..cf32404
--- /dev/null
+++ b/recipes-support/initramfs-config/files/initramfs.lsblk.hook
@@ -0,0 +1,29 @@ 
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2020
+#
+# SPDX-License-Identifier: MIT
+
+#!/bin/sh
+PREREQ=""
+
+prereqs()
+{
+     echo "$PREREQ"
+}
+
+case $1 in
+prereqs)
+     prereqs
+     exit 0
+     ;;
+esac
+
+. /usr/share/initramfs-tools/scripts/functions
+. /usr/share/initramfs-tools/hook-functions
+
+if [ ! -x /usr/bin/lsblk ]; then
+	echo "Warning: couldn't find /usr/bin/lsblk!"
+	exit 0
+fi
+
+copy_exec /usr/bin/lsblk
diff --git a/recipes-support/initramfs-config/files/postinst.tmpl b/recipes-support/initramfs-config/files/postinst.tmpl
new file mode 100644
index 0000000..008f68d
--- /dev/null
+++ b/recipes-support/initramfs-config/files/postinst.tmpl
@@ -0,0 +1,31 @@ 
+#!/bin/sh
+if [ -d /usr/share/secureboot ]; then
+    patch -s -p0 /usr/share/initramfs-tools/scripts/local /usr/share/secureboot/secure-boot-debian-local.patch
+fi
+
+INITRAMFS_CONF=/etc/initramfs-tools/initramfs.conf
+if [ -f ${INITRAMFS_CONF} ]; then
+    sed -i -E 's/(^MODULES=).*/\1${INITRAMFS_MODULES}/' ${INITRAMFS_CONF}
+    sed -i -E 's/(^BUSYBOX=).*/\1${INITRAMFS_BUSYBOX}/' ${INITRAMFS_CONF}
+    sed -i -E 's/(^COMPRESS=).*/\1${INITRAMFS_COMPRESS}/' ${INITRAMFS_CONF}
+    sed -i -E 's/(^KEYMAP=).*/\1${INITRAMFS_KEYMAP}/' ${INITRAMFS_CONF}
+    sed -i -E 's/(^DEVICE=).*/\1${INITRAMFS_NET_DEVICE}/' ${INITRAMFS_CONF}
+    sed -i -E 's/(^NFSROOT=).*/\1${INITRAMFS_NFSROOT}/' ${INITRAMFS_CONF}
+    sed -i -E 's/(^RUNSIZE=).*/\1${INITRAMFS_RUNSIZE}/' ${INITRAMFS_CONF}
+    if grep -Fxq "ROOT=" "${INITRAMFS_CONF}"; then
+        sed -i -E 's/(^ROOT=).*/\1${INITRAMFS_ROOT}/' ${INITRAMFS_CONF}
+    else
+        sed -i -E "\$aROOT=${INITRAMFS_ROOT}" ${INITRAMFS_CONF}
+    fi
+fi
+
+MODULES_LIST_FILE=/etc/initramfs-tools/modules
+if [ -f ${MODULES_LIST_FILE} ]; then
+    for modname in ${INITRAMFS_MODULE_LIST}; do
+        if ! grep -Fxq "$modname" "${MODULES_LIST_FILE}"; then
+            echo "$modname" >> "${MODULES_LIST_FILE}"
+        fi
+    done
+fi
+
+update-initramfs -v -u
diff --git a/recipes-support/initramfs-config/files/secure-boot-debian-local-patch b/recipes-support/initramfs-config/files/secure-boot-debian-local-patch
new file mode 100644
index 0000000..31d4c40
--- /dev/null
+++ b/recipes-support/initramfs-config/files/secure-boot-debian-local-patch
@@ -0,0 +1,77 @@ 
+--- local	2020-06-10 14:54:42.148263121 +0200
++++ ../../../../../../../../../../../recipes-support/initramfs-config/files/local	2020-06-10 14:53:03.723314458 +0200
+@@ -1,5 +1,4 @@
+ # Local filesystem mounting			-*- shell-script -*-
+-
+ local_top()
+ {
+ 	if [ "${local_top_used}" != "yes" ]; then
+@@ -155,34 +154,46 @@
+ local_mount_root()
+ {
+ 	local_top
+-	if [ -z "${ROOT}" ]; then
+-		panic "No root device specified. Boot arguments must include a root= parameter."
++	if [ ! -e /conf/image_uuid ]; then
++		 panic "could not find image_uuid to select correct root file system"
+ 	fi
+-	local_device_setup "${ROOT}" "root file system"
+-	ROOT="${DEV}"
++	local INITRAMFS_IMAGE_UUID=$(cat /conf/image_uuid)
++	local partitions=$(lsblk -nlp -o name)
++	for part in $partitions; do
++			local_device_setup "${part}" "root file system"
++			ROOT="${DEV}"
++
++			# Get the root filesystem type if not set
++			if [ -z "${ROOTFSTYPE}" ] || [ "${ROOTFSTYPE}" = auto ]; then
++					FSTYPE=$(get_fstype "${ROOT}")
++			else
++					FSTYPE=${ROOTFSTYPE}
++			fi
+ 
+-	# Get the root filesystem type if not set
+-	if [ -z "${ROOTFSTYPE}" ] || [ "${ROOTFSTYPE}" = auto ]; then
+-		FSTYPE=$(get_fstype "${ROOT}")
+-	else
+-		FSTYPE=${ROOTFSTYPE}
+-	fi
++		local_premount
+ 
+-	local_premount
++			if [ "${readonly?}" = "y" ]; then
++					roflag=-r
++			else
++					roflag=-w
++			fi
+ 
+-	if [ "${readonly?}" = "y" ]; then
+-		roflag=-r
+-	else
+-		roflag=-w
+-	fi
++			checkfs "${ROOT}" root "${FSTYPE}"
+ 
+-	checkfs "${ROOT}" root "${FSTYPE}"
++			# Mount root
++			# shellcheck disable=SC2086
++			if mount ${roflag} ${FSTYPE:+-t "${FSTYPE}"} ${ROOTFLAGS} "${ROOT}" "${rootmnt?}"; then
++					if [ -e "${rootmnt?}"/etc/os-release ]; then
++							image_uuid=$(sed -n 's/^IMAGE_UUID=//p' "${rootmnt?}"/etc/os-release | tr -d '"' )
++							if [ "${INITRAMFS_IMAGE_UUID}" = "${image_uuid}" ]; then
++									return
++							fi
++					fi
++					umount "${rootmnt?}"
++      fi
++	done
++	panic "Could not find ROOTFS with matching UUID $INITRAMFS_IMAGE_UUID"
+ 
+-	# Mount root
+-	# shellcheck disable=SC2086
+-	if ! mount ${roflag} ${FSTYPE:+-t "${FSTYPE}"} ${ROOTFLAGS} "${ROOT}" "${rootmnt?}"; then
+-		panic "Failed to mount ${ROOT} as root file system."
+-	fi
+ }
+ 
+ local_mount_fs()
diff --git a/recipes-support/initramfs-config/initramfs-config_0.1-cip.bb b/recipes-support/initramfs-config/initramfs-config_0.1-cip.bb
new file mode 100644
index 0000000..ba1c898
--- /dev/null
+++ b/recipes-support/initramfs-config/initramfs-config_0.1-cip.bb
@@ -0,0 +1,35 @@ 
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2020
+#
+# Authors:
+#  Quirin Gylstorff <quirin.gylstorff@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+require recipes-support/initramfs-config/initramfs-config.inc
+
+FILESPATH =. "${LAYERDIR_isar-siemens}/recipes-support/initramfs-config/files:"
+
+DEBIAN_DEPENDS += ", busybox, patch"
+
+SRC_URI += "file://initramfs.lsblk.hook \
+            file://initramfs.image_uuid.hook \
+            file://secure-boot-debian-local-patch"
+
+INITRAMFS_BUSYBOX = "y"
+
+do_install() {
+    # add patch for local to /usr/share/secure boot
+    TARGET=${D}/usr/share/secureboot
+    install -m 0755 -d ${TARGET}
+    install -m 0644 ${WORKDIR}/secure-boot-debian-local-patch ${TARGET}/secure-boot-debian-local.patch
+
+    # add hooks for secure boot
+    HOOKS=${D}/etc/initramfs-tools/hooks
+install -m 0755 -d ${HOOKS}
+    install -m 0740 ${WORKDIR}/initramfs.lsblk.hook ${HOOKS}/lsblk.hook
+    install -m 0740 ${WORKDIR}/initramfs.image_uuid.hook ${HOOKS}/image_uuid.hook
+}
+addtask do_install after do_transform_template