Blame SOURCES/wpa_supplicant-p2p-segfault-on-iface-removal.patch

9dcd88
From b2ad4e6b24ed0271ca76cb27856def0a701fb778 Mon Sep 17 00:00:00 2001
9dcd88
Message-Id: <b2ad4e6b24ed0271ca76cb27856def0a701fb778.1572271835.git.davide.caratti@gmail.com>
9dcd88
From: Davide Caratti <davide.caratti@gmail.com>
9dcd88
Date: Wed, 2 Oct 2019 14:08:41 +0200
9dcd88
Subject: [PATCH] D-Bus: Fix P2P NULL dereference after interface removal
9dcd88
9dcd88
When the P2P management interface is deleted, P2P is then disabled and
9dcd88
global->p2p_init_wpa_s is set to NULL. After that, other interfaces can
9dcd88
still trigger P2P functions (like wpas_p2p_find()) using D-Bus. This
9dcd88
makes wpa_supplicant terminate with SIGSEGV, because it dereferences a
9dcd88
NULL pointer. Fix this by adding proper checks, like it's done with
9dcd88
wpa_cli.
9dcd88
9dcd88
CC: Beniamino Galvani <bgalvani@redhat.com>
9dcd88
CC: Benjamin Berg <benjamin@sipsolutions.net>
9dcd88
Reported-by: Vladimir Benes <vbenes@redhat.com>
9dcd88
Signed-off-by: Davide Caratti <davide.caratti@gmail.com>
9dcd88
---
9dcd88
 wpa_supplicant/dbus/dbus_new_handlers_p2p.c | 69 ++++++++++++++++++++-
9dcd88
 1 file changed, 67 insertions(+), 2 deletions(-)
9dcd88
9dcd88
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
9dcd88
index 8cdd88564..19715eb4c 100644
9dcd88
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
9dcd88
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
9dcd88
@@ -40,6 +40,14 @@ static int wpas_dbus_validate_dbus_ipaddr(struct wpa_dbus_dict_entry entry)
9dcd88
 }
9dcd88
 
9dcd88
 
9dcd88
+static dbus_bool_t no_p2p_mgmt_interface(DBusError *error)
9dcd88
+{
9dcd88
+	dbus_set_error_const(error, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
9dcd88
+			     "Could not find P2P mgmt interface");
9dcd88
+	return FALSE;
9dcd88
+}
9dcd88
+
9dcd88
+
9dcd88
 /**
9dcd88
  * Parses out the mac address from the peer object path.
9dcd88
  * @peer_path - object path of the form
9dcd88
@@ -78,6 +86,22 @@ wpas_dbus_error_persistent_group_unknown(DBusMessage *message)
9dcd88
 }
9dcd88
 
9dcd88
 
9dcd88
+/**
9dcd88
+ * wpas_dbus_error_no_p2p_mgmt_iface - Return a new InterfaceUnknown error
9dcd88
+ * message
9dcd88
+ * @message: Pointer to incoming dbus message this error refers to
9dcd88
+ * Returns: a dbus error message
9dcd88
+ *
9dcd88
+ * Convenience function to create and return an unknown interface error.
9dcd88
+ */
9dcd88
+static DBusMessage * wpas_dbus_error_no_p2p_mgmt_iface(DBusMessage *message)
9dcd88
+{
9dcd88
+	wpa_printf(MSG_DEBUG, "dbus: Could not find P2P mgmt interface");
9dcd88
+	return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
9dcd88
+				      "Could not find P2P mgmt interface");
9dcd88
+}
9dcd88
+
9dcd88
+
9dcd88
 DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
9dcd88
 					 struct wpa_supplicant *wpa_s)
9dcd88
 {
9dcd88
@@ -145,6 +169,10 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
9dcd88
 	}
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s) {
9dcd88
+		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
+		goto error_nop2p;
9dcd88
+	}
9dcd88
 
9dcd88
 	if (wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types,
9dcd88
 			  req_dev_types, NULL, 0, 0, NULL, freq))
9dcd88
@@ -157,8 +185,9 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
9dcd88
 error_clear:
9dcd88
 	wpa_dbus_dict_entry_clear(&entry);
9dcd88
 error:
9dcd88
-	os_free(req_dev_types);
9dcd88
 	reply = wpas_dbus_error_invalid_args(message, entry.key);
9dcd88
+error_nop2p:
9dcd88
+	os_free(req_dev_types);
9dcd88
 	return reply;
9dcd88
 }
9dcd88
 
9dcd88
@@ -166,7 +195,9 @@ error:
9dcd88
 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
9dcd88
 					      struct wpa_supplicant *wpa_s)
9dcd88
 {
9dcd88
-	wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s);
9dcd88
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (wpa_s)
9dcd88
+		wpas_p2p_stop_find(wpa_s);
9dcd88
 	return NULL;
9dcd88
 }
9dcd88
 
9dcd88
@@ -185,6 +216,8 @@ DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
9dcd88
 		return wpas_dbus_error_invalid_args(message, NULL);
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s)
9dcd88
+		return wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
 
9dcd88
 	if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
9dcd88
 		return wpas_dbus_error_unknown_error(message,
9dcd88
@@ -204,6 +237,8 @@ DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
9dcd88
 		return wpas_dbus_error_no_memory(message);
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s)
9dcd88
+		return wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
 
9dcd88
 	if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
9dcd88
 		return dbus_message_new_error(message,
9dcd88
@@ -245,6 +280,8 @@ DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
9dcd88
 	}
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s)
9dcd88
+		return wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
 
9dcd88
 	if (wpas_p2p_ext_listen(wpa_s, period, interval))
9dcd88
 		return wpas_dbus_error_unknown_error(
9dcd88
@@ -350,6 +387,10 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
9dcd88
 	}
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s) {
9dcd88
+		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
+		goto out;
9dcd88
+	}
9dcd88
 
9dcd88
 	if (pg_object_path != NULL) {
9dcd88
 		char *net_id_str;
9dcd88
@@ -433,6 +474,12 @@ static dbus_bool_t wpa_dbus_p2p_check_enabled(struct wpa_supplicant *wpa_s,
9dcd88
 				     "P2P is not available for this interface");
9dcd88
 		return FALSE;
9dcd88
 	}
9dcd88
+	if (!wpa_s->global->p2p_init_wpa_s) {
9dcd88
+		if (out_reply)
9dcd88
+			*out_reply = wpas_dbus_error_no_p2p_mgmt_iface(
9dcd88
+				message);
9dcd88
+		return no_p2p_mgmt_interface(error);
9dcd88
+	}
9dcd88
 	return TRUE;
9dcd88
 }
9dcd88
 
9dcd88
@@ -822,6 +869,8 @@ DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
9dcd88
 		return wpas_dbus_error_invalid_args(message, NULL);
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s)
9dcd88
+		return wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
 
9dcd88
 	if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
9dcd88
 			       WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
9dcd88
@@ -1882,6 +1931,8 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
9dcd88
 
9dcd88
 	wpa_s = peer_args->wpa_s;
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s)
9dcd88
+		return no_p2p_mgmt_interface(error);
9dcd88
 
9dcd88
 	wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
9dcd88
 	if (wpa_s_go) {
9dcd88
@@ -1963,6 +2014,9 @@ dbus_bool_t wpas_dbus_getter_persistent_groups(
9dcd88
 	dbus_bool_t success = FALSE;
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s)
9dcd88
+		return no_p2p_mgmt_interface(error);
9dcd88
+
9dcd88
 	if (!wpa_s->parent->dbus_new_path)
9dcd88
 		return FALSE;
9dcd88
 
9dcd88
@@ -2077,6 +2131,11 @@ DBusMessage * wpas_dbus_handler_add_persistent_group(
9dcd88
 	dbus_message_iter_init(message, &iter);
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s) {
9dcd88
+		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
+		goto err;
9dcd88
+	}
9dcd88
+
9dcd88
 	if (wpa_s->parent->dbus_new_path)
9dcd88
 		ssid = wpa_config_add_network(wpa_s->conf);
9dcd88
 	if (ssid == NULL) {
9dcd88
@@ -2159,6 +2218,10 @@ DBusMessage * wpas_dbus_handler_remove_persistent_group(
9dcd88
 			      DBUS_TYPE_INVALID);
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s) {
9dcd88
+		reply = wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
+		goto out;
9dcd88
+	}
9dcd88
 
9dcd88
 	/*
9dcd88
 	 * Extract the network ID and ensure the network is actually a child of
9dcd88
@@ -2235,6 +2298,8 @@ DBusMessage * wpas_dbus_handler_remove_all_persistent_groups(
9dcd88
 	struct wpa_config *config;
9dcd88
 
9dcd88
 	wpa_s = wpa_s->global->p2p_init_wpa_s;
9dcd88
+	if (!wpa_s)
9dcd88
+		return wpas_dbus_error_no_p2p_mgmt_iface(message);
9dcd88
 
9dcd88
 	config = wpa_s->conf;
9dcd88
 	ssid = config->ssid;
9dcd88
-- 
9dcd88
2.21.0
9dcd88