Procházet zdrojové kódy

msm: camera: core: Add buffer length check to prevent overflow

Previously, context user dumps lacked sufficient checks, risking
buffer overflows. Added length checks for dump headers to ensure
enough buffer space before copying header and exact data from
all kinds of request lists.

CRs-Fixed: 3846871
Change-Id: I02d01af54c9985e5642c31b979c0590494fd5775
Signed-off-by: Atiya Kailany <[email protected]>
Signed-off-by: Haochen Yang <[email protected]>
Atiya Kailany před 8 měsíci
rodič
revize
5fe2c8d7e8
1 změnil soubory, kde provedl 35 přidání a 31 odebrání
  1. 35 31
      drivers/cam_core/cam_context_utils.c

+ 35 - 31
drivers/cam_core/cam_context_utils.c

@@ -1529,7 +1529,6 @@ static int cam_context_user_dump(struct cam_context *ctx,
 	struct cam_context_dump_header  *hdr;
 	uint8_t                         *dst;
 	uint64_t                        *addr, *start;
-	uint32_t                         min_len;
 	size_t                           buf_len, remain_len;
 	uintptr_t                        cpu_addr;
 	uint32_t                         local_len;
@@ -1556,38 +1555,16 @@ static int cam_context_user_dump(struct cam_context *ctx,
 		return -ENOSPC;
 	}
 
-	spin_lock_bh(&ctx->lock);
-	if (!list_empty(&ctx->active_req_list)) {
-		req = list_first_entry(&ctx->active_req_list,
-			struct cam_ctx_request, list);
-	} else if (!list_empty(&ctx->wait_req_list)) {
-		req = list_first_entry(&ctx->wait_req_list,
-			struct cam_ctx_request, list);
-	} else if (!list_empty(&ctx->pending_req_list)) {
-		req = list_first_entry(&ctx->pending_req_list,
-			struct cam_ctx_request, list);
-	} else {
-		CAM_ERR(CAM_CTXT, "[%s][%d] no request to dump",
-			ctx->dev_name, ctx->ctx_id);
-	}
-	spin_unlock_bh(&ctx->lock);
-
-	/* Check for min len in case of available request to dump */
-	if (req != NULL) {
-		remain_len = buf_len - dump_args->offset;
-		min_len = sizeof(struct cam_context_dump_header) +
-			(CAM_CTXT_DUMP_NUM_WORDS + req->num_in_map_entries +
-			(req->num_out_map_entries * 2)) * sizeof(uint64_t);
-
-		if (remain_len < min_len) {
-			CAM_WARN(CAM_CTXT, "dump buffer exhaust remain %zu min %u",
-				remain_len, min_len);
-			cam_mem_put_cpu_buf(dump_args->buf_handle);
-			return -ENOSPC;
-		}
+	/* Dump context info */
+	remain_len = buf_len - dump_args->offset;
+	if (remain_len < sizeof(struct cam_context_dump_header)) {
+		CAM_WARN(CAM_CTXT,
+			"No sufficient space in dump buffer for headers, remain buf size: %d, header size: %d",
+			remain_len, sizeof(struct cam_context_dump_header));
+		cam_mem_put_cpu_buf(dump_args->buf_handle);
+		return -ENOSPC;
 	}
 
-	/* Dump context info */
 	dst = (uint8_t *)cpu_addr + dump_args->offset;
 	hdr = (struct cam_context_dump_header *)dst;
 	local_len =
@@ -1611,6 +1588,15 @@ static int cam_context_user_dump(struct cam_context *ctx,
 	if (!list_empty(&ctx->wait_req_list)) {
 		list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) {
 			for (i = 0; i < req->num_out_map_entries; i++) {
+				remain_len = buf_len - dump_args->offset;
+				if (remain_len < sizeof(struct cam_context_dump_header)) {
+					CAM_WARN(CAM_CTXT,
+						"No sufficient space in dump buffer for headers, remain buf size: %d, header size: %d",
+						remain_len, sizeof(struct cam_context_dump_header));
+					cam_mem_put_cpu_buf(dump_args->buf_handle);
+					return -ENOSPC;
+				}
+
 				dst = (uint8_t *)cpu_addr + dump_args->offset;
 				hdr = (struct cam_context_dump_header *)dst;
 				local_len = dump_args->offset +
@@ -1643,6 +1629,15 @@ static int cam_context_user_dump(struct cam_context *ctx,
 	if (!list_empty(&ctx->pending_req_list)) {
 		list_for_each_entry_safe(req, req_temp, &ctx->pending_req_list, list) {
 			for (i = 0; i < req->num_out_map_entries; i++) {
+				remain_len = buf_len - dump_args->offset;
+				if (remain_len < sizeof(struct cam_context_dump_header)) {
+					CAM_WARN(CAM_CTXT,
+						"No sufficient space in dump buffer for headers, remain buf size: %d, header size: %d",
+						remain_len, sizeof(struct cam_context_dump_header));
+					cam_mem_put_cpu_buf(dump_args->buf_handle);
+					return -ENOSPC;
+				}
+
 				dst = (uint8_t *)cpu_addr + dump_args->offset;
 				hdr = (struct cam_context_dump_header *)dst;
 				local_len = dump_args->offset +
@@ -1675,6 +1670,15 @@ static int cam_context_user_dump(struct cam_context *ctx,
 	if (!list_empty(&ctx->active_req_list)) {
 		list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
 			for (i = 0; i < req->num_out_map_entries; i++) {
+				remain_len = buf_len - dump_args->offset;
+				if (remain_len < sizeof(struct cam_context_dump_header)) {
+					CAM_WARN(CAM_CTXT,
+						"No sufficient space in dump buffer for headers, remain buf size: %d, header size: %d",
+						remain_len, sizeof(struct cam_context_dump_header));
+					cam_mem_put_cpu_buf(dump_args->buf_handle);
+					return -ENOSPC;
+				}
+
 				dst = (uint8_t *)cpu_addr + dump_args->offset;
 				hdr = (struct cam_context_dump_header *)dst;
 				local_len = dump_args->offset +