ixgbe_dcb_config_pfc_82599 uses unbounded u8 map[] to size PFC loop: OOB read + OOB MMIO write (latent)
| Field | Value |
|---|---|
| ID | DF-1862 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:H |
| CWE | CWE-125 Out-of-bounds Read; CWE-787 Out-of-bounds Write |
| File | sys/dev/netif/ix/ixgbe_dcb_82599.c |
| Lines | 321-324, 328 |
| Area | dev/netif (ixgbe DCB PFC config) |
| Confidence | certain |
| Discovered | 2026-07-20 |
| Reported | pending |
| Known CVE | none |
| CVE match | dfly_specific |
Summary
ixgbe_dcb_config_pfc_82599 derives max_tc as the max of map[0..7] without
clamping. Because map[] is u8 (0..255) and ultimately traces back to
cfg->num_tcs.pg_tcs (also u8, never validated to <= 8 anywhere), the
subsequent loop for (i = 0; i <= max_tc; i++) runs up to 256 iterations and
(a) reads hw->fc.high_water[i] / hw->fc.low_water[i] OOB (arrays of size 8),
and (b) computes IXGBE_FCRTL_82599(i)/IXGBE_FCRTH_82599(i)/IXGBE_RXPBSIZE(i)
for i >= 8, clobbering adjacent NIC registers.
No path in the current DragonFlyBSD ix driver reaches this function with
attacker-influenced input, so impact is latent β but the symbol is exported and
any future sysctl/ioctl/KLD that wires up DCB CEE config (as Linux does via
netlink) becomes immediately vulnerable.
Root cause
ixgbe_dcb_82599.c:321-324:
u8 max_tc = 0;
for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) {
if (map[i] > max_tc)
max_tc = map[i];
}
with no clamp. Then ixgbe_dcb_82599.c:328:
for (i = 0; i <= max_tc; i++) {
Inside that loop:
- Line 339-341: reads hw->fc.high_water[i] and hw->fc.low_water[i]
(declared u32[IXGBE_DCB_MAX_TRAFFIC_CLASS] at ixgbe_type.h:3787-3788, size 8)
- Line 341/351/354/358/359: writes IXGBE_FCRTL_82599(i)/IXGBE_FCRTH_82599(i)
(ixgbe_type.h:357-358: 0x03260 + ((_i) * 4) β Intel spec defines only 0..7)
- Line 350: reads IXGBE_RXPBSIZE(i)
(ixgbe_type.h:406: 0x03C00 + ((_i) * 4) β only 0..7)
For any map[k] > 7 (e.g. 0xFF), i proceeds 8..255 and all of those accesses
go OOB.
The map[] values originate in ixgbe_dcb.c:263 ixgbe_dcb_get_tc_from_up(),
which initializes u8 tc = cfg->num_tcs.pg_tcs and only decrements; if
pg_tcs > 8 (never validated anywhere), tc_config[tc] is read OOB and a
tc > 7 is returned into map[].
Threat model & preconditions
- Attacker position: a privileged user able to influence
dcb_config(e.g. via a future sysctl/ioctl wiring up DCB CEE config β Linux exposes this via netlinkDCB_CMD). Currently no such path exists inif_ix.c(verified byrg:if_ix.cinvokes noixgbe_dcb_*symbol). - Privileges gained or impact:
- OOB kernel-heap read of up to
(max_tc - 7) * 4bytes pasthw->fc.high_water[]/low_water[], values written to NIC MMIO. - OOB MMIO writes clobber adjacent NIC registers (RT2CR, RT2SR, RXPBSIZE of other TCs, etc.), causing NIC malfunction, link instability, or machine-check/panic on MMIO fault.
- Required config or capabilities: Intel 82599/X540/X550 NIC present;
dcb_config->num_tcs.pg_tcsset > 8 by the configuration source. - Reachability: currently dormant. Any future KLD module or sysctl/ioctl that wires up DCB CEE config becomes immediately vulnerable.
Proof of concept
Currently no in-kernel path on DragonFlyBSD reaches
ixgbe_dcb_config_pfc_82599 with attacker-controlled map[]. Reproduction
requires either:
- (a) loading a custom KLD that calls ixgbe_dcb_config_pfc_82599(hw, 0xFF, map)
with map[0] = 0xFF and observing the resulting OOB MMIO writes, or
- (b) the addition of a sysctl/ioctl in the future that wires up dcb_config.
Classify as a latent hardening bug, not an in-tree exploit.
Impact
Low-severity latent OOB read + OOB MMIO write. Currently dormant (no in-tree path reaches it with attacker input). Any future DCB config wiring (as Linux does via netlink DCB) would activate it.
Recommended fix
Clamp max_tc to the hardware limit before using it as a loop bound.
--- a/sys/dev/netif/ix/ixgbe_dcb_82599.c
+++ b/sys/dev/netif/ix/ixgbe_dcb_82599.c
@@ -318,6 +318,11 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *map)
IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) {
+ /* map[i] is a u8 but must index a MAX_TRAFFIC_CLASS (8) world.
+ * Clamp before using it as a loop bound to avoid OOB reads of
+ * hw->fc.high_water/low_water and OOB MMIO writes.
+ */
+ if (map[i] >= IXGBE_DCB_MAX_TRAFFIC_CLASS)
+ return IXGBE_ERR_PARAM;
if (map[i] > max_tc)
max_tc = map[i];
}
And in ixgbe_dcb.c, harden the upstream source so map[] can never carry an
out-of-range TC:
--- a/sys/dev/netif/ix/ixgbe_dcb.c
+++ b/sys/dev/netif/ix/ixgbe_dcb.c
@@ -264,7 +264,8 @@ u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up)
struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0];
u8 prio_mask = 1 << up;
u8 tc = cfg->num_tcs.pg_tcs;
-
+ if (tc > IXGBE_DCB_MAX_TRAFFIC_CLASS)
+ tc = IXGBE_DCB_MAX_TRAFFIC_CLASS;
/* If tc is 0 then DCB is likely not enabled or supported */
if (!tc)
goto out;
Timeline
- 2026-07-20 Discovered during automated audit.
- 2026-07-20 Reported to DragonFlyBSD security contact (pending).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1862 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | git-apply-able fix for the cited bug | 373 B | view raw |
| VERDICT.md | verdict | source-confirmation analysis | 714 B | β raw |
| build.sh | build-script | N/A (source-only) | 61 B | view raw |
| run.sh | run-script | N/A (source-only) | 87 B | view raw |
DF-1862 VERDICT
Verdict: REPRODUCED (source-confirmed)
Impact: Low (driver-level NULL deref / OOB / leak / DoS β hardware-gated)
Mechanism: ixgbe_dcb_82599.c L321-324 u8 max_tc=0 for(i<8)if(map[i]>max_tc)max_tc=map[i] no clamp. L328 for(i=0;i<=max_tc;i++) up to 256 iters. Inside: L339-341 read hw->fc.high_water[i]/low_water[i] size 8 ixgb
Citation: sys/dev/netif/ix/ixgbe_dcb_82599.c:321-328
Fix: Applied fix.diff β compiles in batch kernel build (rc=0, -Werror).
Verification method: Source-only line-by-line trace of cited path:line. Low-severity driver bug; PoC trigger requires specific hardware or root context. Confirmed the cited vulnerable pattern exists in source.
Fix verification
fixedfix.diff compiled in batch kernel build rc=0 -Werror
fix.diff compiled in batch kernel build rc=0 -Werror
Confirmed kernel references
β
Detail
Exploit chain
none (Low severity)
Evidence (decisive lines)
Source-confirmed: unbounded u8 map[] drives PFC loop past array bounds (ixgbe_dcb_82599.c:321-328)
Verified recommended fix
Source-confirmed: unbounded u8 map[] drives PFC loop past array bounds (ixgbe_dcb_82599.c:321-328)
Verdict
Source-confirmed: unbounded u8 map[] drives PFC loop past array bounds (ixgbe_dcb_82599.c:321-328)
No comments yet.