Skip to content

Commit efec22b

Browse files
committed
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
2 parents f89ff64 + 6dbda2d commit efec22b

File tree

7 files changed

+113
-36
lines changed

7 files changed

+113
-36
lines changed

include/net/cfg80211.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2651,6 +2651,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
26512651
*/
26522652
unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
26532653

2654+
/**
2655+
* ieee80211_get_mesh_hdrlen - get mesh extension header length
2656+
* @meshhdr: the mesh extension header, only the flags field
2657+
* (first byte) will be accessed
2658+
* Returns the length of the extension header, which is always at
2659+
* least 6 bytes and at most 18 if address 5 and 6 are present.
2660+
*/
2661+
unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
2662+
26542663
/**
26552664
* DOC: Data path helpers
26562665
*

net/mac80211/ibss.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
11081108
sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
11091109
sdata->u.ibss.ibss_join_req = jiffies;
11101110

1111-
memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
1111+
memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
11121112
sdata->u.ibss.ssid_len = params->ssid_len;
11131113

11141114
mutex_unlock(&sdata->u.ibss.mtx);

net/mac80211/rx.c

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
531531

532532
if (ieee80211_is_action(hdr->frame_control)) {
533533
u8 category;
534+
535+
/* make sure category field is present */
536+
if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
537+
return RX_DROP_MONITOR;
538+
534539
mgmt = (struct ieee80211_mgmt *)hdr;
535540
category = mgmt->u.action.category;
536541
if (category != WLAN_CATEGORY_MESH_ACTION &&
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
883888
*/
884889
if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
885890
ieee80211_is_data_present(hdr->frame_control)) {
886-
u16 ethertype;
887-
u8 *payload;
888-
889-
payload = rx->skb->data +
890-
ieee80211_hdrlen(hdr->frame_control);
891-
ethertype = (payload[6] << 8) | payload[7];
892-
if (cpu_to_be16(ethertype) ==
893-
rx->sdata->control_port_protocol)
891+
unsigned int hdrlen;
892+
__be16 ethertype;
893+
894+
hdrlen = ieee80211_hdrlen(hdr->frame_control);
895+
896+
if (rx->skb->len < hdrlen + 8)
897+
return RX_DROP_MONITOR;
898+
899+
skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
900+
if (ethertype == rx->sdata->control_port_protocol)
894901
return RX_CONTINUE;
895902
}
896903

@@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
14621469

14631470
hdr = (struct ieee80211_hdr *)rx->skb->data;
14641471
fc = hdr->frame_control;
1472+
1473+
if (ieee80211_is_ctl(fc))
1474+
return RX_CONTINUE;
1475+
14651476
sc = le16_to_cpu(hdr->seq_ctrl);
14661477
frag = sc & IEEE80211_SCTL_FRAG;
14671478

14681479
if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
1469-
(rx->skb)->len < 24 ||
14701480
is_multicast_ether_addr(hdr->addr1))) {
14711481
/* not fragmented */
14721482
goto out;
@@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
18891899

18901900
hdr = (struct ieee80211_hdr *) skb->data;
18911901
hdrlen = ieee80211_hdrlen(hdr->frame_control);
1902+
1903+
/* make sure fixed part of mesh header is there, also checks skb len */
1904+
if (!pskb_may_pull(rx->skb, hdrlen + 6))
1905+
return RX_DROP_MONITOR;
1906+
1907+
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1908+
1909+
/* make sure full mesh header is there, also checks skb len */
1910+
if (!pskb_may_pull(rx->skb,
1911+
hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
1912+
return RX_DROP_MONITOR;
1913+
1914+
/* reload pointers */
1915+
hdr = (struct ieee80211_hdr *) skb->data;
18921916
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
18931917

18941918
/* frame is in RMC, don't forward */
@@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
18971921
mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
18981922
return RX_DROP_MONITOR;
18991923

1900-
if (!ieee80211_is_data(hdr->frame_control))
1924+
if (!ieee80211_is_data(hdr->frame_control) ||
1925+
!(status->rx_flags & IEEE80211_RX_RA_MATCH))
19011926
return RX_CONTINUE;
19021927

19031928
if (!mesh_hdr->ttl)
@@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
19111936
if (is_multicast_ether_addr(hdr->addr1)) {
19121937
mpp_addr = hdr->addr3;
19131938
proxied_addr = mesh_hdr->eaddr1;
1914-
} else {
1939+
} else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
1940+
/* has_a4 already checked in ieee80211_rx_mesh_check */
19151941
mpp_addr = hdr->addr4;
19161942
proxied_addr = mesh_hdr->eaddr2;
1943+
} else {
1944+
return RX_DROP_MONITOR;
19171945
}
19181946

19191947
rcu_read_lock();
@@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
19411969
}
19421970
skb_set_queue_mapping(skb, q);
19431971

1944-
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
1945-
goto out;
1946-
19471972
if (!--mesh_hdr->ttl) {
19481973
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
1949-
return RX_DROP_MONITOR;
1974+
goto out;
19501975
}
19511976

19521977
if (!ifmsh->mshcfg.dot11MeshForwarding)
@@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
23532378
}
23542379
break;
23552380
case WLAN_CATEGORY_SELF_PROTECTED:
2381+
if (len < (IEEE80211_MIN_ACTION_SIZE +
2382+
sizeof(mgmt->u.action.u.self_prot.action_code)))
2383+
break;
2384+
23562385
switch (mgmt->u.action.u.self_prot.action_code) {
23572386
case WLAN_SP_MESH_PEERING_OPEN:
23582387
case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
23712400
}
23722401
break;
23732402
case WLAN_CATEGORY_MESH_ACTION:
2403+
if (len < (IEEE80211_MIN_ACTION_SIZE +
2404+
sizeof(mgmt->u.action.u.mesh_action.action_code)))
2405+
break;
2406+
23742407
if (!ieee80211_vif_is_mesh(&sdata->vif))
23752408
break;
23762409
if (mesh_action_is_path_sel(mgmt) &&
@@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
29132946
if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
29142947
local->dot11ReceivedFragmentCount++;
29152948

2916-
if (ieee80211_is_mgmt(fc))
2917-
err = skb_linearize(skb);
2918-
else
2949+
if (ieee80211_is_mgmt(fc)) {
2950+
/* drop frame if too short for header */
2951+
if (skb->len < ieee80211_hdrlen(fc))
2952+
err = -ENOBUFS;
2953+
else
2954+
err = skb_linearize(skb);
2955+
} else {
29192956
err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
2957+
}
29202958

29212959
if (err) {
29222960
dev_kfree_skb(skb);

net/mac80211/util.c

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
643643
break;
644644
}
645645

646-
if (id != WLAN_EID_VENDOR_SPECIFIC &&
647-
id != WLAN_EID_QUIET &&
648-
test_bit(id, seen_elems)) {
649-
elems->parse_error = true;
650-
left -= elen;
651-
pos += elen;
652-
continue;
646+
switch (id) {
647+
case WLAN_EID_SSID:
648+
case WLAN_EID_SUPP_RATES:
649+
case WLAN_EID_FH_PARAMS:
650+
case WLAN_EID_DS_PARAMS:
651+
case WLAN_EID_CF_PARAMS:
652+
case WLAN_EID_TIM:
653+
case WLAN_EID_IBSS_PARAMS:
654+
case WLAN_EID_CHALLENGE:
655+
case WLAN_EID_RSN:
656+
case WLAN_EID_ERP_INFO:
657+
case WLAN_EID_EXT_SUPP_RATES:
658+
case WLAN_EID_HT_CAPABILITY:
659+
case WLAN_EID_HT_OPERATION:
660+
case WLAN_EID_VHT_CAPABILITY:
661+
case WLAN_EID_VHT_OPERATION:
662+
case WLAN_EID_MESH_ID:
663+
case WLAN_EID_MESH_CONFIG:
664+
case WLAN_EID_PEER_MGMT:
665+
case WLAN_EID_PREQ:
666+
case WLAN_EID_PREP:
667+
case WLAN_EID_PERR:
668+
case WLAN_EID_RANN:
669+
case WLAN_EID_CHANNEL_SWITCH:
670+
case WLAN_EID_EXT_CHANSWITCH_ANN:
671+
case WLAN_EID_COUNTRY:
672+
case WLAN_EID_PWR_CONSTRAINT:
673+
case WLAN_EID_TIMEOUT_INTERVAL:
674+
if (test_bit(id, seen_elems)) {
675+
elems->parse_error = true;
676+
left -= elen;
677+
pos += elen;
678+
continue;
679+
}
680+
break;
653681
}
654682

655683
if (calc_crc && id < 64 && (filter & (1ULL << id)))

net/wireless/core.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy)
526526
for (i = 0; i < sband->n_channels; i++) {
527527
sband->channels[i].orig_flags =
528528
sband->channels[i].flags;
529-
sband->channels[i].orig_mag =
530-
sband->channels[i].max_antenna_gain;
529+
sband->channels[i].orig_mag = INT_MAX;
531530
sband->channels[i].orig_mpwr =
532531
sband->channels[i].max_power;
533532
sband->channels[i].band = band;

net/wireless/reg.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy,
908908
map_regdom_flags(reg_rule->flags) | bw_flags;
909909
chan->max_antenna_gain = chan->orig_mag =
910910
(int) MBI_TO_DBI(power_rule->max_antenna_gain);
911-
chan->max_power = chan->orig_mpwr =
911+
chan->max_reg_power = chan->max_power = chan->orig_mpwr =
912912
(int) MBM_TO_DBM(power_rule->max_eirp);
913913
return;
914914
}
@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
13311331

13321332
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
13331333
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1334-
chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1334+
chan->max_reg_power = chan->max_power =
1335+
(int) MBM_TO_DBM(power_rule->max_eirp);
13351336
}
13361337

13371338
static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,

net/wireless/util.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
309309
}
310310
EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
311311

312-
static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
312+
unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
313313
{
314314
int ae = meshhdr->flags & MESH_FLAGS_AE;
315-
/* 7.1.3.5a.2 */
315+
/* 802.11-2012, 8.2.4.7.3 */
316316
switch (ae) {
317+
default:
317318
case 0:
318319
return 6;
319320
case MESH_FLAGS_AE_A4:
320321
return 12;
321322
case MESH_FLAGS_AE_A5_A6:
322323
return 18;
323-
case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
324-
return 24;
325-
default:
326-
return 6;
327324
}
328325
}
326+
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
329327

330328
int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
331329
enum nl80211_iftype iftype)
@@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
373371
/* make sure meshdr->flags is on the linear part */
374372
if (!pskb_may_pull(skb, hdrlen + 1))
375373
return -1;
374+
if (meshdr->flags & MESH_FLAGS_AE_A4)
375+
return -1;
376376
if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
377377
skb_copy_bits(skb, hdrlen +
378378
offsetof(struct ieee80211s_hdr, eaddr1),
@@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
397397
/* make sure meshdr->flags is on the linear part */
398398
if (!pskb_may_pull(skb, hdrlen + 1))
399399
return -1;
400+
if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
401+
return -1;
400402
if (meshdr->flags & MESH_FLAGS_AE_A4)
401403
skb_copy_bits(skb, hdrlen +
402404
offsetof(struct ieee80211s_hdr, eaddr1),

0 commit comments

Comments
 (0)