← Blog
0.6.0 · kernel seams

Multi-User Identity, Cap<AudioSession>, and hw-probe: sigil-os#13/#14/#17

June 22, 2026 · sigil-os · Sigil-Docs
kernel security audio identity 0.6.0

Three sigil-os capability seams land in one push: identity.sg closes multi-user authentication (16-slot user table, 16-slot session table, ID_ELEV_TOKEN sudo-equivalent, POSIX rwx check); audiosess.sg delivers Cap<AudioSession> (8 PCM sessions, 44100 Hz stereo, AU_MIC_TOKEN consent gate); hwprobe.sg adds hardware enumeration (HP_NET_TOKEN consent-gated profile submission). All three follow the same broker-held sentinel pattern. QEMU raspi3b PASS. (sigil-os f6930de, 8187fff, dca32c8)


The pattern: broker-held sentinels

All three seams share the same trust contract. A capability token is broker-held — EL0 cannot forge it, cannot read it, cannot guess it. The kernel injects it at the capability boundary. The result is always binary: wrong token returns -1 with no side effects. Right token proceeds.

Three different capabilities. One security contract. The pattern is the point.


identity.sg — sigil-os#13

Commit f6930de. Multi-user authentication with POSIX-style access control.

User table

16 slots × 64 bytes at address 0xA50000. Per-slot fields: uid, gid, home_off, flags, elev_cap. id_user_init() pre-installs two users at boot:

Session table

16 slots × 64 bytes at 0xA51000. Per-slot fields: sess_uid, sess_gid, pid, state, cap_token. id_sess_alloc(uid, pid) binds a pid to a session slot. Every session operation requires a pid match — wrong pid returns -1.

id_elevate() — sudo-equivalent

id_elevate(slot, pid, elev_token) grants uid=0 in the session. The caller must present ID_ELEV_TOKEN (0x494C4F55). The broker holds it; EL0 cannot forge it. Wrong token or wrong pid → -1.

id_access() — POSIX rwx check

id_access(mode, fuid, fgid, uid, gid) evaluates POSIX rwx bits:

identitytest.sg: 17 assertions covering init / alloc / verify / uid / gid, dual-session uniqueness, elevation with wrong + correct token, access checks for owner / other / root, close lifecycle, and invalid-uid guard. QEMU raspi3b PASS (74,200,160).


audiosess.sg — sigil-os#14: Cap<AudioSession>

Commit 8187fff. Eight concurrent PCM audio sessions with mic consent gating.

Format and layout

16-bit stereo 44100 Hz (4 bytes per frame). 8 session slots at 0xA30000 (64-byte header each). Per-slot ring: 4,096 frames (16 KB). Output ring: 2,048 frames (8 KB). Int32 accumulator scratch for mix sum.

Session lifecycle

au_alloc(pid)
Finds a free slot, sets owner pid, initializes volume to 256 (unity gain).
au_write(slot,pid,buf,frames)
Cap check (pid match), then ring fill with advance. Wrong pid → -1.
au_mic_grant(slot,pid,token)
Consent gate — token must equal AU_MIC_TOKEN() (runtime sentinel, broker-held). Wrong pid or wrong token → -1, no mic state change.
au_mix_tick()
Drains up to 512 frames from every ACTIVE session. Sums with per-session L/R volume scaling (0–256), clamps to int16, writes to output ring, calls au_hal_write loopback. Real HAL driver replaces the loopback at kernel integration — no code change needed.
au_close(slot,pid)
Releases slot. Subsequent writes return -1 immediately.

audiosesstest.sg: 8 assertions — alloc / pid / vol, dual-session uniqueness, ring write + read-back, pid auth rejection, mic wrong + correct token. QEMU raspi3b PASS (74,200,160).


hwprobe.sg — sigil-os#17: Hardware Enumeration Profile

Commit dca32c8. Consent-gated hardware profiling with content-addressed submission.

What it reads

Five kernel HW-detect loopback stubs supply the hardware profile fields:

These assemble into a flat key=value profile, one field per line. Real kernel HW-detect syscalls bind at integration — no code change in hwprobe.sg.

Consent gate

Content-addressed profile submission is gated behind HP_NET_TOKEN (0x484E5342). Wrong or absent token → -1 without touching the network. The same token guards DNS, TCP, and UDP in the network seam.

hwprobetest.sg: 11 assertions — per-syscall field / length checks, profile record structure (first line = "cpu_isa=AArch64-v8.0\n" verified byte by byte), consent gate (wrong token → -1, correct → 0). QEMU raspi3b PASS (74,200,160).


Capability sentinel table

All four broker-held sentinel tokens currently defined in sigilOS:

TokenHexGuards
HID_CAP_TOKEN 0x48494421 ("HID!") Keyboard/mouse delivery to WM
HP_NET_TOKEN 0x484E5342 DNS, TCP, UDP, hw-probe submit
AU_MIC_TOKEN runtime sentinel Microphone consent gate
ID_ELEV_TOKEN 0x494C4F55 Privilege elevation (sudo-equiv)

Every sentinel follows the same rule: the broker holds it, EL0 cannot observe it, and the wrong value always returns -1 with no side effects. The table grows as new capabilities are defined — each new seam adds one row.