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:
@@ -14,16 +14,18 @@ use libkos::syscall;
|
||||
use types::bounded::CapSlot;
|
||||
use types::budget::Limits;
|
||||
|
||||
/// Where init put them (see init's manifest: `uses`, the spawn endpoint,
|
||||
/// then control).
|
||||
/// Where init put them (see init's manifest: `uses`, storage (the disk,
|
||||
/// the user's home), the spawn endpoint, then control).
|
||||
const PERMISSION: CapSlot = CapSlot::const_new(0);
|
||||
const STORAGE: CapSlot = CapSlot::const_new(1);
|
||||
const INIT: CapSlot = CapSlot::const_new(2);
|
||||
const CONTROL: CapSlot = CapSlot::const_new(3);
|
||||
const HOME: CapSlot = CapSlot::const_new(2);
|
||||
const INIT: CapSlot = CapSlot::const_new(3);
|
||||
const CONTROL: CapSlot = CapSlot::const_new(4);
|
||||
/// Where storage's buffers are mapped: the whole disk's, a narrowed one's.
|
||||
const STORAGE_BUF_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x0180_0000);
|
||||
const NARROW_BUF_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x0190_0000);
|
||||
const REQUEST_PAGE_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x01C0_0000);
|
||||
const HOME_BUF_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x01B0_0000);
|
||||
/// Read back from the disk image by scripts/test-qemu.sh.
|
||||
const NOTE: &[u8] = b"written by k-os on ext4\n";
|
||||
|
||||
@@ -125,9 +127,9 @@ fn revoke_stops_a_running_app(died: CapSlot) -> Result<(), &'static str> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The owner's area is sealed: seeded from the factory, and what is
|
||||
/// written there one boot reads back the next.
|
||||
fn encrypted_home(fs: &mut Storage) -> Result<(), &'static str> {
|
||||
/// The user's home is sealed: seeded from the factory, and what is written
|
||||
/// there one boot reads back the next. Theirs is the only folder that opens.
|
||||
fn encrypted_home(fs: &mut Storage, home_fs: &mut Storage) -> Result<(), &'static str> {
|
||||
let mut home = [0u8; 512];
|
||||
let mut factory = [0u8; 512];
|
||||
let read = |fs: &mut Storage, path: &[u8], out: &mut [u8]| -> Result<usize, &'static str> {
|
||||
@@ -136,7 +138,7 @@ fn encrypted_home(fs: &mut Storage) -> Result<(), &'static str> {
|
||||
let _ = fs.close(h);
|
||||
Ok(n)
|
||||
};
|
||||
let n = read(fs, b"home/readme.txt", &mut home)?;
|
||||
let n = read(home_fs, b"readme.txt", &mut home)?;
|
||||
let m = read(fs, b"factory/home/readme.txt", &mut factory)?;
|
||||
if home[..n] != factory[..m] {
|
||||
return Err("the encrypted home does not hold the factory's readme");
|
||||
@@ -144,19 +146,29 @@ fn encrypted_home(fs: &mut Storage) -> Result<(), &'static str> {
|
||||
libkos::println!("spawntest: home seeded from the factory, reads back through its seal: ok");
|
||||
const NOTE: &[u8] = b"sealed across a reboot";
|
||||
let mut back = [0u8; 64];
|
||||
match read(fs, b"home/persist.txt", &mut back) {
|
||||
match read(home_fs, b"persist.txt", &mut back) {
|
||||
Ok(n) if &back[..n] == NOTE => libkos::println!("spawntest: an encrypted file from the last boot reads back: ok"),
|
||||
Ok(_) => return Err("an encrypted file from the last boot reads back wrong"),
|
||||
Err(_) => {
|
||||
let h = fs.create(b"home/persist.txt").map_err(|_| "cannot create in home")?;
|
||||
let wrote = fs.write(h, NOTE) == Ok(NOTE.len());
|
||||
let _ = fs.close(h);
|
||||
let h = home_fs.create(b"persist.txt").map_err(|_| "cannot create in home")?;
|
||||
let wrote = home_fs.write(h, NOTE) == Ok(NOTE.len());
|
||||
let _ = home_fs.close(h);
|
||||
if !wrote {
|
||||
return Err("cannot write in home");
|
||||
}
|
||||
libkos::println!("spawntest: wrote an encrypted file for the next boot");
|
||||
}
|
||||
}
|
||||
// A made-up user's: nobody may reach it, the whole disk's holder neither.
|
||||
if fs.create(b"users/0123456789abcdef/home/planted").is_ok() || fs.mkdir(b"users/0123456789abcdef").is_ok() {
|
||||
return Err("someone else's folder could be written");
|
||||
}
|
||||
let mut folders = 0;
|
||||
fs.list_dir(b"users", |e| folders += usize::from(e.name() != b"." && e.name() != b"..")).map_err(|_| "cannot list the users")?;
|
||||
if folders != 1 {
|
||||
return Err("not exactly one user's folder");
|
||||
}
|
||||
libkos::println!("spawntest: only the signed-in user's folder opens: ok");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -164,7 +176,8 @@ fn check() -> Result<(), &'static str> {
|
||||
let mut fs = Storage::attach(STORAGE, STORAGE_BUF_VA).map_err(|_| "cannot attach to storage")?;
|
||||
write_a_file(&mut fs)?;
|
||||
libkos::println!("spawntest: a file written to ext4 reads back: ok");
|
||||
encrypted_home(&mut fs)?;
|
||||
let mut home = Storage::attach(HOME, HOME_BUF_VA).map_err(|_| "cannot attach to home")?;
|
||||
encrypted_home(&mut fs, &mut home)?;
|
||||
|
||||
let died = syscall::create_notification().map_err(|_| "no notification")?;
|
||||
narrow_storage(&mut fs, died)?;
|
||||
|
||||
Reference in New Issue
Block a user