CVE-2021-3658 (published 2022-03-02T23:15Z)

bluetoothd from bluez incorrectly saves adapters' Discoverable status when a device is powered down, and restores it when powered up. If a device is powered down while discoverable, it will be discoverable when powered on again. This could lead to inadvertent exposure of the bluetooth stack to physically nearby attackers.

Severity: LOW
CVSS v2 base score: 3.3 (AV:A/AC:L/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-863
cwe_name: Incorrect Authorization
description: The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. This allows attackers to bypass intended access restrictions.
extended_description: 
            Assuming a user with a given identity, authorization is the process of determining whether that user can access a given resource, based on the user's privileges and any permissions or other access-control specifications that apply to the resource.
            When access control checks are incorrectly applied, users are able to access data or perform actions that they should not be allowed to perform. This can lead to a wide range of problems, including information exposures, denial of service, and arbitrary code execution.
         
         

Fix information:
repo_url: https://github.com/bluez/bluez
commit_details: repo_url: https://github.com/bluez/bluez
author: Luiz Augusto von Dentz
author_date: 2021-06-24 16:32:04-07:00
msg: adapter: Fix storing discoverable setting

discoverable setting shall only be store when changed via Discoverable
property and not when discovery client set it as that be considered
temporary just for the lifetime of the discovery.
repository: repo_url: https://github.com/bluez/bluez
repo_name: bluez/bluez
description: Main BlueZ tree
repo_language: C
owner: bluez
file_changes: filename: adapter.c
change_type: ModificationType.MODIFY
diff: @@ -560,7 +560,11 @@ static void settings_changed(struct btd_adapter *adapter, uint32_t settings)
 	if (changed_mask & MGMT_SETTING_DISCOVERABLE) {
 		g_dbus_emit_property_changed(dbus_conn, adapter->path,
 					ADAPTER_INTERFACE, "Discoverable");
-		store_adapter_info(adapter);
+		/* Only persist discoverable setting if it was not set
+		 * temporarily by discovery.
+		 */
+		if (!adapter->discovery_discoverable)
+			store_adapter_info(adapter);
 		btd_adv_manager_refresh(adapter->adv_manager);
 	}
 
@@ -2162,8 +2166,6 @@ static bool filters_equal(struct mgmt_cp_start_service_discovery *a,
 static int update_discovery_filter(struct btd_adapter *adapter)
 {
 	struct mgmt_cp_start_service_discovery *sd_cp;
-	GSList *l;
-
 
 	DBG("");
 
@@ -2173,17 +2175,24 @@ static int update_discovery_filter(struct btd_adapter *adapter)
 		return -ENOMEM;
 	}
 
-	for (l = adapter->discovery_list; l; l = g_slist_next(l)) {
-		struct discovery_client *client = l->data;
+	/* Only attempt to overwrite current discoverable setting when not
+	 * discoverable.
+	 */
+	if (!(adapter->current_settings & MGMT_OP_SET_DISCOVERABLE)) {
+		GSList *l;
 
-		if (!client->discovery_filter)
-			continue;
+		for (l = adapter->discovery_list; l; l = g_slist_next(l)) {
+			struct discovery_client *client = l->data;
 
-		if (client->discovery_filter->discoverable)
-			break;
-	}
+			if (!client->discovery_filter)
+				continue;
 
-	set_discovery_discoverable(adapter, l ? true : false);
+			if (client->discovery_filter->discoverable) {
+				set_discovery_discoverable(adapter, true);
+				break;
+			}
+		}
+	}
 
 	/*
 	 * If filters are equal, then don't update scan, except for when
@@ -2216,8 +2225,7 @@ static int discovery_stop(struct discovery_client *client)
 		return 0;
 	}
 
-	if (adapter->discovery_discoverable)
-		set_discovery_discoverable(adapter, false);
+	set_discovery_discoverable(adapter, false);
 
 	/*
 	 * In the idle phase of a discovery, there is no need to stop it
@@ -6913,6 +6921,7 @@ static void adapter_stop(struct btd_adapter *adapter)
 	g_free(adapter->current_discovery_filter);
 	adapter->current_discovery_filter = NULL;
 
+	set_discovery_discoverable(adapter, false);
 	adapter->discovering = false;
 
 	while (adapter->connections) {

programming_language: C