No struct iicbus_ivar is ever allocated for children (DF-5559's root-cause file): with DF-5559's accessor fix applied, iicbus_write_ivar returns success while silently discarding every address write
Summary
Children are created bare (ivars NULL), no child_detached exists: even WITH the DF-5559 accessor fix every write_ivar returns 0 while dropping the value (write 0x42 -> read 0x0 forever) - the official interface can never store a child address. Provider-side re-proof on stock (ENXIO, value untouched) plus the silent-drop demonstration on the DF-5559-fixed module; ivar-alloc + child_detached fix (bundled with DF-5632) round-trips 0x42. Also removes the dead DEVTOIICBUS macro casting to a nonexistent struct.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5634 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 3.0 KB | β raw | |
| VERDICT.md | β | 1.4 KB | β raw | |
| verdict.json | β | 3.3 KB | view raw | |
| manifest.json | β | 782 B | view raw | |
| fix.diff | β | 5.5 KB | view raw | |
| run_b_5559.log | β | 936 B | view raw | |
| build.log | β | 30.8 KB | view raw | |
| env.txt | β | 354 B | view raw |
DF-5634 β children are created with no struct iicbus_ivar ever allocated (the DF-5559 root): iicbus_write_ivar returns success while discarding every address write
- File under audit:
sys/bus/iicbus/iicbus.c(pass 2) β root-cause file of DF-5559, whose validated fix patched only the accessor half - Class: incomplete plumbing / silent data loss (hardening completion)
- Severity: Info (no memory-safety consequence by itself; the uninitialized-read consequence was DF-5559)
- Verdict: REPRODUCED (stock: ENXIO + untouched value; with DF-5559's fix: write returns 0 but the value is silently dropped), fix validated
The defect
struct iicbus_ivar (iicbus.h:44-47) exists and the generated accessor
iicbus_get_addr() (iicbus.h:53-56, __BUS_ACCESSOR) routes through
BUS_READ_IVAR/BUS_WRITE_IVAR, but nothing in iicbus.c ever:
- allocates an ivar for a child β
iicbus_attach(:144-146) andiicbus_add_child(:164-171) create children bare (make_deviceleavesdev->ivars = NULL, subr_bus.c); - implements
bus_read_ivar/bus_write_ivar(absent fromiicbus_methods,:59-73) β the uninitialized-stack half, filed and fixed as DF-5559; - frees ivars (
bus_child_detachedabsent).
This is the "longer term allocate iicbus_ivar for children in
bus_add_child per FreeBSD" item from the 2026-10-07 task_log lead. Even
with DF-5559's validated fix (read/write_ivar added, NULL-tolerant),
every child still has ivar == NULL, so:
case IICBUS_IVAR_ADDR:
if (ivar != NULL) /* never true */
ivar->addr = (uint32_t)value;
return (0); /* success -- value discarded */
β iicbus_write_ivar reports success while dropping the write, so no code
path can ever set an iicbus child address through the official interface
(there is no in-tree writer today; the hazard is for the same future
consumers DF-5559 flagged, and the accessor contract itself).
Reproduction (guest)
- Stock (
run_a2.log):BUS_WRITE_IVAR(iicbus0, child, IICBUS_IVAR_ADDR, 0x42)β error 6 (ENXIO);BUS_READ_IVARβ error 6 with the result variable untouched at 0x42424242 β nobody behind the method (DF-5559's uninit class, re-proven from the provider side). - iicbus.ko + DF-5559 fix (
run_b_5559.log):WRITE_IVAR(0x42) error=0(success!) butREAD_IVAR val=0x0β the write was silently discarded;iicbus_get_addr() == 0forever. - Fixed (
run_d_fixed.log): withfix.diffallocating ivars in the correctedbus_add_child(and freeing them in the newbus_child_detached):WRITE error=0,READ val=0x42,iicbus_get_addr=0x42β the round trip works.
Fix
fix.diff (shared with DF-5632): iicbus_add_child allocates a
zeroed struct iicbus_ivar and device_set_ivars(child, ivar);
iicbus_child_detached frees it; the DF-5559 accessors now have a live
ivar to serve. Also removes the dead DEVTOIICBUS macro (iicbus.c:44)
that still casts to the nonexistent struct iicbus_device.
DF-5634 VERDICT β REPRODUCED (silent ivar write drop; the DF-5559 root), fix validated
See README.md for the full narrative. Summary of the decisive evidence:
- Stock (
../DF-5632/run_a2.log):IVAR_RT: WRITE_IVAR(0x42) error=6,READ_IVAR error=6 val=0x42424242β ENXIO, result untouched (the DF-5559 uninitialized class, seen from the provider side). - iicbus.ko + DF-5559's own validated fix (
run_b_5559.log):WRITE_IVAR(0x42) error=0thenREAD_IVAR error=0 val=0x0 iicbus_get_addr=0x0β the write reports success and is silently discarded, because no child ever has an ivar allocated (iicbus.c:144-146, :164-171 create children bare;make_deviceleavesdev->ivars = NULL). - Fixed (
../DF-5632/run_d_fixed.log):dfctl ivar: v1=0x42 v2=0x42β write/read/accessor round trip works with fix.diff's allocation in the correctedbus_add_child+bus_child_detachedfree.
Impact: none by itself (hardening completion of the accessor contract); the memory-safety consequence of the missing read side was DF-5559.
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
fixedWith iicbus.ko rebuilt from fix.diff, the ivar round trip works on a production child: WRITE_IVAR(0x42) error=0, READ_IVAR val=0x42, iicbus_get_addr=0x42 -- the silent drop is gone and the accessor contract functions.
../DF-5632/run_d_fixed.log ('dfctl ivar: kernel rc=0 v0=0x0 v1=0x42 v2=0x42'); ../DF-5632/run_d_fixed_dmesg.txt ('[df5632] IVAR_RT: READ_IVAR error=0 val=0x42 iicbus_get_addr=0x42')
Confirmed kernel references
Detail
Evidence (decisive lines)
run_b_5559.log + dmesg witness ('[df5632] IVAR_RT: WRITE_IVAR(0x42) error=0' then 'READ_IVAR error=0 val=0x0 iicbus_get_addr=0x0' -- silent drop with the DF-5559 fix loaded); stock witness in ../DF-5632/run_a2.log ('IVAR_RT: WRITE error=6', READ 'val=0x42424242' untouched); fixed witness in ../DF-5632/run_d_fixed.log ('dfctl ivar: v1=0x42 v2=0x42')
PoC changes
IVAR_RT ioctl in the ../DF-5632 rig drives production BUS_WRITE_IVAR/BUS_READ_IVAR/iicbus_get_addr on a real iicbus child; baseline uses iicbus.ko rebuilt with DF-5559's own validated fix.diff to isolate the silent-drop delta.
Verified recommended fix
Allocate a zeroed struct iicbus_ivar in iicbus_add_child (device_set_ivars) and free it in a bus_child_detached method; keep the DF-5559 read/write_ivar accessors (fix.diff).
Verdict
REPRODUCED: iicbus children are created with no struct iicbus_ivar ever allocated and no bus_child_detached to free one (iicbus.c:144-146,164-171 -- the DF-5559 root-cause file). Stock: BUS_WRITE/READ_IVAR -> ENXIO with the result variable untouched (the DF-5559 uninit class seen from the provider side). Even with DF-5559's validated accessor fix applied, every child still has ivar==NULL, so iicbus_write_ivar returns success while discarding the value (write 0x42 -> read 0x0, forever): the official interface can never store a child address. fix.diff allocates ivars in the corrected bus_add_child and frees them in a new bus_child_detached; fixed module round-trips 0x42.
No comments yet.