diff options
author | Subhani Shaik <subhanis@codeaurora.org> | 2016-07-22 19:42:59 +0530 |
---|---|---|
committer | Ecco Park <eccopark@google.com> | 2016-07-25 11:34:45 -0700 |
commit | 84228ea6c6aaabd4717dc8932f1b0a73b6105d88 (patch) | |
tree | 9aeb5dc46426c30f91ffa1e36e2cbbcf675927ee /qcwcn/wifi_hal/rssi_monitor.cpp | |
parent | 0919dfde526ab1f2996334835cbd176906e89d0e (diff) | |
download | wlan-84228ea6c6aaabd4717dc8932f1b0a73b6105d88.tar.gz |
WiFi-HAL: Avoid race condition in RSSI monitoring commands/events
There is a possiblility while handling the wlan driver event
in the handleEvent of the RssiMonitor, the RssiMonitor stop
is also triggered. The stop monitor cleans RssiMonitor command
instance. In this case the handleEvent will crash as the object
is already deleted. To avoid this scenario moving the handler
creation under hal_info and adding checks to ensure that handler
is enabled/disabled prior to starting and stopping the monitor
command.
BUG: 29936203
Change-Id: Id0ab73313a03510f0b15b101e381112c4ace4aef
Diffstat (limited to 'qcwcn/wifi_hal/rssi_monitor.cpp')
-rw-r--r-- | qcwcn/wifi_hal/rssi_monitor.cpp | 145 |
1 files changed, 105 insertions, 40 deletions
diff --git a/qcwcn/wifi_hal/rssi_monitor.cpp b/qcwcn/wifi_hal/rssi_monitor.cpp index 6b96c10..8cffe98 100644 --- a/qcwcn/wifi_hal/rssi_monitor.cpp +++ b/qcwcn/wifi_hal/rssi_monitor.cpp @@ -38,20 +38,88 @@ #include "rssi_monitor.h" #include "vendor_definitions.h" -//Singleton Static Instance -RSSIMonitorCommand* RSSIMonitorCommand::mRSSIMonitorCommandInstance = NULL; +/* Used to handle rssi command events from driver/firmware.*/ +typedef struct rssi_monitor_event_handler_s { + RSSIMonitorCommand* mRSSIMonitorCommandInstance; +} rssi_monitor_event_handlers; + +wifi_error initializeRSSIMonitorHandler(hal_info *info) +{ + info->rssi_handlers = (rssi_monitor_event_handlers *)malloc(sizeof( + rssi_monitor_event_handlers)); + if (info->rssi_handlers) { + memset(info->rssi_handlers, 0, sizeof(rssi_monitor_event_handlers)); + } + else { + ALOGE("%s: Allocation of RSSI event handlers failed", + __FUNCTION__); + return WIFI_ERROR_OUT_OF_MEMORY; + } + return WIFI_SUCCESS; +} + +wifi_error cleanupRSSIMonitorHandler(hal_info *info) +{ + rssi_monitor_event_handlers* event_handlers; + if (info && info->rssi_handlers) { + event_handlers = (rssi_monitor_event_handlers*) info->rssi_handlers; + if (event_handlers->mRSSIMonitorCommandInstance) { + delete event_handlers->mRSSIMonitorCommandInstance; + } + memset(event_handlers, 0, sizeof(rssi_monitor_event_handlers)); + return WIFI_SUCCESS; + } + ALOGE ("%s: info or info->rssi_handlers NULL", __FUNCTION__); + return WIFI_ERROR_UNKNOWN; +} + +void RSSIMonitorCommand::enableEventHandling() +{ + pthread_mutex_lock(&rm_lock); + mEventHandlingEnabled = true; + pthread_mutex_unlock(&rm_lock); +} + +void RSSIMonitorCommand::disableEventHandling() +{ + pthread_mutex_lock(&rm_lock); + mEventHandlingEnabled = false; + pthread_mutex_unlock(&rm_lock); +} + +bool RSSIMonitorCommand::isEventHandlingEnabled() +{ + bool eventHandlingEnabled; + pthread_mutex_lock(&rm_lock); + eventHandlingEnabled = mEventHandlingEnabled; + pthread_mutex_unlock(&rm_lock); + + return eventHandlingEnabled; +} + +void RSSIMonitorCommand::setCallbackHandler(wifi_rssi_event_handler handler) +{ + mHandler = handler; +} RSSIMonitorCommand::RSSIMonitorCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd) : WifiVendorCommand(handle, id, vendor_id, subcmd) { - mRSSIMonitorCommandInstance = NULL; memset(&mHandler, 0, sizeof(mHandler)); + if (registerVendorHandler(vendor_id, subcmd)) { + /* Error case should not happen print log */ + ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u", + __FUNCTION__, vendor_id, subcmd); + } + pthread_mutex_init(&rm_lock, NULL); + disableEventHandling(); } RSSIMonitorCommand::~RSSIMonitorCommand() { - mRSSIMonitorCommandInstance = NULL; + unregisterVendorHandler(mVendor_id, mSubcmd); + pthread_mutex_destroy(&rm_lock); } void RSSIMonitorCommand::setReqId(wifi_request_id reqid) @@ -66,10 +134,20 @@ RSSIMonitorCommand* RSSIMonitorCommand::instance(wifi_handle handle, ALOGE("Interface Handle is invalid"); return NULL; } + hal_info *info = getHalInfo(handle); + if (!info || !info->rssi_handlers) { + ALOGE("rssi_handlers is invalid"); + return NULL; + } + + RSSIMonitorCommand* mRSSIMonitorCommandInstance = + info->rssi_handlers->mRSSIMonitorCommandInstance; + if (mRSSIMonitorCommandInstance == NULL) { mRSSIMonitorCommandInstance = new RSSIMonitorCommand(handle, id, OUI_QCA, QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI); + info->rssi_handlers->mRSSIMonitorCommandInstance = mRSSIMonitorCommandInstance; return mRSSIMonitorCommandInstance; } else @@ -92,6 +170,13 @@ RSSIMonitorCommand* RSSIMonitorCommand::instance(wifi_handle handle, int RSSIMonitorCommand::handleEvent(WifiEvent &event) { int ret = WIFI_SUCCESS; + + if (isEventHandlingEnabled() == false) { + ALOGE("%s: RSSI monitor isn't running or already stopped. " + "Nothing to do. Exit", __FUNCTION__); + return ret; + } + WifiVendorCommand::handleEvent(event); /* Parse the vendordata and get the attribute */ @@ -159,29 +244,9 @@ int RSSIMonitorCommand::handleEvent(WifiEvent &event) ALOGE("%s: Wrong subcmd received %d", __FUNCTION__, mSubcmd); } - return NL_SKIP; -} - -int RSSIMonitorCommand::setCallbackHandler(wifi_rssi_event_handler nHandler, - u32 event) -{ - int ret; - mHandler = nHandler; - ret = registerVendorHandler(mVendor_id, event); - if (ret != 0) { - /* Error case should not happen print log */ - ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u", - __FUNCTION__, mVendor_id, mSubcmd); - } return ret; } -wifi_error RSSIMonitorCommand::unregisterHandler(u32 subCmd) -{ - unregisterVendorHandler(mVendor_id, subCmd); - return WIFI_SUCCESS; -} - wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface, s8 max_rssi, @@ -233,15 +298,14 @@ wifi_error wifi_start_rssi_monitoring(wifi_request_id id, return WIFI_ERROR_OUT_OF_MEMORY; } - ret = rssiCommand->setCallbackHandler(eh, - QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI); - if (ret < 0) - goto cleanup; + rssiCommand->setCallbackHandler(eh); ret = vCommand->requestResponse(); if (ret < 0) goto cleanup; + rssiCommand->enableEventHandling(); + cleanup: delete vCommand; return (wifi_error)ret; @@ -255,6 +319,18 @@ wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, WifiVendorCommand *vCommand = NULL; wifi_handle wifiHandle = getWifiHandle(iface); RSSIMonitorCommand *rssiCommand; + rssi_monitor_event_handlers* event_handlers; + hal_info *info = getHalInfo(wifiHandle); + + event_handlers = (rssi_monitor_event_handlers*)info->rssi_handlers; + rssiCommand = event_handlers->mRSSIMonitorCommandInstance; + + if (rssiCommand == NULL || + rssiCommand->isEventHandlingEnabled() == false) { + ALOGE("%s: RSSI monitor isn't running or already stopped. " + "Nothing to do. Exit", __FUNCTION__); + return WIFI_ERROR_NOT_AVAILABLE; + } ret = initialize_vendor_cmd(iface, id, QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI, @@ -285,19 +361,8 @@ wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, if (ret < 0) goto cleanup; - rssiCommand = RSSIMonitorCommand::instance(wifiHandle, id); - if (rssiCommand == NULL) { - ALOGE("%s: Error rssiCommand NULL", __FUNCTION__); - ret = WIFI_ERROR_OUT_OF_MEMORY; - goto cleanup; - } - - ret = rssiCommand->unregisterHandler( - QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI); - if (ret != WIFI_SUCCESS) - goto cleanup; + rssiCommand->disableEventHandling(); - delete rssiCommand; cleanup: delete vCommand; |