diff --git a/0001-D-Bus-Fix-P2P-NULL-dereference-after-interface-remov.patch b/0001-D-Bus-Fix-P2P-NULL-dereference-after-interface-remov.patch new file mode 100644 index 0000000..277d1a2 --- /dev/null +++ b/0001-D-Bus-Fix-P2P-NULL-dereference-after-interface-remov.patch @@ -0,0 +1,209 @@ +From b2ad4e6b24ed0271ca76cb27856def0a701fb778 Mon Sep 17 00:00:00 2001 +From: Davide Caratti +Date: Wed, 2 Oct 2019 14:08:41 +0200 +Subject: [PATCH] D-Bus: Fix P2P NULL dereference after interface removal + +When the P2P management interface is deleted, P2P is then disabled and +global->p2p_init_wpa_s is set to NULL. After that, other interfaces can +still trigger P2P functions (like wpas_p2p_find()) using D-Bus. This +makes wpa_supplicant terminate with SIGSEGV, because it dereferences a +NULL pointer. Fix this by adding proper checks, like it's done with +wpa_cli. + +CC: Beniamino Galvani +CC: Benjamin Berg +Reported-by: Vladimir Benes +Signed-off-by: Davide Caratti +--- + wpa_supplicant/dbus/dbus_new_handlers_p2p.c | 69 ++++++++++++++++++++- + 1 file changed, 67 insertions(+), 2 deletions(-) + +diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +index 8cdd88564..19715eb4c 100644 +--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c ++++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +@@ -40,6 +40,14 @@ static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry) + } + + ++static dbus_bool_t no_p2p_mgmt_interface(DBusError *error) ++{ ++ dbus_set_error_const(error, WPAS_DBUS_ERROR_IFACE_UNKNOWN, ++ "Could not find P2P mgmt interface"); ++ return FALSE; ++} ++ ++ + /** + * Parses out the mac address from the peer object path. + * @peer_path - object path of the form +@@ -78,6 +86,22 @@ wpas_dbus_error_persistent_group_unknown(DBusMessage *message) + } + + ++/** ++ * wpas_dbus_error_no_p2p_mgmt_iface - Return a new InterfaceUnknown error ++ * message ++ * @message: Pointer to incoming dbus message this error refers to ++ * Returns: a dbus error message ++ * ++ * Convenience function to create and return an unknown interface error. ++ */ ++static DBusMessage * wpas_dbus_error_no_p2p_mgmt_iface(DBusMessage *message) ++{ ++ wpa_printf(MSG_DEBUG, "dbus: Could not find P2P mgmt interface"); ++ return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN, ++ "Could not find P2P mgmt interface"); ++} ++ ++ + DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message, + struct wpa_supplicant *wpa_s) + { +@@ -145,6 +169,10 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message, + } + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) { ++ reply = wpas_dbus_error_no_p2p_mgmt_iface(message); ++ goto error_nop2p; ++ } + + if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, + req_dev_types, NULL, 0, 0, NULL, freq)) +@@ -157,8 +185,9 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message, + error_clear: + wpa_dbus_dict_entry_clear(&entry); + error: +- os_free(req_dev_types); + reply = wpas_dbus_error_invalid_args(message, entry.key); ++error_nop2p: ++ os_free(req_dev_types); + return reply; + } + +@@ -166,7 +195,9 @@ error: + DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message, + struct wpa_supplicant *wpa_s) + { +- wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s); ++ wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (wpa_s) ++ wpas_p2p_stop_find(wpa_s); + return NULL; + } + +@@ -185,6 +216,8 @@ DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message, + return wpas_dbus_error_invalid_args(message, NULL); + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) ++ return wpas_dbus_error_no_p2p_mgmt_iface(message); + + if (wpas_p2p_reject(wpa_s, peer_addr) < 0) + return wpas_dbus_error_unknown_error(message, +@@ -204,6 +237,8 @@ DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message, + return wpas_dbus_error_no_memory(message); + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) ++ return wpas_dbus_error_no_p2p_mgmt_iface(message); + + if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) { + return dbus_message_new_error(message, +@@ -245,6 +280,8 @@ DBusMessage * wpas_dbus_handler_p2p_extendedlisten( + } + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) ++ return wpas_dbus_error_no_p2p_mgmt_iface(message); + + if (wpas_p2p_ext_listen(wpa_s, period, interval)) + return wpas_dbus_error_unknown_error( +@@ -350,6 +387,10 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message, + } + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) { ++ reply = wpas_dbus_error_no_p2p_mgmt_iface(message); ++ goto out; ++ } + + if (pg_object_path != NULL) { + char *net_id_str; +@@ -433,6 +474,12 @@ static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s, + "P2P is not available for this interface"); + return FALSE; + } ++ if (!wpa_s->global->p2p_init_wpa_s) { ++ if (out_reply) ++ *out_reply = wpas_dbus_error_no_p2p_mgmt_iface( ++ message); ++ return no_p2p_mgmt_interface(error); ++ } + return TRUE; + } + +@@ -822,6 +869,8 @@ DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message, + return wpas_dbus_error_invalid_args(message, NULL); + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) ++ return wpas_dbus_error_no_p2p_mgmt_iface(message); + + if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method, + WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0) +@@ -1882,6 +1931,8 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_groups( + + wpa_s = peer_args->wpa_s; + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) ++ return no_p2p_mgmt_interface(error); + + wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr); + if (wpa_s_go) { +@@ -1963,6 +2014,9 @@ dbus_bool_t wpas_dbus_getter_persistent_groups( + dbus_bool_t success = FALSE; + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) ++ return no_p2p_mgmt_interface(error); ++ + if (!wpa_s->parent->dbus_new_path) + return FALSE; + +@@ -2077,6 +2131,11 @@ DBusMessage * wpas_dbus_handler_add_persistent_group( + dbus_message_iter_init(message, &iter); + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) { ++ reply = wpas_dbus_error_no_p2p_mgmt_iface(message); ++ goto err; ++ } ++ + if (wpa_s->parent->dbus_new_path) + ssid = wpa_config_add_network(wpa_s->conf); + if (ssid == NULL) { +@@ -2159,6 +2218,10 @@ DBusMessage * wpas_dbus_handler_remove_persistent_group( + DBUS_TYPE_INVALID); + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) { ++ reply = wpas_dbus_error_no_p2p_mgmt_iface(message); ++ goto out; ++ } + + /* + * Extract the network ID and ensure the network is actually a child of +@@ -2235,6 +2298,8 @@ DBusMessage * wpas_dbus_handler_remove_all_persistent_groups( + struct wpa_config *config; + + wpa_s = wpa_s->global->p2p_init_wpa_s; ++ if (!wpa_s) ++ return wpas_dbus_error_no_p2p_mgmt_iface(message); + + config = wpa_s->conf; + ssid = config->ssid; +-- +2.26.2 + diff --git a/0001-P2P-Always-use-global-p2p_long_listen.patch b/0001-P2P-Always-use-global-p2p_long_listen.patch new file mode 100644 index 0000000..a617de8 --- /dev/null +++ b/0001-P2P-Always-use-global-p2p_long_listen.patch @@ -0,0 +1,111 @@ +From 9ad3c12dd1bf56824ef8b3425e057e8d1e84e69d Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Fri, 3 Jan 2020 22:18:51 +0100 +Subject: [PATCH] P2P: Always use global p2p_long_listen + +The p2p_long_listen value was set on the control wpa_s struct while in a +lot of cases it operated on the p2p struct. Explicitly use the global +p2p_init_wpa_s struct in cases where we might not be operating on it +already. + +Without this, simply starting a p2p_listen operation (e.g., using +wpa_cli) will not work properly. As the p2p_long_listen is set on the +controlling interface and wpas_p2p_cancel_remain_on_channel_cb() uses +p2p_init_wpa_s, it would not actually work. This results in +wpa_supplicant stopping listening after the maximum remain-on-channel +time passes when using a separate P2P Device interface. + +Signed-off-by: Benjamin Berg +--- + wpa_supplicant/p2p_supplicant.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c +index 95bacec19..a7d3b7f1d 100644 +--- a/wpa_supplicant/p2p_supplicant.c ++++ b/wpa_supplicant/p2p_supplicant.c +@@ -2422,7 +2422,7 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) + wpas_start_wps_enrollee(group_wpa_s, res); + } + +- wpa_s->p2p_long_listen = 0; ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = 0; + eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); + + eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL); +@@ -4750,7 +4750,8 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) + eloop_cancel_timeout(wpas_p2p_psk_failure_removal, wpa_s, NULL); + eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); +- wpa_s->p2p_long_listen = 0; ++ if (wpa_s->global->p2p_init_wpa_s) ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = 0; + eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL); + wpas_p2p_remove_pending_group_interface(wpa_s); +@@ -5635,7 +5636,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, + go_intent = wpa_s->conf->p2p_go_intent; + + if (!auth) +- wpa_s->p2p_long_listen = 0; ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = 0; + + wpa_s->p2p_wps_method = wps_method; + wpa_s->p2p_persistent_group = !!persistent_group; +@@ -6952,7 +6953,7 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, + u8 seek_cnt, const char **seek_string, int freq) + { + wpas_p2p_clear_pending_action_tx(wpa_s); +- wpa_s->p2p_long_listen = 0; ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = 0; + + if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL || + wpa_s->p2p_in_provisioning) { +@@ -6997,7 +6998,7 @@ static void wpas_p2p_scan_res_ignore_search(struct wpa_supplicant *wpa_s, + static void wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s) + { + wpas_p2p_clear_pending_action_tx(wpa_s); +- wpa_s->p2p_long_listen = 0; ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = 0; + eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); + +@@ -7023,7 +7024,7 @@ void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s) + static void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx) + { + struct wpa_supplicant *wpa_s = eloop_ctx; +- wpa_s->p2p_long_listen = 0; ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = 0; + } + + +@@ -7052,7 +7053,7 @@ int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout) + timeout = 3600; + } + eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); +- wpa_s->p2p_long_listen = 0; ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = 0; + + /* + * Stop previous find/listen operation to avoid trying to request a new +@@ -7064,7 +7065,7 @@ int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout) + + res = wpas_p2p_listen_start(wpa_s, timeout * 1000); + if (res == 0 && timeout * 1000 > wpa_s->max_remain_on_chan) { +- wpa_s->p2p_long_listen = timeout * 1000; ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = timeout * 1000; + eloop_register_timeout(timeout, 0, + wpas_p2p_long_listen_timeout, + wpa_s, NULL); +@@ -7171,7 +7172,7 @@ static void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s) + + int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr) + { +- wpa_s->p2p_long_listen = 0; ++ wpa_s->global->p2p_init_wpa_s->p2p_long_listen = 0; + + if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) + return -1; +-- +2.26.2 + diff --git a/0001-p2p-Limit-P2P_DEVICE-name-to-appropriate-ifname-size.patch b/0001-p2p-Limit-P2P_DEVICE-name-to-appropriate-ifname-size.patch new file mode 100644 index 0000000..a29c513 --- /dev/null +++ b/0001-p2p-Limit-P2P_DEVICE-name-to-appropriate-ifname-size.patch @@ -0,0 +1,30 @@ +From d4348cbbdbdba5d045b5b389ba6ce97b74936f30 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Mon, 15 Jun 2020 16:17:43 +0200 +Subject: [PATCH] p2p: Limit P2P_DEVICE name to appropriate ifname size + +Otherwise the WPA_IF_P2P_DEVICE cannot be created. As this is not a +netdev device, it is acceptable if the name is not completely unique. As +such, simply insert a NUL byte at the appropriate place. +--- + wpa_supplicant/p2p_supplicant.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c +index e94bffe52..17c25889c 100644 +--- a/wpa_supplicant/p2p_supplicant.c ++++ b/wpa_supplicant/p2p_supplicant.c +@@ -3929,6 +3929,10 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s, + wpa_s->ifname); + if (os_snprintf_error(sizeof(ifname), ret)) + return -1; ++ /* Cut length at the maximum size. Note that we don't need to ensure ++ * collision free names here as the created interface is not a netdev. ++ */ ++ ifname[IFNAMSIZ-1] = '\0'; + force_name[0] = '\0'; + wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE; + ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, NULL, NULL, +-- +2.26.2 + diff --git a/wpa_supplicant.spec b/wpa_supplicant.spec index 3e114e6..5eecc95 100644 --- a/wpa_supplicant.spec +++ b/wpa_supplicant.spec @@ -5,7 +5,7 @@ Summary: WPA/WPA2/IEEE 802.1X Supplicant Name: wpa_supplicant Epoch: 1 Version: 2.9 -Release: 4%{?dist} +Release: 5%{?dist} License: BSD Source0: http://w1.fi/releases/%{name}-%{version}.tar.gz Source1: wpa_supplicant.conf @@ -28,6 +28,11 @@ Patch4: wpa_supplicant-gui-qt4.patch # fix AP mode PMF disconnection protection bypass Patch5: 0001-AP-Silently-ignore-management-frame-from-unexpected-.patch +# fix some issues with P2P operation +Patch6: 0001-P2P-Always-use-global-p2p_long_listen.patch +Patch7: 0001-D-Bus-Fix-P2P-NULL-dereference-after-interface-remov.patch +Patch8: 0001-p2p-Limit-P2P_DEVICE-name-to-appropriate-ifname-size.patch + URL: http://w1.fi/wpa_supplicant/ %if %with gui @@ -183,6 +188,9 @@ chmod -R 0644 wpa_supplicant/examples/*.py %changelog +* Mon Jun 15 2020 Benjamin Berg - 1:2.9-5 +- fix some issues with P2P operation + * Thu Apr 23 2020 Davide Caratti - 1:2.9-4 - Enable Tunneled Direct Link Setup (TDLS)