Browse Source

Merge "msm: camera: isp: validate in_port before accessing" into camera-kernel.lnx.4.0

Camera Software Integration 5 years ago
parent
commit
3f28f49226
1 changed files with 44 additions and 6 deletions
  1. 44 6
      drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

+ 44 - 6
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -2110,18 +2110,36 @@ err:
 
 
 static int cam_ife_mgr_check_and_update_fe_v0(
 static int cam_ife_mgr_check_and_update_fe_v0(
 	struct cam_ife_hw_mgr_ctx         *ife_ctx,
 	struct cam_ife_hw_mgr_ctx         *ife_ctx,
-	struct cam_isp_acquire_hw_info    *acquire_hw_info)
+	struct cam_isp_acquire_hw_info    *acquire_hw_info,
+	uint32_t                           acquire_info_size)
 {
 {
 	int i;
 	int i;
 	struct cam_isp_in_port_info       *in_port = NULL;
 	struct cam_isp_in_port_info       *in_port = NULL;
 	uint32_t                           in_port_length = 0;
 	uint32_t                           in_port_length = 0;
 	uint32_t                           total_in_port_length = 0;
 	uint32_t                           total_in_port_length = 0;
 
 
+	if (acquire_hw_info->input_info_offset >=
+		acquire_hw_info->input_info_size) {
+		CAM_ERR(CAM_ISP,
+			"Invalid size offset 0x%x is greater then size 0x%x",
+			acquire_hw_info->input_info_offset,
+			acquire_hw_info->input_info_size);
+		return -EINVAL;
+	}
+
 	in_port = (struct cam_isp_in_port_info *)
 	in_port = (struct cam_isp_in_port_info *)
 		((uint8_t *)&acquire_hw_info->data +
 		((uint8_t *)&acquire_hw_info->data +
 		 acquire_hw_info->input_info_offset);
 		 acquire_hw_info->input_info_offset);
 	for (i = 0; i < acquire_hw_info->num_inputs; i++) {
 	for (i = 0; i < acquire_hw_info->num_inputs; i++) {
 
 
+		if (((uint8_t *)in_port +
+			sizeof(struct cam_isp_in_port_info)) >
+			((uint8_t *)acquire_hw_info +
+			acquire_info_size)) {
+			CAM_ERR(CAM_ISP, "Invalid size");
+			return -EINVAL;
+		}
+
 		if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) ||
 		if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) ||
 			(in_port->num_out_res <= 0)) {
 			(in_port->num_out_res <= 0)) {
 			CAM_ERR(CAM_ISP, "Invalid num output res %u",
 			CAM_ERR(CAM_ISP, "Invalid num output res %u",
@@ -2155,18 +2173,36 @@ static int cam_ife_mgr_check_and_update_fe_v0(
 
 
 static int cam_ife_mgr_check_and_update_fe_v2(
 static int cam_ife_mgr_check_and_update_fe_v2(
 	struct cam_ife_hw_mgr_ctx         *ife_ctx,
 	struct cam_ife_hw_mgr_ctx         *ife_ctx,
-	struct cam_isp_acquire_hw_info    *acquire_hw_info)
+	struct cam_isp_acquire_hw_info    *acquire_hw_info,
+	uint32_t                           acquire_info_size)
 {
 {
 	int i;
 	int i;
 	struct cam_isp_in_port_info_v2    *in_port = NULL;
 	struct cam_isp_in_port_info_v2    *in_port = NULL;
 	uint32_t                           in_port_length = 0;
 	uint32_t                           in_port_length = 0;
 	uint32_t                           total_in_port_length = 0;
 	uint32_t                           total_in_port_length = 0;
 
 
+	if (acquire_hw_info->input_info_offset >=
+		acquire_hw_info->input_info_size) {
+		CAM_ERR(CAM_ISP,
+			"Invalid size offset 0x%x is greater then size 0x%x",
+			acquire_hw_info->input_info_offset,
+			acquire_hw_info->input_info_size);
+		return -EINVAL;
+	}
+
 	in_port = (struct cam_isp_in_port_info_v2 *)
 	in_port = (struct cam_isp_in_port_info_v2 *)
 		((uint8_t *)&acquire_hw_info->data +
 		((uint8_t *)&acquire_hw_info->data +
 		 acquire_hw_info->input_info_offset);
 		 acquire_hw_info->input_info_offset);
 	for (i = 0; i < acquire_hw_info->num_inputs; i++) {
 	for (i = 0; i < acquire_hw_info->num_inputs; i++) {
 
 
+		if (((uint8_t *)in_port +
+			sizeof(struct cam_isp_in_port_info)) >
+			((uint8_t *)acquire_hw_info +
+			acquire_info_size)) {
+			CAM_ERR(CAM_ISP, "Invalid size");
+			return -EINVAL;
+		}
+
 		if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) ||
 		if ((in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) ||
 			(in_port->num_out_res <= 0)) {
 			(in_port->num_out_res <= 0)) {
 			CAM_ERR(CAM_ISP, "Invalid num output res %u",
 			CAM_ERR(CAM_ISP, "Invalid num output res %u",
@@ -2203,7 +2239,8 @@ static int cam_ife_mgr_check_and_update_fe_v2(
 
 
 static int cam_ife_mgr_check_and_update_fe(
 static int cam_ife_mgr_check_and_update_fe(
 	struct cam_ife_hw_mgr_ctx         *ife_ctx,
 	struct cam_ife_hw_mgr_ctx         *ife_ctx,
-	struct cam_isp_acquire_hw_info    *acquire_hw_info)
+	struct cam_isp_acquire_hw_info    *acquire_hw_info,
+	uint32_t                           acquire_info_size)
 {
 {
 	uint32_t major_ver = 0, minor_ver = 0;
 	uint32_t major_ver = 0, minor_ver = 0;
 
 
@@ -2216,10 +2253,10 @@ static int cam_ife_mgr_check_and_update_fe(
 	switch (major_ver) {
 	switch (major_ver) {
 	case 1:
 	case 1:
 		return cam_ife_mgr_check_and_update_fe_v0(
 		return cam_ife_mgr_check_and_update_fe_v0(
-			ife_ctx, acquire_hw_info);
+			ife_ctx, acquire_hw_info, acquire_info_size);
 	case 2:
 	case 2:
 		return cam_ife_mgr_check_and_update_fe_v2(
 		return cam_ife_mgr_check_and_update_fe_v2(
-			ife_ctx, acquire_hw_info);
+			ife_ctx, acquire_hw_info, acquire_info_size);
 		break;
 		break;
 	default:
 	default:
 		CAM_ERR(CAM_ISP, "Invalid ver of common info from user");
 		CAM_ERR(CAM_ISP, "Invalid ver of common info from user");
@@ -3014,7 +3051,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 	acquire_hw_info =
 	acquire_hw_info =
 		(struct cam_isp_acquire_hw_info *)acquire_args->acquire_info;
 		(struct cam_isp_acquire_hw_info *)acquire_args->acquire_info;
 
 
-	rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info);
+	rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info,
+		acquire_args->acquire_info_size);
 	if (rc) {
 	if (rc) {
 		CAM_ERR(CAM_ISP, "buffer size is not enough");
 		CAM_ERR(CAM_ISP, "buffer size is not enough");
 		goto free_cdm;
 		goto free_cdm;