Skip to contentSkip to conversation

Add an overlayfs on /etc for read-only root filesystems

PATCH New Angelo Compagnucci 1 participant 4 messages Nov 3

lore
Share & tools
lore
#0 lore raw

cover Add an overlayfs on /etc for read-only root filesystems

This series adds BR2_ROOTFS_OVERLAYFS_ETC, which mounts an overlayfs on /etc, with its upper layer on a persistent device, before the init system starts. It works with busybox init, sysvinit and systemd.

It is modeled after the overlayfs-etc image feature of openembedded-core (meta/classes-recipe/overlayfs-etc.bbclass and meta/files/overlayfs-etc-preinit.sh.in), which works the same way, independently of the init system:

- the original init is moved aside, and a pre-init script is installed as /sbin/init;
- at boot, the pre-init mounts the persistent device on a mount point (/data by default), mounts the overlayfs on /etc, with its upper and work directories in <mount point>/overlay-etc/, and optionally exposes the original /etc read-only in <mount point>/overlay-etc/lower;
- it then execs the original init, which starts with a writable /etc.

The pre-init script is adapted from the openembedded-core one, and the options mirror its variables (OVERLAYFS_ETC_DEVICE, _FSTYPE, _MOUNT_OPTIONS, _MOUNT_POINT, _EXPOSE_LOWER). It differs on a few points:

- the original init is moved to /usr/libexec/overlayfs-etc/init rather than renamed to /sbin/init.orig, as busybox selects its applet from the name it is called with;
- the mount point is created at build time, so the pre-init does not need to remount the root filesystem read-write (OVERLAYFS_ETC_CREATE_MOUNT_DIRS);
- the overlayfs options are passed in a single -o, as expected by the busybox mount.

As for the /var overlayfs, the options are in the system menu, and the implementation, including the kernel config fixup enabling overlayfs, is in the skeleton, here skeleton-init-common, as the pre-init does not depend on the init system. Only /etc is handled: /var keeps the existing handling.

The persistent device must exist and be formatted, which is left to the integration. If it cannot be mounted, the system boots with the read-only /etc.

Angelo Compagnucci (3):
package/skeleton-init-common: add option to mount an overlayfs on /etc docs/manual: document the /etc overlayfs
support/testing: add runtime tests for the /etc overlayfs

 DEVELOPERS                                    |   1 +
 docs/manual/configure.adoc                    |  32 +++++
 .../overlayfs-etc-preinit.sh                  |  39 ++++++
 .../skeleton-init-common.mk                   |  63 +++++++++
 .../testing/tests/init/test_overlayfs_etc.py  | 128 ++++++++++++++++++
 .../linux-no-overlayfs.fragment               |   2 +
 system/Config.in                              |  62 +++++++++
 7 files changed, 327 insertions(+)
 create mode 100644 package/skeleton-init-common/overlayfs-etc-preinit.sh
 create mode 100644 support/testing/tests/init/test_overlayfs_etc.py
 create mode 100644 support/testing/tests/init/test_overlayfs_etc/linux-no-overlayfs.fragment
Signature · 6 lines
2.34.1

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#1 lore raw

PATCH 1/3 package/skeleton-init-common: add option to mount an overlayfs on /etc

On a read-only root filesystem, only /var can be made writable, and only with systemd. /etc cannot be mounted from /etc/fstab or from a systemd unit, as the init system already needs it when it starts.

Add an option to mount an overlayfs on /etc, with its upper layer on a persistent device, for the busybox, sysvinit and systemd init systems, as done by the overlayfs-etc image feature of openembedded-core: the init program is moved to /usr/libexec/overlayfs-etc/init, keeping its name as busybox selects its applet from it, and a pre-init script, adapted from openembedded-core, is installed as /sbin/init. It mounts the persistent device, mounts the overlayfs on /etc, optionally exposes the original /etc read-only, and then starts the original init.

This is done in skeleton-init-common, as the pre-init does not depend on the init system, and overlayfs support is enabled in the kernel with a package kernel config fixup, as done for the /var overlayfs.

The persistent device must exist and be formatted, which is left to the integration. If it cannot be mounted, the system boots with the read-only /etc.

---
 .../overlayfs-etc-preinit.sh                  | 39 ++++++++++++
 .../skeleton-init-common.mk                   | 63 +++++++++++++++++++
 system/Config.in                              | 62 ++++++++++++++++++
 3 files changed, 164 insertions(+)
 create mode 100644 package/skeleton-init-common/overlayfs-etc-preinit.sh
package/skeleton-init-common/overlayfs-etc-preinit.sh new file +39 -0
new file mode 100644
index 0000000000..c97a2b5c14
@@ -0,0 +1,39 @@
+#!/bin/sh
+# BR2_ROOTFS_OVERLAYFS_ETC pre-init
+#
+# Mount an overlayfs on /etc, with its upper layer on a persistent
+# device, before starting the init system, which already needs /etc.
+#
+# Adapted from overlayfs-etc-preinit.sh.in from openembedded-core.
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+MOUNT_POINT="@MOUNT_POINT@"
+OVERLAY_DIR="${MOUNT_POINT}/overlay-etc"
+
+echo "overlayfs-etc: mounting @DEVICE@ on ${MOUNT_POINT}"
+
+mount -t proc proc /proc
+mount -t sysfs sysfs /sys
+
+if mount -n -t "@FSTYPE@" -o "@MOUNT_OPTIONS@" "@DEVICE@" "${MOUNT_POINT}"; then
+	mkdir -p "${OVERLAY_DIR}/upper" "${OVERLAY_DIR}/work"
+
+	if @EXPOSE_LOWER@; then
+		# Read-only access to the original /etc content
+		mkdir -p "${OVERLAY_DIR}/lower"
+		mount -n -o bind,ro /etc "${OVERLAY_DIR}/lower"
+	fi
+
+	mount -n -t overlay \
+		-o "lowerdir=/etc,upperdir=${OVERLAY_DIR}/upper,workdir=${OVERLAY_DIR}/work,index=off,xino=off,redirect_dir=off,metacopy=off" \
+		overlay-etc /etc ||
+		echo "overlayfs-etc: mounting the /etc overlay failed"
+else
+	echo "overlayfs-etc: mounting @DEVICE@ failed, /etc is not writable"
+fi
+
+umount /sys
+umount /proc
+
+exec @INIT@ "$@"
package/skeleton-init-common/skeleton-init-common.mk +63 -0

67 lines not on this page · raw message

system/Config.in +62 -0

68 lines not on this page · raw message

Signature · 6 lines
2.34.1

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#2 lore raw

PATCH 2/3 docs/manual: document the /etc overlayfs

In reply to Angelo Compagnucci

Explain how the /etc overlayfs works, the options to configure it, the requirements on the persistent device, and that only /etc is handled.

---
 docs/manual/configure.adoc | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
docs/manual/configure.adoc +32 -0
index e0358aa0f9..6aacc8fefb 100644
@@ -429,3 +429,35 @@ can be chosen from +System configuration+, +Init system+:
 The solution recommended by Buildroot developers is to use the
 *BusyBox init* as it is sufficient for most embedded
 systems. *systemd* can be used for more complex situations.
+
+==== Writable /etc on a read-only root filesystem
+
+When the root filesystem stays read-only (+BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW+
+disabled), +/etc+ can still be made writable with an overlayfs whose
+upper layer is on a persistent device, by enabling
++BR2_ROOTFS_OVERLAYFS_ETC+. This works with the BusyBox, systemV and
+systemd init systems.
+
+The init system reads +/etc+ as soon as it starts, so the overlay
+can't be mounted from +/etc/fstab+ or from a systemd unit. Instead,
+Buildroot moves the init program to +/usr/libexec/overlayfs-etc/init+
+and installs a small script as +/sbin/init+, which:
+
+ * mounts the persistent device (+BR2_ROOTFS_OVERLAYFS_ETC_DEVICE+,
+   +BR2_ROOTFS_OVERLAYFS_ETC_FSTYPE+, +BR2_ROOTFS_OVERLAYFS_ETC_MOUNT_OPTIONS+)
+   on +BR2_ROOTFS_OVERLAYFS_ETC_MOUNT_POINT+ (+/data+ by default);
+ * mounts an overlayfs on +/etc+, with the original +/etc+ as the lower
+   layer and +<mount point>/overlay-etc/upper+ as the upper layer;
+ * optionally (+BR2_ROOTFS_OVERLAYFS_ETC_EXPOSE_LOWER+), bind-mounts the
+   original +/etc+ read-only on +<mount point>/overlay-etc/lower+;
+ * starts the original init program.
+
+The persistent device must already exist and be formatted, which is
+left to the integration, and it must not be listed in +/etc/fstab+.
+If it cannot be mounted, the system still boots, with a read-only
++/etc+.
+
+Only +/etc+ is handled. With systemd, +/var+ is managed by the
++/var management+ option. With BusyBox or systemV init, +/var+ only
+provides volatile directories (symbolic links to +/tmp+ and +/run+),
+and +/var/lib+ stays read-only.
Signature · 6 lines
2.34.1

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot
#3 lore raw

PATCH 3/3 support/testing: add runtime tests for the /etc overlayfs

In reply to Angelo Compagnucci

Test the /etc overlayfs with the busybox, sysvinit and systemd init systems, with a read-only ext4 root filesystem and a second ext4 disk as the persistent device: the original init runs as PID 1, /etc is an overlay whose changes are stored on the persistent device and survive a reboot, and the original /etc is exposed read-only. Also check that the system still boots, with a read-only /etc, without the persistent device.

The kernel configuration disables overlayfs, to check that the option enables it.

---
 DEVELOPERS                                    |   1 +
 .../testing/tests/init/test_overlayfs_etc.py  | 128 ++++++++++++++++++
 .../linux-no-overlayfs.fragment               |   2 +
 3 files changed, 131 insertions(+)
 create mode 100644 support/testing/tests/init/test_overlayfs_etc.py
 create mode 100644 support/testing/tests/init/test_overlayfs_etc/linux-no-overlayfs.fragment
DEVELOPERS +1 -0
index 1b9dd41f01..0c6e777133 100644
@@ -262,6 +262,7 @@ F:	package/sshguard/
 F:	package/sunwait/
 F:	package/sysdig/
 F:	package/uthash/
+F:	support/testing/tests/init/test_overlayfs_etc.py
 
 N:	Andy Shevchenko <[email protected]>
 F:	package/fb-test-app/
support/testing/tests/init/test_overlayfs_etc.py new file +128 -0

128 lines not on this page · raw message

support/testing/tests/init/test_overlayfs_etc/linux-no-overlayfs.fragment new file +2 -0
new file mode 100644
index 0000000000..f59e353141
@@ -0,0 +1,2 @@
+# Disabled here, to check that BR2_ROOTFS_OVERLAYFS_ETC enables it
+# CONFIG_OVERLAY_FS is not set
Signature · 6 lines
2.34.1

_______________________________________________
buildroot mailing list
[email protected]
https://lists.buildroot.org/mailman/listinfo/buildroot