DDB 'b addr,count' silently truncates the skip count (radix-16 lexer + int struct fields) β breakpoint armed but can never fire, garbage negative Count displayed
Summary
Three unchecked conversions (radix-16 lexer, unvalidated db_expr_t, int fields) with an exact-zero stop comparison: 'b ticks,4294967296' yields Count -1802079594 - a silently dead tripwire with zero diagnostics while listed as armed (the DF-5721 dead-instrument class via a distinct root cause). Live-proven on stock; range-check fix validated.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5726 Β· 13 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.8 KB | β raw | |
| VERDICT.md | β | 2.3 KB | β raw | |
| serial_vm1.sh | β | 1.8 KB | view raw | |
| drive_ddb.py | β | 2.2 KB | view raw | |
| enter_ddb.sh | β | 867 B | view raw | |
| run.sh | β | 218 B | view raw | |
| session1-smp.serial.log | β | 14.5 KB | view raw | |
| baseline-up.serial.log | β | 29.3 KB | view raw | |
| env.txt | β | 350 B | view raw | |
| fix.diff | β | 601 B | view raw | |
| fix_build.log | β | 5.7 MB | β download | |
| fix_run.log | β | 15.2 KB | view raw | |
| verdict.json | β | 2.8 KB | view raw |
DF-5726 β DDB b addr,count silently truncates the skip count to a garbage/negative int β breakpoint never fires, no diagnostic
Severity: Low (DDB console is root-gated; operational "silent disarm" defect, same instrument-is-dead class as DF-5721).
What breaks
The break addr[,count] skip count travels through three unchecked
conversions, none of which validates:
db_lex.c:203βdb_tok_number = db_tok_number * r + digitwith default radix 16 (db_lex.c:119), so a decimal-looking literal like4294967296is parsed as hex0x4294967296;db_break.c:271-278βdb_breakpoint_cmd()maps only the literal-1to 1 and passes any otherdb_expr_t(long) straight through;db_break.c:106-107βinit_count/countareintfields (db_break.h:52-53):0x4294967296truncates to0x94967296= -1802079594.
A stop then requires --bkpt->count == 0 exactly (db_run.c:100), reachable
only from count==1; a zero or negative count therefore never fires β the
breakpoint is silently dead while show breaks still lists it as armed.
Live proof (stock kernel)
baseline-up.serial.log (UP) / session1-smp.serial.log (SMP):
db> b ticks,4294967296 db> b bootverbose,2 db> show breaks Map Count Address *ffffffff8159eea0 2 bootverbose *ffffffff8159eea0 -1802079594 ticks <-- garbage negative skip count
Fix
Validate in db_breakpoint_cmd() β see fix.diff (count < 1 || count >
INT_MAX β db_error). Validated on the patched kernel: b ticks,4294967296
now errors with "skip count out of range" and adds nothing; b ticks,2 still
works.
Reproduce
./serial_vm1.sh up && ./enter_ddb.sh DF5725_SOCK=/tmp/opencode/df-5725-ser-up.sock ./drive_ddb.py \ "b ticks,4294967296" 2 "b bootverbose,2" 2 "show breaks" 3 "d ticks" 2 "d bootverbose" 2 "c" 8
DF-5726 β VERDICT
reproduced β impact: none (silent-disarm correctness defect; no memory
unsafety). The documented break addr[,count] skip count is mangled by
unchecked conversions and the breakpoint silently never fires while show
breaks lists it as armed with a garbage count.
Environment
Same rig as DF-5725 (stock X86_64_GENERIC, UP, socket-serial DDB; guest
/sys/ddb/db_break.c MD5 = audited tree). Observed on both the SMP and UP
instances (identical).
Observation (exact)
db> b ticks,4294967296 db> b bootverbose,2 db> show breaks Map Count Address *ffffffff8159eea0 2 bootverbose *ffffffff8159eea0 -1802079594 ticks
4294967296 (decimal intent) parsed with DDB's default radix 16
(sys/ddb/db_lex.c:119, accumulation at db_lex.c:203) as 0x4294967296,
passed as db_expr_t (long) through db_breakpoint_cmd()
(sys/ddb/db_break.c:271-278, only the literal -1 is remapped), then stored
into the int fields init_count/count (db_break.c:106-107,
sys/ddb/db_break.h:52-53): 0x4294967296 β 0x94967296 = -1802079594.
A stop requires --bkpt->count == 0 exactly (sys/ddb/db_run.c:100), i.e.
the pre-decrement count must be 1. A zero or negative count never reaches it:
the breakpoint is dead while listed as armed β the same
dead-instrument/DF-5721 operational class, and every value β₯ 2^31 silently
produces one.
Why it matters
An incident-response operator who writes b kafka_probe,4294967296 (a
deliberate "skip 4G hits" style count) arms nothing, with zero diagnostics.
Fix validation
fix.diff (db_break.c): count < 1 || count > INT_MAX β db_error. On the
combined-fix kernel (fix_run.log):
db> b ticks,4294967296 breakpoint: skip count out of range db> show breaks ... only the other breakpoints; nothing added ... db> b ticks,2 (still accepted, Count 2)
Baseline reproduced / patched behavior gone β fixed.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
fixedStock kernel: garbage negative Count displayed, bp armed-never-fires. Patched kernel: db_error 'breakpoint: skip count out of range', breakpoint not added, in-range counts (2) unaffected. Bad behavior gone.
findings/poc/DF-5726/fix.diff; fix_run.log ('breakpoint: skip count out of range' + show breaks listing only valid entries); baseline-up.serial.log
Confirmed kernel references
Detail
Evidence (decisive lines)
baseline-up.serial.log / session1-smp.serial.log: 'b ticks,4294967296' + 'b bootverbose,2' -> show breaks prints 'Count -1802079594' for ticks (2 for bootverbose). fix_run.log (patched): 'breakpoint: skip count out of range' error, nothing added; count 2 still accepted.
PoC changes
No seed PoC; uses the DF-5725 pack's serial rig (drive_ddb.py/serial_vm1.sh/enter_ddb.sh).
Verified recommended fix
Reject out-of-range skip counts in db_breakpoint_cmd(): if (count < 1 || count > INT_MAX) db_error(...) (fix.diff).
Verdict
b addr,count stores the skip count through three unchecked conversions (radix-16 lexer accumulation db_lex.c:203, db_expr_t pass-through db_break.c:271-278, int fields db_break.c:106-107): live-proven that 'b ticks,4294967296' arms a breakpoint with Count -1802079594 (0x4294967296 truncated to 0x94967296), and since a stop requires --bkpt->count == 0 exactly (db_run.c:100), zero/negative/truncated counts silently never fire while show breaks lists the breakpoint as armed. Root-gated DDB console -> Low; dead-instrument operational class (DF-5721 family), no memory unsafety.
No comments yet.