瀏覽代碼

msm: camera: common: Fix invalid packet access

Instead of caching packet address pointer, store packet handle
in page fault req info structutre to obtain packet address through
mem manager to avoid potential access to dangling packet pointer which
resulted from UMD called to free the packet buffer before kernel finishes
handling page fault. If the packet was freed, then querying to get packet
address from memory manager will fail since the mem handle is invalid.
If it is invalid, the page fault handler will return before accessing
the dangling packet.

CRs-Fixed: 3287554
Change-Id: I02bc0c706b64f1dc0d098d8189f2f129a91efba7
Signed-off-by: Sokchetra Eung <[email protected]>
Sokchetra Eung 2 年之前
父節點
當前提交
56cc1d37bc

+ 24 - 7
drivers/cam_core/cam_context_utils.c

@@ -167,12 +167,11 @@ free_mem:
 int cam_context_buf_done_from_hw(struct cam_context *ctx,
 	void *done_event_data, uint32_t evt_id)
 {
-	int j;
-	int result;
+	int j, result, rc;
 	struct cam_ctx_request *req;
 	struct cam_hw_done_event_data *done =
 		(struct cam_hw_done_event_data *)done_event_data;
-	int rc;
+	struct cam_packet *packet;
 
 	if (!ctx || !done) {
 		CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, done);
@@ -228,10 +227,22 @@ int cam_context_buf_done_from_hw(struct cam_context *ctx,
 		"[%s][ctx_id %d] : req[%llu] : Signaling %d",
 		ctx->dev_name, ctx->ctx_id, req->request_id, result);
 
+	if (cam_presil_mode_enabled()) {
+		rc = cam_packet_util_get_packet_addr(&packet, req->pf_data.packet_handle,
+			req->pf_data.packet_offset);
+		if (rc) {
+			CAM_ERR(CAM_CTXT,
+				"[%s][%d] : req[%llu] failed to get packet address for handle: 0x%llx",
+				ctx->dev_name, ctx->ctx_id, req->request_id,
+				req->pf_data.packet_handle);
+			return rc;
+		}
+	}
+
 	for (j = 0; j < req->num_out_map_entries; j++) {
 		/* Get buf handles from packet and retrieve them from presil framework */
 		if (cam_presil_mode_enabled()) {
-			rc = cam_presil_retrieve_buffers_from_packet(req->pf_data.packet,
+			rc = cam_presil_retrieve_buffers_from_packet(packet,
 				ctx->img_iommu_hdl, req->out_map_entries[j].resource_handle);
 			if (rc) {
 				CAM_ERR(CAM_CTXT, "Failed to retrieve image buffers rc:%d", rc);
@@ -510,7 +521,6 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
 	req->num_out_acked          = 0;
 	req->flushed                = 0;
 	atomic_set(&req->num_in_acked, 0);
-	memset(&req->pf_data, 0, sizeof(struct cam_hw_mgr_pf_request_info));
 
 	remain_len = cam_context_parse_config_cmd(ctx, cmd, &packet);
 	if (IS_ERR(packet)) {
@@ -561,6 +571,9 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
 	req->request_id = packet->header.request_id;
 	req->status = 1;
 	req->req_priv = cfg.priv;
+	req->pf_data.packet_handle = cmd->packet_handle;
+	req->pf_data.packet_offset = cmd->offset;
+	req->pf_data.req = req;
 
 	for (i = 0; i < req->num_out_map_entries; i++) {
 		rc = cam_sync_get_obj_ref(req->out_map_entries[i].sync_id);
@@ -1669,6 +1682,7 @@ static void __cam_context_req_mini_dump(struct cam_ctx_request *req,
 	struct cam_packet                *packet = NULL;
 	unsigned long                     bytes_written = 0;
 	unsigned long                     bytes_required = 0;
+	int rc;
 
 	bytes_required = sizeof(*req_md);
 	if (start_addr + bytes_written + bytes_required > end_addr)
@@ -1709,14 +1723,17 @@ static void __cam_context_req_mini_dump(struct cam_ctx_request *req,
 		bytes_written += bytes_required;
 	}
 
-	packet = (struct cam_packet *)req->pf_data.packet;
+	rc = cam_packet_util_get_packet_addr(&packet, req->pf_data.packet_handle,
+		req->pf_data.packet_offset);
+	if (rc)
+		return;
 	if (packet && packet->num_io_configs) {
 		bytes_required = packet->num_io_configs * sizeof(struct cam_buf_io_cfg);
 		if (start_addr + bytes_written + bytes_required > end_addr)
 			goto end;
 
 		io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
-			    packet->io_configs_offset / 4);
+			packet->io_configs_offset / 4);
 		req_md->io_cfg = (struct cam_buf_io_cfg *)(start_addr + bytes_written);
 		memcpy(req_md->io_cfg, io_cfg, bytes_required);
 		bytes_written += bytes_required;

+ 5 - 4
drivers/cam_core/cam_hw_mgr_intf.h

@@ -226,15 +226,16 @@ struct cam_hw_stop_args {
 	void              *args;
 };
 
-
 /**
  * struct cam_hw_mgr_pf_request_info - page fault debug data
  *
- * @packet:     pointer to packet
- * @req:        pointer to req (HW specific)
+ * @packet_handle:     packet handle
+ * @offset:            packet offset
+ * @req:               pointer to req (HW specific)
  */
 struct cam_hw_mgr_pf_request_info {
-	void    *packet;
+	uint64_t packet_handle;
+	uint64_t packet_offset;
 	void    *req;
 };
 

+ 11 - 4
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.c

@@ -1336,8 +1336,6 @@ static int cam_cre_mgr_process_io_cfg(struct cam_cre_hw_mgr *hw_mgr,
 	int32_t merged_sync_in_obj;
 	struct cam_cre_request *cre_request;
 
-	prep_arg->pf_data->packet = packet;
-
 	rc = cam_cre_mgr_process_cmd_io_buf_req(hw_mgr, packet, ctx_data,
 		req_idx);
 	if (rc) {
@@ -2281,7 +2279,6 @@ static int cam_cre_mgr_prepare_hw_update(void *hw_priv,
 
 	prepare_args->num_hw_update_entries = 1;
 	prepare_args->priv = ctx_data->req_list[request_idx];
-	prepare_args->pf_data->packet = packet;
 	cre_req->hang_data.packet = packet;
 	ktime_get_boottime_ts64(&ts);
 	ctx_data->last_req_time = (uint64_t)((ts.tv_sec * 1000000000) +
@@ -2409,10 +2406,20 @@ static void cam_cre_mgr_dump_pf_data(struct cam_cre_hw_mgr  *hw_mgr,
 {
 	struct cam_packet          *packet;
 	struct cam_hw_dump_pf_args *pf_args;
+	size_t                      len;
+	uintptr_t                   packet_addr;
 
-	packet = pf_cmd_args->pf_req_info->packet;
 	pf_args = pf_cmd_args->pf_args;
 
+	rc = cam_mem_get_cpu_buf(pf_cmd_args->pf_req_info->packet_handle, &packet_addr, &len);
+	if (rc) {
+		CAM_ERR(CAM_CRE, "Fail to get packet address from handle: %llu",
+			pf_cmd_args->pf_req_info->packet_handle);
+		return;
+	}
+	packet = (struct cam_packet *)((uint8_t *)packet_addr +
+		(uint32_t)pf_cmd_args->pf_req_info->packet_offset);
+
 	cam_packet_util_dump_io_bufs(packet, hw_mgr->iommu_hdl,
 		hw_mgr->iommu_sec_hdl, pf_args, false);
 

+ 6 - 3
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -5640,8 +5640,6 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
 		return rc;
 	}
 
-	prepare_args->pf_data->packet = packet;
-
 	CAM_DBG(CAM_REQ, "req id = %lld for ctx = %u",
 		packet->header.request_id, ctx_data->ctx_id);
 	/* Update Buffer Address from handles and patch information */
@@ -6913,10 +6911,15 @@ static void cam_icp_mgr_dump_pf_data(struct cam_icp_hw_mgr *hw_mgr,
 {
 	struct cam_packet          *packet;
 	struct cam_hw_dump_pf_args *pf_args;
+	int                         rc;
 
-	packet = pf_cmd_args->pf_req_info->packet;
 	pf_args = pf_cmd_args->pf_args;
 
+	rc = cam_packet_util_get_packet_addr(&packet, pf_cmd_args->pf_req_info->packet_handle,
+		pf_cmd_args->pf_req_info->packet_offset);
+	if (rc)
+		return;
+
 	/*
 	 * res_id_support is false since ICP doesn't have knowledge
 	 * of res_id. FW submits packet to HW

+ 3 - 0
drivers/cam_isp/cam_isp_context.c

@@ -6092,6 +6092,9 @@ static int __cam_isp_ctx_config_dev_in_top_state(
 	req_isp->bubble_detected = false;
 	req_isp->cdm_reset_before_apply = false;
 	req_isp->hw_update_data.packet = packet;
+	req->pf_data.packet_handle = cmd->packet_handle;
+	req->pf_data.packet_offset = cmd->offset;
+	req->pf_data.req = req;
 
 	for (i = 0; i < req_isp->num_fence_map_out; i++) {
 		rc = cam_sync_get_obj_ref(req_isp->fence_map_out[i].sync_id);

+ 13 - 7
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -11924,14 +11924,13 @@ static void cam_ife_mgr_pf_dump(struct cam_ife_hw_mgr_ctx *ctx)
 static void cam_ife_mgr_pf_dump_mid_info(
 	struct cam_ife_hw_mgr_ctx    *ctx,
 	struct cam_hw_cmd_args       *hw_cmd_args,
-	struct cam_isp_hw_intf_data  *hw_intf_data)
+	struct cam_isp_hw_intf_data  *hw_intf_data,
+	struct cam_packet            *packet)
 {
-	struct cam_packet                  *packet;
 	struct cam_isp_hw_get_cmd_update    cmd_update;
 	struct cam_isp_hw_get_res_for_mid   get_res;
 	int                                 rc = 0;
 
-	packet = hw_cmd_args->u.pf_cmd_args->pf_req_info->packet;
 	get_res.mid = hw_cmd_args->u.pf_cmd_args->pf_args->pf_smmu_info->mid;
 	cmd_update.cmd_type = CAM_ISP_HW_CMD_GET_RES_FOR_MID;
 	cmd_update.data = (void *) &get_res;
@@ -11964,12 +11963,17 @@ static void cam_ife_mgr_dump_pf_data(
 	struct cam_packet                  *packet;
 	struct cam_isp_hw_intf_data        *hw_intf_data;
 	struct cam_hw_dump_pf_args         *pf_args;
+	struct cam_hw_mgr_pf_request_info  *pf_req_info;
 	bool                               *ctx_found;
-	int                                 i, j;
+	int                                 i, j, rc;
 
 	ctx = (struct cam_ife_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map;
+	pf_req_info = hw_cmd_args->u.pf_cmd_args->pf_req_info;
+	rc = cam_packet_util_get_packet_addr(&packet, pf_req_info->packet_handle,
+		pf_req_info->packet_offset);
+	if (rc)
+		return;
 
-	packet  = hw_cmd_args->u.pf_cmd_args->pf_req_info->packet;
 	pf_args = hw_cmd_args->u.pf_cmd_args->pf_args;
 	ctx_found = &(pf_args->pf_context_info.ctx_found);
 
@@ -11992,7 +11996,8 @@ static void cam_ife_mgr_dump_pf_data(
 		 */
 		if (!g_ife_hw_mgr.hw_pid_support) {
 			if (ctx->base[i].split_id == CAM_ISP_HW_SPLIT_LEFT)
-				cam_ife_mgr_pf_dump_mid_info(ctx, hw_cmd_args, hw_intf_data);
+				cam_ife_mgr_pf_dump_mid_info(ctx, hw_cmd_args, hw_intf_data,
+					packet);
 			continue;
 		}
 
@@ -12002,7 +12007,8 @@ static void cam_ife_mgr_dump_pf_data(
 				CAM_ERR(CAM_ISP, "PF found for %s%d pid: %u",
 					ctx->base[i].hw_type == CAM_ISP_HW_TYPE_VFE ? "VFE" : "SFE",
 					ctx->base[i].idx, pf_args->pf_smmu_info->pid);
-				cam_ife_mgr_pf_dump_mid_info(ctx, hw_cmd_args, hw_intf_data);
+				cam_ife_mgr_pf_dump_mid_info(ctx, hw_cmd_args, hw_intf_data,
+					packet);
 
 				/* If MID found - stop hw res and dump client info */
 				if (ctx->flags.pf_mid_found) {

+ 4 - 1
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c

@@ -4676,7 +4676,10 @@ static void cam_tfe_mgr_dump_pf_data(
 	ctx = (struct cam_tfe_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map;
 
 	pf_cmd_args = hw_cmd_args->u.pf_cmd_args;
-	packet  = pf_cmd_args->pf_req_info->packet;
+	rc = cam_packet_util_get_packet_addr(packet,
+		pf_cmd_args->pf_req_info->packet_handle, pf_cmd_args->pf_req_info->packet_offset);
+	if (rc)
+		return rc;
 	ctx_found = &pf_cmd_args->pf_args->pf_context_info.ctx_found;
 	resource_type = &pf_cmd_args->pf_args->pf_context_info.resource_type;
 

+ 0 - 1
drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c

@@ -756,7 +756,6 @@ int cam_isp_add_io_buffers(
 	num_out_buf = prepare->num_out_map_entries;
 	num_in_buf  = prepare->num_in_map_entries;
 	io_cfg_used_bytes = 0;
-	prepare->pf_data->packet = prepare->packet;
 
 	/* Max one hw entries required for each base */
 	if (prepare->num_hw_update_entries + 1 >=

+ 13 - 9
drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c

@@ -1033,7 +1033,6 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
 		sizeof(struct cam_buf_io_cfg),
 		packet->header.request_id,
 		ctx_data->jpeg_dev_acquire_info.dev_type);
-	prepare_args->pf_data->packet = packet;
 
 	prepare_args->num_out_map_entries = 0;
 
@@ -1931,17 +1930,22 @@ static void cam_jpeg_mgr_dump_pf_data(
 	struct cam_jpeg_hw_mgr  *hw_mgr,
 	struct cam_hw_cmd_args  *hw_cmd_args)
 {
-	struct cam_jpeg_hw_ctx_data   *ctx_data;
-	struct cam_packet             *packet;
-	struct cam_jpeg_match_pid_args jpeg_pid_mid_args;
-	struct cam_hw_dump_pf_args    *pf_args;
-	uint32_t                       dev_type;
-	bool                           hw_pid_support = true;
-	int                            rc = 0;
+	struct cam_jpeg_hw_ctx_data       *ctx_data;
+	struct cam_packet                 *packet;
+	struct cam_jpeg_match_pid_args     jpeg_pid_mid_args;
+	struct cam_hw_dump_pf_args        *pf_args;
+	struct cam_hw_mgr_pf_request_info *pf_req_info;
+	uint32_t                           dev_type;
+	bool                               hw_pid_support = true;
+	int                                rc = 0;
 
 	ctx_data = (struct cam_jpeg_hw_ctx_data  *)hw_cmd_args->ctxt_to_hw_map;
 	pf_args = hw_cmd_args->u.pf_cmd_args->pf_args;
-	packet  = hw_cmd_args->u.pf_cmd_args->pf_req_info->packet;
+	pf_req_info = hw_cmd_args->u.pf_cmd_args->pf_req_info;
+	rc = cam_packet_util_get_packet_addr(&packet,
+		pf_req_info->packet_handle, pf_req_info->packet_offset);
+	if (rc)
+		return;
 
 	jpeg_pid_mid_args.fault_mid = pf_args->pf_smmu_info->mid;
 	jpeg_pid_mid_args.pid = pf_args->pf_smmu_info->pid;

+ 14 - 12
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c

@@ -3322,8 +3322,6 @@ static int cam_ope_mgr_prepare_hw_update(void *hw_priv,
 	prepare_args->num_hw_update_entries       = 1;
 	prepare_args->hw_update_entries[0].addr   = (uintptr_t)ope_req->cdm_cmd;
 	prepare_args->priv                        = ope_req;
-	prepare_args->pf_data->packet             = packet;
-	prepare_args->pf_data->req                = ope_req;
 
 	CAM_INFO(CAM_REQ, "OPE req %x num_batch %d", ope_req, ope_req->num_batch);
 
@@ -4107,13 +4105,14 @@ static void cam_ope_mgr_dump_pf_data(
 	struct cam_ope_hw_mgr  *hw_mgr,
 	struct cam_hw_cmd_args *hw_cmd_args)
 {
-	struct cam_ope_ctx             *ctx_data;
-	struct cam_packet              *packet;
-	struct cam_buf_io_cfg          *io_cfg = NULL;
-	struct cam_ope_request         *ope_request;
-	struct ope_io_buf              *io_buf = NULL;
-	struct cam_ope_match_pid_args  ope_pid_mid_args;
-	struct cam_hw_dump_pf_args     *pf_args;
+	struct cam_ope_ctx                *ctx_data;
+	struct cam_packet                 *packet;
+	struct cam_buf_io_cfg             *io_cfg = NULL;
+	struct cam_ope_request            *ope_request;
+	struct ope_io_buf                 *io_buf = NULL;
+	struct cam_ope_match_pid_args      ope_pid_mid_args;
+	struct cam_hw_dump_pf_args        *pf_args;
+	struct cam_hw_mgr_pf_request_info *pf_req_info;
 
 	int          device_idx;
 	bool         *ctx_found;
@@ -4127,9 +4126,12 @@ static void cam_ope_mgr_dump_pf_data(
 
 	ctx_data    = (struct cam_ope_ctx *)hw_cmd_args->ctxt_to_hw_map;
 	pf_args = hw_cmd_args->u.pf_cmd_args->pf_args;
-	packet  = hw_cmd_args->u.pf_cmd_args->pf_req_info->packet;
-
-	ope_request = hw_cmd_args->u.pf_cmd_args->pf_req_info->req;
+	pf_req_info = hw_cmd_args->u.pf_cmd_args->pf_req_info;
+	rc = cam_packet_util_get_packet_addr(&packet, pf_req_info->packet_handle,
+		pf_req_info->packet_offset);
+	if (rc)
+		return rc;
+	ope_request = pf_req_info->req;
 
 	ope_pid_mid_args.fault_mid =  pf_args->pf_smmu_info->mid;
 	ope_pid_mid_args.fault_pid = pf_args->pf_smmu_info->pid;

+ 26 - 0
drivers/cam_utils/cam_packet_util.c

@@ -22,6 +22,32 @@ struct cam_patch_unique_src_buf_tbl {
 	uint32_t      flags;
 };
 
+int cam_packet_util_get_packet_addr(struct cam_packet **packet,
+	uint64_t packet_handle, uint32_t offset)
+{
+	uintptr_t          packet_addr;
+	size_t             len;
+	int                rc = 0;
+
+	if (!packet) {
+		CAM_ERR(CAM_UTIL, "Invalid parameter packet is NULL");
+		return -EINVAL;
+	}
+
+	rc = cam_mem_get_cpu_buf(packet_handle, &packet_addr,
+		&len);
+	if (rc) {
+		CAM_ERR(CAM_UTIL, "Failed to get packet address from handle: 0x%llx rc: %d",
+			packet_handle, rc);
+		*packet = NULL;
+		return rc;
+	}
+
+	*packet = (struct cam_packet *)((uint8_t *)packet_addr + offset);
+
+	return rc;
+}
+
 int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
 	size_t *len)
 {

+ 13 - 0
drivers/cam_utils/cam_packet_util.h

@@ -9,6 +9,7 @@
 
 #include <media/cam_defs.h>
 #include "cam_hw_mgr_intf.h"
+
 /**
  * @brief                  KMD scratch buffer information
  *
@@ -31,6 +32,18 @@ struct cam_kmd_buf_info {
 typedef int (*cam_packet_generic_blob_handler)(void *user_data,
 	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data);
 
+/**
+ * @brief                  Get packet buffer address
+ *
+ * @packet:                Pointer to packet to be retrieved
+ * @packet_handle:         Buffer handle of the packet
+ * @offset:                offset to packet start address
+ *
+ * @return:                0 for success
+ */
+int cam_packet_util_get_packet_addr(struct cam_packet **packet,
+	uint64_t packet_handle, uint32_t offset);
+
 /**
  * cam_packet_util_get_cmd_mem_addr()
  *