From bc5a34bba293c7c2d17ca8ebf3494848c71b0fd6 Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Tue, 9 Oct 2018 18:35:45 +0530 Subject: [PATCH] qcacld-3.0: Cancel iface_idle_work before wma_wmi_stop When interface change timer expires, wma_wmi_service_close() is called from hdd_iface_change_callback()->hdd_wlan_stop_modules() ->cds_close(). wmi_handle is made null here. At the same time, if there is a modem reboot, host will receive early indication from FW. Due to this, icnss driver sent ICNSS_UEVENT_FW_DOWN event to host and it calls wmi_stop() again from icnss_call_driver_uevent()->pld_snoc_uevent()-> wlan_hdd_pld_uevent() -> wlan_hdd_set_the_pld_uevent()-> wma_wmi_stop() -> wmi_stop(). As wmi_handle which was marked null during wlan stop modules, this causes potential NULL pointer dereference. Flush iface_idle_work before wma_wmi_stop and add NULL check before accessing wmi_handle. Change-Id: I1bfa8ab7329040c0b5ba989c0d7de7bf7228dd35 CRs-Fixed: 2328575 --- core/hdd/src/wlan_hdd_driver_ops.c | 23 +++++++++++++++++++++-- core/wma/src/wma_main.c | 4 ++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index b41f92695e06..cbb69d7fb101 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -1484,8 +1484,6 @@ static void wlan_hdd_purge_notifier(void) return; } - qdf_cancel_delayed_work(&hdd_ctx->iface_idle_work); - mutex_lock(&hdd_ctx->iface_change_lock); cds_shutdown_notifier_call(); cds_shutdown_notifier_purge(); @@ -1561,6 +1559,25 @@ static void wlan_hdd_handle_the_pld_uevent(struct pld_uevent_data *uevent) } } +/** + * wlan_hdd_flush_iface_idle_work() - function to flush the interface idle work + * event + * + * Return: void + */ +static void wlan_hdd_flush_iface_idle_work(void) +{ + struct hdd_context *hdd_ctx; + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (!hdd_ctx) { + hdd_err("hdd context is NULL "); + return; + } + + qdf_cancel_delayed_work(&hdd_ctx->iface_idle_work); +} + /** * wlan_hdd_pld_uevent() - update driver status * @dev: device @@ -1574,7 +1591,9 @@ static void wlan_hdd_pld_uevent(struct device *dev, hdd_enter(); hdd_info("pld event %d", uevent->uevent); + wlan_hdd_flush_iface_idle_work(); wma_wmi_stop(); + wlan_hdd_set_the_pld_uevent(uevent); mutex_lock(&hdd_init_deinit_lock); wlan_hdd_handle_the_pld_uevent(uevent); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 75da6a21bf68..d86c8aed8c73 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3044,9 +3044,9 @@ void wma_wmi_stop(void) tp_wma_handle wma_handle; wma_handle = cds_get_context(QDF_MODULE_ID_WMA); - if (wma_handle == NULL) { + if ((!wma_handle) || (!wma_handle->wmi_handle)) { QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO, - "wma_handle is NULL\n"); + "wma_handle or wmi_handle is NULL\n"); return; } wmi_stop(wma_handle->wmi_handle);