feat(users): per-user sealed folders users/<id>/{home,apps,data,permissions}; storage SET_USER/LOCK/PURGE; init sign-in/sign-out loop (purge fresh/removed/guest, seed from factory, session start/stop); shell logout; pm user+system app shelves; terminal SIGNED_OUT; per-program stack (gatekeeper 12p); 128K load scratch

This commit is contained in:
2026-10-28 01:08:50 +01:00
parent 29a25bd8c2
commit 91f7d28834
38 changed files with 1156 additions and 378 deletions

View File

@@ -37,9 +37,9 @@ staged() {
fi
}
# home/, system/ and data/ are encrypted, so not made here: init seeds them
# from factory/ (plaintext) once the gatekeeper has the key.
mkdir -p "${ROOT}/bin" "${ROOT}/apps" "${ROOT}/factory/home" "${ROOT}/factory/system/permissions" "${ROOT}/factory/data"
# Each user's folder in users/ is encrypted, so not filled here: init seeds
# a new user's areas from factory/ (plaintext) once they are signed in.
mkdir -p "${ROOT}/bin" "${ROOT}/apps" "${ROOT}/users" "${ROOT}/factory/home" "${ROOT}/factory/permissions" "${ROOT}/factory/data" "${ROOT}/factory/apps"
# System servers and the shell: init starts these.
copy display-qemu display
copy input-qemu input
@@ -55,7 +55,7 @@ app ls
app sleep
app snake
staged counter inbox/counter
# The owner's first files.
# A user's first files.
cp -r disk/home/. "${ROOT}/factory/home/"
# Only the test image: its presence makes init run the self-test.
if [ -n "${SMPTEST:-}" ]; then

View File

@@ -1,9 +1,9 @@
#!/bin/bash
# Boots IMAGE headless and waits for the self-test (init's SMP checks, then
# spawntest) to report; the machine halts itself when done. Twice, on one
# fresh keystore: the first boot sets a passcode up at the gatekeeper, the
# second gets it wrong once and then right. Exit 0 only if both unlock and
# both say "SMPTEST PASS".
# fresh keystore: the first boot sets up its first user at the gatekeeper,
# the second gets the passcode wrong once and then right. Exit 0 only if
# both sign in and both say "SMPTEST PASS".
set -uo pipefail
IMAGE="${1:?usage: test-qemu.sh IMAGE}"
@@ -40,18 +40,20 @@ boot() {
return $s
}
# First boot: a new passcode (twice), no duress passcode (twice empty).
boot 1234 1234 "" ""
# First boot: the first user's name, a passcode (twice), no duress
# passcode (twice empty).
boot tester 1234 1234 "" ""
status=$?
first_ok=0
grep -aq "the owner is in" "${LOG}" && grep -aq "SMPTEST PASS" "${LOG}" && first_ok=1
echo "test-qemu: first boot: passcode set up: $([ ${first_ok} -eq 1 ] && echo ok || echo FAIL)"
# Second boot: the keystore remembers; a wrong guess, then the passcode.
boot 9999 1234
grep -aq "init: tester is in" "${LOG}" && grep -aq "SMPTEST PASS" "${LOG}" && first_ok=1
echo "test-qemu: first boot: first user set up: $([ ${first_ok} -eq 1 ] && echo ok || echo FAIL)"
# Second boot: the keystore remembers; a wrong guess, then the passcode,
# then on past the menu.
boot tester 9999 tester 1234 ""
[ ${status} -eq 0 ] && status=$?
second_ok=0
grep -aq "the owner is in" "${LOG}" && grep -aq "from the last boot reads back: ok" "${LOG}" && second_ok=1
echo "test-qemu: second boot: wrong passcode refused, right one unlocks, sealed file kept: $([ ${second_ok} -eq 1 ] && echo ok || echo FAIL)"
grep -aq "init: tester is in" "${LOG}" && grep -aq "from the last boot reads back: ok" "${LOG}" && second_ok=1
echo "test-qemu: second boot: wrong passcode refused, right one signs in, sealed file kept: $([ ${second_ok} -eq 1 ] && echo ok || echo FAIL)"
rm -f "${KEYS}" "${MON}"
grep -a "smptest:\|spawntest:\|Hello\|SMPTEST" "${LOG}"
@@ -62,10 +64,18 @@ if command -v e2fsck >/dev/null && command -v debugfs >/dev/null; then
echo "test-qemu: e2fsck rejects the disk:"; cat "${LOG}.fsck"; disk_ok=0
elif [ "$(debugfs -R 'cat /selftest.txt' "${IMAGE}" 2>/dev/null)" != "written by k-os on ext4" ]; then
echo "test-qemu: /selftest.txt is not on the disk"; disk_ok=0
elif debugfs -R 'cat /home/readme.txt' "${IMAGE}" 2>/dev/null | grep -aq "Welcome"; then
echo "test-qemu: /home/readme.txt is plaintext on the disk"; disk_ok=0
elif ! debugfs -R 'cat /home/readme.txt' "${IMAGE}" 2>/dev/null | head -c 8 | grep -aq "KOSFILE1"; then
echo "test-qemu: /home/readme.txt is not a sealed file"; disk_ok=0
fi
# The one user's folder: users/<16 hex digits>.
user="$(debugfs -R 'ls /users' "${IMAGE}" 2>/dev/null | grep -aoE '[0-9a-f]{16}' | head -1)"
readme="/users/${user}/home/readme.txt"
if [ "${disk_ok}" -eq 0 ]; then
:
elif [ -z "${user}" ]; then
echo "test-qemu: no user's folder on the disk"; disk_ok=0
elif debugfs -R "cat ${readme}" "${IMAGE}" 2>/dev/null | grep -aq "Welcome"; then
echo "test-qemu: ${readme} is plaintext on the disk"; disk_ok=0
elif ! debugfs -R "cat ${readme}" "${IMAGE}" 2>/dev/null | head -c 8 | grep -aq "KOSFILE1"; then
echo "test-qemu: ${readme} is not a sealed file"; disk_ok=0
else
echo "test-qemu: e2fsck clean, file on disk, home sealed"
fi