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:
49
docs/ipc.md
49
docs/ipc.md
@@ -91,22 +91,37 @@ and budget listed there. Storage, started before the log server, receives
|
||||
its log endpoint from init later (`SET_LOG`, accepted only from the
|
||||
unbadged holder of its endpoint).
|
||||
|
||||
Nothing that touches user data starts before the owner is authenticated.
|
||||
Nothing that touches a user's files starts before someone has signed in.
|
||||
Init starts the log, input, display and terminal servers, then the
|
||||
gatekeeper (`types::gatekeeper`), handing it only the terminal, the keystore
|
||||
(a small disk of its own, told from the data disk by its size) and the
|
||||
virtio-rng device. Init calls `UNLOCK`, which returns once the owner is in,
|
||||
then `KEY`, whose reply is the master key; init passes it to storage
|
||||
(`SET_KEY`, from the unbadged holder only, each half once), and a fresh
|
||||
32-byte seed (`SEED` → `SET_SEED`) for storage's randomness this boot.
|
||||
Storage's encrypted areas (`home/`, `system/`, each app's `data/<id>/`;
|
||||
crate `filecrypt`, layer `storage_server::encrypted`) open once both are
|
||||
in. With a new key (a fresh device, or one just wiped: `UNLOCK`'s word 1)
|
||||
init empties those areas and seeds them from the plaintext `factory/`;
|
||||
an area that is missing is seeded too. Only then does init start the
|
||||
permission manager and the desktop. If the gatekeeper cannot
|
||||
unlock, init stops there. The gatekeeper exits, and its capabilities go
|
||||
with it.
|
||||
virtio-rng device. Init calls `UNLOCK`, which returns once someone is in:
|
||||
`[OK, flags, user id, role]`, a guest (`GUEST`) or a new keystore
|
||||
(`FRESH`) among the flags. Then `KEY` (their master key), `SEED` (32 fresh
|
||||
random bytes for storage this sign-in), `NAME`, and `REMOVED` until `DONE`
|
||||
(users the owner removed just now). The gatekeeper exits.
|
||||
|
||||
Each user's files are in `users/<id>/` (`types::user`: the id in hex, or
|
||||
`guest`): `home/`, `permissions/`, and per app `apps/<id>/` and
|
||||
`data/<id>/`, each sealed under its own key derived from that user's
|
||||
master key (crate `filecrypt`, layer `storage_server::encrypted`); the rest
|
||||
of the disk is plaintext. While storage is still locked, init removes what
|
||||
must go (`PURGE`, init only, only in `users/`, only while locked): every
|
||||
user's folder on a new keystore, a removed user's, the last guest's. Then
|
||||
it tells storage who is in (`SET_USER`) and hands over the key and seed
|
||||
(`SET_KEY`, `SET_SEED`, a half per call, each once a sign-in; init only).
|
||||
Only the signed-in user's folder opens; anyone else's is refused. Init
|
||||
seeds whatever area of theirs is missing from the plaintext `factory/`,
|
||||
then starts the session: the permission manager (the user's folder, and
|
||||
`apps/` read-only) and the desktop. If the gatekeeper cannot unlock, init
|
||||
stops there.
|
||||
|
||||
Signing out (`types::spawn::SIGN_OUT`, sent one way through the copy of
|
||||
init's endpoint the shell holds) stops everything the session ran (the
|
||||
shell, the permission manager, every app), tells the terminal
|
||||
(`SIGNED_OUT`, init only), locks storage (`LOCK`, init only: every grant
|
||||
taken back, every file closed, the key forgotten), removes a guest's
|
||||
files, and runs the gatekeeper again.
|
||||
|
||||
A program's `uses` endpoints arrive as badged copies with `Execute` and
|
||||
`Delegate`: the badge (unique per copy) tells the server which client is
|
||||
@@ -135,12 +150,12 @@ log endpoint is the terminal prints there with `println!`: standard output
|
||||
is whatever text endpoint a program was given. `READ` (`types::terminal`)
|
||||
blocks until a line is typed and returns it in chunks, the last ending in
|
||||
`\n`. Ctrl+C there drops the line. Keys typed while no line is read are
|
||||
kept for the next one, except Ctrl+C, which signals the notification its
|
||||
first `ON_INTERRUPT` caller gave. `REDRAW` repaints the screen and takes
|
||||
kept for the next one, except Ctrl+C, which signals the notification the
|
||||
session's first `ON_INTERRUPT` caller (its shell) gave. `REDRAW` repaints the screen and takes
|
||||
input focus back.
|
||||
|
||||
The desktop is the shell, given the terminal, the permission manager and
|
||||
`/home` (its `/`). Everything the owner runs is an app (docs/apps.md): a
|
||||
The desktop is the shell, given the terminal, the permission manager,
|
||||
the user's `home/` (its `/`) and signing out. Everything the owner runs is an app (docs/apps.md): a
|
||||
command that is not a built-in asks the permission manager (`types::apps`,
|
||||
client `libkos::apps`) to run it, passing the terminal as its output and a
|
||||
read-only grant to the current folder (`cd`, `pwd`). The permission manager
|
||||
|
||||
Reference in New Issue
Block a user