Ver código fonte

msm: camera: cdm: Acquire mutex lock before accessing client data

There is a chance of use after release of client data in
cdm internal operation calls. Hence acquire mutex lock whenever
accessing client data to avoid use after release scenario.

CRs-Fixed: 3010261
Change-Id: Iaf7f41d56301299a6f63a5dc1090334063019881
Signed-off-by: Shravya Samala <[email protected]>
Shravya Samala 3 anos atrás
pai
commit
e647fae22b
1 arquivos alterados com 13 adições e 9 exclusões
  1. 13 9
      drivers/cam_cdm/cam_cdm_core_common.c

+ 13 - 9
drivers/cam_cdm/cam_cdm_core_common.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/delay.h>
@@ -180,10 +180,12 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 			(struct cam_cdm_bl_cb_request_entry *)data;
 
 		client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl);
+		mutex_lock(&cdm_hw->hw_mutex);
 		client = core->clients[client_idx];
 		if ((!client) || (client->handle != node->client_hdl)) {
 			CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
 				node->client_hdl);
+			mutex_unlock(&cdm_hw->hw_mutex);
 			return;
 		}
 		cam_cdm_get_client_refcount(client);
@@ -202,6 +204,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 		}
 		mutex_unlock(&client->lock);
 		cam_cdm_put_client_refcount(client);
+		mutex_unlock(&cdm_hw->hw_mutex);
 		return;
 	} else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE ||
 			status == CAM_CDM_CB_STATUS_HW_FLUSH ||
@@ -217,7 +220,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 		if ((!client) || (client->handle != node->client_hdl)) {
 			CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
 				node->client_hdl);
-				return;
+			return;
 		}
 		cam_cdm_get_client_refcount(client);
 		mutex_lock(&client->lock);
@@ -239,6 +242,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 
 	for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) {
 		if (core->clients[i] != NULL) {
+			mutex_lock(&cdm_hw->hw_mutex);
 			client = core->clients[i];
 			cam_cdm_get_client_refcount(client);
 			mutex_lock(&client->lock);
@@ -261,6 +265,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 			}
 			mutex_unlock(&client->lock);
 			cam_cdm_put_client_refcount(client);
+			mutex_unlock(&cdm_hw->hw_mutex);
 		}
 	}
 }
@@ -320,35 +325,34 @@ int cam_cdm_stream_ops_internal(void *hw_priv,
 		return -EINVAL;
 
 	core = (struct cam_cdm *)cdm_hw->core_info;
+	mutex_lock(&cdm_hw->hw_mutex);
 	client_idx = CAM_CDM_GET_CLIENT_IDX(*handle);
 	client = core->clients[client_idx];
 	if (!client) {
 		CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle);
+		mutex_unlock(&cdm_hw->hw_mutex);
 		return -EINVAL;
 	}
 	cam_cdm_get_client_refcount(client);
 	if (*handle != client->handle) {
 		CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle);
-		cam_cdm_put_client_refcount(client);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto end;
 	}
 	if (operation == true) {
 		if (true == client->stream_on) {
 			CAM_ERR(CAM_CDM,
 				"Invalid CDM client is already streamed ON");
-			cam_cdm_put_client_refcount(client);
-			return rc;
+			goto end;
 		}
 	} else {
 		if (client->stream_on == false) {
 			CAM_ERR(CAM_CDM,
 				"Invalid CDM client is already streamed Off");
-			cam_cdm_put_client_refcount(client);
-			return rc;
+			goto end;
 		}
 	}
 
-	mutex_lock(&cdm_hw->hw_mutex);
 	if (operation == true) {
 		if (!cdm_hw->open_count) {
 			struct cam_ahb_vote ahb_vote;