From 6244fe26e054accec2214890a40d09096918c3f9 Mon Sep 17 00:00:00 2001 From: Mitchell R Date: Fri, 22 May 2026 23:30:13 +0200 Subject: [PATCH] fix(terminal+journal): run as root via sudo + add bfkiosk NOPASSWD sudoers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Terminal spawns bash as bfkiosk (unprivileged) → can't read journal, can't run rauc/systemctl, can't fix anything useful. Now runs sudo bash --login (with fallback to plain bash if sudo unavailable). Journal streaming: sudo journalctl instead of plain journalctl so bfkiosk can read system journal without systemd-journal group. Pi-gen image: drops /etc/sudoers.d/betterframe-kiosk granting bfkiosk passwordless sudo. Gated by the on-screen code + lockout ladder, so root access still requires physical presence. --- .../01-install-kiosk/01-run-chroot.sh | 4 ++++ kiosk/src/remote_debug.rs | 23 +++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/deploy/pi-gen/stage-betterframe-client/01-install-kiosk/01-run-chroot.sh b/deploy/pi-gen/stage-betterframe-client/01-install-kiosk/01-run-chroot.sh index 94dd927..9bd0b1f 100755 --- a/deploy/pi-gen/stage-betterframe-client/01-install-kiosk/01-run-chroot.sh +++ b/deploy/pi-gen/stage-betterframe-client/01-install-kiosk/01-run-chroot.sh @@ -13,6 +13,10 @@ for grp in video render input audio; do fi done +# --- Passwordless sudo for bfkiosk (remote terminal runs as root) --- +echo 'bfkiosk ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/betterframe-kiosk +chmod 440 /etc/sudoers.d/betterframe-kiosk + # --- Binary --- install -d -o bfkiosk -g bfkiosk -m 755 /opt/betterframe/kiosk install -m 755 /tmp/bf-files/betterframe-kiosk /opt/betterframe/kiosk/betterframe-kiosk diff --git a/kiosk/src/remote_debug.rs b/kiosk/src/remote_debug.rs index e5546e2..37f5e7f 100644 --- a/kiosk/src/remote_debug.rs +++ b/kiosk/src/remote_debug.rs @@ -121,9 +121,9 @@ impl JournalStream { let kill_clone = kill.clone(); std::thread::spawn(move || { - // Try unit-scoped first, fall back to all journal if permission denied. - let mut child = match Command::new("journalctl") - .args(["--user-unit", "betterframe-kiosk", "-f", "--no-pager", "-o", "short-iso", "-n", "50"]) + // Use sudo so bfkiosk user can read system journal. + let mut child = match Command::new("sudo") + .args(["journalctl", "-u", "betterframe-kiosk", "-f", "--no-pager", "-o", "short-iso", "-n", "50"]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() @@ -219,13 +219,26 @@ pub struct TerminalSession { impl TerminalSession { pub fn spawn() -> Result<(Self, std::process::ChildStdout, std::process::ChildStderr), String> { - let mut child = Command::new("bash") - .args(["--login"]) + // Run as root so the operator can actually fix things (journal, + // rauc, systemctl, usermod). The on-screen code + lockout ladder + // gates access; once past that, full root is the point. + let mut child = Command::new("sudo") + .args(["bash", "--login"]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .env("TERM", "xterm-256color") .spawn() + .or_else(|_| { + // Fallback if sudo not available / not configured for bfkiosk. + Command::new("bash") + .args(["--login"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .env("TERM", "xterm-256color") + .spawn() + }) .map_err(|e| format!("bash spawn: {e}"))?; let stdout = child.stdout.take().ok_or("no stdout")?;