mouse/src
Diff
6c32d9c0f434 → ea9ff564e7ff
Makefile
Mode 100644 → 100644; object 23df1ae09371 → 3a8df4295e43
@@ -17,7 +17,7 @@ ./scripts/run-qemu.sh check: image - ./scripts/check-c1.sh + ./scripts/check-c2.sh audit: image @printf '%s\n' "static ELF audit passed during the container build"
README.md
Mode 100644 → 100644; object 22264dd53c4d → 0d330f2b91e4
@@ -1,6 +1,6 @@ # MOUSE source tree -This repository builds the MOUSE C1 boot image: Linux 6.18.35 from pinned +This repository builds the MOUSE C2 boot image: Linux 6.18.35 from pinned kernel.org source using MOUSE's own x86_64 configuration, a MOUSE-owned mini rootfs with ChimeraUtils and static OpenRC 0.63.3, and `cheesed` from the sibling repository as `/sbin/cheesed`. @@ -43,7 +43,8 @@ `make check` requires `expect`. It boots enabled and disabled policy variants under QEMU, verifies strict `/etc/rc.conf` translation into disposable -runlevels, required-service ordering, `supervise-daemon` restart state, +runlevels, required-service ordering, `supervise-daemon` restart exhaustion and +administrative recovery, forced termination on the declared stop schedule, runtime-only `service` operations, the absence of `rc-update`, and orderly OpenRC shutdown before poweroff and reboot.
patches/openrc-mouse-tool-surface.patch
Mode 100644 → 100644; object 4e7232bd3602 → 99cc1148992c
@@ -37,6 +37,42 @@
subdir('supervise-daemon')
-subdir('swclock')
subdir('value')
+--- a/src/shared/meson.build
++++ b/src/shared/meson.build
+@@ -1,5 +1,9 @@
+-version_h = vcs_tag(input : 'version.h.in', output : 'version.h')
+-vcs_tag(input : 'version.in', output : 'version')
++version_data = configuration_data()
++version_data.set('VCS_TAG', meson.project_version())
++version_h = configure_file(input : 'version.h.in', output : 'version.h',
++ configuration : version_data)
++configure_file(input : 'version.in', output : 'version',
++ configuration : version_data)
+
+ shared_sources = [
+ 'misc.c',
+--- a/src/service/meson.build
++++ b/src/service/meson.build
+@@ -6,6 +6,7 @@
+ 'service_inactive',
+ 'service_wasinactive',
+ 'service_hotplugged',
++ 'service_failed',
+ 'service_started_daemon',
+ 'service_crashed',
+ ]
+--- a/sh/supervise-daemon.sh
++++ b/sh/supervise-daemon.sh
+@@ -95,6 +95,9 @@
+ elif service_inactive; then
+ ewarn "status: inactive"
+ return 16
++ elif service_failed; then
++ eerror "status: failed"
++ return 32
+ elif service_started; then
+ if service_crashed; then
+ if ! _check_supervised; then
--- a/sh/init.sh.Linux.in
+++ b/sh/init.sh.Linux.in
@@ -11,14 +11,14 @@
rootfs/etc/init.d/mouse_optional
Mode 100644 → 100644; object 22c47ff88361 → 173b05646a96
@@ -1,13 +1,12 @@
#!/sbin/openrc-run
-description="MOUSE optional C1 proof service"
+description="MOUSE optional supervised proof service"
supervisor=supervise-daemon
-command=/bin/sleep
-command_args="2147483647"
-respawn_delay=1
+command=/usr/libexec/mouse-c2-daemon
+respawn_delay=0
respawn_max=3
respawn_period=10
-retry="TERM/3/KILL/2"
+retry="TERM/1/KILL/1"
depend() {
need mouse_ready
@@ -15,6 +14,10 @@
start_post() {
checkpath --file /run/mouse-optional.started
+}
+
+start_pre() {
+ rm -f /run/mouse-c2-daemon.term
}
stop_post() {
scripts/build-static-base.sh
Mode 100755 → 100755; object 9933e70c811f → 34ee7674690d
@@ -440,6 +440,11 @@ install -m 0755 "$sysroot/usr/bin/tput" "$base_root/usr/bin/tput" ln -s tcsh "$base_root/usr/bin/csh" +install -d -m 0755 "$base_root/usr/libexec" +"$cc" -O2 -Wall -Wextra -Werror \ + "$repo_dir/support/mouse-c2-daemon.c" \ + -o "$base_root/usr/libexec/mouse-c2-daemon" + printf '%s\n' '#!/bin/sh' 'exec /usr/bin/tput clear' >"$base_root/usr/bin/clear" chmod 0755 "$base_root/usr/bin/clear"
scripts/check-c1.exp
Mode 100755 → 100755; object d05d6fff0169 → 55c458a50cd2
@@ -70,6 +70,10 @@
await_exact "cheesed\r" "cheesed in /proc/1"
await_exact "mouse:~# " "the prompt after the PID 1 check"
+send -- "cat /usr/lib/rc/version\r"
+await_exact "0.63.3\r" "the pinned OpenRC release identity"
+await_exact "mouse:~# " "the prompt after the OpenRC version check"
+
send -- "sh -c 'test -f /run/mouse-ready.started'; echo READY_\$status\r"
await_exact "READY_0\r" "the required service marker"
await_exact "mouse:~# " "the prompt after the required service check"
@@ -91,7 +95,7 @@
await_exact "status: started" "supervise-daemon service status"
await_exact "mouse:~# " "the prompt after service status"
- send -- "sh -c 'old_child=`cat /run/openrc/options/mouse_optional/child_pid`; kill -TERM \"\$old_child\"; sleep 3; new_child=`cat /run/openrc/options/mouse_optional/child_pid`; test \"\$old_child\" != \"\$new_child\"'; echo RESPAWN_\$status\r"
+ send -- "sh -c 'old_child=`cat /run/openrc/options/mouse_optional/child_pid`; kill -KILL \"\$old_child\"; sleep 3; new_child=`cat /run/openrc/options/mouse_optional/child_pid`; test \"\$old_child\" != \"\$new_child\"'; echo RESPAWN_\$status\r"
await_exact "RESPAWN_0\r" "supervise-daemon replacing a terminated child"
await_exact "mouse:~# " "the prompt after the respawn check"
scripts/check-c2.exp
Mode → 100755; object → 611947eec58e
@@ -1,0 +1,92 @@
+#!/usr/bin/expect -f
+
+if {$argc != 1} {
+ puts stderr "usage: check-c2.exp RUNNER"
+ exit 2
+}
+
+set runner [file normalize [lindex $argv 0]]
+set timeout 45
+
+proc fail {message} {
+ puts stderr "C2 check failed: $message"
+ exit 1
+}
+
+proc await_exact {text description} {
+ expect {
+ -exact $text {
+ return
+ }
+ timeout {
+ fail "timed out waiting for $description"
+ }
+ eof {
+ fail "QEMU exited while waiting for $description"
+ }
+ }
+}
+
+proc await_clean_exit {action} {
+ expect {
+ eof {
+ set result [wait]
+ set status [lindex $result 3]
+ if {$status != 0} {
+ fail "QEMU exited with status $status after $action"
+ }
+ }
+ timeout {
+ fail "QEMU did not exit after $action"
+ }
+ }
+}
+
+spawn -noecho $runner
+await_exact "cheesed: C1 bootstrap complete; cheesed is PID 1" "PID 1 confirmation"
+await_exact "cheesed: enabled optional services: mouse_optional" "enabled-service policy"
+await_exact "cheesed: OpenRC default transition complete" "the default transition"
+await_exact "mouse:~# " "the tcsh prompt"
+
+send -- "sh -c 'i=0; while \[ \"\$i\" -lt 4 \]; do child=`cat /run/openrc/options/mouse_optional/child_pid`; kill -KILL \"\$child\"; i=\$((i + 1)); sleep 1; done'; echo EXHAUST_\$status\r"
+await_exact "EXHAUST_0\r" "four supervised crashes"
+await_exact "mouse:~# " "the prompt after exhausting respawns"
+
+send -- "service mouse_optional status; echo FAILED_STATUS_\$status\r"
+await_exact "status: failed" "the failed service status"
+await_exact "FAILED_STATUS_32\r" "the failed status exit code"
+await_exact "mouse:~# " "the prompt after failed status"
+
+send -- "sh -c 'test -e /run/openrc/failed/mouse_optional'; echo FAILED_MARKER_\$status\r"
+await_exact "FAILED_MARKER_0\r" "OpenRC's failed-state marker"
+await_exact "mouse:~# " "the prompt after the failed marker"
+
+send -- "service mouse_optional restart\r"
+await_exact "Starting mouse_optional" "administrative recovery"
+await_exact "mouse:~# " "the prompt after administrative recovery"
+send -- "service mouse_optional status\r"
+await_exact "status: started" "started status after recovery"
+await_exact "mouse:~# " "the prompt after recovered status"
+send -- "sh -c 'test ! -e /run/openrc/failed/mouse_optional'; echo RECOVERED_\$status\r"
+await_exact "RECOVERED_0\r" "the cleared failed state"
+await_exact "mouse:~# " "the prompt after the recovery-state check"
+
+send -- "set stubborn=`cat /run/openrc/options/mouse_optional/child_pid`; service mouse_optional stop\r"
+await_exact "Stopping mouse_optional" "the forced runtime stop"
+await_exact "mouse:~# " "the prompt after the forced runtime stop"
+send -- "sh -c 'test -f /run/mouse-c2-daemon.term'; echo TERM_SEEN_\$status\r"
+await_exact "TERM_SEEN_0\r" "the daemon observing and ignoring SIGTERM"
+await_exact "mouse:~# " "the prompt after the SIGTERM marker check"
+send -- "sh -c '! kill -0 \"\$1\" 2>/dev/null' sh \"\$stubborn\"; echo FORCED_GONE_\$status\r"
+await_exact "FORCED_GONE_0\r" "supervise-daemon escalating to SIGKILL"
+await_exact "mouse:~# " "the prompt after forced termination"
+
+send -- "service mouse_optional start\r"
+await_exact "Starting mouse_optional" "the final runtime start"
+await_exact "mouse:~# " "the prompt after the final runtime start"
+send -- "kill -TERM 1\r"
+await_exact "cheesed: received poweroff request" "the poweroff request"
+await_exact "cheesed: OpenRC shutdown transition complete" "the shutdown transition"
+await_clean_exit "poweroff"
+
+puts "C2 QEMU supervision checks passed"
scripts/check-c2.sh
Mode → 100755; object → 5745b1f8d219
@@ -1,0 +1,7 @@ +#!/bin/sh +set -eu + +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) + +"$script_dir/check-c1.sh" +"$script_dir/check-c2.exp" "$script_dir/run-qemu.sh"
support/mouse-c2-daemon.c
Mode → 100644; object → 81fea5db201d
@@ -1,0 +1,41 @@
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+
+static const char ready_path[] = "/run/mouse-c2-daemon.ready";
+static const char term_path[] = "/run/mouse-c2-daemon.term";
+
+static void write_marker(const char *path, const char *contents, size_t length)
+{
+ int descriptor = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+
+ if (descriptor == -1)
+ return;
+ (void)write(descriptor, contents, length);
+ (void)close(descriptor);
+}
+
+static void handle_term(int signal_number)
+{
+ static const char marker[] = "SIGTERM\n";
+
+ (void)signal_number;
+ write_marker(term_path, marker, sizeof(marker) - 1);
+}
+
+int main(void)
+{
+ static const char marker[] = "ready\n";
+ struct sigaction action = {
+ .sa_handler = handle_term,
+ };
+
+ if (sigemptyset(&action.sa_mask) == -1)
+ return 1;
+ if (sigaction(SIGTERM, &action, NULL) == -1)
+ return 1;
+ write_marker(ready_path, marker, sizeof(marker) - 1);
+
+ for (;;)
+ pause();
+}