From 80279fb7ba5b71981a60988b0307afa43f78f6b1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 May 2015 16:22:20 +0200 Subject: cfg80211: properly send NL80211_ATTR_DISCONNECTED_BY_AP in disconnect When we disconnect from the AP, drivers call cfg80211_disconnect(). This doesn't know whether the disconnection was initiated locally or by the AP though, which can cause problems with the supplicant, for example with WPS. This issue obviously doesn't show up with any mac80211 based driver since mac80211 doesn't call this function. Fix this by requiring drivers to indicate whether the disconnect is locally generated or not. I've tried to update the drivers, but may not have gotten the values correct, and some drivers may currently not be able to report correct values. In case of doubt I left it at false, which is the current behaviour. For libertas, make adjustments as indicated by Dan Williams. Reported-by: Matthieu Mauger Tested-by: Matthieu Mauger Signed-off-by: Johannes Berg --- net/wireless/util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/wireless/util.c') diff --git a/net/wireless/util.c b/net/wireless/util.c index 70051ab52f4f..4cb34557b873 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -887,7 +887,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) case EVENT_DISCONNECTED: __cfg80211_disconnected(wdev->netdev, ev->dc.ie, ev->dc.ie_len, - ev->dc.reason, true); + ev->dc.reason, + !ev->dc.locally_generated); break; case EVENT_IBSS_JOINED: __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, -- cgit v1.2.3 From 6cbfb1bb66e4e85da5db78e8ff429a85bd84ce64 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 22 May 2015 10:57:22 +0200 Subject: cfg80211: ignore netif running state when changing iftype It was possible for mac80211 to be coerced into an unexpected flow causing sdata union to become corrupted. Station pointer was put into sdata->u.vlan.sta memory location while it was really master AP's sdata->u.ap.next_beacon. This led to station entry being later freed as next_beacon before __sta_info_flush() in ieee80211_stop_ap() and a subsequent invalid pointer dereference crash. The problem was that ieee80211_ptr->use_4addr wasn't cleared on interface type changes. This could be reproduced with the following steps: # host A and host B have just booted; no # wpa_s/hostapd running; all vifs are down host A> iw wlan0 set type station host A> iw wlan0 set 4addr on host A> printf 'interface=wlan0\nssid=4addrcrash\nchannel=1\nwds_sta=1' > /tmp/hconf host A> hostapd -B /tmp/conf host B> iw wlan0 set 4addr on host B> ifconfig wlan0 up host B> iw wlan0 connect -w hostAssid host A> pkill hostapd # host A crashed: [ 127.928192] BUG: unable to handle kernel NULL pointer dereference at 00000000000006c8 [ 127.929014] IP: [] __sta_info_flush+0xac/0x158 ... [ 127.934578] [] ieee80211_stop_ap+0x139/0x26c [ 127.934578] [] ? dump_trace+0x279/0x28a [ 127.934578] [] __cfg80211_stop_ap+0x84/0x191 [ 127.934578] [] cfg80211_stop_ap+0x3f/0x58 [ 127.934578] [] nl80211_stop_ap+0x1b/0x1d [ 127.934578] [] genl_family_rcv_msg+0x259/0x2b5 Note: This isn't a revert of f8cdddb8d61d ("cfg80211: check iface combinations only when iface is running") as far as functionality is considered because b6a550156bc ("cfg80211/mac80211: move more combination checks to mac80211") moved the logic somewhere else already. Fixes: f8cdddb8d61d ("cfg80211: check iface combinations only when iface is running") Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg --- net/wireless/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/wireless/util.c') diff --git a/net/wireless/util.c b/net/wireless/util.c index 4cb34557b873..baf7218cec15 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -945,7 +945,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, ntype == NL80211_IFTYPE_P2P_CLIENT)) return -EBUSY; - if (ntype != otype && netif_running(dev)) { + if (ntype != otype) { dev->ieee80211_ptr->use_4addr = false; dev->ieee80211_ptr->mesh_id_up_len = 0; wdev_lock(dev->ieee80211_ptr); -- cgit v1.2.3