Эх сурвалжийг харах

qcacld-3.0: Fix mem leak with NDP peer multicast address list

Currently, NDP peer multicast address is derived from peer MAC address
and cached in the host. While removing the NDP peer, peer MAC address
is used to search the cached multicast address list. Because of this,
peer multicast address list is not getting freed.

To resolve this, derive peer multicast address from the peer MAC address
while clearing the cached multicast address list.

Since MAX NDP sessions are 8, allocate memory for peer multicast address
list during the NAN vdev private object allocation. This avoids the
special handling for peer multicast list in multiple error scenarios.

Change-Id: Ifbf890a4b9c8be54d84a5b57ed8f6c237ecd51ca
CRs-Fixed: 3085069
Bapiraju Alla 3 жил өмнө
parent
commit
6058846058

+ 2 - 3
components/nan/core/src/nan_main_i.h

@@ -30,6 +30,7 @@
 #include "qdf_status.h"
 #include "nan_public_structs.h"
 #include "wlan_objmgr_cmn.h"
+#include "cfg_nan.h"
 
 struct wlan_objmgr_vdev;
 struct wlan_objmgr_psoc;
@@ -152,7 +153,6 @@ struct nan_psoc_priv_obj {
  * @ndp_init_done: Flag to indicate NDP initialization complete after first peer
  *		   connection.
  * @peer_mc_addr_list: Peer multicast address list
- * @num_peer_mc_addr: Number of entries in peer multicast list
  */
 struct nan_vdev_priv_obj {
 	qdf_spinlock_t lock;
@@ -165,8 +165,7 @@ struct nan_vdev_priv_obj {
 	struct qdf_mac_addr primary_peer_mac;
 	void *disable_context;
 	bool ndp_init_done;
-	struct qdf_mac_addr *peer_mc_addr_list;
-	uint8_t num_peer_mc_addr;
+	struct qdf_mac_addr peer_mc_addr_list[MAX_NDP_SESSIONS];
 };
 
 /**

+ 5 - 1
components/nan/dispatcher/inc/cfg_nan.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -168,6 +169,9 @@
 			CFG_VALUE_OR_DEFAULT, \
 			"Keep alive timeout of a peer")
 
+/* MAX NDP sessions supported */
+#define MAX_NDP_SESSIONS 8
+
 /*
  * <ini>
  * ndp_max_sessions - To configure max ndp sessions
@@ -189,7 +193,7 @@
 #define CFG_NDP_MAX_SESSIONS CFG_INI_UINT( \
 			"ndp_max_sessions", \
 			1, \
-			8, \
+			MAX_NDP_SESSIONS, \
 			8, \
 			CFG_VALUE_OR_DEFAULT, \
 			"max ndp sessions host supports")

+ 22 - 38
components/nan/dispatcher/src/nan_ucfg_api.c

@@ -203,37 +203,24 @@ inline void ucfg_nan_set_peer_mc_list(struct wlan_objmgr_vdev *vdev,
 		return;
 	}
 
+	cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions);
+
 	qdf_spin_lock_bh(&priv_obj->lock);
-	if (!priv_obj->peer_mc_addr_list) {
-		cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions);
-
-		priv_obj->peer_mc_addr_list =
-				qdf_mem_malloc(max_ndp_sessions *
-					       sizeof(struct qdf_mac_addr));
-		if (!priv_obj->peer_mc_addr_list) {
-			nan_err("Failed to allocate multicast address list");
-			goto end;
-		}
-		priv_obj->num_peer_mc_addr = 0;
-	} else {
-		for (i = 0; i < max_ndp_sessions; i++) {
-			if (qdf_is_macaddr_zero(
-					&priv_obj->peer_mc_addr_list[i])) {
-				list_idx = i;
-				break;
-			}
-		}
-		if (list_idx == max_ndp_sessions) {
-			nan_err("Peer multicast address list is full");
-			goto end;
+	for (i = 0; i < max_ndp_sessions; i++) {
+		if (qdf_is_macaddr_zero(&priv_obj->peer_mc_addr_list[i])) {
+			list_idx = i;
+			break;
 		}
 	}
+	if (list_idx == max_ndp_sessions) {
+		nan_err("Peer multicast address list is full");
+		goto end;
+	}
 	/* Derive peer multicast addr */
 	peer_mac_addr.bytes[0] = 0x33;
 	peer_mac_addr.bytes[1] = 0x33;
 	peer_mac_addr.bytes[2] = 0xff;
 	priv_obj->peer_mc_addr_list[list_idx] = peer_mac_addr;
-	priv_obj->num_peer_mc_addr++;
 
 end:
 	qdf_spin_unlock_bh(&priv_obj->lock);
@@ -260,28 +247,25 @@ inline void ucfg_nan_clear_peer_mc_list(struct wlan_objmgr_psoc *psoc,
 	struct nan_vdev_priv_obj *priv_obj = nan_get_vdev_priv_obj(vdev);
 	int i;
 	uint32_t max_ndp_sessions = 0;
+	struct qdf_mac_addr derived_peer_mc_addr;
 
 	if (!priv_obj) {
 		nan_err("priv_obj is null");
 		return;
 	}
 
+	/* Derive peer multicast addr */
+	derived_peer_mc_addr = *peer_mac_addr;
+	derived_peer_mc_addr.bytes[0] = 0x33;
+	derived_peer_mc_addr.bytes[1] = 0x33;
+	derived_peer_mc_addr.bytes[2] = 0xff;
 	qdf_spin_lock_bh(&priv_obj->lock);
-	if (priv_obj->peer_mc_addr_list) {
-		cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions);
-		for (i = 0; i < max_ndp_sessions; i++) {
-			if (qdf_is_macaddr_equal(
-				&priv_obj->peer_mc_addr_list[i],
-				peer_mac_addr)) {
-				qdf_zero_macaddr(
-					   &priv_obj->peer_mc_addr_list[i]);
-				priv_obj->num_peer_mc_addr--;
-				break;
-			}
-		}
-		if (priv_obj->num_peer_mc_addr == 0) {
-			qdf_mem_free(priv_obj->peer_mc_addr_list);
-			priv_obj->peer_mc_addr_list = NULL;
+	cfg_nan_get_ndp_max_sessions(psoc, &max_ndp_sessions);
+	for (i = 0; i < max_ndp_sessions; i++) {
+		if (qdf_is_macaddr_equal(&priv_obj->peer_mc_addr_list[i],
+					 &derived_peer_mc_addr)) {
+			qdf_zero_macaddr(&priv_obj->peer_mc_addr_list[i]);
+			break;
 		}
 	}
 	qdf_spin_unlock_bh(&priv_obj->lock);