Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a873fb67 authored by Tejas Prajapati's avatar Tejas Prajapati Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: isp: validate in_port before accessing



in_port information we are getting from the UMD and accessing
it directly without validation which might lead to
corruption and device failure.

CRs-Fixed: 2629969
Change-Id: I0a1c57db9b94f9657427872ae6797635c6aed668
Signed-off-by: default avatarTejas Prajapati <tpraja@codeaurora.org>
parent 1ed6c5c6
Loading
Loading
Loading
Loading
+44 −6
Original line number Original line Diff line number Diff line
@@ -2119,18 +2119,36 @@ static int cam_ife_hw_mgr_acquire_res_root(


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",
@@ -2164,18 +2182,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",
@@ -2209,7 +2245,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;


@@ -2222,10 +2259,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");
@@ -2728,7 +2765,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;