[PATCH 0/3] Multi-Link element fuzzer and an off-by-one it found

Louis Kotze loukot at gmail.com
Mon Aug 24 00:31:44 PDT 2026


The existing fuzzers do not cover Multi-Link element parsing, so this
adds one and fixes the first thing it reported.

The bug is a one-octet over-read in get_basic_mle_eml_capa() and
get_basic_mle_link_id(): both reject buffers shorter than
MULTI_LINK_CONTROL_LEN and then read buf[MULTI_LINK_CONTROL_LEN]. It is
reachable while processing scan results, so an AP advertising a Basic
Multi-Link element with an element length of 3 triggers it before
authentication or association.

I would not describe the impact as more than minor, and I checked rather
than assumed. Sweeping the two accessors over every buffer length up to
the caller's maximum shows the only faulting length is 2 and the read
never goes further than the octet immediately past the buffer. No
faulting path returns a value, so the octet does not reach the caller.
The element also has to be the last one in the frame for the read to
leave the allocation at all, since wpa_scan_res stores the IEs inline.

For what it is worth, ieee80211_mle_size_ok() in the kernel starts from
the same two octet check but computes the expected Common Info size
first and rejects on "len < fixed + common" before reading that octet,
so it does not have the equivalent problem.

On that basis I judged this below the threshold for handling it as a
security issue and am sending it here. If you would rather it had gone
another route, please say so.

Patch 2 adds boundary tests for the accessors. They use exactly sized
allocations, so the regression case only fails when the tests are built
with AddressSanitizer or run under valgrind; without patch 1 test-mle
aborts with a heap-buffer-overflow in get_basic_mle_link_id().

Patch 3 is the fuzzer. It covers ieee802_11_parse_elems(), the Basic
Multi-Link element accessors, per-STA profile parsing for each Link ID,
subelement defragmentation and element defragmentation. The corpus is
nine seeds: six built by hand for structure and three real Multi-Link
elements taken from hwsim captures.

Region coverage over those nine seeds, measured with llvm-cov:
get_basic_mle_mld_addr() 100%, get_basic_mle_link_id() 91%,
get_basic_mle_eml_capa() 88%, ieee802_11_defrag() 86%,
ieee802_11_parse_link_profile() 64%, ieee802_11_parse_mle() 56%,
ieee802_11_defrag_mle_subelem() 40%.

Several runs, including ones with a structural dictionary, produced
nothing beyond the bug fixed here.

Louis Kotze (3):
  MLD: Fix off-by-one read of Common Info Length in Basic MLE accessors
  tests: Multi-Link element accessor boundary tests
  tests: Add fuzzer for Multi-Link element parsing

 src/common/ieee802_11_common.c                |   6 +-
 tests/Makefile                                |   7 +-
 tests/fuzzing/ml-elems/Makefile               |  24 +++
 .../ml-elems/corpus/basic-eml-mldcapa.bin     | Bin 0 -> 17 bytes
 .../ml-elems/corpus/basic-fragmented.bin      | Bin 0 -> 267 bytes
 .../fuzzing/ml-elems/corpus/basic-minimal.bin | Bin 0 -> 12 bytes
 .../ml-elems/corpus/basic-per-sta-profile.bin | Bin 0 -> 23 bytes
 .../ml-elems/corpus/basic-two-profiles.bin    | Bin 0 -> 34 bytes
 .../ml-elems/corpus/real-3a23468610da.bin     | Bin 0 -> 18 bytes
 .../ml-elems/corpus/real-47a767cf0825.bin     | Bin 0 -> 7 bytes
 .../ml-elems/corpus/real-5b120aca880d.bin     | Bin 0 -> 140 bytes
 .../fuzzing/ml-elems/corpus/reconfig-type.bin | Bin 0 -> 12 bytes
 tests/fuzzing/ml-elems/ml-elems.c             | 117 ++++++++++++
 tests/test-mle.c                              | 173 ++++++++++++++++++
 14 files changed, 324 insertions(+), 3 deletions(-)
 create mode 100644 tests/fuzzing/ml-elems/Makefile
 create mode 100644 tests/fuzzing/ml-elems/corpus/basic-eml-mldcapa.bin
 create mode 100644 tests/fuzzing/ml-elems/corpus/basic-fragmented.bin
 create mode 100644 tests/fuzzing/ml-elems/corpus/basic-minimal.bin
 create mode 100644 tests/fuzzing/ml-elems/corpus/basic-per-sta-profile.bin
 create mode 100644 tests/fuzzing/ml-elems/corpus/basic-two-profiles.bin
 create mode 100644 tests/fuzzing/ml-elems/corpus/real-3a23468610da.bin
 create mode 100644 tests/fuzzing/ml-elems/corpus/real-47a767cf0825.bin
 create mode 100644 tests/fuzzing/ml-elems/corpus/real-5b120aca880d.bin
 create mode 100644 tests/fuzzing/ml-elems/corpus/reconfig-type.bin
 create mode 100644 tests/fuzzing/ml-elems/ml-elems.c
 create mode 100644 tests/test-mle.c

-- 
2.55.0




More information about the Hostap mailing list