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:
@@ -12,35 +12,45 @@ pub enum Device {
|
||||
}
|
||||
|
||||
/// A storage grant: a folder (or the whole disk, `b""`) and whether it may
|
||||
/// be changed.
|
||||
/// be changed. With `user`, the path is inside the signed-in user's folder.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Scope {
|
||||
pub path: &'static [u8],
|
||||
pub write: bool,
|
||||
pub user: bool,
|
||||
}
|
||||
|
||||
const fn disk(path: &'static [u8], write: bool) -> Scope {
|
||||
Scope { path, write, user: false }
|
||||
}
|
||||
|
||||
const fn users(path: &'static [u8], write: bool) -> Scope {
|
||||
Scope { path, write, user: true }
|
||||
}
|
||||
|
||||
pub struct Program {
|
||||
pub name: &'static str,
|
||||
pub file: &'static [u8],
|
||||
pub limits: Limits,
|
||||
/// Its stack, in pages.
|
||||
pub stack_pages: usize,
|
||||
/// Serves an endpoint, which it finds in slot 0.
|
||||
pub serves: bool,
|
||||
/// Handed over in this order, after it starts.
|
||||
pub devices: &'static [Device],
|
||||
/// Authenticates the owner: init waits for the master key before
|
||||
/// starting anything that touches user data.
|
||||
pub unlocks: bool,
|
||||
/// Earlier programs' endpoints it may call, in its next slots; each
|
||||
/// program's copy carries its own badge, so a server can tell them apart.
|
||||
pub uses: &'static [&'static str],
|
||||
/// Storage it may reach, in the slot after `uses`.
|
||||
pub storage: Option<Scope>,
|
||||
/// Storage it may reach, in the slots after `uses`.
|
||||
pub storage: &'static [Scope],
|
||||
/// Takes the console over from init; everyone else prints through it.
|
||||
pub console: bool,
|
||||
/// May have init spawn programs, whose limits together stay within this.
|
||||
pub spawns: Option<Limits>,
|
||||
/// May halt the machine.
|
||||
pub system_control: bool,
|
||||
/// May sign the user out (`types::spawn::SIGN_OUT`), in the last slot.
|
||||
pub signs_out: bool,
|
||||
}
|
||||
|
||||
/// Enough for a small program: its image, stack and a little heap.
|
||||
@@ -56,14 +66,15 @@ const fn server(name: &'static str, file: &'static [u8], limits: Limits) -> Prog
|
||||
name,
|
||||
file,
|
||||
limits,
|
||||
stack_pages: crate::load::STACK_PAGES,
|
||||
serves: true,
|
||||
devices: &[],
|
||||
unlocks: false,
|
||||
uses: &[],
|
||||
storage: None,
|
||||
storage: &[],
|
||||
console: false,
|
||||
spawns: None,
|
||||
system_control: false,
|
||||
signs_out: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,46 +91,52 @@ pub const SERVERS: &[Program] = &[
|
||||
},
|
||||
// Text on the display, lines from the keyboard (it takes input focus).
|
||||
Program { uses: &["display"], ..server("terminal", b"bin/terminal", SMALL) },
|
||||
// Nothing that touches user data starts before the owner is in. It
|
||||
// holds the screen (through the terminal), its keystore and randomness,
|
||||
// and exits once it has handed over the key.
|
||||
Program {
|
||||
uses: &["terminal"],
|
||||
devices: &[Device::Keystore, Device::Random],
|
||||
unlocks: true,
|
||||
// argon2's 16 MiB, its image and a little more.
|
||||
..server("gatekeeper", b"bin/gatekeeper", Limits { pages: 4096 + 160, regions: 6, ..SMALL })
|
||||
},
|
||||
// The only one that equips apps (docs/apps.md): it reaches every app's
|
||||
// files and the owner's decisions, and runs apps through init.
|
||||
Program {
|
||||
uses: &["terminal", "display"],
|
||||
storage: Some(Scope { path: b"", write: true }),
|
||||
// Room for a few apps at a time.
|
||||
spawns: Some(Limits { pages: 512, endpoints: 8, notifications: 8, regions: 8 }),
|
||||
..server("permission", b"bin/permission", Limits { pages: 96, ..SMALL })
|
||||
},
|
||||
server("session", b"bin/session", SMALL),
|
||||
];
|
||||
|
||||
/// Started for each sign-in, before anything that touches a user's files.
|
||||
/// It holds the screen (through the terminal), its keystore and randomness,
|
||||
/// and exits once it has handed over who is in and their key.
|
||||
pub const GATEKEEPER: Program = Program {
|
||||
uses: &["terminal"],
|
||||
devices: &[Device::Keystore, Device::Random],
|
||||
// A user's record is KiBs, and it handles a few at once.
|
||||
stack_pages: 12,
|
||||
// argon2's 16 MiB, its image and a little more.
|
||||
..server("gatekeeper", b"bin/gatekeeper", Limits { pages: 4096 + 160, regions: 6, ..SMALL })
|
||||
};
|
||||
|
||||
/// Started for each signed-in user, and stopped when they sign out. The
|
||||
/// permission manager is the only one that equips apps (docs/apps.md): it
|
||||
/// reaches the user's apps, their data and decisions, and the system's apps
|
||||
/// (read-only), and runs apps through init.
|
||||
pub const SESSION: &[Program] = &[Program {
|
||||
uses: &["terminal", "display"],
|
||||
storage: &[users(b"", true), disk(b"apps", false)],
|
||||
// Room for a few apps at a time.
|
||||
spawns: Some(Limits { pages: 512, endpoints: 8, notifications: 8, regions: 8 }),
|
||||
..server("permission", b"bin/permission", Limits { pages: 96, ..SMALL })
|
||||
}];
|
||||
|
||||
/// Run on the test image after the SMP self-test, instead of the desktop:
|
||||
/// spawns through init, then reports and halts.
|
||||
pub const TESTS: &[Program] = &[Program {
|
||||
serves: false,
|
||||
// The permission manager, to run an app the way the shell does.
|
||||
uses: &["permission"],
|
||||
storage: Some(Scope { path: b"", write: true }),
|
||||
storage: &[disk(b"", true), users(b"home", true)],
|
||||
spawns: Some(Limits { pages: 128, endpoints: 2, notifications: 2, regions: 2 }),
|
||||
system_control: true,
|
||||
..server("spawntest", b"bin/spawntest", SMALL)
|
||||
}];
|
||||
|
||||
/// The desktop; the test image runs the SMP self-test instead. The shell
|
||||
/// holds the owner's files and asks the permission manager to run apps;
|
||||
/// it holds nothing to give them beyond that.
|
||||
/// holds the user's files and asks the permission manager to run apps;
|
||||
/// it holds nothing to give them beyond that, and may sign the user out.
|
||||
pub const DESKTOP: &[Program] = &[Program {
|
||||
serves: false,
|
||||
uses: &["terminal", "permission"],
|
||||
storage: Some(Scope { path: b"home", write: true }),
|
||||
storage: &[users(b"home", true)],
|
||||
signs_out: true,
|
||||
..server("shell", b"bin/shell", SMALL)
|
||||
}];
|
||||
|
||||
Reference in New Issue
Block a user