summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhaoyang Liu <zhaoyang@codeaurora.org>2017-11-27 15:51:54 +0800
committersnandini <snandini@codeaurora.org>2017-12-21 08:46:59 -0800
commit14cccfbeed3c2d0eb9d303bc4fe80485f202d105 (patch)
treea8d652a58f6cea248e5f83a9f3a92d8cde4676bd
parentf6183233f20c88245e6f70ce64541e5439422239 (diff)
qcacld-3.0: avoid double free chip power stats buffer
qcacld-2.0 to qcacld-3.0 propagation. Add mutex lock to block concurrent threads access power status debugfs reading operation. This way can avoid the risk of double free power stats memory buffer. Change-Id: I5ffbe4170aaf468d8c50eddef5bd8c16cea6439c CRs-Fixed: 2149333
-rw-r--r--core/hdd/inc/wlan_hdd_main.h4
-rw-r--r--core/hdd/src/wlan_hdd_debugfs.c46
2 files changed, 45 insertions, 5 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 6bde7308bb87..48ffb741fd7b 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -2050,6 +2050,10 @@ struct hdd_context_s {
uint32_t num_derived_addr;
unsigned long provisioned_intf_addr_mask;
unsigned long derived_intf_addr_mask;
+#ifdef WLAN_POWER_DEBUGFS
+ /* mutex lock to block concurrent access */
+ struct mutex power_stats_lock;
+#endif
};
int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
diff --git a/core/hdd/src/wlan_hdd_debugfs.c b/core/hdd/src/wlan_hdd_debugfs.c
index 8a01df5399ed..844b566b8262 100644
--- a/core/hdd/src/wlan_hdd_debugfs.c
+++ b/core/hdd/src/wlan_hdd_debugfs.c
@@ -614,6 +614,8 @@ static ssize_t __wlan_hdd_read_power_debugfs(struct file *file,
if (!wlan_hdd_modules_are_enabled(hdd_ctx))
return -EINVAL;
+ mutex_lock(&hdd_ctx->power_stats_lock);
+
if (adapter->chip_power_stats)
qdf_mem_free(adapter->chip_power_stats);
@@ -627,6 +629,7 @@ static ssize_t __wlan_hdd_read_power_debugfs(struct file *file,
sme_power_debug_stats_req(hdd_ctx->hHal,
hdd_power_debugstats_cb,
&context)) {
+ mutex_unlock(&hdd_ctx->power_stats_lock);
hdd_err("chip power stats request failed");
return -EINVAL;
}
@@ -634,6 +637,7 @@ static ssize_t __wlan_hdd_read_power_debugfs(struct file *file,
rc = wait_for_completion_timeout(&context.completion,
msecs_to_jiffies(WLAN_WAIT_TIME_POWER_STATS));
if (!rc) {
+ mutex_unlock(&hdd_ctx->power_stats_lock);
hdd_err("Target response timed out Power stats");
/* Invalidate the Stats context magic */
spin_lock(&hdd_context_lock);
@@ -644,15 +648,17 @@ static ssize_t __wlan_hdd_read_power_debugfs(struct file *file,
chip_power_stats = adapter->chip_power_stats;
if (!chip_power_stats) {
+ mutex_unlock(&hdd_ctx->power_stats_lock);
hdd_err("Power stats retrieval fails!");
return -EINVAL;
}
power_debugfs_buf = qdf_mem_malloc(POWER_DEBUGFS_BUFFER_MAX_LEN);
if (!power_debugfs_buf) {
- hdd_err("Power stats buffer alloc fails!");
qdf_mem_free(chip_power_stats);
adapter->chip_power_stats = NULL;
+ mutex_unlock(&hdd_ctx->power_stats_lock);
+ hdd_err("Power stats buffer alloc fails!");
return -EINVAL;
}
@@ -683,6 +689,7 @@ static ssize_t __wlan_hdd_read_power_debugfs(struct file *file,
qdf_mem_free(chip_power_stats);
adapter->chip_power_stats = NULL;
+ mutex_unlock(&hdd_ctx->power_stats_lock);
ret_cnt = simple_read_from_buffer(buf, count, pos,
power_debugfs_buf, len);
@@ -825,26 +832,54 @@ static const struct file_operations fops_powerdebugs = {
};
/**
- * wlan_hdd_create_power_stats_file() - API to create power stats file
+ * wlan_hdd_init_power_stats_debugfs() - API to init power stats debugfs
* @adapter: interface adapter pointer
*
* Return: QDF_STATUS
*/
-static QDF_STATUS wlan_hdd_create_power_stats_file(hdd_adapter_t *adapter)
+static QDF_STATUS wlan_hdd_init_power_stats_debugfs(hdd_adapter_t *adapter)
{
+ hdd_context_t *hdd_ctx;
+
if (!debugfs_create_file("power_stats", 00400 | 00040 | 00004,
adapter->debugfs_phy, adapter,
&fops_powerdebugs))
return QDF_STATUS_E_FAILURE;
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ if (wlan_hdd_validate_context(hdd_ctx))
+ return QDF_STATUS_E_FAILURE;
+
+ mutex_init(&hdd_ctx->power_stats_lock);
+
return QDF_STATUS_SUCCESS;
}
+/**
+ * wlan_hdd_deinit_power_stats_debugfs() - API to deinit power stats debugfs
+ * @hdd_ctx: hdd context pointer
+ *
+ * Return: None
+ */
+static void wlan_hdd_deinit_power_stats_debugfs(hdd_adapter_t *adapter)
+{
+ hdd_context_t *hdd_ctx;
+
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ if (wlan_hdd_validate_context(hdd_ctx))
+ return;
+
+ mutex_destroy(&hdd_ctx->power_stats_lock);
+}
#else
-static QDF_STATUS wlan_hdd_create_power_stats_file(hdd_adapter_t *adapter)
+static QDF_STATUS wlan_hdd_init_power_stats_debugfs(hdd_adapter_t *adapter)
{
return QDF_STATUS_SUCCESS;
}
+
+static void wlan_hdd_deinit_power_stats_debugfs(hdd_adapter_t *adapter)
+{
+}
#endif
/**
@@ -883,7 +918,7 @@ QDF_STATUS hdd_debugfs_init(hdd_adapter_t *adapter)
&fops_patterngen))
return QDF_STATUS_E_FAILURE;
- if (QDF_STATUS_SUCCESS != wlan_hdd_create_power_stats_file(adapter))
+ if (QDF_STATUS_SUCCESS != wlan_hdd_init_power_stats_debugfs(adapter))
return QDF_STATUS_E_FAILURE;
if (0 != wlan_hdd_create_ll_stats_file(adapter))
@@ -902,6 +937,7 @@ QDF_STATUS hdd_debugfs_init(hdd_adapter_t *adapter)
*/
void hdd_debugfs_exit(hdd_adapter_t *adapter)
{
+ wlan_hdd_deinit_power_stats_debugfs(adapter);
debugfs_remove_recursive(adapter->debugfs_phy);
}
#endif /* #ifdef WLAN_OPEN_SOURCE */