Explorar o código

qcacmn: Fix race between ser psoc close and vdev destroy handler

In wlan_serialization_psoc_disable the timers are freed without
holding lock and at the same time the
wlan_serialization_cleanup_vdev_timers from vdev destroy handler
is accessing the timers, this result in cleanup_vdev_timers
accessing freed timer memory resulting in assert.

Fix is to free timer memory while holding timer lock. Also as the
lock can be used by vdev delete handler after freeing in
psoc_disable, move the init and deinit of the lock to psoc create
and destroy handlers respectively.

Change-Id: Idf822a91022de6b51c7ee1895f71b6fb94fedd72
CRs-Fixed: 2721064
Abhishek Singh %!s(int64=5) %!d(string=hai) anos
pai
achega
62fb09b241

+ 5 - 3
umac/cmn_services/serialization/src/wlan_serialization_main.c

@@ -52,11 +52,12 @@ QDF_STATUS wlan_serialization_psoc_disable(struct wlan_objmgr_psoc *psoc)
 	if (status != QDF_STATUS_SUCCESS)
 		ser_err("ser cleanning up all timer failed");
 
+	/* Use lock to free to avoid any race where timer is still in use */
+	wlan_serialization_acquire_lock(&ser_soc_obj->timer_lock);
 	qdf_mem_free(ser_soc_obj->timers);
 	ser_soc_obj->timers = NULL;
 	ser_soc_obj->max_active_cmds = 0;
-
-	wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock);
+	wlan_serialization_release_lock(&ser_soc_obj->timer_lock);
 error:
 	return status;
 }
@@ -87,7 +88,6 @@ QDF_STATUS wlan_serialization_psoc_enable(struct wlan_objmgr_psoc *psoc)
 		goto error;
 	}
 
-	wlan_serialization_create_lock(&ser_soc_obj->timer_lock);
 	status = QDF_STATUS_SUCCESS;
 
 error:
@@ -127,6 +127,7 @@ static QDF_STATUS wlan_serialization_psoc_create_handler(
 		ser_err("Obj attach failed");
 		goto error;
 	}
+	wlan_serialization_create_lock(&soc_ser_obj->timer_lock);
 	ser_debug("ser psoc obj created");
 	status = QDF_STATUS_SUCCESS;
 
@@ -331,6 +332,7 @@ wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc,
 	if (status != QDF_STATUS_SUCCESS)
 		ser_err("ser psoc private obj detach failed");
 
+	wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock);
 	ser_debug("ser psoc obj deleted with status %d", status);
 	qdf_mem_free(ser_soc_obj);