diff --git a/README.md b/README.md index e4940dc..ff1a6fd 100644 --- a/README.md +++ b/README.md @@ -122,11 +122,40 @@ docs/ Installation, firmware, runner setup - [docs/firmware.md](docs/firmware.md) — what needs extracting from Windows and why - [docs/runner-setup.md](docs/runner-setup.md) — one-time Gitea runner preparation +## Boot status + +Confirmed on hardware, from a USB stick: + +- GRUB loads the kernel and the device tree +- The kernel comes up and probes the SDM850 — UFS controller, display + subsystem, WiFi and IPA all appear as platform devices, so + `DEVICE_CMDLINE` and the DTB are right +- The framebuffer console works (`simple-framebuffer`, 240x67) +- The root filesystem mounts and systemd starts + +Not yet confirmed: reaching a login prompt, and anything past it. SELinux is +shipped permissive — see below. + +### SELinux + +The build labels the filesystem offline with `setfiles`, so enforcing should +work. It ships **permissive** anyway, because the failure mode is unusually +punishing: an unlabelled root takes PID 1 down with `Failed to allocate manager +object` before anything can be logged into and repaired, and `/.autorelabel` +cannot save it because nothing survives long enough to act on the flag. + +Once the machine is up and you are happy with it: + +```sh +sudo setenforce 1 # try it for this boot +sudo sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config +``` + +Or set `SELINUX_MODE=enforcing` in `config/device.env` and rebuild. + ## Caveats -The build has not yet been confirmed to boot on real hardware. The device tree, -kernel command line and firmware layout are taken from Fedora's Snapdragon WoA -documentation and the aarch64-laptops project; the parts specific to the C630's -older SDM850 are reasoned from those rather than tested. Expect to spend a boot -or two adjusting `DEVICE_CMDLINE` in `config/device.env`. Findings belong in -this README. +The kernel command line and firmware layout are taken from Fedora's Snapdragon +WoA documentation and the aarch64-laptops project; the parts specific to the +C630's older SDM850 are reasoned from those rather than derived from +documentation for this machine. Findings belong in this README. diff --git a/build/stage2.sh b/build/stage2.sh index ebd2196..f8b373c 100755 --- a/build/stage2.sh +++ b/build/stage2.sh @@ -73,13 +73,14 @@ find "$WORK" -mindepth 1 -maxdepth 1 \ # becomes a no-op. Only a stock Fedora image pays for it. # --------------------------------------------------------------------------- if command -v mke2fs >/dev/null && command -v mcopy >/dev/null \ - && command -v sgdisk >/dev/null && command -v zstd >/dev/null; then + && command -v sgdisk >/dev/null && command -v setfiles >/dev/null; then echo "build tooling already present in the container image" else log "Installing build tooling into the container" dnf -y install --setopt=install_weak_deps=False \ --setopt=cachedir="$DNF_CACHE" --setopt=keepcache=1 \ e2fsprogs dosfstools mtools gdisk util-linux rsync zstd findutils \ + policycoreutils \ >/dev/null fi @@ -261,9 +262,8 @@ printf 'root=UUID=%s ro %s\n' "$ROOT_UUID" "$DEVICE_CMDLINE" \ ln -sf ../run/systemd/resolve/stub-resolv.conf "$ROOTFS/etc/resolv.conf" echo "$DEVICE_NAME" > "$ROOTFS/etc/hostname" -# mke2fs -d does not reliably carry SELinux labels across, and the builder has -# no policy loaded anyway. Relabel on first boot. -: > "$ROOTFS/.autorelabel" +# SELinux labelling happens later, once the bind mounts are gone — see +# "Labelling the filesystem for SELinux" below. # --------------------------------------------------------------------------- log "Configuring the target system" @@ -399,6 +399,47 @@ for d in dev/pts dev sys proc; do fi done +# --------------------------------------------------------------------------- +log "Labelling the filesystem for SELinux" +# --------------------------------------------------------------------------- +# mke2fs -d builds the filesystem from a directory tree and carries security.* +# xattrs across, but nothing has set them: the tree came out of dnf, not out of +# a running SELinux system. Boot an unlabelled root and systemd cannot set a +# context on anything under /dev, logs a screenful of "Permission denied", and +# dies with "Failed to allocate manager object". /.autorelabel does not rescue +# it — PID 1 never survives long enough to act on the flag. +# +# So label it here, after the bind mounts are gone (or setfiles would walk the +# builder's /proc) and before /boot is split out, so /boot's files are labelled +# with everything else. +FILE_CONTEXTS="$ROOTFS/etc/selinux/targeted/contexts/files/file_contexts" +LABELLED=0 +if [ -f "$FILE_CONTEXTS" ] && command -v setfiles >/dev/null; then + if setfiles -F -r "$ROOTFS" "$FILE_CONTEXTS" "$ROOTFS"; then + LABELLED=1 + echo "filesystem labelled" + else + echo "warning: setfiles failed — falling back to a first-boot relabel" >&2 + fi +else + echo "warning: no SELinux policy or no setfiles in this container" >&2 +fi + +mkdir -p "$ROOTFS/etc/selinux" +cat > "$ROOTFS/etc/selinux/config" < "$ROOTFS/.autorelabel" +fi + mv "$ROOTFS/boot" "$WORK/boot" mkdir -p "$ROOTFS/boot" rm -rf "$WORK/boot/efi" diff --git a/config/device.env b/config/device.env index 5a6fbcb..59bf53f 100644 --- a/config/device.env +++ b/config/device.env @@ -44,6 +44,15 @@ : "${FEDORA_RELEASE:=44}" : "${TARGET_ARCH:=aarch64}" +# --- selinux ------------------------------------------------------------ +# The build labels the filesystem offline with setfiles, so enforcing is +# viable. It ships permissive anyway: an unlabelled or mislabelled filesystem +# takes PID 1 down with "Failed to allocate manager object" before anything can +# be logged in and fixed, and on a machine this awkward to debug that trade is +# not worth making by default. Switch with `sudo setenforce 1` once it is up, +# or set this to enforcing and rebuild. +: "${SELINUX_MODE:=permissive}" + # --- default account ---------------------------------------------------- # Password is expired at first login, so it must be changed immediately. : "${DEFAULT_USER:=fedora}"