β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-1075

Multicast filter buffer allocated before device descriptor is read -> OOB write / kernel panic on interface up

Field Value
ID DF-1075
Status new
Severity Medium
CVSS 3.1 CVSS:3.1/AV:P/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
CWE CWE-131 Incorrect Calculation of Buffer Size (CWE-787 consequence)
File sys/bus/u4b/net/if_kue.c
Lines 488-493 (allocation in kue_attach), 439-440 (descriptor read in kue_attach_post), 381-385 (memcpy in kue_setmulti)
Area bus/u4b/net (Kawasaki LSI KL5KUSB101B USB Ethernet)
Confidence certain
Discovered 2026-07-14
Reported pending
Known CVE none
CVE match dfly_specific

Summary

kue_attach() allocates sc->sc_mcfilters using KUE_MCFILTCNT(sc), but the device descriptor that KUE_MCFILTCNT reads has not been fetched yet at that point (it is only read later in kue_attach_post()). The softc is zero-initialised by newbus, so KUE_MCFILTCNT(sc) is 0, kmalloc(0) returns the sentinel ZERO_LENGTH_PTR = (void *)-8 (kern_slaballoc.c:193, 890), and the NULL check at line 490 passes because (void *)-8 != NULL. Later, a malicious (or even legitimate) USB device reports kue_mcastfilt >= 1 in GET_ETHER_DESCRIPTOR; on the next multicast reconfiguration (which happens automatically when the interface is brought up due to default IPv6 multicast), kue_setmulti() memcpy()s ETHER_ADDR_LEN bytes into &ZERO_LENGTH_PTR[0] = 0xFFFF...FFF8 on x86-64, an unmapped kernel address, causing a page fault and immediate kernel panic. The write target is the fixed ZERO_LENGTH_PTR sentinel, which the attacker cannot redirect, so this is a reliable DoS with no path to code execution.

Root cause

Walkthrough:

  1. kue_attach() (if_kue.c:468) runs first; at line 488 it calls sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, M_USBDEV, M_WAITOK).

  2. KUE_MCFILTCNT is defined in if_kuereg.h:69 as (UGETW((x)->sc_desc.kue_mcastfilt) & 0x7FFF) β€” i.e., it reads a uint16 out of the device descriptor. At this instant sc_desc is whatever newbus left: device softcs are zero-allocated with M_ZERO at subr_bus.c:1953-1954, so kue_mcastfilt = {0, 0}, KUE_MCFILTCNT(sc) = 0, and 0 * ETHER_ADDR_LEN = 0.

  3. DragonFlyBSD's slab allocator returns the sentinel ZERO_LENGTH_PTR for kmalloc(0) (kern_slaballoc.c:888-891, with ZERO_LENGTH_PTR = (void *)-8 at line 193).

  4. The subsequent if (sc->sc_mcfilters == NULL) test at if_kue.c:490 does NOT catch this because (void *)-8 is non-NULL.

  5. kue_attach() then calls uether_ifattach() (line 501), which queues ue_attach_post_task; the post task calls kue_attach_post() (if_kue.c:422-444), which loads firmware, resets the chip, and only THEN reads the descriptor at lines 439-440 via kue_ctl(KUE_CMD_GET_ETHER_DESCRIPTOR, &sc->sc_desc, sizeof(sc->sc_desc)). A malicious device supplies kue_mcastfilt encoding any value N >= 1, so KUE_MCFILTCNT(sc) now returns N. The sc_mcfilters buffer is NEVER reallocated β€” it is still the 0-byte ZERO_LENGTH_PTR.

  6. When kue_setmulti() (if_kue.c:354-398) runs in response to SIOCADDMULTI (queued from uether_ioctl() at usb_ethernet.c:497-504), the loop at lines 373-387 iterates i from 0; for each AF_LINK multicast entry with i < KUE_MCFILTCNT(sc) it executes memcpy(KUE_MCFILT(sc, i), ..., ETHER_ADDR_LEN) (lines 383-385).

  7. KUE_MCFILT(sc, i) expands (if_kuereg.h:70-71) to (char *)&sc->sc_mcfilters[i * ETHER_ADDR_LEN], which for i = 0 is (char *)ZERO_LENGTH_PTR + 0 = (char *)0xFFFFFFFFFFFFFFF8 on x86-64. The first such memcpy writes 6 bytes starting at an unmapped kernel address and the CPU traps with a page fault, immediately panic'ing the kernel.

Because every iteration writes to the fixed sentinel (which is always unmapped), there is no path by which the attacker can land the write on a mapped, attacker-influenced region β€” this caps impact at denial of service.

Note that real KL5KUSB101B hardware reportedly advertises a 128-entry filter (comment at if_kue.c:51), so this bug does not require a malicious device; any genuine kue(4) NIC whose firmware reports a non-zero multicast filter count will panic the host the moment its interface is brought up with IPv6 enabled.

Threat model & preconditions

  • Attacker position: Anyone who can attach a USB device to the target β€” physical plug-in, USB-C charging station, compromised USB hub, or a BadUSB / Rubber-Ducky-class gadget. No kernel privileges and no authentication are needed. The device must merely present one of the ~30 supported (VID, PID) pairs (if_kue.c:104-139, all trivially spoofable via a USB gadget), accept the KUE_CMD_SEND_SCAN firmware-download requests (return success / stall β€” kue_load_fw ignores some failures and kue_attach_post ignores the rest at line 430-433), and respond to KUE_CMD_GET_ETHER_DESCRIPTOR with kue_mcastfilt >= 1.
  • Privileges gained or impact: Complete system crash / reboot (A:H). No confidentiality or integrity impact because the write address is the unredirectable ZERO_LENGTH_PTR sentinel in unmapped KVA.
  • Required config or capabilities: Default kernel with kue. Local ueN interface brought up (often automatic via NetworkManager / dhcpcd / default IPv6).
  • Reachability: Trigger sequence: 1. Plug in malicious kue-identifying USB device. 2. kue driver attaches β†’ kue_attach() (allocates 0-byte buffer) β†’ kue_attach_post() (reads malicious descriptor). 3. Interface is brought up (ifconfig ueN up β€” commonly done automatically). 4. IPv6 stack installs the solicited-node and all-nodes multicast addresses (33:33:00:00:00:01, 33:33:ff:<last3>) β†’ fires SIOCADDMULTI β†’ kue_setmulti() β†’ OOB write β†’ page fault β†’ kernel panic.

Proof of PoC

Two-part PoC.

(A) Malicious USB device side β€” implemented as a Linux USB gadget (Pi Zero W / BeagleBone / any configfs-gadget target) or a Facedancer board.

  • Device descriptor: bcdDevice != 0x0202 (so kue_load_fw doesn't early-return at if_kue.c:305-306) and one of the kue_devs[] VID/PID tuples, e.g. idVendor=0x04cf (KLSI), idProduct=0x0001 (DUH3E10BT).
  • Control endpoint handlers: 1. ACK or accept the three KUE_CMD_SEND_SCAN (0xFF) OUT requests carrying kue_code_seg / kue_fix_seg / kue_trig_seg (size and content do not matter β€” kue_ctl just needs to return success). 2. Respond to the vendor IN request bmRequestType=0xC0 bRequest=0x00 (KUE_CMD_GET_ETHER_DESCRIPTOR) with a 16-byte kue_ether_desc whose bytes [12..13] (kue_mcastfilt) are little-endian >= 1, e.g. 0x20 0x00 (N=32); the remaining bytes can be anything.

(B) Host trigger β€” after the device enumerates and the kue driver attaches:

sudo ifconfig ue0 up
# or just wait for dhcpcd / NetworkManager to do it.

On a DragonFlyBSD host with IPv6 enabled (the default), the in-kernel IPv6 code will immediately add 33:33:00:00:00:01 and 33:33:ff:xx:xx:xx to the interface, triggering SIOCADDMULTI and thus kue_setmulti(). The first memcpy into &ZERO_LENGTH_PTR[0] panics the kernel.

Build & run

# gadget descriptor Python (pyusb/facedancer) runs on the attacker device
python3 kue_evil_gadget.py

# host side: nothing to compile, just bring up the interface
sudo ifconfig ue0 up

Expected output

Fatal trap 12: page fault while in kernel mode
fault virtual address   = 0xFFFFFFFFFFFFFFF8
cpuid = 0
instruction pointer     = 0x<PC inside memcpy>
kue_setmulti(...) at if_kue.c:383
...
panic: from-rights-free

Impact

Reliable kernel panic from a USB plug-in + interface up. The write is to the unredirectable ZERO_LENGTH_PTR sentinel so no code-execution primitive. Medium severity per "physical access + automatic trigger" + "reliable DoS". Affects both malicious and legitimate kue NICs.

Move the sc_mcfilters allocation from kue_attach() (where KUE_MCFILTCNT is 0 because the descriptor has not been read) into kue_attach_post() (where it has just been read), and guard the kfree() in kue_detach() because DragonFlyBSD's kfree(NULL) panics (kern_slaballoc.c:1406-1407) while kfree(ZERO_LENGTH_PTR) is a no-op β€” so removing the early kmalloc(0) leaves sc_mcfilters == NULL on the uether_ifattach-failure path, which must not be freed.

--- a/sys/bus/u4b/net/if_kue.c
+++ b/sys/bus/u4b/net/if_kue.c
@@ -435,6 +435,17 @@ kue_attach_post(struct usb_ether *ue)
    /* read ethernet descriptor */
    kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR,
        0, &sc->sc_desc, sizeof(sc->sc_desc));
+
+   /*
+    * Allocate the multicast filter buffer now that the device has
+    * reported its multicast filter capacity in the descriptor above.
+    * This MUST happen here, not in kue_attach(): at kue_attach() time
+    * the descriptor has not been fetched yet and the zero-initialised
+    * softc would yield KUE_MCFILTCNT(sc)==0, producing a zero-length
+    * allocation that kue_setmulti() would later write past.
+    */
+   sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN,
+       M_USBDEV, M_WAITOK);

    /* copy in ethernet address */
    memcpy(ue->ue_eaddr, sc->sc_desc.kue_macaddr, sizeof(ue->ue_eaddr));
 }
@@ -485,13 +496,6 @@ kue_attach(device_t dev)
        goto detach;
    }

-   sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN,
-       M_USBDEV, M_WAITOK);
-   if (sc->sc_mcfilters == NULL) {
-       device_printf(dev, "failed allocating USB memory\n");
-       goto detach;
-   }
-
    ue->ue_sc = sc;
    ue->ue_dev = dev;
    ue->ue_udev = uaa->device;
@@ -514,12 +518,15 @@ static int
 kue_detach(device_t dev)
 {
    struct kue_softc *sc = device_get_softc(dev);
    struct usb_ether *ue = &sc->sc_ue;

    usbd_transfer_unsetup(sc->sc_xfer, KUE_N_TRANSFER);
    uether_ifdetach(ue);
+
+   /* kfree(NULL) panics on DragonFlyBSD, so guard the free for the
+    * uether_ifattach-failure path where kue_attach_post never ran. */
+   if (sc->sc_mcfilters != NULL)
+       kfree(sc->sc_mcfilters, M_USBDEV);
    lockuninit(&sc->sc_lock);
-   kfree(sc->sc_mcfilters, M_USBDEV);

    return (0);
 }

A defense-in-depth follow-up would also cap KUE_MCFILTCNT (e.g. min(UGETW(...) & 0x7FFF, 128)) so a malicious device cannot force a ~192 KB allocation, and would widen the i * ETHER_ADDR_LEN argument to kue_ctl() / USETW(wLength) so it does not silently truncate when i * 6 > 65535.

References

Timeline

  • 2026-07-14 Discovered during automated audit.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1075 Β· 15 files
FileTypeDescriptionSize
df1075_harness.c trigger-source kernel-module harness replicating the exact buggy kmalloc(0)+memcpy pattern from if_kue.c 3.4 KB view raw
df1075_fixed_pattern.c exploit-chain fixed-pattern harness demonstrating corrected allocation order (no panic) 3.0 KB view raw
Makefile build-script kmod Makefile for buggy harness 190 B ↓ download
Makefile.fixed build-script kmod Makefile for fixed-pattern harness 131 B ↓ download
build.sh build-log build script for both harnesses 439 B view raw
run.sh run-log run script (buggy/fixed modes) 1.4 KB view raw
panic_full.txt panic-signature Fatal trap 12: page fault at 0xFFFFFFFFFFFFFFF8 from buggy harness on unpatched #0 kernel 987 B view raw
panic.txt panic-signature panic excerpt with DF-1075 harness kprintf markers 677 B view raw
fix.diff suggested-fix git-apply-able fix: move sc_mcfilters alloc to kue_attach_post, guard kfree in kue_detach 1.8 KB view raw
fix_build.log build-log full nativekernel build output for single-fix kernel (rc=0) 5.6 MB ↓ download
env.txt environment uname, cc version, sysctl, patched source line numbers 650 B view raw
VERDICT.md verdict full narrative: mechanism, source trace, harness proof, fix validation 5.7 KB ↓ raw
README.md readme human-readable PoC overview and reproduction instructions 2.9 KB ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme human-readable PoC overview and reproduction instructions
↓ download raw

DF-1075 PoC β€” Multicast filter buffer allocated before device descriptor is read

Bug

kue_attach() (sys/bus/u4b/net/if_kue.c:488-493) allocates sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, ...) BEFORE the device descriptor is read. At this point sc_desc is zero-initialised, so KUE_MCFILTCNT(sc) == 0, and kmalloc(0) returns ZERO_LENGTH_PTR = (void *)-8. The NULL check at line 490 does not catch (void *)-8. Later, kue_attach_post() reads the real descriptor (if_kue.c:439-440), but the buffer is never reallocated. When kue_setmulti() memcpy's into KUE_MCFILT(sc, 0) = &sc->sc_mcfilters[0] = (char *)-8, the kernel panics with a page fault at the unmapped ZERO_LENGTH_PTR address.

PoC approach

The actual kue(4) driver requires physical USB hardware (a KLSI KL5KUSB101B USB-Ethernet adapter or a malicious USB gadget). This KVM guest has no USB devices. The bug is therefore demonstrated by:

  1. Source-level trace β€” every cited line confirmed in sys/.
  2. Kernel-module harness (df1075_harness.c) that replicates the exact buggy kmalloc(0) + memcpy pattern and produces the predicted panic.

The real attacker-side PoC (for hardware-equipped targets): - Malicious USB gadget presenting a supported (VID, PID) (e.g. 0x04cf:0x0001), accepting KUE_CMD_SEND_SCAN firmware-download requests, and responding to KUE_CMD_GET_ETHER_DESCRIPTOR with kue_mcastfilt >= 1. - Host brings up the interface (ifconfig ue0 up, often automatic). - IPv6 adds multicast addresses β†’ SIOCADDMULTI β†’ kue_setmulti() β†’ panic.

Build (inside the guest, as root)

cd /root/poc_df1075 && make       # buggy-pattern harness
cd /root/poc_df1075_fixed && make # fixed-pattern harness

Run

# On UNPATCHED kernel (#0): loads buggy harness β†’ guest panics
kldload /root/poc_df1075/df1075_harness.ko

# On FIXED kernel (#1): loads fixed-pattern harness β†’ no panic
kldload /root/poc_df1075_fixed/df1075_fixed.ko
dmesg | tail -6

Expected output

Buggy harness (unpatched #0):

Fatal trap 12: page fault while in kernel mode
fault virtual address   = 0xfffffffffffffff8
fault code      = supervisor write data, page not present
Stopped at      df1075_modevent+0x91:   movl    $0x3333,(%rbx)

Guest is down (DDB prompt).

Fixed-pattern harness (patched #1):

DF-1075-FIXED: kmalloc(32*6=192) returned 0xfffff8004f22ccd0
DF-1075-FIXED: memcpy into &mcfilters[0]=0xfffff8004f22ccd0 SUCCEEDED, no panic
DF-1075-FIXED: wrote 33:33:ff:00:00:01
DF-1075-FIXED: kfree OK β€” fix verified, no panic

Guest stays up.

Impact

Reliable kernel panic (DoS) from USB device plug-in + interface up. The write target is the fixed ZERO_LENGTH_PTR sentinel ((void *)-8), which the attacker cannot redirect, so there is no path to code execution. Medium severity (physical access + automatic trigger). Affects both malicious and legitimate kue NICs.

VERDICT.md verdict full narrative: mechanism, source trace, harness proof, fix validation
↓ download raw

DF-1075 β€” Multicast filter buffer allocated before device descriptor is read β†’ OOB write / kernel panic

Finding

kue_attach() in sys/bus/u4b/net/if_kue.c allocates sc->sc_mcfilters via kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, ...) at a point where the device descriptor (sc->sc_desc) has NOT been fetched yet. Because the softc is zero-initialised by newbus (M_ZERO), KUE_MCFILTCNT(sc) reads UGETW(sc_desc.kue_mcastfilt) & 0x7FFF == 0, so the allocation is kmalloc(0). DragonFlyBSD's slab allocator returns ZERO_LENGTH_PTR = (void *)-8 for zero-length allocations (sys/kern/kern_slaballoc.c:888-891, #define ZERO_LENGTH_PTR ((void *)-8) at line 193). The subsequent NULL check at if_kue.c:490 does NOT catch this because (void *)-8 != NULL.

Later, kue_attach_post() fetches the real descriptor (if_kue.c:439-440) and a malicious (or legitimate) device reports kue_mcastfilt >= 1. The sc_mcfilters buffer is NEVER reallocated. When kue_setmulti() runs (if_kue.c:383-385), it does memcpy(KUE_MCFILT(sc, i), ..., ETHER_ADDR_LEN) where KUE_MCFILT(sc, 0) = &sc->sc_mcfilters[0] = (char *)-8 + 0 β€” an unmapped kernel address. The write faults and the kernel panics.

Impact: Reliable kernel panic (DoS) from USB device attachment + interface up. The write target is the fixed ZERO_LENGTH_PTR sentinel, which the attacker cannot redirect, so there is no path to code execution. Medium severity (physical access + automatic trigger).

Verification approach

This KVM guest has no USB hardware β€” usbconfig list returns "No device match", and QEMU cannot emulate a KLSI KL5KUSB101B adapter. The actual kue(4) driver cannot be triggered. Therefore the bug is verified by:

  1. Source-level trace β€” every cited line confirmed in sys/.
  2. Kernel-module harness replicating the exact buggy allocation+write pattern, which produces the exact predicted panic.

Source trace (all confirmed)

Claim Citation Verified
kue_attach() allocates sc_mcfilters before descriptor read if_kue.c:488-493 βœ…
KUE_MCFILTCNT(sc) reads sc_desc.kue_mcastfilt via UGETW if_kuereg.h:69 βœ…
UGETW({0,0}) == 0 usb_endian.h:49-51 βœ…
NULL check passes ((void*)-8 != NULL) if_kue.c:490 βœ…
kmalloc(0) returns ZERO_LENGTH_PTR kern_slaballoc.c:888-891 βœ…
ZERO_LENGTH_PTR = (void *)-8 kern_slaballoc.c:193 βœ…
Descriptor read happens later in kue_attach_post if_kue.c:439-440 βœ…
sc_mcfilters never reallocated (absence β€” grep confirms no other kmalloc of sc_mcfilters) βœ…
kue_setmulti memcpy into KUE_MCFILT(sc, 0) if_kue.c:383-385 βœ…
KUE_MCFILT(sc, 0) = &sc->sc_mcfilters[0] = (char*)-8 if_kuereg.h:70-71 βœ…

Harness proof (buggy pattern on unpatched #0 kernel)

A kernel module (df1075_harness.c) replicates the exact driver pattern:

mcfilters = kmalloc(0 * 6, M_HARNESS, M_WAITOK);  // kue_attach:488
// NULL check passes (ZERO_LENGTH_PTR != NULL)    // kue_attach:490
memcpy(&mcfilters[0], mac, 6);                    // kue_setmulti:383-385

Loading it on the unpatched #0 kernel produced (from boot.log):

DF-1075: kmalloc(0) returned 0xfffffffffffffff8 (ZERO_LENGTH_PTR expected 0xfffffffffffffff8)
DF-1075: NULL check would PASS (BUG: missed) (bug: sentinel is non-NULL)
DF-1075: about to memcpy 6 bytes into &mcfilters[0] = 0xfffffffffffffff8
DF-1075: THIS SHOULD PANIC WITH: Fatal trap 12: page fault

Fatal trap 12: page fault while in kernel mode
fault virtual address   = 0xfffffffffffffff8
fault code      = supervisor write data, page not present
Stopped at      df1075_modevent+0x91:   movl    $0x3333,(%rbx)

The fault address 0xFFFFFFFFFFFFFFF8 is exactly ZERO_LENGTH_PTR. The fault code "supervisor write data, page not present" confirms a write to an unmapped address. The movl $0x3333,(%rbx) instruction is the memcpy writing the first 4 bytes of the multicast address 33:33:00:00:00:01 into %rbx which holds 0xFFFFFFFFFFFFFFF8.

This matches the finding's predicted output exactly.

Fix

The fix moves the sc_mcfilters allocation from kue_attach() to kue_attach_post() (after the descriptor is read), and guards the kfree() in kue_detach() with a NULL check (since kue_attach_post may not have run on the uether_ifattach-failure path, and kfree(NULL) panics on DragonFlyBSD).

See fix.diff.

Fix validation

The fixed kernel (#1, built from patched source) was validated:

  1. Patch applies cleanly β€” patch -p1 succeeded, all 3 hunks.
  2. Kernel compiles β€” make -j6 nativekernel rc=0.
  3. Fixed source verified β€” sc_mcfilters kmalloc now at line 453 in kue_attach_post() (after descriptor read at 439-440); old allocation removed from kue_attach(); kfree guarded at line 533-534.
  4. Fixed-pattern harness (df1075_fixed_pattern.c) loaded on the patched #1 kernel β€” kmalloc(192) returned 0xfffff8004f22ccd0 (valid KVA), memcpy succeeded, NO panic: DF-1075-FIXED: kmalloc(32*6=192) returned 0xfffff8004f22ccd0 DF-1075-FIXED: memcpy into &mcfilters[0]=0xfffff8004f22ccd0 SUCCEEDED, no panic DF-1075-FIXED: wrote 33:33:ff:00:00:01 DF-1075-FIXED: kfree OK β€” fix verified, no panic

The actual kue(4) driver cannot be triggered without USB hardware, so fix_status = not_testable for the live driver β€” but the before/after harness validation confirms the mechanism is closed.

Verdict

REPRODUCED (panic via harness replicating the exact driver code pattern). Impact: panic (DoS) β€” write to unredirectable ZERO_LENGTH_PTR sentinel, no escalation path. Fix: VALIDATED (compiles, allocation moved, harness before/after confirms mechanism closed).

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

not_testable (no USB HW). Compile+boot+harness validated: buggy harness panics on #0, fixed-pattern harness succeeds on #1.

BEFORE: Fatal trap 12 at 0xfffffffffffffff8. AFTER: kmalloc(192) valid, memcpy succeeds.
↓ fix.diffDragonFly 6.5-DEVELOPMENT #1: Wed Jul 15 00:54:26 UTC 2026

Confirmed kernel references

Detail

Exploit chain

none -- DoS only (write to fixed ZERO_LENGTH_PTR sentinel, unredirectable). USB device-only trigger. No escalation path.

Evidence (decisive lines)

BEFORE: kmalloc(0)=0xfffffffffffffff8, Fatal trap 12 page fault at that addr. AFTER: kmalloc(192)=valid ptr, memcpy succeeds.

PoC changes

Authored: df1075_harness.c (kld replicating buggy pattern), df1075_fixed_pattern.c (corrected), fix.diff (move alloc to kue_attach_post + guard kfree), VERDICT.md, manifest.json.

Verified recommended fix

Move sc_mcfilters kmalloc from kue_attach to kue_attach_post (after descriptor read at :439-440). Remove NULL check (M_WAITOK). Guard kfree in kue_detach with NULL check. Matches finding proposal. Full diff in findings/poc/DF-1075/fix.diff.

Verdict

REPRODUCED (kld harness). kue_attach if_kue.c:488-493 kmalloc(KUE_MCFILTCNT6) BEFORE descriptor read -> sc_desc zero -> count=0 -> kmalloc(0)=ZERO_LENGTH_PTR(-8) -> NULL check passes (-8!=NULL) -> kue_setmulti memcpy to (void)-8 -> page fault. Harness panics: Fatal trap 12 at 0xfffffffffffffff8.