Просмотр исходного кода

qcacld-3.0: Fix race between dequeue logs and deinit connectivity logging

As part of stop modules, the deinit connectivity logging happens and
the queue, all the pointers are deinitialized. But while
initializing the write pointer the write pointer spinlock is not
acquired. This results in null pointer dereference of write_ptr
from other context.

Protect the access to the write pointer before setting it to
NULL in wlan_connectivity_logging_stop().

Change-Id: I69dc57b9e661004203f58754824496953105726f
CRs-Fixed: 3054306
Pragaspathi Thilagaraj 3 лет назад
Родитель
Сommit
c3548d50ff
1 измененных файлов с 9 добавлено и 1 удалено
  1. 9 1
      components/cmn_services/logging/src/wlan_connectivity_logging.c

+ 9 - 1
components/cmn_services/logging/src/wlan_connectivity_logging.c

@@ -66,18 +66,21 @@ void wlan_connectivity_logging_stop(void)
 	if (!qdf_atomic_read(&global_cl.is_active))
 	if (!qdf_atomic_read(&global_cl.is_active))
 		return;
 		return;
 
 
+	qdf_spin_lock_bh(&global_cl.write_ptr_lock);
+
 	global_cl.osif_cb_context = NULL;
 	global_cl.osif_cb_context = NULL;
 	global_cl.osif_cbks.wlan_connectivity_log_send_to_usr = NULL;
 	global_cl.osif_cbks.wlan_connectivity_log_send_to_usr = NULL;
 
 
 	qdf_atomic_set(&global_cl.is_active, 0);
 	qdf_atomic_set(&global_cl.is_active, 0);
 	global_cl.read_ptr = NULL;
 	global_cl.read_ptr = NULL;
 	global_cl.write_ptr = NULL;
 	global_cl.write_ptr = NULL;
-	qdf_spinlock_destroy(&global_cl.write_ptr_lock);
 	global_cl.read_idx = 0;
 	global_cl.read_idx = 0;
 	global_cl.write_idx = 0;
 	global_cl.write_idx = 0;
 
 
 	qdf_mem_vfree(global_cl.head);
 	qdf_mem_vfree(global_cl.head);
 	global_cl.head = NULL;
 	global_cl.head = NULL;
+	qdf_spin_unlock_bh(&global_cl.write_ptr_lock);
+	qdf_spinlock_destroy(&global_cl.write_ptr_lock);
 }
 }
 
 
 void
 void
@@ -123,6 +126,11 @@ static bool wlan_logging_is_queue_empty(void)
 
 
 	qdf_spin_lock_bh(&global_cl.write_ptr_lock);
 	qdf_spin_lock_bh(&global_cl.write_ptr_lock);
 
 
+	if (!global_cl.write_ptr) {
+		qdf_spin_unlock_bh(&global_cl.write_ptr_lock);
+		return true;
+	}
+
 	if (global_cl.read_ptr == global_cl.write_ptr &&
 	if (global_cl.read_ptr == global_cl.write_ptr &&
 	    !global_cl.write_ptr->is_record_filled) {
 	    !global_cl.write_ptr->is_record_filled) {
 		qdf_spin_unlock_bh(&global_cl.write_ptr_lock);
 		qdf_spin_unlock_bh(&global_cl.write_ptr_lock);