|
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
|
|
|
|
|
|
if (ieee80211_is_action(hdr->frame_control)) {
|
|
|
u8 category;
|
|
|
+
|
|
|
+ /* make sure category field is present */
|
|
|
+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
|
|
|
+ return RX_DROP_MONITOR;
|
|
|
+
|
|
|
mgmt = (struct ieee80211_mgmt *)hdr;
|
|
|
category = mgmt->u.action.category;
|
|
|
if (category != WLAN_CATEGORY_MESH_ACTION &&
|
|
@@ -1892,6 +1897,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
|
|
|
|
|
hdr = (struct ieee80211_hdr *) skb->data;
|
|
|
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
|
|
+
|
|
|
+ /* make sure fixed part of mesh header is there, also checks skb len */
|
|
|
+ if (!pskb_may_pull(rx->skb, hdrlen + 6))
|
|
|
+ return RX_DROP_MONITOR;
|
|
|
+
|
|
|
+ mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
|
|
|
+
|
|
|
+ /* make sure full mesh header is there, also checks skb len */
|
|
|
+ if (!pskb_may_pull(rx->skb,
|
|
|
+ hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
|
|
|
+ return RX_DROP_MONITOR;
|
|
|
+
|
|
|
+ /* reload pointers */
|
|
|
+ hdr = (struct ieee80211_hdr *) skb->data;
|
|
|
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
|
|
|
|
|
|
/* frame is in RMC, don't forward */
|
|
@@ -1915,9 +1934,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
|
|
if (is_multicast_ether_addr(hdr->addr1)) {
|
|
|
mpp_addr = hdr->addr3;
|
|
|
proxied_addr = mesh_hdr->eaddr1;
|
|
|
- } else {
|
|
|
+ } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
|
|
|
+ /* has_a4 already checked in ieee80211_rx_mesh_check */
|
|
|
mpp_addr = hdr->addr4;
|
|
|
proxied_addr = mesh_hdr->eaddr2;
|
|
|
+ } else {
|
|
|
+ return RX_DROP_MONITOR;
|
|
|
}
|
|
|
|
|
|
rcu_read_lock();
|
|
@@ -2354,6 +2376,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|
|
}
|
|
|
break;
|
|
|
case WLAN_CATEGORY_SELF_PROTECTED:
|
|
|
+ if (len < (IEEE80211_MIN_ACTION_SIZE +
|
|
|
+ sizeof(mgmt->u.action.u.self_prot.action_code)))
|
|
|
+ break;
|
|
|
+
|
|
|
switch (mgmt->u.action.u.self_prot.action_code) {
|
|
|
case WLAN_SP_MESH_PEERING_OPEN:
|
|
|
case WLAN_SP_MESH_PEERING_CLOSE:
|
|
@@ -2372,6 +2398,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|
|
}
|
|
|
break;
|
|
|
case WLAN_CATEGORY_MESH_ACTION:
|
|
|
+ if (len < (IEEE80211_MIN_ACTION_SIZE +
|
|
|
+ sizeof(mgmt->u.action.u.mesh_action.action_code)))
|
|
|
+ break;
|
|
|
+
|
|
|
if (!ieee80211_vif_is_mesh(&sdata->vif))
|
|
|
break;
|
|
|
if (mesh_action_is_path_sel(mgmt) &&
|