qcacmn: Fix use after free for vdev in tdls
When disconnect happens, TDLS_NOTIFY_STA_DISCONNECTION will be send to scheduler_thread, in bad case, it is processed after 3s later, and the vdev passed in notify msg has been freed in the period, invalid vdev causes invalid memory access. change as below: 1.1 Get vdev ref before send msg 1.2 register callback for release ref 1.3 send msg to scheduler_thread 1.4 process tdls notify msg and call callback function. Change-Id: I2b03db8b30db623796f2e8299f14ee31e28efb91 CRs-Fixed: 2275019
This commit is contained in:
@@ -128,20 +128,55 @@ void hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev)
|
||||
ucfg_tdls_notify_reset_adapter(vdev);
|
||||
}
|
||||
|
||||
static void hdd_notify_sta_connect_callback(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
if (!vdev) {
|
||||
cfg80211_err("vdev is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
||||
}
|
||||
|
||||
void
|
||||
hdd_notify_sta_connect(uint8_t session_id,
|
||||
bool tdls_chan_swit_prohibited,
|
||||
bool tdls_prohibited,
|
||||
struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct tdls_sta_notify_params notify_info;
|
||||
struct tdls_sta_notify_params notify_info = {0};
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!vdev) {
|
||||
cfg80211_err("vdev is NULL");
|
||||
return;
|
||||
}
|
||||
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
cfg80211_err("can't get vdev");
|
||||
return;
|
||||
}
|
||||
|
||||
notify_info.session_id = session_id;
|
||||
notify_info.vdev = vdev;
|
||||
notify_info.tdls_chan_swit_prohibited = tdls_chan_swit_prohibited;
|
||||
notify_info.tdls_prohibited = tdls_prohibited;
|
||||
ucfg_tdls_notify_sta_connect(¬ify_info);
|
||||
notify_info.callback = hdd_notify_sta_connect_callback;
|
||||
status = ucfg_tdls_notify_sta_connect(¬ify_info);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
cfg80211_err("ucfg_tdls_notify_sta_connect failed");
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
||||
}
|
||||
}
|
||||
|
||||
static void hdd_notify_sta_disconnect_callback(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
if (!vdev) {
|
||||
cfg80211_err("vdev is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
||||
}
|
||||
|
||||
void hdd_notify_sta_disconnect(uint8_t session_id,
|
||||
@@ -149,14 +184,32 @@ void hdd_notify_sta_disconnect(uint8_t session_id,
|
||||
bool user_disconnect,
|
||||
struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
struct tdls_sta_notify_params notify_info;
|
||||
struct tdls_sta_notify_params notify_info = {0};
|
||||
QDF_STATUS status;
|
||||
|
||||
if (!vdev) {
|
||||
cfg80211_err("vdev is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
cfg80211_err("can't get vdev");
|
||||
return;
|
||||
}
|
||||
|
||||
notify_info.session_id = session_id;
|
||||
notify_info.lfr_roam = lfr_roam;
|
||||
notify_info.tdls_chan_swit_prohibited = false;
|
||||
notify_info.tdls_prohibited = false;
|
||||
notify_info.vdev = vdev;
|
||||
notify_info.user_disconnect = user_disconnect;
|
||||
ucfg_tdls_notify_sta_disconnect(¬ify_info);
|
||||
|
||||
notify_info.callback = hdd_notify_sta_disconnect_callback;
|
||||
status = ucfg_tdls_notify_sta_disconnect(¬ify_info);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
cfg80211_err("ucfg_tdls_notify_sta_disconnect failed");
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
||||
}
|
||||
}
|
||||
int wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_pdev *pdev,
|
||||
struct net_device *dev, const uint8_t *mac)
|
||||
|
Reference in New Issue
Block a user