⬢ DragonFlyBSD Kernel Audit
DF-3485 / disasm.stock.txt
← back to finding ↓ download raw
SHIPPED /boot/kernel/ng_iface.ko (built from the tree's ng_iface.c, stock flags)
objdump -dr --disassemble=ng_iface_constructor -- the inlined ng_iface_get_unit()
array-extension path.  Relocations prove the callee identity.

 588:	e8 00 00 00 00       	callq  58d        # reloc 0x589: _kmalloc   (newarray)
 58d:	48 85 c0             	test   %rax,%rax
 590:	0f 84 ac 00 00 00    	je     642        # ENOMEM path
 596:	4c 63 15 00 00 00 00 	movslq 0x0(%rip),%r10   # reloc: .bss-4  = ng_iface_units_len
 59d:	4c 8b 0d 00 00 00 00 	mov    0x0(%rip),%r9    # reloc: .bss+4  = ng_iface_units
 5a4:	48 89 c7             	mov    %rax,%rdi          # rdi = newarray
 5af:	4c 89 ce             	mov    %r9,%rsi           # src = ng_iface_units
 5b6:	4c 89 da             	mov    %r11,%rdx          # len
 5c5:	e8 00 00 00 00       	callq  5ca                # reloc 0x5c6: memmove (bcopy)
 5e0:	7e 2d                	jle    60f                # fill loop skipped/...
 600:	c7 02 ff ff ff ff    	movl   $0xffffffff,(%rdx) # newarray[i] = ~0
 60a:	48 39 d0             	cmp    %rdx,%rax
 60d:	75 f1                	jne    600
 60f:	48 c7 c6 00 00 00 00 	mov    $0x0,%rsi          # reloc 0x612: M_NETGRAPH
 616:	4c 89 cf             	mov    %r9,%rdi           # *** rdi = ng_iface_units ***
 61d:	e8 00 00 00 00       	callq  622                # reloc 0x61e: _kfree
                                                                     ^ return addr = +0x3a2 = the panic frame

>>> THERE IS NO NULL TEST between the load at 59d and the call at 61d.
>>> The source-level guard `if (ng_iface_units != NULL)` (ng_iface.c:294)
>>> does not exist in the binary.  First call has ng_iface_units == NULL
>>> => kfree(NULL) => panic("trying to free NULL pointer")
>>> (sys/kern/kern_slaballoc.c:1406-1407).

Why GCC may drop the guard is documented in-tree: sys/sys/systm.h:257-260

    /* ... the following ...
     *       assumes that (to) and (from) cannot be NULL (even when (len) might
     *       be 0), and will optimize-out later NULL tests on (to) or (from).
     */
    #define bcopy(from, to, len) __builtin_memmove(...)

bcopy(ng_iface_units, ...) at ng_iface.c:290 makes GCC treat
ng_iface_units as provably non-NULL afterwards, so the test at :294 is
dead code.  Rebuilding the module from the unmodified tree reproduces the
identical unguarded pattern (verified 2026-09-13), i.e. this is the
current tree's compiled behavior, not a stale binary.