From 1221f59a669ecb51408376c8827d608e1d9ac2db Mon Sep 17 00:00:00 2001 From: Abhijit Pradhan Date: Fri, 19 Oct 2018 18:52:09 +0530 Subject: [PATCH] qcacmn: Fix dfs null pointer dereference issue When a DFS pulse is being processed, a channel change change can happen. And the channel change initializes the radar filters which means it frees and allocates the DFS filtering data structures. This may result in memory violation (NULL Pointer dereference). To avoid the memory violation lock the filter initialization and DFS pulse processing. Change-Id: I37c80d409433a9f97bd1f5e78b2b1e780b130290 CRs-Fixed: 2317455 --- umac/dfs/core/src/dfs.h | 14 ++++++++++++++ .../core/src/filtering/dfs_partial_offload_radar.c | 2 ++ umac/dfs/core/src/misc/dfs_filter_init.c | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 76c4b9205aa1..09e4469947fd 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -186,6 +186,15 @@ #define PRECAC_LIST_LOCK_DESTROY(_dfs) qdf_spinlock_destroy( \ &(_dfs)->dfs_precac_lock) +#define WLAN_DFS_DATA_STRUCT_LOCK(_dfs) \ + qdf_spin_lock_bh(&(_dfs)->dfs_data_struct_lock) +#define WLAN_DFS_DATA_STRUCT_UNLOCK(_dfs) \ + qdf_spin_unlock_bh(&(_dfs)->dfs_data_struct_lock) +#define WLAN_DFS_DATA_STRUCT_LOCK_CREATE(_dfs) \ + qdf_spinlock_create(&(_dfs)->dfs_data_struct_lock) +#define WLAN_DFS_DATA_STRUCT_LOCK_DESTROY(_dfs) \ + qdf_spinlock_destroy(&(_dfs)->dfs_data_struct_lock) + /* Mask for time stamp from descriptor */ #define DFS_TSMASK 0xFFFFFFFF /* Shift for time stamp from descriptor */ @@ -1002,6 +1011,10 @@ struct dfs_event_log { * @dfs_freq_offset: Frequency offset where radar was found. * @dfs_cac_aborted: DFS cac is aborted. * @dfs_disable_radar_marking: To mark or unmark NOL chan as radar hit. + * @dfs_data_struct_lock: DFS data structure lock. This is to protect + * all the filtering data structures. For + * example: dfs_bin5radars, dfs_filtertype, + * etc. */ struct wlan_dfs { uint32_t dfs_debug_mask; @@ -1134,6 +1147,7 @@ struct wlan_dfs { uint8_t dfs_bw_reduced; int32_t dfs_freq_offset; bool dfs_cac_aborted; + qdf_spinlock_t dfs_data_struct_lock; }; /** diff --git a/umac/dfs/core/src/filtering/dfs_partial_offload_radar.c b/umac/dfs/core/src/filtering/dfs_partial_offload_radar.c index e1a508c174bd..9493626d9ea0 100644 --- a/umac/dfs/core/src/filtering/dfs_partial_offload_radar.c +++ b/umac/dfs/core/src/filtering/dfs_partial_offload_radar.c @@ -417,7 +417,9 @@ void dfs_get_po_radars(struct wlan_dfs *dfs) rinfo.dfs_radars[i].rp_rssithresh = RSSI_THERSH_AR900B; } + WLAN_DFS_DATA_STRUCT_LOCK(dfs); dfs_init_radar_filters(dfs, &rinfo); + WLAN_DFS_DATA_STRUCT_UNLOCK(dfs); } #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(HOST_DFS_SPOOF_TEST) diff --git a/umac/dfs/core/src/misc/dfs_filter_init.c b/umac/dfs/core/src/misc/dfs_filter_init.c index 723fe1a8c46d..33b579d1496c 100644 --- a/umac/dfs/core/src/misc/dfs_filter_init.c +++ b/umac/dfs/core/src/misc/dfs_filter_init.c @@ -117,7 +117,13 @@ static os_timer_func(dfs_task) return; } + /* Need to take a lock here since dfs filtering data structures are + * freed and re-allocated in dfs_init_radar_filters() during channel + * change which may happen in the middle of dfs pulse processing. + */ + WLAN_DFS_DATA_STRUCT_LOCK(dfs); dfs_process_radarevent(dfs, dfs->dfs_curchan); + WLAN_DFS_DATA_STRUCT_UNLOCK(dfs); dfs->wlan_radar_tasksched = 0; } @@ -220,6 +226,7 @@ int dfs_main_attach(struct wlan_dfs *dfs) STAILQ_INIT(&dfs->dfs_arq); STAILQ_INIT(&(dfs->dfs_eventq)); WLAN_DFSEVENTQ_LOCK_CREATE(dfs); + WLAN_DFS_DATA_STRUCT_LOCK_CREATE(dfs); dfs->events = dfs_alloc_dfs_events(); if (!(dfs->events)) { @@ -411,6 +418,7 @@ void dfs_main_detach(struct wlan_dfs *dfs) dfs->events = NULL; } + WLAN_DFS_DATA_STRUCT_LOCK_DESTROY(dfs); WLAN_DFSQ_LOCK_DESTROY(dfs); WLAN_ARQ_LOCK_DESTROY(dfs); WLAN_DFSEVENTQ_LOCK_DESTROY(dfs);