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
Tento commit je obsažen v:
Abhishek Singh
2023-04-20 11:58:34 +05:30
odevzdal Madan Koyyalamudi
rodič 89f62ba1f3
revize 9266c2d271
4 změnil soubory, kde provedl 60 přidání a 20 odebrání

Zobrazit soubor

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

Zobrazit soubor

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

Zobrazit soubor

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

Zobrazit soubor

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