#6 fix some issues with P2P operation
Merged 3 years ago by dcaratti. Opened 3 years ago by benzea.
rpms/ benzea/wpa_supplicant f32  into  f32

@@ -0,0 +1,209 @@ 

+ From b2ad4e6b24ed0271ca76cb27856def0a701fb778 Mon Sep 17 00:00:00 2001

+ From: Davide Caratti <davide.caratti@gmail.com>

+ 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 <bgalvani@redhat.com>

+ CC: Benjamin Berg <benjamin@sipsolutions.net>

+ Reported-by: Vladimir Benes <vbenes@redhat.com>

+ Signed-off-by: Davide Caratti <davide.caratti@gmail.com>

+ ---

+  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

+ 

@@ -0,0 +1,111 @@ 

+ From 9ad3c12dd1bf56824ef8b3425e057e8d1e84e69d Mon Sep 17 00:00:00 2001

+ From: Benjamin Berg <bberg@redhat.com>

+ 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 <bberg@redhat.com>

+ ---

+  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

+ 

@@ -0,0 +1,30 @@ 

+ From d4348cbbdbdba5d045b5b389ba6ce97b74936f30 Mon Sep 17 00:00:00 2001

+ From: Benjamin Berg <bberg@redhat.com>

+ 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

+ 

file modified
+9 -1
@@ -5,7 +5,7 @@ 

  Name: wpa_supplicant

  Epoch: 1

  Version: 2.9

- Release: 3%{?dist}

+ Release: 4%{?dist}

  License: BSD

  Source0: http://w1.fi/releases/%{name}-%{version}.tar.gz

  Source1: wpa_supplicant.conf
@@ -28,6 +28,11 @@ 

  # 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 @@ 

  

  

  %changelog

+ * Mon Jun 15 2020 Benjamin Berg <bberg@redhat.com> - 1:2.9-4

+ - fix some issues with P2P operation

+ 

  * Fri Jan 31 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1:2.9-3

  - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild

  

Pull in a few fixes for P2P operation.

Looks ok, is it worth adding also this?

commit 9ad3c12dd
Author: Benjamin Berg bberg@redhat.com
Date: Fri Jan 3 22:18:51 2020 +0100

P2P: Always use global p2p_long_listen

Ah yes, probably a good idea. For some reason that only seems to be hit in NetworkManager automated test, but I don't remember why that might be the case :)

I'll update teh PR.

rebased onto 7b5dd52

3 years ago

Pull-Request has been merged by dcaratti

3 years ago