From 4c1de194bcc7bbf766e18993c6d02cf8806ebf50 Mon Sep 17 00:00:00 2001 From: DevomB Date: Thu, 8 Oct 2026 19:04:24 -0700 Subject: [PATCH 1/2] The compositor configuration's, the zone-border patch's and the chrome's comments are shorter, with their reasons kept: cleanup-held's cut of dwl-config.h, dwl-zone-borders.py, kryptik-chrome and docs/architecture.md, redone on main by hand, comments only Only comment regions are taken from 65a6fbb, and the patch script's edit comments lose their numbers, all eight. Main's text stays where the cut drops a reason the chrome and compositor rely on: the border colour comes from the app_id prefix only the proxy stamps; passphrases reach the daemon as a descriptor, never argv or the environment; the consent window drops keys because a hostile zone's may be waiting; the watcher's lock goes with its subshell and a second watcher leaves. architecture.md keeps main's fullscreen bar, which the cut predates. --- build/desktop/dwl-config.h | 5 ++-- docs/architecture.md | 14 +++++----- tools/desktop/dwl-zone-borders.py | 19 +++++++------ tools/desktop/kryptik-chrome | 44 +++++++++++-------------------- 4 files changed, 34 insertions(+), 48 deletions(-) diff --git a/build/desktop/dwl-config.h b/build/desktop/dwl-config.h index a1305940..fcf21f0c 100644 --- a/build/desktop/dwl-config.h +++ b/build/desktop/dwl-config.h @@ -85,9 +85,8 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } -/* commands: zone launches, where --ask has the chrome prompt for a passphrase - * if the zone needs one, and the chrome's own menu, a text program that needs - * a zone 0 terminal of its own, as its window at login has */ +/* commands: zone launches (the chrome asks for a passphrase if needed) and the + * chrome's menu, a text program in a zone 0 terminal of its own */ static const char *termcmd[] = { "kryptik-launch", "--ask", "work", "--", "havoc", NULL }; static const char *personalcmd[] = { "kryptik-launch", "--ask", "personal", "--", "havoc", NULL }; static const char *untrustedcmd[] = { "kryptik-launch", "--ask", "untrusted", "--", "havoc", "lynx", NULL }; diff --git a/docs/architecture.md b/docs/architecture.md index 68856569..0803d563 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -19,8 +19,8 @@ A zone is the unit of isolation, and every process belongs to exactly one. The trusted base, like Qubes' `dom0`: PID 1, the services, kryptikd, the compositor and the desktop session. It has no route out and runs no user applications (ADR-003), which the desktop suite checks process by process. -kryptikd creates the other zones as root; unprivileged -user namespaces are off ([privileged launch](design/privileged-launch.md)). +kryptikd creates the other zones as root; unprivileged user namespaces are +off ([privileged launch](design/privileged-launch.md)). ### Shipped zones @@ -52,11 +52,11 @@ The chrome's menu is its menu window. ## Between zones -Nothing crosses by default. The broker in kryptikd identifies a caller by its -socket's peer uid and carries two things ([broker](design/broker.md)): a file -transfer, one file one way to a zone the sender's policy names, after the user -approves it; and the clipboard, one per zone, moved between zones only by a -user gesture in zone 0. +Nothing crosses by default. The [broker](design/broker.md) in kryptikd +identifies a caller by its socket's peer uid and carries two things. A file +transfer sends one file, one way, to a zone listed in the sender's policy, +once the user approves it. Each zone has one clipboard, moved to another zone +only by a user gesture in zone 0. Routed zones reach the network through isolated ports on the `net` zone's bridge. The `net` zone can also send zone 0 a clock offset and releases, both diff --git a/tools/desktop/dwl-zone-borders.py b/tools/desktop/dwl-zone-borders.py index ea5de94c..4083f25e 100755 --- a/tools/desktop/dwl-zone-borders.py +++ b/tools/desktop/dwl-zone-borders.py @@ -105,7 +105,7 @@ """ EDITS = [ - # (1) Client: the zone's colour, the band that marks it unfocused, the bar. + # Client: the zone's colour, the band that marks it unfocused, the bar. (""" struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ """, """ struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ @@ -114,7 +114,7 @@ struct wlr_scene_rect *bands[4]; /* top, bottom, left, right */ struct wlr_scene_tree *bar; /* Kryptik: names the zone above a fullscreen window */ """), - # (2) The ZoneColor type, beside Rule so config.h can define the table. + # The ZoneColor type, beside Rule so config.h can define the table. ("""typedef struct { const char *id; const char *title; @@ -136,7 +136,7 @@ const float border[4]; } ZoneColor; """), - # (3) The chooser, defined before applyrules (its first neighbour). + # The chooser, placed before applyrules. ("""void applyrules(Client *c) { @@ -173,7 +173,7 @@ applyrules(Client *c) { """), - # (4) mapnotify: zone-coloured borders, then the band over them as four + # mapnotify: zone-coloured borders, then the band over them as four # strips. The surface stays below both, or a buffer larger than its # configure would paint over the right and bottom borders. A new window # starts unfocused, so the band starts enabled; the bar starts hidden. @@ -197,7 +197,7 @@ c->bar = wlr_scene_tree_create(c->scene); wlr_scene_node_set_enabled(&c->bar->node, 0); """), - # (5) resize: the band is the ring of the border nearest the surface. + # resize: the band is the ring of the border nearest the surface. (""" wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); """, """ wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw); @@ -210,7 +210,7 @@ wlr_scene_node_set_position(&c->bands[2]->node, c->bw - bandpx, c->bw); wlr_scene_node_set_position(&c->bands[3]->node, c->geom.width - c->bw, c->bw); """), - # (6) focusclient: the colour is the zone's either way; focus hides the band. + # focusclient: the colour is the zone's either way; focus hides the band. (""" if (!exclusive_focus && !seat->drag) client_set_border_color(c, focuscolor); """, @@ -220,7 +220,7 @@ wlr_scene_node_set_enabled(&c->band->node, 0); } """), - # (7) focusclient, the window losing focus: its band comes back. + # focusclient, the window losing focus: its band comes back. (""" } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { client_set_border_color(old_c, bordercolor); """, @@ -228,7 +228,7 @@ client_set_border_color(old_c, old_c->zoneborder); wlr_scene_node_set_enabled(&old_c->band->node, 1); """), - # (8) setfullscreen: keep the border; dwl's 0 would let a window hide its zone. + # setfullscreen: keep the border; dwl's 0 would let a window hide its zone. (""" c->bw = fullscreen ? 0 : borderpx; client_set_fullscreen(c, fullscreen); """, @@ -464,8 +464,7 @@ \t\t\treturn c; \t} """), - # setmon also chooses focus after mapping; preserve another zone's actual - # keyboard focus even when the selected monitor has changed. + # setmon also picks focus after mapping: keep another zone's keyboard focus across monitors. ("""\t\tsetfloating(c, c->isfloating); \t} \tfocusclient(focustop(selmon), 1); diff --git a/tools/desktop/kryptik-chrome b/tools/desktop/kryptik-chrome index f582fbf8..5bd44b42 100755 --- a/tools/desktop/kryptik-chrome +++ b/tools/desktop/kryptik-chrome @@ -21,24 +21,20 @@ # window, then launch (kryptik-launch hands # over here when it has no terminal) # kryptik-chrome --focus print the focused zone, from the record -# kryptik-chrome --confirm ID ask the broker's question ID in a trusted -# window and write back the answer: yes only +# kryptik-chrome --confirm ID ask the broker's question ID in a trusted window: yes only # for the code it shows, typed after it shows # # Passphrases are read by kryptik-launch on the chrome's own terminal and go # to the daemon as a descriptor, never in argv or the environment. -# The verified root's zone files, not /etc's: /etc is an overlay the state -# partition can shadow, and the labels shown must match the colours dwl draws. +# The verified root's zone files, which dwl's colours match: the state partition can shadow /etc. ZONES=/usr/lib/kryptik/zones LAUNCH=/usr/bin/kryptik-launch -# `havoc [option...] [program [args...]]`: no -e, and an unknown option makes -# it print its usage and exit. +# havoc takes the program as plain arguments: it has no -e, and exits on an unknown option. TERMINAL=/usr/bin/havoc RT="${XDG_RUNTIME_DIR:-/tmp}" FOCUS="$RT/kryptik/focus" -# The last window from a zone. The menu shows this one: opening the menu -# focuses the menu, so the plain record would only ever name zone 0. +# The last zone window, for the menu: once the menu has focus, the focus record names zone 0. FOCUS_ZONE="$RT/kryptik/focus.zone" CONSENT=/run/kryptik-consent @@ -99,17 +95,14 @@ run_status() { mkdir -p "$RT/kryptik" 2>/dev/null # The menu window, so a fresh session shows something usable. "$TERMINAL" /usr/bin/kryptik-chrome --menu & - # The consent watcher: one trusted window per question the broker leaves. - # Holding watcher.lock exclusively tells the broker someone is here to ask - # (consent.rs refuses at once if it can take the lock shared); the kernel - # drops it when this subshell dies. Confirm windows must not inherit it, - # and a second session's watcher exits quietly. + # The consent watcher. Holding watcher.lock tells the broker someone is here + # to ask (consent.rs refuses at once otherwise); the kernel drops it with this + # subshell, and a second session's watcher exits quietly. ( exec 9> "$CONSENT/watcher.lock" 2>/dev/null || exit 0 flock -n 9 || exit 0 - # From here a write creates, never follows or clobbers: any member of - # group kryptik can plant a link in the directory. That also makes the - # .dialog claim one exclusive create. + # Writes create, never follow or clobber: group kryptik can plant links here. + # That also makes each .dialog claim one exclusive create. set -C while :; do for ask in "$CONSENT"/*.ask; do @@ -117,10 +110,10 @@ run_status() { id="${ask##*/}"; id="${id%.ask}" [ -e "$CONSENT/$id.dialog" ] && continue : > "$CONSENT/$id.dialog" 2>/dev/null || continue + # A window must not hold the lock past the watcher's death. "$TERMINAL" /usr/bin/kryptik-chrome --confirm "$id" 9>&- & done - # A window writes its code and answer even for a question - # withdrawn meanwhile; whatever outlives its question goes. + # A window may write its code and answer after its question is withdrawn. for f in "$CONSENT"/*.dialog "$CONSENT"/*.code "$CONSENT"/*.answer; do [ -e "$f" ] || continue [ -e "${f%.*}.ask" ] || rm -f "$f" @@ -206,8 +199,7 @@ run_menu() { b) set -- "$TERMINAL" /usr/bin/lynx ;; esac echo "launching in zone $z: $*" - # --ask: a passphrase is read on this zone 0 terminal, - # never on a zone's. + # --ask: a passphrase is read on this zone 0 terminal, never a zone's. "$LAUNCH" --ask "$z" -- "$@" || sleep 3 ;; *) echo "?"; sleep 1 ;; @@ -236,8 +228,7 @@ run_confirm() { # ID # A question with no kind is a transfer. kind="$(sed -n 's/^kind=//p' "$ask")" if [ "$kind" = clock ]; then - # The clock (docs/design/time.md): the network's time is too far from - # this machine's to accept unasked. Only the user, with a watch, can say. + # The network's time is too far from this machine's to accept unasked (docs/design/time.md). now="$(sed -n 's/^now=//p' "$ask")"; proposed="$(sed -n 's/^proposed=//p' "$ask")" sources="$(sed -n 's/^sources=//p' "$ask")" echo "================ KRYPTIK - set the clock? (zone 0) ================" @@ -274,14 +265,11 @@ run_confirm() { # ID [ "$(cat | wc -c)" -eq 0 ] || echo "(what was typed before this question showed is ignored)" stty "$was" fi - # The answer is a code drawn for this question alone: no zone sees this - # window, so none can type it. It is kept beside the question for zone 0's - # tests; whatever can read this directory could write the answer anyway. - # Writes here create, never follow or clobber: any member of group kryptik - # can plant a link in the directory. An answer that cannot be written is - # no answer, which the broker takes as a refusal. + # Writes create, never follow or clobber: any member of group kryptik can plant a link. set -C + # A code for this question alone: no zone sees this window, so none can type it. code=$(( $(od -An -N1 -tu1 /dev/urandom) % 90 + 10 )) + # Kept for zone 0's tests; whatever can read it could write the answer anyway. (umask 077; printf '%s\n' "$code" > "$CONSENT/$id.code") 2>/dev/null \ || echo "kryptik-chrome --confirm $id: the code could not be written beside the question" >> "$RT/kryptik/session.log" printf 'Type %s and Enter to allow; anything else refuses: ' "$code" From f5715596b9bdfc77e68869eab0d7e7c228186e15 Mon Sep 17 00:00:00 2001 From: DevomB Date: Thu, 8 Oct 2026 19:06:43 -0700 Subject: [PATCH 2/2] The chrome keeps how the broker tests for the consent watcher and why an answer that cannot be written is safe From a non-author read: the cut lost that consent.rs refuses at once if it can take watcher.lock shared, and that an unwritten answer is a refusal. --- tools/desktop/kryptik-chrome | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/desktop/kryptik-chrome b/tools/desktop/kryptik-chrome index 5bd44b42..7a3650f6 100755 --- a/tools/desktop/kryptik-chrome +++ b/tools/desktop/kryptik-chrome @@ -96,8 +96,9 @@ run_status() { # The menu window, so a fresh session shows something usable. "$TERMINAL" /usr/bin/kryptik-chrome --menu & # The consent watcher. Holding watcher.lock tells the broker someone is here - # to ask (consent.rs refuses at once otherwise); the kernel drops it with this - # subshell, and a second session's watcher exits quietly. + # to ask: consent.rs refuses at once if it can take the lock shared. The + # kernel drops it with this subshell, and a second session's watcher exits + # quietly. ( exec 9> "$CONSENT/watcher.lock" 2>/dev/null || exit 0 flock -n 9 || exit 0 @@ -277,6 +278,7 @@ run_confirm() { # ID if read -r reply; then [ "$reply" = "$code" ] && answer=yes fi + # An answer that cannot be written is none: the broker takes that as a refusal. if printf '%s\n' "$answer" > "$CONSENT/$id.answer.tmp" && mv -f "$CONSENT/$id.answer.tmp" "$CONSENT/$id.answer"; then echo "-> $answer" else