diff --git a/buildroot-source-patches/0006-gsettings-desktop-schemas-48.patch b/buildroot-source-patches/0006-gsettings-desktop-schemas-48.patch new file mode 100644 index 0000000..b883a4a --- /dev/null +++ b/buildroot-source-patches/0006-gsettings-desktop-schemas-48.patch @@ -0,0 +1,14 @@ +diff --git a/package/gsettings-desktop-schemas/gsettings-desktop-schemas.mk b/package/gsettings-desktop-schemas/gsettings-desktop-schemas.mk +--- a/package/gsettings-desktop-schemas/gsettings-desktop-schemas.mk ++++ b/package/gsettings-desktop-schemas/gsettings-desktop-schemas.mk +@@ -7 +7 @@ +-GSETTINGS_DESKTOP_SCHEMAS_VERSION_MAJOR = 45 ++GSETTINGS_DESKTOP_SCHEMAS_VERSION_MAJOR = 48 +diff --git a/package/gsettings-desktop-schemas/gsettings-desktop-schemas.hash b/package/gsettings-desktop-schemas/gsettings-desktop-schemas.hash +--- a/package/gsettings-desktop-schemas/gsettings-desktop-schemas.hash ++++ b/package/gsettings-desktop-schemas/gsettings-desktop-schemas.hash +@@ -1,2 +1,2 @@ +-# From https://download.gnome.org/sources/gsettings-desktop-schemas/45/gsettings-desktop-schemas-45.0.sha256sum +-sha256 365c8d04daf79b38c8b3dc9626349a024f9e4befdd31fede74b42f7a9fbe0ae2 gsettings-desktop-schemas-45.0.tar.xz ++# From https://download.gnome.org/sources/gsettings-desktop-schemas/48/gsettings-desktop-schemas-48.0.sha256sum ++sha256 e68f155813bf18f865a8b2c8e9d473588b6ccadcafbb666ab788857c6c2d1bd3 gsettings-desktop-schemas-48.0.tar.xz diff --git a/rootfs-overlay/usr/bin/atom-install b/rootfs-overlay/usr/bin/atom-install index c3d6796..93381bf 100755 --- a/rootfs-overlay/usr/bin/atom-install +++ b/rootfs-overlay/usr/bin/atom-install @@ -79,4 +79,10 @@ if [ -d /sys/firmware/efi ] && command -v efibootmgr >/dev/null 2>&1; then [ -n "$NUM" ] && efibootmgr -n "$NUM" >/dev/null 2>&1 || true fi +# Completion marker for atom-installer-launch: singularity-installer exits 0 both when +# the install finished and when the user just closed the window, so the launcher cannot +# tell "reboot into the new system" from "user bailed out" by exit status alone. +mkdir -p /run/atom 2>/dev/null || true +: > /run/atom/install-complete 2>/dev/null || true + log "done: $DEV provisioned" diff --git a/rootfs-overlay/usr/bin/atom-install-session b/rootfs-overlay/usr/bin/atom-install-session index 4cbf9b3..05ae224 100755 --- a/rootfs-overlay/usr/bin/atom-install-session +++ b/rootfs-overlay/usr/bin/atom-install-session @@ -26,4 +26,8 @@ sscommon_log "installer: DRM master free after ${_i} ticks (marker=$([ -e /run/s export LIBSEAT_BACKEND=builtin sscommon_log "LIBSEAT_BACKEND=builtin (installer only: seatd may be absent at install time)" -sscommon_exec_labwc -s "atom-installer-launch" +# -S, not -s: terminate the compositor when the startup command exits. With -s labwc +# outlives the installer and the user is left staring at a bare compositor after the +# final "Restart now" button (which only closes the window). atom-installer-launch +# reboots on a finished install, so -S only matters for the give-up path. +sscommon_exec_labwc -S "atom-installer-launch" diff --git a/rootfs-overlay/usr/bin/atom-installer-launch b/rootfs-overlay/usr/bin/atom-installer-launch index e029c21..3739f44 100755 --- a/rootfs-overlay/usr/bin/atom-installer-launch +++ b/rootfs-overlay/usr/bin/atom-installer-launch @@ -1,9 +1,56 @@ #!/bin/sh set -eu -if [ -x /usr/bin/singularity-splash ]; then - rm -f "${XDG_RUNTIME_DIR:-/run/user/0}/singularity-shell-ready" - singularity-splash >/dev/null 2>&1 & -fi +# Wrapper around singularity-installer for both the live disk installer +# (atom-install-session) and the OOBE own-labwc fallback (atom-oobe-session). +# +# It does NOT exec the installer: the installer's own last page ends with a button +# labelled "Restart now" / "Start using ..." that only closes the window, so whatever +# has to happen after it exits has to happen here. Without that, labwc stays up with +# no client left and the user is looking at a bare compositor: a black screen with a +# cursor. Both session scripts run labwc with -S (terminate on exit), so returning +# from here tears the session down. +# +# install mode, install finished -> reboot, which is what the button promises +# oobe mode, account provisioned -> return, greetd moves on to the greeter +# neither -> the user closed the wizard early or it crashed; +# relaunch it, bounded, then give up +MARKER_INSTALL=/run/atom/install-complete +MARKER_OOBE=/var/lib/sinty/.oobe-done -exec singularity-installer "$@" +MODE=install +for a in "$@"; do + [ "$a" = "--oobe" ] && MODE=oobe +done + +_try=0 +while [ "$_try" -lt 3 ]; do + _try=$((_try + 1)) + + if [ -x /usr/bin/singularity-splash ]; then + rm -f "${XDG_RUNTIME_DIR:-/run/user/0}/singularity-shell-ready" + singularity-splash >/dev/null 2>&1 & + fi + + _rc=0 + singularity-installer "$@" || _rc=$? + + if [ "$MODE" = oobe ]; then + if [ -f "$MARKER_OOBE" ]; then + echo "[installer-launch] oobe complete (rc=${_rc}), handing over" >&2 + exit 0 + fi + elif [ -f "$MARKER_INSTALL" ]; then + echo "[installer-launch] install complete (rc=${_rc}), rebooting" >&2 + # Give the compositor a moment to finish painting the last frame, else the + # reboot races the window close and the screen flickers to black first. + sleep 1 + exec reboot + fi + + echo "[installer-launch] installer exited rc=${_rc} without completing (attempt ${_try})" >&2 + sleep 1 +done + +echo "[installer-launch] giving up after ${_try} attempts" >&2 +exit 1 diff --git a/rootfs-overlay/usr/bin/atom-oobe-session b/rootfs-overlay/usr/bin/atom-oobe-session index d48bd50..edbaa21 100755 --- a/rootfs-overlay/usr/bin/atom-oobe-session +++ b/rootfs-overlay/usr/bin/atom-oobe-session @@ -18,8 +18,17 @@ export ATOM_OOBE_APPLY=1 # fine to /run/singularity (0770 greeter:singularity-session) since root bypasses the # mode. exec singularity-installer DIRECT (not atom-installer-launch): the persistent # compositor + boot-splash already paint the logo, so a second splash client just competes. -export XDG_RUNTIME_DIR=/run/singularity -export WAYLAND_DISPLAY=wayland-0 +# +# XDG_RUNTIME_DIR stays root's own (/run/user/0) and the compositor socket is reached +# through an absolute WAYLAND_DISPLAY, which libwayland uses verbatim. Pointing +# XDG_RUNTIME_DIR at /run/singularity instead makes every client library root writes +# its runtime state there (at-spi, dconf, gvfs, ...) as root-owned 0700 dirs, in a +# directory the greeter (uid greeter) owns and has to write after we exit: the greeter +# then dies on "can't create /run/singularity/greeter-ready: Permission denied" and +# greetd loops on "greeter exited without creating a session". +WAYLAND_SOCKET=/run/singularity/wayland-0 +export XDG_RUNTIME_DIR=/run/user/0 +export WAYLAND_DISPLAY="$WAYLAND_SOCKET" export HOME=/run/user/0 export XDG_CACHE_HOME=/run/user/0/.cache XDG_CONFIG_HOME=/run/user/0/.config mkdir -p "$XDG_CACHE_HOME" "$XDG_CONFIG_HOME" 2>/dev/null || true @@ -50,14 +59,15 @@ _try=0 _i=0 while [ -f /run/atom/installed ] && [ "$_try" -lt 5 ]; do _i=0 - while [ ! -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ] && [ "$_i" -lt 300 ]; do + while [ ! -S "$WAYLAND_SOCKET" ] && [ "$_i" -lt 300 ]; do sleep 0.1 _i=$((_i + 1)) done - [ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ] || break + [ -S "$WAYLAND_SOCKET" ] || break _try=$((_try + 1)) sscommon_log "oobe: compositor socket up (${_i} ticks), running OOBE as client (attempt ${_try})" - sscommon_mark_greeter_ready + # chmod: the greeter rewrites this file after we hand over, and root created it. + sscommon_mark_greeter_ready chmod _rc=0 dbus-run-session -- singularity-installer --oobe || _rc=$? if [ -f "${MARKER}" ]; then @@ -75,10 +85,15 @@ fi # Fallback: no persistent compositor (e.g. a live/uninstalled boot where it is gated # off by ConditionPathExists) -> start our own labwc, as before. Never worse than today. sscommon_log "oobe: compositor socket absent (${_i} ticks), fallback own-labwc" +# Our own labwc binds its socket itself; an inherited absolute WAYLAND_DISPLAY would +# only mislead the clients it starts. +unset WAYLAND_DISPLAY export XDG_RUNTIME_DIR=/run/user/0 export HOME="$XDG_RUNTIME_DIR" sscommon_xdg_dirs sscommon_wait_splash 50 sscommon_mark_greeter_ready chmod sleep 0.3 -sscommon_exec_labwc -s "atom-installer-launch --oobe" +# -S: labwc terminates when the wizard exits, so greetd gets its session end and starts +# the greeter instead of leaving a clientless compositor on screen. +sscommon_exec_labwc -S "atom-installer-launch --oobe" diff --git a/rootfs-overlay/usr/share/singularity/labwc-locked/rc.xml b/rootfs-overlay/usr/share/singularity/labwc-locked/rc.xml index bab7555..c28fc8e 100644 --- a/rootfs-overlay/usr/share/singularity/labwc-locked/rc.xml +++ b/rootfs-overlay/usr/share/singularity/labwc-locked/rc.xml @@ -18,7 +18,7 @@ cannot call the shell's dev.sinty.desktop directly: this compositor runs as the greeter user and the shell owns that name on the logged-in user's own session bus, which D-Bus refuses to a cross-uid peer. So they go through - /usr/bin/singularity-shortcut, whose per-session --serve half (started by + /usr/bin/singularity-shortcut, whose per-session serve half (started by singularity-desktop-session as the user) forwards over a group-owned socket. Pre-login no session is serving, so those Execute calls no-op and only the lock is in force. (Live per-user rebinds and xkb/theme still need the shell's diff --git a/scripts/package.sh b/scripts/package.sh index 2623f9e..4959e5e 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -85,9 +85,21 @@ if [ -f "${FW_ROOT_PUB}" ]; then # mid-refactor); otherwise build it from source. if { [ -z "${FW_VERIFY_BIN}" ] || [ ! -x "${FW_VERIFY_BIN}" ]; } \ && [ -d "${ATOMLOOPS}/cmd/fw-verify" ]; then - ( cd "${ATOMLOOPS}" && CGO_ENABLED=0 "${ATOMLOOPS_GO:-go}" build -ldflags '-s -w' \ - -o "${REPO_DIR}/artifacts/fw-verify" ./cmd/fw-verify ) - FW_VERIFY_BIN="${REPO_DIR}/artifacts/fw-verify" + # Fail soft on a build error too, not only on an absent cmd/fw-verify. + # build-initramfs.sh already treats a missing verifier as "no firmware + # verifier, base firmware only", so an AtomLoops checkout whose fw-verify + # does not compile (a mid-refactor HEAD, a dependency it cannot resolve + # offline) is a degraded image, not a broken build -- but under set -e the + # bare go build aborts the whole run, after the erofs, the verity tree and + # the UKI are already done. + if ( cd "${ATOMLOOPS}" && CGO_ENABLED=0 "${ATOMLOOPS_GO:-go}" build -ldflags '-s -w' \ + -o "${REPO_DIR}/artifacts/fw-verify" ./cmd/fw-verify ); then + FW_VERIFY_BIN="${REPO_DIR}/artifacts/fw-verify" + else + echo "package: warn: cannot build fw-verify from ${ATOMLOOPS}" >&2 + echo "package: warn: shipping base survival firmware, no firmware add-on verification" >&2 + FW_VERIFY_BIN= + fi fi if [ -n "${FW_VERIFY_BIN}" ] && [ -x "${FW_VERIFY_BIN}" ]; then export FW_VERIFY_BIN FW_ROOT_PUB