wifi: avoid buffer overflow reading IEs

This commit is contained in:
Thomas Haller
2017-03-10 00:24:16 +01:00
committed by Beniamino Galvani
parent 961d572472
commit 2b64961d05

View File

@@ -625,10 +625,21 @@ get_max_rate_vht_160_ss3 (int mcs)
return 0; return 0;
} }
static guint32 static gboolean
get_max_rate_ht (guint16 ht_cap_info, const guint8 *supported_mcs_set) get_max_rate_ht (const guint8 *bytes, guint len, guint32 *out_maxrate)
{ {
guint32 mcs, i, j; guint32 mcs, i, j, m;
guint8 ht_cap_info;
const guint8 *supported_mcs_set;
/* https://mrncciew.com/2014/10/19/cwap-ht-capabilities-ie/
http://luci.subsignal.org/~jow/802.11n-2009.pdf */
if (len != 26)
return FALSE;
ht_cap_info = bytes[0];
supported_mcs_set = &bytes[3];
/* Find the maximum supported mcs rate */ /* Find the maximum supported mcs rate */
mcs = -1; mcs = -1;
@@ -642,42 +653,57 @@ get_max_rate_ht (guint16 ht_cap_info, const guint8 *supported_mcs_set)
/* Check for 40Mhz wide channel support */ /* Check for 40Mhz wide channel support */
if (ht_cap_info & (1 << 1)) if (ht_cap_info & (1 << 1))
return get_max_rate_ht_40 (mcs); m = get_max_rate_ht_40 (mcs);
else else
return get_max_rate_ht_20 (mcs); m = get_max_rate_ht_20 (mcs);
*out_maxrate = m;
return TRUE;
} }
static guint32 static gboolean
get_max_rate_vht (guint32 vht_cap, guint16 tx_map) get_max_rate_vht (const guint8 *bytes, guint len, guint32 *out_maxrate)
{ {
guint32 mcs = 7; guint32 mcs, m;
guint8 vht_cap, tx_map;
/* https://tda802dot11.blogspot.it/2014/10/vht-capabilities-element-vht.html
* http://chimera.labs.oreilly.com/books/1234000001739/ch03.html#management_frames */
if (len != 12)
return FALSE;
vht_cap = bytes[0];
tx_map = bytes[8];
/* Check for mcs rates 8 and 9 support */ /* Check for mcs rates 8 and 9 support */
if (tx_map & 0x2a) if (tx_map & 0x2a)
mcs = 9; mcs = 9;
else if (tx_map & 0x15) else if (tx_map & 0x15)
mcs = 8; mcs = 8;
else
mcs = 7;
/* Check for 160Mhz wide channel support and /* Check for 160Mhz wide channel support and
* spatial stream support */ * spatial stream support */
if (vht_cap & (1 << 2)) { if (vht_cap & (1 << 2)) {
if (tx_map & 0x30) if (tx_map & 0x30)
return get_max_rate_vht_160_ss3 (mcs); m = get_max_rate_vht_160_ss3 (mcs);
else if (tx_map & 0x0C) else if (tx_map & 0x0C)
return get_max_rate_vht_160_ss2 (mcs); m = get_max_rate_vht_160_ss2 (mcs);
else else
return get_max_rate_vht_160_ss1 (mcs); m = get_max_rate_vht_160_ss1 (mcs);
} else { } else {
if (tx_map & 0x30) if (tx_map & 0x30)
return get_max_rate_vht_80_ss3 (mcs); m = get_max_rate_vht_80_ss3 (mcs);
else if (tx_map & 0x0C) else if (tx_map & 0x0C)
return get_max_rate_vht_80_ss2 (mcs); m = get_max_rate_vht_80_ss2 (mcs);
else else
return get_max_rate_vht_80_ss1 (mcs); m = get_max_rate_vht_80_ss1 (mcs);
} }
return 0; *out_maxrate = m;
return TRUE;
} }
/* Management Frame Information Element IDs, ieee80211_eid */ /* Management Frame Information Element IDs, ieee80211_eid */
@@ -691,6 +717,8 @@ get_max_rate (const guint8 *bytes, gsize len)
guint32 max_rate = 0; guint32 max_rate = 0;
while (len) { while (len) {
guint32 m;
if (len < 2) if (len < 2)
return 0; return 0;
@@ -703,10 +731,14 @@ get_max_rate (const guint8 *bytes, gsize len)
switch (id) { switch (id) {
case WLAN_EID_HT_CAPABILITY: case WLAN_EID_HT_CAPABILITY:
max_rate = NM_MAX (max_rate, get_max_rate_ht (*bytes, bytes+3)); if (!get_max_rate_ht (bytes, elem_len, &m))
return 0;
max_rate = NM_MAX (max_rate, m);
break; break;
case WLAN_EID_VHT_CAPABILITY: case WLAN_EID_VHT_CAPABILITY:
max_rate = NM_MAX (max_rate, get_max_rate_vht (*bytes, *(bytes+8))); if (!get_max_rate_vht (bytes, elem_len, &m))
return 0;
max_rate = NM_MAX (max_rate, m);
break; break;
} }