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

qcacmn: Fix cm req accessed outside cm req or CM lock

wlan_cm_get_rnr, uses the cm request without lock and pass the
pointer to the caller instead of passing a copy.

Fix it by copying the rnr info while holding the lock. and move the
cm req access logic to core from dispatcher.

Change-Id: I72861021d98b996a379a2917874b5dadbc37c6af
CRs-Fixed: 3483871
Abhishek Singh 2 жил өмнө
parent
commit
9266c2d271

+ 11 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_main_api.h

@@ -1303,6 +1303,17 @@ void cm_set_candidate_custom_sort_cb(
  */
 bool cm_is_connect_req_reassoc(struct wlan_cm_connect_req *req);
 
+/**
+ * cm_get_rnr() - get rnr
+ * @vdev:vdev
+ * @cm_id: connect mgr id
+ * @rnr: pointer to copy rnr info
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS cm_get_rnr(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id,
+		      struct reduced_neighbor_report *rnr);
+
 #ifdef CONN_MGR_ADV_FEATURE
 /**
  * cm_free_connect_rsp_ies() - Function to free all connection IEs.

+ 41 - 0
umac/mlme/connection_mgr/core/src/wlan_cm_util.c

@@ -1652,6 +1652,47 @@ wlan_cm_id cm_get_cm_id_by_scan_id(struct cnx_mgr *cm_ctx,
 	return CM_ID_INVALID;
 }
 
+QDF_STATUS cm_get_rnr(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id,
+		      struct reduced_neighbor_report *rnr)
+{
+	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
+	struct cm_req *cm_req;
+	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
+	struct cnx_mgr *cm_ctx;
+
+	if (prefix != CONNECT_REQ_PREFIX)
+		return QDF_STATUS_E_INVAL;
+
+	cm_ctx = cm_get_cm_ctx(vdev);
+	if (!cm_ctx)
+		return QDF_STATUS_E_INVAL;
+
+	cm_req_lock_acquire(cm_ctx);
+	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
+	while (cur_node) {
+		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
+		cm_req = qdf_container_of(cur_node, struct cm_req, node);
+
+		if (cm_req->cm_id == cm_id) {
+			if (!cm_req->connect_req.cur_candidate ||
+			    !cm_req->connect_req.cur_candidate->entry)
+				break;
+
+			qdf_mem_copy(rnr,
+				&cm_req->connect_req.cur_candidate->entry->rnr,
+				sizeof(*rnr));
+			cm_req_lock_release(cm_ctx);
+			return QDF_STATUS_SUCCESS;
+		}
+
+		cur_node = next_node;
+		next_node = NULL;
+	}
+	cm_req_lock_release(cm_ctx);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
 #ifdef WLAN_POLICY_MGR_ENABLE
 static void
 cm_get_pcl_chan_weigtage_for_sta(struct wlan_objmgr_pdev *pdev,

+ 4 - 3
umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_api.h

@@ -500,11 +500,12 @@ void wlan_cm_set_candidate_custom_sort_cb(
  * wlan_cm_get_rnr() - get rnr
  * @vdev:vdev
  * @cm_id: connect mgr id
+ * @rnr: pointer to copy rnr info
  *
- * Return: rnr pointer
+ * Return: QDF_STATUS
  */
-struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev,
-						wlan_cm_id cm_id);
+QDF_STATUS wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id,
+			   struct reduced_neighbor_report *rnr);
 
 /**
  * wlan_cm_disc_cont_after_rso_stop() - Continue disconnect after RSO stop

+ 4 - 17
umac/mlme/connection_mgr/dispatcher/src/wlan_cm_api.c

@@ -351,31 +351,18 @@ void wlan_cm_set_candidate_custom_sort_cb(
 
 #endif
 
-struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev,
-						wlan_cm_id cm_id)
+QDF_STATUS wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id,
+			   struct reduced_neighbor_report *rnr)
 {
 	enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev);
-	struct cm_req *cm_req;
-	struct cnx_mgr *cm_ctx;
 
 	if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) {
 		mlme_err("vdev %d Invalid mode %d",
 			 wlan_vdev_get_id(vdev), op_mode);
-		return NULL;
+		return QDF_STATUS_E_NOSUPPORT;
 	}
 
-	cm_ctx = cm_get_cm_ctx(vdev);
-	if (!cm_ctx)
-		return NULL;
-	cm_req = cm_get_req_by_cm_id(cm_ctx, cm_id);
-	if (!cm_req)
-		return NULL;
-
-	if (cm_req->connect_req.cur_candidate &&
-	    cm_req->connect_req.cur_candidate->entry)
-		return &cm_req->connect_req.cur_candidate->entry->rnr;
-
-	return NULL;
+	return cm_get_rnr(vdev, cm_id, rnr);
 }
 
 void