Repository navigation
Each laptop claim in the guide has a check behind it, or is named as waiting for hardware - #485
Merged
Merged
Conversation
…or, in the zone that holds it ADR-025 hands a zone a descriptor on the partition the user gave it, and needs a reader there that parses the filesystem on that descriptor: mtools, exfat-fuse and ntfs-3g take paths, and reopening a block device by path is refused to the zone. tools/stick is that reader, a crate of its own, since kryptikd keeps to libc alone (ADR-010). It is fatfs 0.3.6, without chrono, behind kryptik-stick: no arguments says what the zone was given, then list [DIR], get PATH [DEST], put FILE [DIR]. The descriptor comes from the zone's broker (`stick`, answered `ok ro|rw WHAT` with SCM_RIGHTS), or --device FILE for an image. A read-only grant refuses every write whatever fatfs asks. Nothing on either side is written over. Names from the stick reach the terminal with control characters as `?`, and reach a path only as one component. A tree nested past 32 directories is refused. A put is synced to the device before it is reported. FAT's dates come from the zone's clock as UTC, held to 1980-2107. CI tests it and builds it for musl. The Distro workflow builds it beside kryptikd, held to the same path check, and stage 04 installs it (KRYPTIK_STICK_BIN, the stick step). The licence texts of fatfs, bitflags, byteorder and log are in build/licences, and check-rust-licences.sh reads its lock.
The stick reader parses a FAT filesystem in the zone, but nothing in zone 0 could hand it a stick: the design (removable-storage.md) has kryptikd make a device-mapper linear mapping of the one partition the user picks and pass it to the zone through its broker, never mounting it. stick.rs decides which block devices may be given (a partition of a USB disk or SD card, or such a disk with no partition table; held by nothing, mounted nowhere, not on a disk the system's own mappings use), makes the mapping read-only unless the user chose to write, records the grant under /run/kryptik-stick, and on eject wipes the mapping's table so every read and write on a descriptor the zone kept fails, then removes it once the last closes. A zone file says `[storage] removable = false` to take no stick; the vault's does, and the net zone never takes one. The broker answers `stick` with the zone's descriptor and `ok ro|rw WHAT`; the launch daemon has `sticks`, `stick-grant ZONE PART ro|rw` and `stick-eject ZONE` for the chrome, and `info` says what a zone holds; root has `kryptikd stick list|grant|eject`. A zone's stick goes back when the zone stops. Checked with unit tests on a stand-in /sys of the kernel's shape (a USB partition named with its vendor, model, size and GPT name; a stick with no partition table; an SD card; an NVMe disk refused; a held, mounted or system-disk partition refused; bad names), the grant record round trip, the mapping lookup, the zone key, and the broker parse.
…s suite plugs one in A stick plugged in now opens a window of the chrome naming each partition by what sysfs says of it; a letter and a zone's number give it to that zone to read, or with w to write too, and e with the number takes it back. The menu's d opens the same window, and its zone lines say which zone holds a stick. kryptik-launch gains --sticks, --stick-grant and --stick-eject for it. Eject now writes out what the zone left unsynced, then wipes the mapping's table and drops what was cached of the stick: a wiped table alone left the pages the zone had read readable through a descriptor it kept. A stick pulled out without eject loses its grant the next time the sticks are listed, which the chrome does whenever a block device comes or goes, and a grant is refused while a program in the zone still holds the mapping of a stick taken back from it. zones-test.sh plugs a FAT stick into the running guest through QMP (vm-drive.py's plug: and unplug: steps, run-ovmf.sh --usb-port) and runs guest-tests/stick-check.sh between the plugs: zone 0 mounts and probes nothing; vault and the net zone are refused; untrusted, given it read-only, lists it and copies a file off whole, cannot write, and has no node for it; another zone asking is refused; eject frees the partition at once and a descriptor the zone kept reads only EIO; what the zone puts with a write grant is on the image the host reads after pulling it out; a program holding the stick when it is pulled out reads EIO and the grant ends with no oops; and the install medium plugged in offers its ESP, which the reader lists, and its root, which the reader refuses. chrome-sticks.sh checks the window and the watcher against a stand-in launcher, and vm-drive.py's test the plug steps against a stand-in QMP socket.
If lvm2's rules ship, 13-dm-disk.rules runs blkid on every device-mapper device as it appears or changes, so a grant would have zone 0 parse the stick's superblock as root through kryptik-stick-ZONE, which 59-kryptik-removable.rules keeps eudev from doing on the partition itself. 12-kryptik-stick.rules sets device-mapper's disable flags for those mappings, by their sysfs name and by the name 10-dm.rules imports. stick-check.sh's new round, after the grant: eudev holds no ID_FS_ property for the mapping or the partition.
A video call in a zone had the microphone and no camera: the kernel built no video support. ADR-026 grants the camera as the microphone is granted. The kernel builds Video4Linux and uvcvideo as modules, filtered to cameras and test drivers, with no camera button input device; modprobe.d/camera.conf keeps uvcvideo from loading by alias, and stage 05 checks both. vivid is built as a module for the zones suite to stand in for a camera, without its framebuffer; the hardening checker's finding on it is accepted, with why. kryptikd's camera.rs: a zone that may hold the camera (a new [camera] use key; vault's file says no, and the net zone never does) gets at start a directory of its own from a tmpfs that allows device nodes, bound at /run/kryptik/camera without nodev, /dev/video0 linking into it, and a Landlock rule for it. A grant loads uvcvideo, binds again what an earlier grant's end let go of, finds the first capture node in sysfs and makes it there, owned by the zone's root, mode 0600. Its end, by the user, the zone's stop or the screen lock, removes the node, unbinds the driver from the device so a kept descriptor fails, and unloads uvcvideo unless something still holds it, which the chrome then says. The launch daemon has camera-grant and camera-revoke, kryptik-launch --camera-grant and --camera-revoke, root kryptikd camera grant|revoke| status. The chrome's menu has k<N> and k and a Camera line, a window says which zone holds the camera for as long as it does, and kryptik-lock takes the camera back as the screen locks. Checked: camera.rs unit tests on a stand-in sysfs (the first capture node, not a metadata one, numbered as numbers, its name shown plainly; the device and bus to let go of; the record round trip), the zone key, and chrome-camera.sh against a stand-in launcher. zones-test step 2c runs guest-tests/camera-check.sh with vivid: no load by alias, no camera before a grant, vault and net refused, the grant's node and a captured frame, the zone's stop ending it, another zone finding none, k alone failing a kept descriptor and unloading uvcvideo, a grant to a running zone. gui-check's lock round: the screen locking takes it back.
A mapping ejected while its zone still held the stick is removed by device-mapper once the zone's last descriptor closes, from a workqueue, so the eject kryptikd runs at the zone's stop can find it and then lose it between two dmsetup calls, and logged that as a failure. Eject now treats a mapping that is gone as done, says whether a grant ended rather than whether a mapping was there, and still clears a mapping left without a grant. stick-check.sh's rounds that look for the mapping to be gone wait up to ten seconds for that removal instead of looking once.
The chrome opens its camera window within a second or two of a grant, and a window that maps takes the keyboard: granted after the round's zone 0 window had it, the camera window could take it before the lock did, which the round would read as the lock's doing. Granted first, and waited for, the window is under the round's own.
A directory tree nested one level past MAX_DEPTH stops the copy off the stick with the limit named, where a stick built to loop would otherwise recurse until the zone's stack or disk ran out.
Every walk of the stick's directories, path lookup included, now goes through one loop that stops with "the stick's filesystem is malformed" past FAT's 65,536 entries in a directory, or past as many entries or bytes as the volume has room for in one command. fatfs follows a cluster chain that loops, so a directory could be endless (list grew its list until the zone's memory ran out), and directories aliasing an ancestor multiplied under get, past what the depth limit stops, until the zone's disk was full. put looks for the name within the same bounds before fatfs walks the directory to add to it. A name holding a control character is no file name here: FAT allows none, and the errors that name a path here carried it to the terminal. Errors show paths as names are shown, and the marks that turn text around show as '?' too. The stick's row in stage 04 sits above kryptikd's comment, which is kryptikd's.
… as kryptikd is Stage 06's strict audit flags every static Rust binary for both, and lists kryptikd and the proxy by name; kryptik-stick is built the same way.
…suspend suite's fixes
…wn aliases kmod's modprobe skips a blacklisted module's own aliases with or without -b, so a dry run by the alias names nothing either way and could not show the alias belongs to uvcvideo; modinfo reads it from the module.
…he camera A zone holding the microphone or the camera has a window of the chrome's that says so, but a window the user puts in full screen covers it, and only dwl's bar above that window stays in sight: a zone could take a grant, wait for full screen, and record with nothing on screen saying so. The bar now reads, after the zone's name, "mic ZONE" and "cam ZONE" for whichever zones hold them, on every fullscreen window, not only the holder's. dwl learns them from two files through one inotify descriptor on its event loop, and draws every fullscreen bar again on a change: the camera's grant record, which kryptikd writes as root, and the microphone's holder, which the mixer now writes into its own control directory (uid 87, 0640, group kryptik) at its start and on every grant and revoke. dwl takes a file only if it is a regular file of its writer's that no one else may write, and a name only if it is a zone dwl knows; anything else marks nothing. kryptikd's launch daemon mounts the camera's tmpfs as it starts, so the compositor's watch is on it and not on the directory beneath. gui-test, with vivid as the camera: untrusted fullscreen, granted the camera and recorded as the microphone's holder, its bar reads "untrusted mic untrusted cam untrusted" pixel for pixel; both taken back, and a record of the microphone's holder put in place by root rather than the mixer, the bar names the zone alone. The sound suite checks the mixer's record on the grant and once the zone's stop has ended it.
…a directory made anew drops An inotify watch belongs to the directory's inode: the mixer's control directory made again, or anything mounted over a watched directory, ends the watch, and every later grant went unmarked until dwl restarted. dwl now also reads both records once a second, draws the fullscreen bars again only when a holder changed, and sets both watches again each time, which keeps a watch that is there as it is. The gui round makes the mixer's directory anew before the records are written, so the marks it checks come through a directory dwl did not first watch, and puts the mixer's own back after.
…Bluetooth and input methods, and the laptop bullet rewritten
…ooth and input methods, and the laptop bullet rewritten
…awake, and the desktop suite checks it
…, and the desktop suite checks it
… and the desktop suite checks it
…, and the desktop suite checks it # Conflicts: # docs/status.md
…ke, and the desktop suite checks it # Conflicts: # docs/status.md
…ore lock-0's window opens, and the desktop suite is named beside the zones suite as loading vivid
…out round lists the sticks only once the kernel has let the stick's partition go
…deo0, as no other is granted the camera; the camera suite is named in the image's program list
…ard, so untrusted's fullscreen has ended for Alt+e to give back
…xy, so stage 04 installs it
… card pulled out, so a moved microphone and a pulled USB card no longer leave a loop spinning
…hes, a zone's sched and ioprio calls refused, proxy-calls ending at a proxy's exit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The guide's laptop text, read claim by claim against the suites, as the release item asks of the guide.
What was wrong:
vaulthas no socket at the mixer either (the sound suite's mixer-zones round requires exactly that).kryptik suspenditself (the suite only ran kryptik-lock --suspend).What changed:
plug-sound:/unplug-sound:, run-ovmf's new sparesnd2backend, xHCI port): a zone's tone goes to the USB card with the built-in one closed (usb-sound-card, plays-on-usb); pulled out mid-tone, the mixer closes the card and the tone goes on on the built-in card, the mixer not restarting (usb-pull-moves-sound) and the zone playing to its end (usb-pull-zone-plays-on); the host finds that tone (550 Hz) in the first card's WAV. A grant to work moves the microphone from untrusted and ends untrusted's record (microphone-moves); the menu saysuntrusted, RECORDING NOW(chrome-says-recording);ccloses the microphone's window (microphone-window-taken-back).kryptik suspend; the menu's line for work readsWAITING for its passphrase (pN)(menu-says-waiting); after the real sleep, Enter alone where the chrome asks again leaves work waiting, the daemon asked nothing (enter-leaves-zone-waiting; the host presses Enter at GT ZONE-PASS-SKIP whether or not the window came, so the later rounds run).vaultplays nothing; a USB device takes the sound after a few quiet seconds and gives it back at once when pulled; the known-limitations line keeps the exact hardware sentence and adds what QEMU lacks (lid, microphone and brightness keys, backlight, UVC cameras). Status rows name the new checks.How it was checked: bash -n on each changed script; tools/tests/vm-drive.py gains a stand-in QMP case for the new steps (CI; this laptop's Python has no AF_UNIX). The suites run in the stack's Distro proof; until then the new rounds are unproven.