summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorstsp <stsp@openbsd.org>2020-02-18 08:29:35 +0000
committerstsp <stsp@openbsd.org>2020-02-18 08:29:35 +0000
commit774cd68c72db9a16e7653dacd99590787afb74e6 (patch)
tree7e5a38608af7d635a1c935db9188853925a1a59a /sys/net80211
parentAdd IPv6 support to umb(4). (diff)
downloadwireguard-openbsd-774cd68c72db9a16e7653dacd99590787afb74e6.tar.xz
wireguard-openbsd-774cd68c72db9a16e7653dacd99590787afb74e6.zip
Fix an mbuf corruption issue which occurs in net80211 hostap mode.
When sizing a memory allocation for a probe response frame, the AP used the SSID length stored in the node structure which represents the client, but used the actual length of the SSID when copying it into the frame. If the actual length is sufficiently large this will result in corruption of an adjacent mbuf on the free list since m->m_next will be overwritten with data written to the tail of the probe response frame. Bad things happen later on when the adjacent mbuf is used. Sometimes the corruption is detected by mbufpl's use-after-free checking, at other times we end up crashing somewhere in the network stack. To prevent such a mistake from occuring again I am removing the 'ni' argument from ieee80211_get_probe_resp() altogether. It is not needed. A quick workaround is to configure a short SSID. Debugged with help from claudio, kettenis, and dlg. ok claudio
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_output.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 37cf81c8f2e..6880f7fc2d7 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_output.c,v 1.126 2019/07/29 10:50:09 stsp Exp $ */
+/* $OpenBSD: ieee80211_output.c,v 1.127 2020/02/18 08:29:35 stsp Exp $ */
/* $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $ */
/*-
@@ -73,8 +73,7 @@ struct mbuf *ieee80211_getmgmt(int, int, u_int);
struct mbuf *ieee80211_get_probe_req(struct ieee80211com *,
struct ieee80211_node *);
#ifndef IEEE80211_STA_ONLY
-struct mbuf *ieee80211_get_probe_resp(struct ieee80211com *,
- struct ieee80211_node *);
+struct mbuf *ieee80211_get_probe_resp(struct ieee80211com *);
#endif
struct mbuf *ieee80211_get_auth(struct ieee80211com *,
struct ieee80211_node *, u_int16_t, u_int16_t);
@@ -1239,7 +1238,7 @@ ieee80211_get_probe_req(struct ieee80211com *ic, struct ieee80211_node *ni)
* [tlv] HT Operation (802.11n)
*/
struct mbuf *
-ieee80211_get_probe_resp(struct ieee80211com *ic, struct ieee80211_node *ni)
+ieee80211_get_probe_resp(struct ieee80211com *ic)
{
const struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
struct mbuf *m;
@@ -1247,7 +1246,7 @@ ieee80211_get_probe_resp(struct ieee80211com *ic, struct ieee80211_node *ni)
m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA,
8 + 2 + 2 +
- 2 + ni->ni_esslen +
+ 2 + ic->ic_bss->ni_esslen +
2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) +
2 + 1 +
((ic->ic_opmode == IEEE80211_M_IBSS) ? 2 + 2 : 0) +
@@ -1268,13 +1267,13 @@ ieee80211_get_probe_resp(struct ieee80211com *ic, struct ieee80211_node *ni)
frm = mtod(m, u_int8_t *);
memset(frm, 0, 8); frm += 8; /* timestamp is set by hardware */
LE_WRITE_2(frm, ic->ic_bss->ni_intval); frm += 2;
- frm = ieee80211_add_capinfo(frm, ic, ni);
+ frm = ieee80211_add_capinfo(frm, ic, ic->ic_bss);
frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid,
ic->ic_bss->ni_esslen);
frm = ieee80211_add_rates(frm, rs);
- frm = ieee80211_add_ds_params(frm, ic, ni);
+ frm = ieee80211_add_ds_params(frm, ic, ic->ic_bss);
if (ic->ic_opmode == IEEE80211_M_IBSS)
- frm = ieee80211_add_ibss_params(frm, ni);
+ frm = ieee80211_add_ibss_params(frm, ic->ic_bss);
if (ic->ic_curmode == IEEE80211_MODE_11G)
frm = ieee80211_add_erp(frm, ic);
if (rs->rs_nrates > IEEE80211_RATE_SIZE)
@@ -1777,7 +1776,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
break;
#ifndef IEEE80211_STA_ONLY
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
- if ((m = ieee80211_get_probe_resp(ic, ni)) == NULL)
+ if ((m = ieee80211_get_probe_resp(ic)) == NULL)
senderr(ENOMEM, is_tx_nombuf);
break;
#endif