Stack buffer overflow in wi_write_wep LUCENT WEP-key load (wk_keylen up to 16 copied into wi_keydat[14])
Summary
wi_write_wep at if_wi.c:1751-1769: LUCENT branch memcpy(wkey[i].wi_keydat, wk_key, keylen). wi_keydat is u8[14] (if_wavelan_ieee.h:293). wk_keylen from net80211 up to IEEE80211_KEYBUF_SIZE=16 (bounded by ioctl, WEP cipher accepts >=5 no max). keylen 15-16 -> 1-2B past wi_keydat. i==3 (last slot) -> off wkey[4] stack array into frame. Triggered on state transition (AUTH/RUN) calling wi_write_wep. SYSCAP_NONET_WIFI required. Fix: clamp keylen to sizeof(wi_keydat).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1400 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| wi_overflow.c | trigger-source | byte-exact harness replicating wi_write_wep LUCENT keylen overflow | 3.9 KB | view raw |
| build.sh | build-script | cc -O2 -o wi_overflow wi_overflow.c | 78 B | view raw |
| run.sh | run-script | run harness | 24 B | view raw |
| run.log | run-log | decisive harness output, OVERFLOW CONFIRMED | 820 B | view raw |
| env.txt | environment | uname, cc version | 227 B | view raw |
| fix.diff | suggested-fix | clamp keylen to sizeof(wi_keydat) | 502 B | view raw |
| VERDICT.md | verdict | full analysis | 4.0 KB | β raw |
| README.md | readme | reproduce guide | 1.5 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 |
DF-1400 β wi_write_wep LUCENT WEP-key stack overflow (PoC)
Summary
wi_write_wep LUCENT branch (sys/dev/netif/wi/if_wi.c:1766-1769) does
memcpy(wkey[i].wi_keydat, wk_key, keylen) with keylen up to
IEEE80211_KEYBUF_SIZE=16 into wi_keydat[14], overflowing by 1-2 bytes per
slot; on the last slot (i==3) the overflow runs off the wkey[4] stack array
into the frame. Triggered on a WiFi state transition (AUTH/RUN) calling
wi_write_wep. Requires SYSCAP_NONET_WIFI.
Reachability
wi(4) is a loadable module (if_wi.ko), not in GENERIC, attaching only to
Prism/Lucent WiFi cards. The QEMU guest has no WiFi hardware, so the bug is
not live-reachable here. Proven deterministically with a byte-exact harness
replicating struct wi_key (if_wavelan_ieee.h:290-292) and the wkey[4]
stack array.
Build / run
./build.sh && ./run.sh
Expected output (bug present)
slot 3: wrote 16 bytes into 14-byte wi_keydat -> 2 byte(s) past end [runs OFF the wkey[4] array into the frame] frame region after wkey[4] corrupted by last slot: YES OVERFLOW CONFIRMED: keylen=16 > wi_keydat[14] overflows by 2 byte(s) per slot ...
On a fixed driver the copy is bounded to sizeof(wi_keydat) = 14.
Fix
Clamp keylen to sizeof(wkey[i].wi_keydat) before the memcpy (fix.diff).
Validated to compile into a rebuilt if_wi.ko (-Werror, rc=0).
Files
wi_overflow.cβ byte-exact harness.build.sh/run.sh/run.log/env.txt/fix.diff/VERDICT.md/manifest.json.
DF-1400 β wi_write_wep LUCENT WEP-key stack overflow
Verdict: REPRODUCED (primitive proven via source trace + byte-exact harness). Fix compiles.
wi_write_wep (LUCENT firmware branch) copies a WEP key of up to
IEEE80211_KEYBUF_SIZE=16 bytes into a 14-byte wi_keydat field with no
bounds check, overflowing by 1-2 bytes per key slot; on the last slot
(i==3) the overflow runs off the wkey[4] stack array into the surrounding
frame. Confirmed real by source tracing + a byte-exact harness. Not
live-reachable on the QEMU guest because wi(4) attaches only to
Prism/Lucent WiFi hardware (absent in QEMU) and the code is a loadable module.
The fix compiles cleanly (-Werror).
Mechanism (trigger β primitive β effect)
sys/dev/netif/wi/if_wi.c:1764-1769 (LUCENT branch):
struct wi_key wkey[IEEE80211_WEP_NKID]; /* wkey[4] on stack */
...
memset(wkey, 0, sizeof(wkey));
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
keylen = vap->iv_nw_keys[i].wk_keylen; /* up to 16 */
wkey[i].wi_keylen = htole16(keylen);
memcpy(wkey[i].wi_keydat, vap->iv_nw_keys[i].wk_key, keylen); /* SINK */
}
Destination (sys/dev/netif/wi/if_wavelan_ieee.h:290-292):
struct wi_key {
u_int16_t wi_keylen;
u_int8_t wi_keydat[14]; /* <-- 14-byte destination */
};
IEEE80211_KEYBUF_SIZE = 16(sys/netproto/802_11/ieee80211_crypto.h:34),IEEE80211_WEP_NKID = 4(ieee80211.h:1272).wk_keylenis bounded by the ioctl path toIEEE80211_KEYBUF_SIZE(16); the WEP cipher accepts>=5with no upper bound, so 15-16 reaches here.memcpyof 16 bytes intowi_keydat[14]overflows by 2 bytes. Fori==3(the last slot), the overflow runs off thewkey[4]array into the stack frame.
Primitive
- Class: stack buffer overflow, 1-2 bytes per slot (keylen 15-16),
attacker-controlled key material content; on the last slot the overflow
escapes the
wkey[4]array into the surrounding frame. - Trigger: WiFi state transition (AUTH/RUN) that calls
wi_write_wep. - Effect: stack corruption in the LUCENT WEP-key write path β panic or potential control-flow corruption on real Prism/Lucent WiFi hardware.
Reachability / threat model
wiis a loadable module (if_wi.ko), NOT inX86_64_GENERIC. It attaches only to Prism/Lucent IEEE 802.11 WiFi cards. The QEMU guest has no WiFi hardware, sowi_write_wepnever runs live here.- Realistic threat: a host with Prism/Lucent WiFi joining a crafted/rogue AP,
or a malicious local user triggering a WEP key set on attached WiFi that
transitions to AUTH/RUN. Requires
SYSCAP_NONET_WIFI. - Validated the primitive deterministically with the byte-exact harness
(
wi_overflow.c):keylen=16intowi_keydat[14]overflows by 2 bytes per slot; the last slot (i==3) corrupts the frame canary.
Harness proof (run.log)
wi_key.wi_keydat capacity: 14 bytes keylen (wk_keylen, up to IEEE80211_KEYBUF_SIZE): 16 slot 3: wrote 16 bytes into 14-byte wi_keydat -> 2 byte(s) past end [runs OFF the wkey[4] array into the frame] frame region after wkey[4] corrupted by last slot: YES OVERFLOW CONFIRMED: keylen=16 > wi_keydat[14] overflows by 2 byte(s) per slot; last slot overruns wkey[4] into the stack frame.
Fix validation
fix.diff clamps keylen to sizeof(wkey[i].wi_keydat) (=14) before the
memcpy. The fix was applied to in-guest /usr/src and the if_wi.ko module
rebuilt cleanly (cc ... -Werror, RC=0). Runtime re-test is not possible on
this guest (no WiFi HW), so fix_status = not_testable for runtime, with the
diff verified to apply + compile and the harness logic confirming the
clamp bounds the copy to 14 bytes.
Kernel references
sys/dev/netif/wi/if_wi.c:1766-1769(sink: unchecked keylen β memcpy)sys/dev/netif/wi/if_wavelan_ieee.h:290-292(struct wi_key, 14-bytewi_keydat)sys/netproto/802_11/ieee80211_crypto.h:34(IEEE80211_KEYBUF_SIZE=16)sys/netproto/802_11/ieee80211.h:1272(IEEE80211_WEP_NKID=4)
Fix verification
not_testablecompile+harness validated
module build rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
REPRODUCED (harness). wi_write_wep LUCENT keylen=16 vs wi_keydat[14] -> 2B overflow per slot. wi.ko module, no WiFi HW.
No comments yet.