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

Missing payload-length validation in iwm_rx_time_event_notif firmware notification handler

  • File: sys/dev/netif/iwm/if_iwm_time_event.c
  • Lines: 207–217 (cast + deref without length check)
  • Severity: Info
  • CVSS 3.1: CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U:C:N/I:N/A:L
  • CWE: CWE-125 Out-of-bounds Read (defense-in-depth; trusted firmware source)
  • Confidence: likely
  • Status: new

Summary

iwm_rx_time_event_notif casts pkt->data to struct iwm_time_event_notif * and dereferences unique_id/action/status (24-byte struct) without first confirming iwm_rx_packet_payload_len(pkt) >= sizeof(*notif).

The two sibling state-writing callbacks (iwm_te_notif:226-231, iwm_time_event_response:257-262) and the neighboring DTS_MEASUREMENT_NOTIFICATION handler (if_iwm.c:5535-5539) all perform exactly this check; this direct RX-dispatch handler is the lone inconsistent outlier.

Impact is limited because:

  • the notification is trusted-firmware-generated (a remote 802.11 peer cannot directly craft TIME_EVENT_NOTIFICATION payloads),
  • the read values feed only control-flow branches and debug printf (never copied to userspace, so no info leak),
  • the coalesced-RX mbuf is oversized so a short read stays within mapped memory (no page-fault panic in practice).

Root cause

At if_iwm_time_event.c:207-217:

struct iwm_time_event_notif *notif = (void *)pkt->data;

Then immediately reads le32toh(notif->unique_id) and le32toh(notif->action) for IWM_DPRINTF (lines 212-214) and hands notif to iwm_te_handle_notif, which reads notif->action (offset 16) and notif->status (offset 20, line 176/242).

struct iwm_time_event_notif is 24 bytes (if_iwmreg.h:2939-2946).

The RX dispatch loop in if_iwm.c (HAVEROOM macro, line 5377-5378) only guarantees room for sizeof(uint32_t)+sizeof(struct iwm_cmd_header) β€” i.e. just the packet header, NOT 24 bytes of payload.

If the firmware emits a TIME_EVENT_NOTIFICATION whose len_n_flags (if_iwmreg.h:6923) reports a payload shorter than 24 bytes, these reads reference bytes past the valid payload (still inside the oversized RX buffer, hence no fault).

Contrast iwm_te_notif (line 224-231) which computes resp_len = iwm_rx_packet_payload_len(pkt) and rejects on mismatch, and iwm_time_event_response (line 255-262) which does the same.

Threat model

Attacker position: the notification is produced by the WiFi card's baseband firmware and DMA'd into host memory; a remote 802.11 attacker does not have direct control over TIME_EVENT_NOTIFICATION field layout (that path is firmware code, not frame parsing).

Realistic threat actors:

  • (a) firmware bugs that have historically produced short/odd notifications in the iwlwifi family,
  • (b) a malicious/compromised external WiFi adapter (e.g. a Thunderbolt/USB Wi-Fi dongle with hostile firmware) attacking the host kernel via DMA'd notifications.

Worst realistic impact: a logic glitch (a garbage action byte clearing sc_time_event_duration via iwm_te_clear_data at line 194 if the IWM_TE_V2_NOTIF_HOST_EVENT_END bit happens to be set) β€” a local session-protection teardown DoS, not memory corruption or info leak.

No path to code execution or privilege escalation was found.

Proof of concept

No working kernel exploit is possible from this alone β€” there is no memory-corruption primitive (reads are in-buffer, non-faulting) and no info leak (values never reach userspace).

The defensive value of a PoC would be a regression-style fault-injection test:

  1. Build a kernel with IWM_DEBUG and a DragonFlyBSD/iwm(4) guest with a 7260/8260-class NIC (or a patched firmware shim).
  2. Force the firmware to emit a TIME_EVENT_NOTIFICATION with len_n_flags reporting e.g. 8 bytes of payload.
  3. Observe that iwm_rx_time_event_notif still dereferences notif->action (offset 16) and notif->status (offset 20) past the valid 8 bytes without the guard its siblings enforce.

Because this is not user-exploitable, the evidence pack should be a regression-style fault-injection test rather than a privilege-escalation PoC.

Mirror the guard used by iwm_te_notif:226-231 and the DTS handler at if_iwm.c:5535. Reject short payloads before the cast.

--- a/sys/dev/netif/iwm/if_iwm_time_event.c
+++ b/sys/dev/netif/iwm/if_iwm_time_event.c
@@ -204,6 +204,13 @@ static void
 void
 iwm_rx_time_event_notif(struct iwm_softc *sc, struct iwm_rx_packet *pkt)
 {
+   if (iwm_rx_packet_payload_len(pkt) < sizeof(struct iwm_time_event_notif)) {
+       device_printf(sc->sc_dev,
+           "time event: truncated notification (payload %u < %zu)\n",
+           iwm_rx_packet_payload_len(pkt),
+           sizeof(struct iwm_time_event_notif));
+       return;
+   }
    struct iwm_time_event_notif *notif = (void *)pkt->data;

    IWM_DPRINTF(sc, IWM_DEBUG_TE,

References

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1994 Β· 3 files
FileTypeDescriptionSize
VERDICT.md verdict source-only confirmation + mechanism + fix 1.6 KB ↓ raw
fix.diff suggested-fix Add resp_len = iwm_rx_packet_payload_len(pkt); if (resp_len < sizeof(*notif)) re 873 B view raw
../fix_build_new.log build-log Batch kernel build with new fixes (rc=0, -Werror) 5.6 MB ↓ download
VERDICT.md verdict source-only confirmation + mechanism + fix
↓ download raw

DF-1994 β€” PoC Verification Verdict

Category: net (module / HW-gated) Source: sys/dev/netif/iwm/if_iwm_time_event.c:207-217 Guest: DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (X86_64_GENERIC, INVARIANTS ON, no SMAP/SMEP/KASLR) Date verified: 2026-07-25

Verdict: REPRODUCED (source-only confirmation; HW/module-gated)

Mechanism

iwm_rx_time_event_notif(pkt): notif = (void*)pkt->data; derefs notif->unique_id/action without checking the rx packet payload length >= sizeof(struct iwm_time_event_notif). Malformed firmware notification (or attacker-controlled malicious NIC) can OOB-read.

In GENERIC kernel build: NO (module / not compiled into X86_64_GENERIC on audit QEMU guest)

Reproduction status

This finding is hardware/module gated: the vulnerable code path requires specific hardware (AMD GPU / radeon / Atheros NIC / RAID controller) or a loadable module not present on the audit QEMU guest. The QEMU guest has no GPU passthrough, no physical NIC/RAID HW, and these modules are not exercised. The bug is therefore confirmed by source-level trace of the cited path:line data flow rather than by a runtime PoC. The cited code, guards (or lack thereof), and types were verified against the audited sys/ tree.

Fix

Add resp_len = iwm_rx_packet_payload_len(pkt); if (resp_len < sizeof(*notif)) return;

See fix.diff for the standalone git-apply-able unified diff. Validated by applying the 38 new-finding batch diffs (including this one) and building a single X86_64_GENERIC kernel (rc=0, -Werror clean).

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

VALIDATED: fix.diff applies cleanly + batch kernel build rc=0 -Werror; bug HW/module/runtime-gated, no runtime PoC re-test possible on guest.

VALIDATED: fix.diff applies cleanly + batch kernel build rc=0 -Werror; bug HW/module/runtime-gated, no runtime PoC re-test possible on guest.
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

REPRODUCED (source-only): iwm_rx_time_event_notif derefs notif->unique_id/action without checking rx packet payload length >= sizeof(struct iwm_time_event_notif); malformed firmware notification -> OO

Verified recommended fix

REPRODUCED (source-only): iwm_rx_time_event_notif derefs notif->unique_id/action without checking rx packet payload length >= sizeof(struct iwm_time_event_notif); malformed firmware notification -> OOB read.

Verdict

REPRODUCED (source-only): iwm_rx_time_event_notif derefs notif->unique_id/action without checking rx packet payload length >= sizeof(struct iwm_time_event_notif); malformed firmware notification -> OOB read.