$radix/$maxoff/$maxwidth FCN_NULL writes accept any 64-bit value unvalidated β silent semantic corruption of the DDB expression language and symbol attribution (beyond DF-5724)
Summary
The FCN_NULL fast path stores any value: $radix=3 makes db_lex parse in base 3 while silently accepting invalid digits (print/d 19 -> 12; even later set literals misparse), $maxoff=-1 casts to ULONG_MAX inverting the symbol-attribution threshold (db_active+0x2000000 misattributed to xhci_devclass+0x1a4a620, 27MiB off). Live-reproduced on stock across 5 boots; no crash primitive (comparison/multiply-only consumers); DF-5724's fix validates tabstops/maxwidth but leaves radix/maxoff. validating-setter fix (radix in {8,10,16}, maxoff >= 0).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5730 Β· 17 files| File | Type | Description | Size | |
|---|---|---|---|---|
| session-live.log | β | 1.0 KB | view raw | |
| session2-live.log | β | 539 B | view raw | |
| session5-control.log | β | 157 B | view raw | |
| serial.radix-session.raw | β | 591 B | β download | |
| serial.maxoff-session.raw | β | 293 B | β download | |
| serial.control-reboot.raw | β | 13.3 KB | β download | |
| drive.py | β | 4.5 KB | view raw | |
| drive2.py | β | 2.4 KB | view raw | |
| drive3.py | β | 1.2 KB | view raw | |
| run.sh | β | 201 B | view raw | |
| run2.sh | β | 909 B | view raw | |
| run3-control.sh | β | 912 B | view raw | |
| run4-control.sh | β | 1.2 KB | view raw | |
| run5-control.sh | β | 908 B | view raw | |
| serial_vm.sh | β | 1.7 KB | view raw | |
| fix.diff | β | 2.0 KB | view raw | |
| env.txt | β | 400 B | view raw |
Fix verification
not_testableNo rebuild performed: Info-severity semantic finding with no memory-safety behavior to observe post-patch; the setter pattern itself (same file, same shape) was build- and run-validated on this guest by DF-5724's fix validation (findings/poc/DF-5724/serial.fixedkernel.log, build.log). fix.diff applies cleanly to pristine sys/ddb/db_variables.c (git apply --check).
fix.diff; DF-5724 pack's serial.fixedkernel.log + build.log (pattern proof)
Confirmed kernel references
Detail
Evidence (decisive lines)
session-live.log (radix: 10->3, 19->12, $maxwidth stores -20; restoration via 0x/0t); session2-live.log (maxoff: xhci_devclass+0x1a4a620 vs raw form, restored); serial.control-reboot.raw line 203 'reboot by root' at exactly the scheduled minute after DDB continue (liveness control); zero 'Fatal trap|panic' in all session logs
PoC changes
Authored fresh (no seed): five-boot rig β boot1 radix/maxwidth double-corruption, boot2 maxoff attribution direction, boots 3-5 liveness controls (session-bound markers proved unreliable: csh SIGHUP; decisive control is the init-parented 'shutdown -r +1' firing on time post-continue)
Verified recommended fix
Validating db_varfcn_t setters: $radix accepts only 8/10/16, $maxoff >= 0 (db_error longjmps before the store) β mirrors DF-5724's validated setter pattern
Verdict
Reproduced live on the stock kernel via the socket-serial DDB rig: db_write_variable's FCN_NULL fast path (sys/ddb/db_variables.c:120-129) accepts any 64-bit value for $radix/$maxoff/$maxwidth with zero validation (table db_variables.c:48-53). set $radix=3 silently corrupts the debugger's own expression language β db_lex.c:190-205 parses every subsequent literal in base 3 and accepts digits invalid for the base (print/d 19 -> 12, digit 9 in base 3; print/d 10 -> 3), and the corruption feeds back into later stores (set $maxwidth=-55 stores -20 because '55' parsed base-3); recovery needs forced 0x/0t prefixes. set $maxoff=-1 casts to ULONG_MAX and inverts the symbol-attribution threshold (db_sym.c:289): print/a db_active+0x2000000 flips from raw -0x7c858478 to xhci_devclass+0x1a4a620, misattributing a 27MiB-distant address to an unrelated symbol. NO memory-safety primitive exists for these three variables β every consumer is comparison-only or multiply-only (db_output.c:221, db_sym.c:289, db_print.c:56, db_lex.c:170-216) β and the FCN_NULL register writes are type-safe (register_t slots in a __packed trapframe, frame.h:55-84). Zero Fatal traps across all five boots; a shutdown scheduled before DDB entry fired exactly on time after continue, proving kernel/userspace healthy post-c. Info: defense-in-depth completing DF-5724's setter fix (which covers $tabstops/$maxwidth but leaves $radix/$maxoff FCN_NULL).
No comments yet.