Message ID | 20220126072231.1749903-1-alhe@linux.microsoft.com |
---|---|
State | Accepted, archived |
Commit | 4f876982a856c54a8074c85346632e33caa7ef53 |
Headers | show |
Series | initramfs-framework: Add overlayroot module | expand |
On Wed, Jan 26, 2022 at 2:22 AM Alejandro Hernandez Samaniego <alhe@linux.microsoft.com> wrote: > > When installed, this module mounts a read-write (RW) overlay on > top of a root filesystem, which is kept read-only (RO). > > It 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. > > It requires rootrw=<foo> to be passed as a kernel parameter to > specify the device/partition to be used as RW by the overlay and > has a dependency on overlayfs support being present in the > running kernel. > > It does not require the read-only IMAGE_FEATURE to be enabled. Alejandro, What's the higher level use case for this ? It would be worth capturing it in the commit log. Is this filling a gap in existing functionality ? Is it for spinning up initramfs only configurations ? A security thing ? > > Signed-off-by: Alejandro Enedino Hernandez Samaniego <alhe@linux.microsoft.com> > --- > .../initramfs-framework/overlayroot | 93 +++++++++++++++++++ > .../initrdscripts/initramfs-framework_1.0.bb | 9 ++ > 2 files changed, 102 insertions(+) > create mode 100644 meta/recipes-core/initrdscripts/initramfs-framework/overlayroot > > diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot > new file mode 100644 > index 0000000000..ec5700e8fc > --- /dev/null > +++ b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot > @@ -0,0 +1,93 @@ > +#!/bin/sh > + The new script should have a copyright and SPDX identifier .. Don't take this as great wisdom, it is something thatI always forget to to as well! On that note, is this completely from scratch or is it the assembly of other bits and pieces found elsewhere ? It would be good to document that as well. > +# Simple initramfs module intended to mount a read-write (RW) > +# overlayfs on top of /, keeping the original root filesystem > +# as read-only (RO). > +# > +# NOTE: The read-only IMAGE_FEATURE is not required for this to work > +# > +# It relies on the initramfs-module-rootfs to mount the original > +# root filesystem, and requires 'rootrw=<foo>' to be passed as a > +# kernel parameter, specifying the device/partition intended to > +# use as RW. > +# > +# It also has a dependency on overlayfs being enabled in the > +# running kernel via KERNEL_FEATURES (kmeta) or any other means. > +# > +# The RO root filesystem remains accessible by the system, mounted > +# at /rofs > + > +PATH=/sbin:/bin:/usr/sbin:/usr/bin > + > +# We get OLDROOT from the rootfs module > +OLDROOT="/rootfs" > + > +NEWROOT="${RWMOUNT}/root" > +RWMOUNT="/overlay" > +ROMOUNT="${RWMOUNT}/rofs" > +UPPER_DIR="${RWMOUNT}/upper" > +WORK_DIR="${RWMOUNT}/work" > + > +MODULES_DIR=/init.d > + > +exit_gracefully() { > + echo $1 >/dev/console > + echo >/dev/console > + echo "OverlayRoot mounting failed, starting system as read-only" >/dev/console > + echo >/dev/console > + > + # Make sure / is mounted as read only anyway. > + # Borrowed from rootfs-postcommands.bbclass > + # Tweak the mount option and fs_passno for rootfs in fstab For maintenance reasons, it would be a good idea to expand on (in words) what the tweak is, what the old value is, and the new. > + 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 > + . $MODULES_DIR/99-finish > + eval "finish_run" > +} > + > + > +if [ -z "$bootparam_rootrw" ]; then > + exit_gracefully "rootrw= kernel parameter doesn't exist and its required to mount the overlayfs" > +fi > + > +mkdir -p ${RWMOUNT} > + > +# Mount RW device > +if mount -n -t ${bootparam_rootfstype:-ext4} -o ${bootparam_rootflags:-defaults} ${bootparam_rootrw} ${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 > + > +exec chroot ${NEWROOT}/ ${bootparam_init:-/sbin/init} || exit_gracefully "Couldn't chroot into overlay" What's the boot flow in the end ? The r/w overlay is setup, and the rest of the initrams -> full boot happens as normal ? Bruce > diff --git a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb > index 9e8c1dc3ab..4e76e20026 100644 > --- a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb > +++ b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb > @@ -18,6 +18,7 @@ SRC_URI = "file://init \ > file://e2fs \ > file://debug \ > file://lvm \ > + file://overlayroot \ > " > > S = "${WORKDIR}" > @@ -49,6 +50,9 @@ do_install() { > # lvm > install -m 0755 ${WORKDIR}/lvm ${D}/init.d/09-lvm > > + # overlayroot needs to run after rootfs module but before finish > + install -m 0755 ${WORKDIR}/overlayroot ${D}/init.d/91-overlayroot > + > # Create device nodes expected by some kernels in initramfs > # before even executing /init. > install -d ${D}/dev > @@ -64,6 +68,7 @@ PACKAGES = "${PN}-base \ > initramfs-module-rootfs \ > initramfs-module-debug \ > initramfs-module-lvm \ > + initramfs-module-overlayroot \ > " > > FILES:${PN}-base = "/init /init.d/99-finish /dev" > @@ -107,3 +112,7 @@ FILES:initramfs-module-debug = "/init.d/00-debug" > SUMMARY:initramfs-module-lvm = "initramfs lvm rootfs support" > RDEPENDS:initramfs-module-lvm = "${PN}-base" > FILES:initramfs-module-lvm = "/init.d/09-lvm" > + > +SUMMARY:initramfs-module-overlayroot = "initramfs support for mounting a RW overlay on top of a RO root filesystem" > +RDEPENDS:initramfs-module-overlayroot = "${PN}-base initramfs-module-rootfs" > +FILES:initramfs-module-overlayroot = "/init.d/91-overlayroot" > -- > 2.25.1 > > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#160961): https://lists.openembedded.org/g/openembedded-core/message/160961 > Mute This Topic: https://lists.openembedded.org/mt/88691930/1050810 > Group Owner: openembedded-core+owner@lists.openembedded.org > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [bruce.ashfield@gmail.com] > -=-=-=-=-=-=-=-=-=-=-=- > -- - Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end - "Use the force Harry" - Gandalf, Star Trek II
On 1/26/22 7:11 AM, Bruce Ashfield wrote: > On Wed, Jan 26, 2022 at 2:22 AM Alejandro Hernandez Samaniego > <alhe@linux.microsoft.com> wrote: >> When installed, this module mounts a read-write (RW) overlay on >> top of a root filesystem, which is kept read-only (RO). >> >> It 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. >> >> It requires rootrw=<foo> to be passed as a kernel parameter to >> specify the device/partition to be used as RW by the overlay and >> has a dependency on overlayfs support being present in the >> running kernel. >> >> It does not require the read-only IMAGE_FEATURE to be enabled. > Alejandro, > > What's the higher level use case for this ? It would be worth capturing > it in the commit log. Is this filling a gap in existing functionality ? Is it > for spinning up initramfs only configurations ? A security thing ? Hi Bruce, thanks for reviewing this and pointing out what I missed, I'll be sending a v2 later today. There may be several reasons why we'd want to have the possibility of keeping the original rootfs unmodified, and keeping user customizations on a separate device, for example it would make it easier to perform a factory reset on a device. >> Signed-off-by: Alejandro Enedino Hernandez Samaniego <alhe@linux.microsoft.com> >> --- >> .../initramfs-framework/overlayroot | 93 +++++++++++++++++++ >> .../initrdscripts/initramfs-framework_1.0.bb | 9 ++ >> 2 files changed, 102 insertions(+) >> create mode 100644 meta/recipes-core/initrdscripts/initramfs-framework/overlayroot >> >> diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot >> new file mode 100644 >> index 0000000000..ec5700e8fc >> --- /dev/null >> +++ b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot >> @@ -0,0 +1,93 @@ >> +#!/bin/sh >> + > The new script should have a copyright and SPDX identifier .. Don't > take this as great wisdom, it is something thatI always forget to to > as well! > > On that note, is this completely from scratch or is it the assembly of > other bits and pieces found elsewhere ? It would be good to document > that as well. Oops! completely forgot!, I'll add it. This is loosely based on the overlay-etc.bbclass the difference is that the class only works for overlaying /etc and it doesnt require an initramfs, but, while its possible to tinker it in such a way that it overlays /, its not possible to access the original (RO) / after booting the system, this is the reason why this has to be done from initramfs and why this doesnt patch the overlay-etc.bbclass instead. I believe Ubuntu has this feature, coming from the cloud-initramfs package, functionally it should be similar although no code was borrowed from there. I'll add a note about the overlay-etc class though. >> +# Simple initramfs module intended to mount a read-write (RW) >> +# overlayfs on top of /, keeping the original root filesystem >> +# as read-only (RO). >> +# >> +# NOTE: The read-only IMAGE_FEATURE is not required for this to work >> +# >> +# It relies on the initramfs-module-rootfs to mount the original >> +# root filesystem, and requires 'rootrw=<foo>' to be passed as a >> +# kernel parameter, specifying the device/partition intended to >> +# use as RW. >> +# >> +# It also has a dependency on overlayfs being enabled in the >> +# running kernel via KERNEL_FEATURES (kmeta) or any other means. >> +# >> +# The RO root filesystem remains accessible by the system, mounted >> +# at /rofs >> + >> +PATH=/sbin:/bin:/usr/sbin:/usr/bin >> + >> +# We get OLDROOT from the rootfs module >> +OLDROOT="/rootfs" >> + >> +NEWROOT="${RWMOUNT}/root" >> +RWMOUNT="/overlay" >> +ROMOUNT="${RWMOUNT}/rofs" >> +UPPER_DIR="${RWMOUNT}/upper" >> +WORK_DIR="${RWMOUNT}/work" >> + >> +MODULES_DIR=/init.d >> + >> +exit_gracefully() { >> + echo $1 >/dev/console >> + echo >/dev/console >> + echo "OverlayRoot mounting failed, starting system as read-only" >/dev/console >> + echo >/dev/console >> + >> + # Make sure / is mounted as read only anyway. >> + # Borrowed from rootfs-postcommands.bbclass >> + # Tweak the mount option and fs_passno for rootfs in fstab > For maintenance reasons, it would be a good idea to expand on (in > words) what the tweak is, what the old value is, and the new. Actually that comment (along with the next couple of lines) is coming from the rootfs-postcommands.bbclass to mount the root filesystem RO. > >> + 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 >> + . $MODULES_DIR/99-finish >> + eval "finish_run" >> +} >> + >> + >> +if [ -z "$bootparam_rootrw" ]; then >> + exit_gracefully "rootrw= kernel parameter doesn't exist and its required to mount the overlayfs" >> +fi >> + >> +mkdir -p ${RWMOUNT} >> + >> +# Mount RW device >> +if mount -n -t ${bootparam_rootfstype:-ext4} -o ${bootparam_rootflags:-defaults} ${bootparam_rootrw} ${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 >> + >> +exec chroot ${NEWROOT}/ ${bootparam_init:-/sbin/init} || exit_gracefully "Couldn't chroot into overlay" > What's the boot flow in the end ? The r/w overlay is setup, and the rest of the > initrams -> full boot happens as normal ? > > Bruce In the initramfs-framework flow, this would be the last module that is run, and "replaces" the finish module, so the rest of the initramfs-modules that were installed should have been run already keeping the same boot flow, although, instead of the finish module executing switch_root to the now mounted real root, this chroots into the now mounted real RW root overlay. This patch does not install (or create any rdepends to) the initramfs-module-overlayroot package on purpose, the original flow using initramfs-framework is kept, it would only change to the above flow when a user manually installs this module on their initramfs image. Alejandro > >> diff --git a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb >> index 9e8c1dc3ab..4e76e20026 100644 >> --- a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb >> +++ b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb >> @@ -18,6 +18,7 @@ SRC_URI = "file://init \ >> file://e2fs \ >> file://debug \ >> file://lvm \ >> + file://overlayroot \ >> " >> >> S = "${WORKDIR}" >> @@ -49,6 +50,9 @@ do_install() { >> # lvm >> install -m 0755 ${WORKDIR}/lvm ${D}/init.d/09-lvm >> >> + # overlayroot needs to run after rootfs module but before finish >> + install -m 0755 ${WORKDIR}/overlayroot ${D}/init.d/91-overlayroot >> + >> # Create device nodes expected by some kernels in initramfs >> # before even executing /init. >> install -d ${D}/dev >> @@ -64,6 +68,7 @@ PACKAGES = "${PN}-base \ >> initramfs-module-rootfs \ >> initramfs-module-debug \ >> initramfs-module-lvm \ >> + initramfs-module-overlayroot \ >> " >> >> FILES:${PN}-base = "/init /init.d/99-finish /dev" >> @@ -107,3 +112,7 @@ FILES:initramfs-module-debug = "/init.d/00-debug" >> SUMMARY:initramfs-module-lvm = "initramfs lvm rootfs support" >> RDEPENDS:initramfs-module-lvm = "${PN}-base" >> FILES:initramfs-module-lvm = "/init.d/09-lvm" >> + >> +SUMMARY:initramfs-module-overlayroot = "initramfs support for mounting a RW overlay on top of a RO root filesystem" >> +RDEPENDS:initramfs-module-overlayroot = "${PN}-base initramfs-module-rootfs" >> +FILES:initramfs-module-overlayroot = "/init.d/91-overlayroot" >> -- >> 2.25.1 >> >> >> -=-=-=-=-=-=-=-=-=-=-=- >> Links: You receive all messages sent to this group. >> View/Reply Online (#160961): https://lists.openembedded.org/g/openembedded-core/message/160961 >> Mute This Topic: https://lists.openembedded.org/mt/88691930/1050810 >> Group Owner: openembedded-core+owner@lists.openembedded.org >> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [bruce.ashfield@gmail.com] >> -=-=-=-=-=-=-=-=-=-=-=- >> > > -- > - Thou shalt not follow the NULL pointer, for chaos and madness await > thee at its end > - "Use the force Harry" - Gandalf, Star Trek II
Hi Alejandro, Thanks for your patch. I recently submitted two classes overlayfs and overlayfs-etc to do the same thing you want to achieve. Could you please take a look if you can use them instead? If not, perhaps we could adapt it to suit your needs? Regards, Vyacheslav On 26.01.2022 08:22, Alejandro Hernandez Samaniego wrote: > When installed, this module mounts a read-write (RW) overlay on > top of a root filesystem, which is kept read-only (RO). > > It 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. > > It requires rootrw=<foo> to be passed as a kernel parameter to > specify the device/partition to be used as RW by the overlay and > has a dependency on overlayfs support being present in the > running kernel. > > It does not require the read-only IMAGE_FEATURE to be enabled. > > Signed-off-by: Alejandro Enedino Hernandez Samaniego <alhe@linux.microsoft.com> > --- > .../initramfs-framework/overlayroot | 93 +++++++++++++++++++ > .../initrdscripts/initramfs-framework_1.0.bb | 9 ++ > 2 files changed, 102 insertions(+) > create mode 100644 meta/recipes-core/initrdscripts/initramfs-framework/overlayroot > > diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot > new file mode 100644 > index 0000000000..ec5700e8fc > --- /dev/null > +++ b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot > @@ -0,0 +1,93 @@ > +#!/bin/sh > + > +# Simple initramfs module intended to mount a read-write (RW) > +# overlayfs on top of /, keeping the original root filesystem > +# as read-only (RO). > +# > +# NOTE: The read-only IMAGE_FEATURE is not required for this to work > +# > +# It relies on the initramfs-module-rootfs to mount the original > +# root filesystem, and requires 'rootrw=<foo>' to be passed as a > +# kernel parameter, specifying the device/partition intended to > +# use as RW. > +# > +# It also has a dependency on overlayfs being enabled in the > +# running kernel via KERNEL_FEATURES (kmeta) or any other means. > +# > +# The RO root filesystem remains accessible by the system, mounted > +# at /rofs > + > +PATH=/sbin:/bin:/usr/sbin:/usr/bin > + > +# We get OLDROOT from the rootfs module > +OLDROOT="/rootfs" > + > +NEWROOT="${RWMOUNT}/root" > +RWMOUNT="/overlay" > +ROMOUNT="${RWMOUNT}/rofs" > +UPPER_DIR="${RWMOUNT}/upper" > +WORK_DIR="${RWMOUNT}/work" > + > +MODULES_DIR=/init.d > + > +exit_gracefully() { > + echo $1 >/dev/console > + echo >/dev/console > + echo "OverlayRoot mounting failed, starting system as read-only" >/dev/console > + echo >/dev/console > + > + # Make sure / is mounted as read only anyway. > + # Borrowed from rootfs-postcommands.bbclass > + # 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 > + . $MODULES_DIR/99-finish > + eval "finish_run" > +} > + > + > +if [ -z "$bootparam_rootrw" ]; then > + exit_gracefully "rootrw= kernel parameter doesn't exist and its required to mount the overlayfs" > +fi > + > +mkdir -p ${RWMOUNT} > + > +# Mount RW device > +if mount -n -t ${bootparam_rootfstype:-ext4} -o ${bootparam_rootflags:-defaults} ${bootparam_rootrw} ${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 > + > +exec chroot ${NEWROOT}/ ${bootparam_init:-/sbin/init} || exit_gracefully "Couldn't chroot into overlay" > diff --git a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb > index 9e8c1dc3ab..4e76e20026 100644 > --- a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb > +++ b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb > @@ -18,6 +18,7 @@ SRC_URI = "file://init \ > file://e2fs \ > file://debug \ > file://lvm \ > + file://overlayroot \ > " > > S = "${WORKDIR}" > @@ -49,6 +50,9 @@ do_install() { > # lvm > install -m 0755 ${WORKDIR}/lvm ${D}/init.d/09-lvm > > + # overlayroot needs to run after rootfs module but before finish > + install -m 0755 ${WORKDIR}/overlayroot ${D}/init.d/91-overlayroot > + > # Create device nodes expected by some kernels in initramfs > # before even executing /init. > install -d ${D}/dev > @@ -64,6 +68,7 @@ PACKAGES = "${PN}-base \ > initramfs-module-rootfs \ > initramfs-module-debug \ > initramfs-module-lvm \ > + initramfs-module-overlayroot \ > " > > FILES:${PN}-base = "/init /init.d/99-finish /dev" > @@ -107,3 +112,7 @@ FILES:initramfs-module-debug = "/init.d/00-debug" > SUMMARY:initramfs-module-lvm = "initramfs lvm rootfs support" > RDEPENDS:initramfs-module-lvm = "${PN}-base" > FILES:initramfs-module-lvm = "/init.d/09-lvm" > + > +SUMMARY:initramfs-module-overlayroot = "initramfs support for mounting a RW overlay on top of a RO root filesystem" > +RDEPENDS:initramfs-module-overlayroot = "${PN}-base initramfs-module-rootfs" > +FILES:initramfs-module-overlayroot = "/init.d/91-overlayroot" >
On 26.01.2022 19:09, Alejandro Hernandez Samaniego wrote: > Oops! completely forgot!, I'll add it. > > This is loosely based on the overlay-etc.bbclass the difference is that > the class only works for overlaying /etc and it doesnt require an > initramfs, but, while its possible to tinker it in such a way that it > overlays /, its not possible to access the original (RO) / after booting the > system, this is the reason why this has to be done from initramfs and why > this doesnt patch the overlay-etc.bbclass instead. > > I believe Ubuntu has this feature, coming from the cloud-initramfs > package, functionally it should be similar although no code was borrowed > from there. > > I'll add a note about the overlay-etc class though. I missed this part when I answered to your first email this morning. I generally against expanding the scope of overlayfs (i.e. using it for the whole / ), because it creates a bigger migration effort when you need to update the files on a persistent partition. I see the only difference in your code is that you provide access to original lower layer fs. Why would you want to do that? Thanks, Vyacheslav
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot new file mode 100644 index 0000000000..ec5700e8fc --- /dev/null +++ b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot @@ -0,0 +1,93 @@ +#!/bin/sh + +# Simple initramfs module intended to mount a read-write (RW) +# overlayfs on top of /, keeping the original root filesystem +# as read-only (RO). +# +# NOTE: The read-only IMAGE_FEATURE is not required for this to work +# +# It relies on the initramfs-module-rootfs to mount the original +# root filesystem, and requires 'rootrw=<foo>' to be passed as a +# kernel parameter, specifying the device/partition intended to +# use as RW. +# +# It also has a dependency on overlayfs being enabled in the +# running kernel via KERNEL_FEATURES (kmeta) or any other means. +# +# The RO root filesystem remains accessible by the system, mounted +# at /rofs + +PATH=/sbin:/bin:/usr/sbin:/usr/bin + +# We get OLDROOT from the rootfs module +OLDROOT="/rootfs" + +NEWROOT="${RWMOUNT}/root" +RWMOUNT="/overlay" +ROMOUNT="${RWMOUNT}/rofs" +UPPER_DIR="${RWMOUNT}/upper" +WORK_DIR="${RWMOUNT}/work" + +MODULES_DIR=/init.d + +exit_gracefully() { + echo $1 >/dev/console + echo >/dev/console + echo "OverlayRoot mounting failed, starting system as read-only" >/dev/console + echo >/dev/console + + # Make sure / is mounted as read only anyway. + # Borrowed from rootfs-postcommands.bbclass + # 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 + . $MODULES_DIR/99-finish + eval "finish_run" +} + + +if [ -z "$bootparam_rootrw" ]; then + exit_gracefully "rootrw= kernel parameter doesn't exist and its required to mount the overlayfs" +fi + +mkdir -p ${RWMOUNT} + +# Mount RW device +if mount -n -t ${bootparam_rootfstype:-ext4} -o ${bootparam_rootflags:-defaults} ${bootparam_rootrw} ${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 + +exec chroot ${NEWROOT}/ ${bootparam_init:-/sbin/init} || exit_gracefully "Couldn't chroot into overlay" diff --git a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb index 9e8c1dc3ab..4e76e20026 100644 --- a/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb +++ b/meta/recipes-core/initrdscripts/initramfs-framework_1.0.bb @@ -18,6 +18,7 @@ SRC_URI = "file://init \ file://e2fs \ file://debug \ file://lvm \ + file://overlayroot \ " S = "${WORKDIR}" @@ -49,6 +50,9 @@ do_install() { # lvm install -m 0755 ${WORKDIR}/lvm ${D}/init.d/09-lvm + # overlayroot needs to run after rootfs module but before finish + install -m 0755 ${WORKDIR}/overlayroot ${D}/init.d/91-overlayroot + # Create device nodes expected by some kernels in initramfs # before even executing /init. install -d ${D}/dev @@ -64,6 +68,7 @@ PACKAGES = "${PN}-base \ initramfs-module-rootfs \ initramfs-module-debug \ initramfs-module-lvm \ + initramfs-module-overlayroot \ " FILES:${PN}-base = "/init /init.d/99-finish /dev" @@ -107,3 +112,7 @@ FILES:initramfs-module-debug = "/init.d/00-debug" SUMMARY:initramfs-module-lvm = "initramfs lvm rootfs support" RDEPENDS:initramfs-module-lvm = "${PN}-base" FILES:initramfs-module-lvm = "/init.d/09-lvm" + +SUMMARY:initramfs-module-overlayroot = "initramfs support for mounting a RW overlay on top of a RO root filesystem" +RDEPENDS:initramfs-module-overlayroot = "${PN}-base initramfs-module-rootfs" +FILES:initramfs-module-overlayroot = "/init.d/91-overlayroot"
When installed, this module mounts a read-write (RW) overlay on top of a root filesystem, which is kept read-only (RO). It 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. It requires rootrw=<foo> to be passed as a kernel parameter to specify the device/partition to be used as RW by the overlay and has a dependency on overlayfs support being present in the running kernel. It does not require the read-only IMAGE_FEATURE to be enabled. Signed-off-by: Alejandro Enedino Hernandez Samaniego <alhe@linux.microsoft.com> --- .../initramfs-framework/overlayroot | 93 +++++++++++++++++++ .../initrdscripts/initramfs-framework_1.0.bb | 9 ++ 2 files changed, 102 insertions(+) create mode 100644 meta/recipes-core/initrdscripts/initramfs-framework/overlayroot