============================================================ DF-0055 — kernel panic signatures (dfbsd-qemu/boot.log excerpts) 3/3 deterministic reproductions; two distinct-but-same-root-cause panics. Both originate in udev_dev_read -> udev_event_externalize, the exact function/lines cited in the finding (kern_udev.c:566/571). ============================================================ ============================================================ RUN 1 — double-free detected by malloc layer ============================================================ panic: memory chunk 0xfffff80067b36860 is already free! cpuid = 1 Trace beginning at frame 0xfffff800ab6ec448 chunk_mark_free() at chunk_mark_free+0xae 0xffffffff806554ce chunk_mark_free() at chunk_mark_free+0xae 0xffffffff806554ce _kfree() at _kfree+0x262 0xffffffff806577f2 _prop_dictionary_free() at _prop_dictionary_free+0xe0 0xffffffff809dc290 prop_object_release() at prop_object_release+0xfd 0xffffffff809e0ebd udev_dev_read() at udev_dev_read+0x14f 0xffffffff806636df Debugger("panic") CPU1 stopping CPUs: 0x00000001 stopped Stopped at Debugger+0x7c: movb $0,0xbd77f9(%rip) db> Interpretation: Reader 1's udev_event_externalize() freed the shared ev->ev.ev_dict (line 571). Reader 2's udev_event_externalize() re-derived the same dangling pointer, prop_object_release() drove the stale refcount to 0, _prop_dictionary_free() -> _kfree() tried to free an already-free chunk; chunk_mark_free() caught the double-free and panicked. ============================================================ RUN 2 — refcount underflow caught by proplib assertion ============================================================ panic: assertion "ocnt != 0" failed in prop_object_release at /usr/src/sys/libprop/prop_object.c:1085 cpuid = 1 Trace beginning at frame 0xfffff800ab9a74c8 prop_object_release() at prop_object_release+0x277 0xffffffff809e1037 prop_object_release() at prop_object_release+0x277 0xffffffff809e1037 udev_dev_read() at udev_dev_read+0x162 0xffffffff806636f2 dev_dread() at dev_dread+0xa3 0xffffffff8062c383 devfs_fo_read() at devfs_fo_read+0x100 0xffffffff80921930 kern_preadv() at kern_preadv()+0x1e5 0xffffffff806a6aa5 Debugger("panic") CPU1 stopping CPUs: 0x00000001 stopped Stopped at Debugger+0x7c: movb $0,0xbd77f9(%rip) db> Interpretation: Same UAF; the dangling ev_dict's stale refcount (after reader 1's free + reader 2's retain-on-garbage) underflowed to 0xffffffff on reader 2's release; the _PROP_ASSERT(ocnt != 0) guard at prop_object.c:1085 fired. The two prop_object_release frames = the temp `dict` releasing its "evdict" child (the dangling ev_dict). ============================================================ RUN 3 — identical to RUN 2 (cpuid = 0 this time) ============================================================ panic: assertion "ocnt != 0" failed in prop_object_release at /usr/src/sys/libprop/prop_object.c:1085 cpuid = 0 Trace beginning at frame 0xfffff800aba354c8 prop_object_release() at prop_object_release+0x277 0xffffffff809e1037 prop_object_release() at prop_object_release+0x277 0xffffffff809e1037 udev_dev_read() at udev_dev_read+0x162 0xffffffff806636f2 dev_dread() at dev_dread+0xa3 0xffffffff8062c383 devfs_fo_read() at devfs_fo_read+0x100 0xffffffff80921930 kern_preadv() at kern_preadv()+0x1e5 0xffffffff806a6aa5 Debugger("panic") CPU0 stopping CPUs: 0x00000002 stopped Stopped at Debugger+0x7c: movb $0,0xbd77f9(%rip) db> ============================================================ NOTE: panic happens after only the FIRST create/destroy cycle's event reaches the second reader; the trigger is deterministic, not a tight race. (udev_lk serializes the two reads; reader 2's marker is guaranteed to still precede the event because reader 1 cannot advance reader 2's marker.) ============================================================