diff --git a/wpa_supplicant-0.6.4-handle-invalid-ies.patch b/wpa_supplicant-0.6.4-handle-invalid-ies.patch new file mode 100644 index 0000000..e012f3c --- /dev/null +++ b/wpa_supplicant-0.6.4-handle-invalid-ies.patch @@ -0,0 +1,85 @@ +commit fd630bc183fb79d0a14b5f3a346544f3d277bd05 +Author: Jouni Malinen +Date: Wed Aug 27 09:52:16 2008 +0300 + + Fixed WEXT scan result parser to not crash on invalid IEs (zero len buffer) + + If IWEVGENIE or custom event wpa_ie/rsn_ie is received in scan with empty + buffer, the previous version ended up calling realloc(NULL, 0) which seems + to return a non-NULL value in some cases. When this return value is passed + again into realloc with realloc(ptr, 0), the returned value could be NULL. + If the ptr is then freed (os_free(data.ie) in SIOCGIWAP handling), glibc + may crash due to invalid pointer being freed (or double-freed?). The + non-NULL realloc(NULL, 0) return value from glibc looks a bit odd behavior, + but anyway, better avoid this case completely and just skip the IE events + that have an empty buffer. + + This issue should not show up with drivers that produce proper scan results + since the IEs will always include the two-octet header. However, it seems + to be possible to see this when using 64-bit kernel and 32-bit userspace + with incorrect compat-ioctl processing. + +diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c +index 45e3e1f..98dddd6 100644 +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -1618,6 +1618,9 @@ static void wext_get_scan_iwevgenie(struct iw_event *iwe, + char *genie, *gpos, *gend; + u8 *tmp; + ++ if (iwe->u.data.length == 0) ++ return; ++ + gpos = genie = custom; + gend = genie + iwe->u.data.length; + if (gend > end) { +@@ -1650,7 +1653,7 @@ static void wext_get_scan_custom(struct iw_event *iwe, + int bytes; + spos = custom + 7; + bytes = custom + clen - spos; +- if (bytes & 1) ++ if (bytes & 1 || bytes == 0) + return; + bytes /= 2; + tmp = os_realloc(res->ie, res->ie_len + bytes); +@@ -1664,7 +1667,7 @@ static void wext_get_scan_custom(struct iw_event *iwe, + int bytes; + spos = custom + 7; + bytes = custom + clen - spos; +- if (bytes & 1) ++ if (bytes & 1 || bytes == 0) + return; + bytes /= 2; + tmp = os_realloc(res->ie, res->ie_len + bytes); +diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c +index 6aac427..a3c4733 100644 +--- a/src/drivers/driver_wext.c ++++ b/src/drivers/driver_wext.c +@@ -1447,6 +1447,9 @@ static void wext_get_scan_iwevgenie(struct iw_event *iwe, + char *genie, *gpos, *gend; + u8 *tmp; + ++ if (iwe->u.data.length == 0) ++ return; ++ + gpos = genie = custom; + gend = genie + iwe->u.data.length; + if (gend > end) { +@@ -1479,7 +1482,7 @@ static void wext_get_scan_custom(struct iw_event *iwe, + int bytes; + spos = custom + 7; + bytes = custom + clen - spos; +- if (bytes & 1) ++ if (bytes & 1 || bytes == 0) + return; + bytes /= 2; + tmp = os_realloc(res->ie, res->ie_len + bytes); +@@ -1493,7 +1496,7 @@ static void wext_get_scan_custom(struct iw_event *iwe, + int bytes; + spos = custom + 7; + bytes = custom + clen - spos; +- if (bytes & 1) ++ if (bytes & 1 || bytes == 0) + return; + bytes /= 2; + tmp = os_realloc(res->ie, res->ie_len + bytes); diff --git a/wpa_supplicant-0.6.4-scan-fixes-1.patch b/wpa_supplicant-0.6.4-scan-fixes-1.patch new file mode 100644 index 0000000..832756a --- /dev/null +++ b/wpa_supplicant-0.6.4-scan-fixes-1.patch @@ -0,0 +1,23 @@ +commit 2064c2f98515016c376f3b69bfe161c85639e764 +Author: Dan Nicholson +Date: Wed Sep 24 12:48:33 2008 +0300 + + Restore scan request settings if initial association failed + + The scan path to initiate another scan if the initial association failed + was broken due to wpa_s->scan_req being zeroed earlier in + wpa_supplicant_scan(). This caused the second scan to bail out early + since it thought this was not a requested scan. + +diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c +index c2549e2..8767109 100644 +--- a/wpa_supplicant/scan.c ++++ b/wpa_supplicant/scan.c +@@ -137,6 +137,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) + if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 && + !wpa_s->use_client_mlme) { + wpa_s->scan_res_tried++; ++ wpa_s->scan_req = scan_req; + wpa_printf(MSG_DEBUG, "Trying to get current scan results " + "first without requesting a new scan to speed up " + "initial association"); diff --git a/wpa_supplicant-0.6.4-scan-fixes-2.patch b/wpa_supplicant-0.6.4-scan-fixes-2.patch new file mode 100644 index 0000000..3e8a3dd --- /dev/null +++ b/wpa_supplicant-0.6.4-scan-fixes-2.patch @@ -0,0 +1,37 @@ +commit 23e072374ea500002b8beec5d0e87f9fc6a7609c +Author: Dan Nicholson +Date: Wed Sep 24 12:51:08 2008 +0300 + + Don't post scan results when initial scan is emtpy + + When the initial scan is made, just the cached results from the driver + are used. If this is empty, it's useless to post the results since + another scan is being scheduled immediately. This just causes extra + processing from listeners for no gain. + +diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c +index 0f9b338..04e3152 100644 +--- a/wpa_supplicant/events.c ++++ b/wpa_supplicant/events.c +@@ -551,9 +551,18 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) + goto req_scan; + } + +- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); +- +- wpa_supplicant_dbus_notify_scan_results(wpa_s); ++ /* ++ * Don't post the results if this was the initial cached ++ * and there were no results. ++ */ ++ if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1 && ++ wpa_s->scan_res->num == 0) { ++ wpa_msg(wpa_s, MSG_DEBUG, "Cached scan results are " ++ "empty - not posting"); ++ } else { ++ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); ++ wpa_supplicant_dbus_notify_scan_results(wpa_s); ++ } + + if (wpa_s->conf->ap_scan == 2 || wpa_s->disconnected) + return; diff --git a/wpa_supplicant-0.6.4-set-mode-handler.patch b/wpa_supplicant-0.6.4-set-mode-handler.patch new file mode 100644 index 0000000..dbd0586 --- /dev/null +++ b/wpa_supplicant-0.6.4-set-mode-handler.patch @@ -0,0 +1,144 @@ +commit ec5f180a24cd31ba9d3d7f2abc9dc557fd16602f +Author: Dan Williams +Date: Mon Sep 29 16:45:49 2008 +0300 + + Add an optional set_mode() driver_ops handler for setting mode before keys + + A bug just got reported as a result of this for mac80211 drivers. + + https://bugzilla.redhat.com/show_bug.cgi?id=459399 + + The basic problem is that since taking the device down clears the keys + from the driver on many mac80211-based cards, and since the mode gets + set _after_ the keys have been set in the driver, the keys get cleared + on a mode switch and the resulting association is wrong. The report is + about ad-hoc mode specifically, but this could happen when switching + from adhoc back to managed mode. + +diff --git a/src/drivers/driver.h b/src/drivers/driver.h +index 70dc075..77a2ceb 100644 +--- a/src/drivers/driver.h ++++ b/src/drivers/driver.h +@@ -929,6 +929,20 @@ struct wpa_driver_ops { + * Returns: 0 on success, -1 on failure + */ + int (*set_probe_req_ie)(void *, const u8 *ies, size_t ies_len); ++ ++ /** ++ * set_mode - Request driver to set the operating mode ++ * @priv: private driver interface data ++ * @mode: Operation mode (infra/ibss) IEEE80211_MODE_* ++ * ++ * This handler will be called before any key configuration and call to ++ * associate() handler in order to allow the operation mode to be ++ * configured as early as possible. This information is also available ++ * in associate() params and as such, some driver wrappers may not need ++ * to implement set_mode() handler. ++ * Returns: 0 on success, -1 on failure ++ */ ++ int (*set_mode)(void *priv, int mode); + }; + + /** +diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c +index da4f90f..f55bd2e 100644 +--- a/src/drivers/driver_ndis.c ++++ b/src/drivers/driver_ndis.c +@@ -2829,5 +2829,7 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = { + NULL /* mlme_remove_sta */, + NULL /* update_ft_ies */, + NULL /* send_ft_action */, +- wpa_driver_ndis_get_scan_results ++ wpa_driver_ndis_get_scan_results, ++ NULL /* set_probe_req_ie */, ++ NULL /* set_mode */ + }; +diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c +index 98dddd6..a207363 100644 +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -2226,8 +2226,6 @@ static int wpa_driver_nl80211_associate( + wpa_driver_nl80211_set_bssid(drv, NULL) < 0) + ret = -1; + +- if (wpa_driver_nl80211_set_mode(drv, params->mode) < 0) +- ret = -1; + /* TODO: should consider getting wpa version and cipher/key_mgmt suites + * from configuration, not from here, where only the selected suite is + * available */ +@@ -2859,6 +2857,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { + .get_scan_results2 = wpa_driver_nl80211_get_scan_results, + .deauthenticate = wpa_driver_nl80211_deauthenticate, + .disassociate = wpa_driver_nl80211_disassociate, ++ .set_mode = wpa_driver_nl80211_set_mode, + .associate = wpa_driver_nl80211_associate, + .set_auth_alg = wpa_driver_nl80211_set_auth_alg, + .init = wpa_driver_nl80211_init, +diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c +index 5c6e6f1..7f7f129 100644 +--- a/src/drivers/driver_test.c ++++ b/src/drivers/driver_test.c +@@ -982,5 +982,6 @@ const struct wpa_driver_ops wpa_driver_test_ops = { + NULL /* update_ft_ies */, + NULL /* send_ft_action */, + wpa_driver_test_get_scan_results2, +- NULL /* set_probe_req_ie */ ++ NULL /* set_probe_req_ie */, ++ NULL /* set_mode */ + }; +diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c +index 6b7f1a7..a618a74 100644 +--- a/src/drivers/driver_wext.c ++++ b/src/drivers/driver_wext.c +@@ -2206,8 +2206,6 @@ int wpa_driver_wext_associate(void *priv, + wpa_driver_wext_set_bssid(drv, NULL) < 0) + ret = -1; + +- if (wpa_driver_wext_set_mode(drv, params->mode) < 0) +- ret = -1; + /* TODO: should consider getting wpa version and cipher/key_mgmt suites + * from configuration, not from here, where only the selected suite is + * available */ +@@ -2782,6 +2780,7 @@ const struct wpa_driver_ops wpa_driver_wext_ops = { + .get_scan_results2 = wpa_driver_wext_get_scan_results, + .deauthenticate = wpa_driver_wext_deauthenticate, + .disassociate = wpa_driver_wext_disassociate, ++ .set_mode = wpa_driver_wext_set_mode, + .associate = wpa_driver_wext_associate, + .set_auth_alg = wpa_driver_wext_set_auth_alg, + .init = wpa_driver_wext_init, +diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c +index 4c9482f..a36c65b 100644 +--- a/wpa_supplicant/wpa_supplicant.c ++++ b/wpa_supplicant/wpa_supplicant.c +@@ -937,6 +937,11 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, + * previous association. */ + wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); + ++ if (wpa_drv_set_mode(wpa_s, ssid->mode)) { ++ wpa_printf(MSG_WARNING, "Failed to set operating mode"); ++ assoc_failed = 1; ++ } ++ + #ifdef IEEE8021X_EAPOL + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { + if (ssid->leap) { +diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h +index a2e3dd5..9afae2a 100644 +--- a/wpa_supplicant/wpa_supplicant_i.h ++++ b/wpa_supplicant/wpa_supplicant_i.h +@@ -448,6 +448,14 @@ static inline int wpa_drv_set_wpa(struct wpa_supplicant *wpa_s, int enabled) + return 0; + } + ++static inline int wpa_drv_set_mode(struct wpa_supplicant *wpa_s, int mode) ++{ ++ if (wpa_s->driver->set_mode) { ++ return wpa_s->driver->set_mode(wpa_s->drv_priv, mode); ++ } ++ return 0; ++} ++ + static inline int wpa_drv_associate(struct wpa_supplicant *wpa_s, + struct wpa_driver_associate_params *params) + { diff --git a/wpa_supplicant-0.6.4-validate-wext-event.patch b/wpa_supplicant-0.6.4-validate-wext-event.patch new file mode 100644 index 0000000..769a010 --- /dev/null +++ b/wpa_supplicant-0.6.4-validate-wext-event.patch @@ -0,0 +1,65 @@ +commit 36b5e559f1387d4e02059753ecfb04461d62f381 +Author: Jouni Malinen +Date: Sat Sep 27 10:49:56 2008 +0300 + + Validate WEXT event iwe->u.data.length before using the event data + + This is needed to avoid crashing wpa_supplicant with invalid event messages + that may be received when using 64-bit kernel with 32-bit userspace. + +diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c +index a3c4733..6b7f1a7 100644 +--- a/src/drivers/driver_wext.c ++++ b/src/drivers/driver_wext.c +@@ -652,12 +652,20 @@ static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, + } + break; + case IWEVMICHAELMICFAILURE: ++ if (custom + iwe->u.data.length > end) { ++ wpa_printf(MSG_DEBUG, "WEXT: Invalid " ++ "IWEVMICHAELMICFAILURE length"); ++ return; ++ } + wpa_driver_wext_event_wireless_michaelmicfailure( + ctx, custom, iwe->u.data.length); + break; + case IWEVCUSTOM: +- if (custom + iwe->u.data.length > end) ++ if (custom + iwe->u.data.length > end) { ++ wpa_printf(MSG_DEBUG, "WEXT: Invalid " ++ "IWEVCUSTOM length"); + return; ++ } + buf = os_malloc(iwe->u.data.length + 1); + if (buf == NULL) + return; +@@ -673,14 +681,29 @@ static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, + wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL); + break; + case IWEVASSOCREQIE: ++ if (custom + iwe->u.data.length > end) { ++ wpa_printf(MSG_DEBUG, "WEXT: Invalid " ++ "IWEVASSOCREQIE length"); ++ return; ++ } + wpa_driver_wext_event_wireless_assocreqie( + drv, custom, iwe->u.data.length); + break; + case IWEVASSOCRESPIE: ++ if (custom + iwe->u.data.length > end) { ++ wpa_printf(MSG_DEBUG, "WEXT: Invalid " ++ "IWEVASSOCRESPIE length"); ++ return; ++ } + wpa_driver_wext_event_wireless_assocrespie( + drv, custom, iwe->u.data.length); + break; + case IWEVPMKIDCAND: ++ if (custom + iwe->u.data.length > end) { ++ wpa_printf(MSG_DEBUG, "WEXT: Invalid " ++ "IWEVPMKIDCAND length"); ++ return; ++ } + wpa_driver_wext_event_wireless_pmkidcand( + drv, custom, iwe->u.data.length); + break;