mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 08:41:13 -07:00
Mount the rootfs read-only on both images
The rootfs mounted read-write, so a slot ran with its own files open to change, and the factory-slot mounts rode along on the release image. Both images now carry the read-only-rootfs feature: the ro root line and the rcS default, the volatile links made at rootfs time, a writable copy of /var/lib at boot, a build failure for a post-install that needs the machine, and the removal of shadow, base-passwd, update-rc.d and update-alternatives. What must last or change at run time is handled file by file: - forgefirm-users renders the four account files from the record into /run/forgefirm/accounts and bind-mounts each copy over its /etc file (useradd and the rest are gone with shadow); a render writes through the mount, and the image's own files apply until the first render. - forgefirm-banner bind-mounts a copy of /etc/issue and writes the address block through it. - sshd keeps its host keys under /data/forgefirm/ssh, so the fingerprint survives updates; both sshd configs carry the same HostKey lines. - forgefirm-logging passes logrotate a state file under /var/run (logrotate refuses to run without one). - forgefirm-persist points the boot timestamp and the random seed at /data/forgefirm. The dev image appends the /factory slot mounts, without nofail (busybox mount hands it to the kernel, which rejects it). The rootfs command entries lose their semicolons: on scarthgap the value is the task's vardeps, split on whitespace, so "name;" left the function body out of the signature and a changed body did not remake the rootfs; with the bodies tracked, the dev image's DATETIME string needs a vardepsexclude. release.sh gains the read-only gate (root ro, no /factory line, ROOTFS_READ_ONLY=yes, host keys on /data). image.health checks the mounts, the account binds, the banner bind, the host keys and the dev-only /factory mounts. Proven on the bench reference (dev image 20260909140901): / ro, /data rw, /var/lib a tmpfs copy, the four account files and /etc/issue bound from tmpfs, the host keys in /data/forgefirm/ssh, no "Read-only file system" line in any log; forgectrl.auth and commission.account-login (a temporary account rendered, logged in over HTTPS and removed again), kernel.latch-locked-idle and motion.liveness-probe PASS; logrotate runs with the volatile state. forgetest unit tests 335 OK; both images build clean, and debugfs on the built rootfs shows every setting above.
This commit is contained in:
@@ -241,6 +241,26 @@ ROOT_PW=$(printf '%s\n' "$ROOT_SHADOW" | awk -F: '{print $2}')
|
||||
|| die "release rootfs has a non-empty root password field: the policy is an empty field (empty-root-password in forgefirm-image.bb); a build drift"
|
||||
echo "root policy gate OK (root field empty; sshd refuses root and empty passwords)"
|
||||
|
||||
# Read-only rootfs gate. The release rootfs mounts read-only: the root
|
||||
# line of the built fstab carries ro, the rcS default agrees (the
|
||||
# read-only-rootfs image feature), no factory-slot mount is in the
|
||||
# release fstab (those belong to the dev image), and sshd keeps its host
|
||||
# keys on /data, where the read-only rootfs cannot hold them.
|
||||
FSTAB=$(debugfs -R "cat /etc/fstab" "$EXT4" 2>/dev/null)
|
||||
[ -n "$FSTAB" ] \
|
||||
|| die "release rootfs carries no /etc/fstab"
|
||||
printf '%s\n' "$FSTAB" | awk '$1 == "/dev/root" && $2 == "/" { print $4 }' \
|
||||
| grep -Eq '(^|,)ro(,|$)' \
|
||||
|| die "release fstab does not mount / read-only (base-files fstab or read-only-rootfs drift?)"
|
||||
printf '%s\n' "$FSTAB" | grep -Eq '^[^#]*[[:space:]]/factory/' \
|
||||
&& die "release fstab mounts a factory slot under /factory (dev image only)"
|
||||
RCS=$(debugfs -R "cat /etc/default/rcS" "$EXT4" 2>/dev/null)
|
||||
printf '%s\n' "$RCS" | grep -q '^ROOTFS_READ_ONLY=yes$' \
|
||||
|| die "release rcS has no ROOTFS_READ_ONLY=yes (read-only-rootfs image feature drift?)"
|
||||
[ "$(printf '%s\n' "$SSHD_CONFIG" | grep -c '^HostKey /data/forgefirm/ssh/')" = 3 ] \
|
||||
|| die "release sshd_config does not keep the host keys under /data/forgefirm/ssh (recipes-connectivity/openssh drift?)"
|
||||
echo "read-only rootfs gate OK (/ ro, no /factory mounts, host keys on /data)"
|
||||
|
||||
# Config-level guard: debug-tweaks must not sit in the shared kas config,
|
||||
# where it would apply to every target including the release image.
|
||||
if ( cd "$REPO" && kas dump kas/forgefirm-glowforge.yml 2>/dev/null ) \
|
||||
|
||||
Reference in New Issue
Block a user