From: Masashi Honma Date: Fri, 29 May 2026 23:09:46 +0000 (+0900) Subject: wifi: mac80211: Fix overread in PREQ frame processing X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8b40b1d24a6099fe9fac8e207d4cb04ab5e0baae;p=thirdparty%2Fkernel%2Fstable.git wifi: mac80211: Fix overread in PREQ frame processing When the AF flag is enabled, hwmp_preq_frame_process() overreads target_addr by 2 bytes. Since this occurs within the socket buffer, it does not read across memory boundaries and therefore poses no security risk; however, we will fix it as a precaution. In this fix, a new function mesh_path_parse_request_frame() is established to separate the implementation of frame format validation and the check for unsupported features. This is intended to facilitate future work when implementing the currently unsupported parts. Assisted-by: Claude:Sonnet 4.6 Signed-off-by: Masashi Honma Link: https://patch.msgid.link/20260529230952.124754-4-masashi.honma@gmail.com Signed-off-by: Johannes Berg --- diff --git a/include/linux/ieee80211-mesh.h b/include/linux/ieee80211-mesh.h index f709263c310b..8fbd31d9538d 100644 --- a/include/linux/ieee80211-mesh.h +++ b/include/linux/ieee80211-mesh.h @@ -358,4 +358,33 @@ ieee80211_mesh_hwmp_perr_get_rcode(const u8 *ie, u8 dst_idx) (dst->flags & AE_F) ? ETH_ALEN : 0]); } +/* IEEE Std 802.11-2016 9.4.2.113 PREQ element */ +static inline bool ieee80211_mesh_preq_size_ok(const u8 *pos, u8 elen) +{ + struct ieee80211_mesh_hwmp_preq_bottom *preq_elem_bottom = + ieee80211_mesh_hwmp_preq_get_bottom(pos); + u8 target_count; + int needed; + + /* Check if the element contains flags */ + needed = sizeof(struct ieee80211_mesh_hwmp_preq_top); + if (elen < needed) + return false; + + /* Check if the element contains target_count */ + needed += (ieee80211_mesh_preq_prep_ae_enabled(pos) ? ETH_ALEN : 0) + /* Originator External Address */ + + sizeof(struct ieee80211_mesh_hwmp_preq_bottom); + if (elen < needed) + return false; + + target_count = preq_elem_bottom->target_count; + /* IEEE Std 802.11-2016 Table 14-10 to 14-16 */ + if (target_count < 1) + return false; + + needed += target_count * sizeof(struct ieee80211_mesh_hwmp_preq_target); + return elen == needed; +} + #endif /* LINUX_IEEE80211_MESH_H */ diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 378338778a23..ef6eff52f32a 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -929,9 +929,17 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, return; if (elems->preq) { - if (elems->preq_len != 37) - /* Right now we support just 1 destination and no AE */ + struct ieee80211_mesh_hwmp_preq_bottom *preq_elem_bottom = + ieee80211_mesh_hwmp_preq_get_bottom(elems->preq); + + /* Right now we do not support AE (Address Extension) */ + if (ieee80211_mesh_preq_prep_ae_enabled(elems->preq)) goto free; + + /* Right now we only support 1 target */ + if (preq_elem_bottom->target_count != 1) + goto free; + path_metric = hwmp_route_info_get(sdata, mgmt, elems->preq, MPATH_PREQ); if (path_metric) diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c index 8b30e361b622..3d441ff9593d 100644 --- a/net/mac80211/parse.c +++ b/net/mac80211/parse.c @@ -563,8 +563,13 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params, elems->awake_window = (void *)pos; break; case WLAN_EID_PREQ: - elems->preq = pos; - elems->preq_len = elen; + if (ieee80211_mesh_preq_size_ok(pos, elen)) { + elems->preq = pos; + elems->preq_len = elen; + } else { + elem_parse_failed = + IEEE80211_PARSE_ERR_BAD_ELEM_SIZE; + } break; case WLAN_EID_PREP: elems->prep = pos;