
Test if /boot is previously mounted on the OLDROOT and move it into NEWROOT (ro). (From OE-Core rev: 4c930500814dbec735e7958aaaf0593ae0119622) Signed-off-by: Anibal Limon <anibal@limonsoftware.com> Signed-off-by: Antonin Godard <antonin.godard@bootlin.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
4.2 KiB
#!/bin/sh
SPDX-License-Identifier: MIT
Copyright 2022 (C), Microsoft Corporation
Simple initramfs module intended to mount a read-write (RW)
overlayfs on top of /, keeping the original root filesystem
as read-only (RO), free from modifications by the user.
NOTE: The read-only IMAGE_FEATURE is not required for this to work
This script is based on the overlay-etc.bbclass, which sets up
an overlay on top of the /etc directory, but in this case allows
accessing the original, unmodified rootfs at /rofs after boot.
It relies on the initramfs-module-rootfs to mount the original
root filesystem, and requires 'overlayrootrwdev=' to be passed as a
kernel parameter, specifying the device/partition intended to
use as RW.
Mount options of the RW device can be tweaked with 'overlayrootfstype='
(defaults to 'ext4') and 'overlayrootfsflags=' ('defaults').
This module needs to be executed after the initramfs-module-rootfs
since it relies on it to mount the filesystem at initramfs startup
but before the finish module which normally switches root.
After overlayroot is executed the usual boot flow continues from
the real init process.
If something goes wrong while running this module, the rootfs
is still mounted RO (with no overlay) and the finish module is
executed to continue booting normally.
It also has a dependency on overlayfs being enabled in the
running kernel via KERNEL_FEATURES (kmeta) or any other means.
PATH=/sbin:/bin:/usr/sbin:/usr/bin
We get OLDROOT from the rootfs module
OLDROOT="${ROOTFS_DIR}"
RWMOUNT="/overlay" NEWROOT="${RWMOUNT}/root" ROMOUNT="${RWMOUNT}/rofs" UPPER_DIR="${RWMOUNT}/upper" WORK_DIR="${RWMOUNT}/work"
MODULES_DIR=/init.d
Something went wrong, make sure / is mounted as read only anyway.
exit_gracefully() { echo $1 >/dev/console echo >/dev/console echo "OverlayRoot mounting failed, starting system as read-only" >/dev/console echo >/dev/console
# The following is borrowed from rootfs-postcommands.bbclass
# This basically looks at the real rootfs mounting options and
# replaces them with "ro"
# Tweak the mount option and fs_passno for rootfs in fstab
if [ -f ${OLDROOT}/etc/fstab ]; then
sed -i -e '/^[#[:space:]]*\/dev\/root/{s/defaults/ro/;s/\([[:space:]]*[[:digit:]]\)\([[:space:]]*\)[[:digit:]]$/\1\20/}' ${OLDROOT}/etc/fstab
fi
# Tweak the "mount -o remount,rw /" command in busybox-inittab inittab
if [ -f ${OLDROOT}/etc/inittab ]; then
sed -i 's|/bin/mount -o remount,rw /|/bin/mount -o remount,ro /|' ${OLDROOT}/etc/inittab
fi
# Continue as if the overlayroot module didn't exist to continue booting
. $MODULES_DIR/99-finish
eval "finish_run"
}
migrate legacy parameter
if [ ! -z "$bootparam_rootrw" ]; then bootparam_overlayrootrwdev="$bootparam_rootrw" fi
if [ -z "$bootparam_overlayrootrwdev" ]; then exit_gracefully "overlayrootrwdev= kernel parameter doesn't exist and its required to mount the overlayfs" fi
mkdir -p ${RWMOUNT}
Mount RW device
if mount -n -t ${bootparam_overlayrootfstype:-ext4} -o ${bootparam_overlayrootfsflags:-defaults} ${bootparam_overlayrootrwdev} ${RWMOUNT} then # Set up overlay directories mkdir -p ${UPPER_DIR} mkdir -p ${WORK_DIR} mkdir -p ${NEWROOT} mkdir -p ${ROMOUNT}
# Remount OLDROOT as read-only
mount -o bind ${OLDROOT} ${ROMOUNT}
mount -o remount,ro ${ROMOUNT}
# Mount RW overlay
mount -t overlay overlay -o lowerdir=${ROMOUNT},upperdir=${UPPER_DIR},workdir=${WORK_DIR} ${NEWROOT} || exit_gracefully "initramfs-overlayroot: Mounting overlay failed"
else exit_gracefully "initramfs-overlayroot: Mounting RW device failed" fi
Set up filesystems on overlay
mkdir -p ${NEWROOT}/proc mkdir -p ${NEWROOT}/dev mkdir -p ${NEWROOT}/sys mkdir -p ${NEWROOT}/rofs
mount -n --move ${ROMOUNT} ${NEWROOT}/rofs mount -n --move /proc ${NEWROOT}/proc mount -n --move /sys ${NEWROOT}/sys mount -n --move /dev ${NEWROOT}/dev
Mount/move boot if is already mounted
if mountpoint -q ${OLDROOT}/boot; then mount -n --move ${OLDROOT}/boot ${NEWROOT}/boot fi
exec chroot ${NEWROOT}/ ${bootparam_init:-/sbin/init} || exit_gracefully "Couldn't chroot into overlay"