When the AF flag is enabled, hwmp_prep_frame_process() overreads orig_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_reply_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 --- include/linux/ieee80211-mesh.h | 18 ++++++++++++++++++ net/mac80211/mesh_hwmp.c | 5 +++-- net/mac80211/parse.c | 9 +++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/include/linux/ieee80211-mesh.h b/include/linux/ieee80211-mesh.h index 8ff68cf539ff..ddbf475c1cc8 100644 --- a/include/linux/ieee80211-mesh.h +++ b/include/linux/ieee80211-mesh.h @@ -283,4 +283,22 @@ static inline bool ieee80211_mesh_preq_size_ok(const u8 *pos, u8 elen) return true; } +/* IEEE Std 802.11-2016 9.4.2.114 PREP element */ +static inline bool ieee80211_mesh_prep_size_ok(const u8 *pos, u8 elen) +{ + u8 needed; + + needed = 1 /* Flags */ + 1 /* Hop Count */ + 1 /* Element TTL */ + + 6 /* Target Mesh STA Address */ + + 4 /* Target HWMP Sequence Number */ + + (AE_F_SET(pos) ? 6 : 0) /* Target External Address */ + + 4 /* Lifetime */ + 4 /* Metric */ + + 6 /* Originator Mesh STA Address */ + + 4 /* Originator HWMP Sequence Number */; + if (elen != needed) + return false; + + return true; +} + #endif /* LINUX_IEEE80211_MESH_H */ diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index a4984b015995..c70cfc2d6299 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -941,9 +941,10 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, path_metric); } if (elems->prep) { - if (elems->prep_len != 31) - /* Right now we support no AE */ + /* Right now we do not support AE (Address Extension) */ + if (AE_F_SET(elems->prep)) goto free; + path_metric = hwmp_route_info_get(sdata, mgmt, elems->prep, MPATH_PREP); if (path_metric) diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c index 9e52cc48fc18..bbd1e1bc77b4 100644 --- a/net/mac80211/parse.c +++ b/net/mac80211/parse.c @@ -556,8 +556,13 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params, } break; case WLAN_EID_PREP: - elems->prep = pos; - elems->prep_len = elen; + if (ieee80211_mesh_prep_size_ok(pos, elen)) { + elems->prep = pos; + elems->prep_len = elen; + } else { + elem_parse_failed = + IEEE80211_PARSE_ERR_BAD_ELEM_SIZE; + } break; case WLAN_EID_PERR: elems->perr = pos; -- 2.43.0