From 51c39420e3a49d1a7f05a77c64369b7623088238 Mon Sep 17 00:00:00 2001 From: Sreesudhan Ramakrish Ramkumar Date: Fri, 12 Dec 2014 04:20:59 -0800 Subject: msm: camera: isp: Validate input parameter for vfe_write and vfe_read Validate input parameters for read and write operations in vfe to ensure operations are performed within vfe register boundary and within structure limits passed by caller. Change-Id: If3719de65b32773c2b6ff904da76a951dbfb11eb Signed-off-by: Sreesudhan Ramakrish Ramkumar --- .../platform/msm/camera_v2/isp/msm_isp_util.c | 126 +++++++++++++-------- .../msm/camera_v2/sensor/io/msm_camera_io_util.c | 11 ++ .../msm/camera_v2/sensor/io/msm_camera_io_util.h | 2 + 3 files changed, 89 insertions(+), 50 deletions(-) diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index c598555..ff213fc 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -917,7 +917,8 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, /* Validate input parameters */ switch (reg_cfg_cmd->cmd_type) { case VFE_WRITE: - case VFE_READ: { + case VFE_READ: + case VFE_WRITE_MB: { if ((reg_cfg_cmd->u.rw_info.reg_offset > (UINT_MAX - reg_cfg_cmd->u.rw_info.len)) || ((reg_cfg_cmd->u.rw_info.reg_offset + @@ -943,6 +944,58 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, } break; } + + case VFE_WRITE_DMI_16BIT: + case VFE_WRITE_DMI_32BIT: + case VFE_WRITE_DMI_64BIT: + case VFE_READ_DMI_16BIT: + case VFE_READ_DMI_32BIT: + case VFE_READ_DMI_64BIT: { + if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { + if ((reg_cfg_cmd->u.dmi_info.hi_tbl_offset <= + reg_cfg_cmd->u.dmi_info.lo_tbl_offset) || + (reg_cfg_cmd->u.dmi_info.hi_tbl_offset - + reg_cfg_cmd->u.dmi_info.lo_tbl_offset != + (sizeof(uint32_t)))) { + pr_err("%s:%d hi %d lo %d\n", + __func__, __LINE__, + reg_cfg_cmd->u.dmi_info.hi_tbl_offset, + reg_cfg_cmd->u.dmi_info.hi_tbl_offset); + return -EINVAL; + } + if (reg_cfg_cmd->u.dmi_info.len <= sizeof(uint32_t)) { + pr_err("%s:%d len %d\n", + __func__, __LINE__, + reg_cfg_cmd->u.dmi_info.len); + return -EINVAL; + } + if (((UINT_MAX - + reg_cfg_cmd->u.dmi_info.hi_tbl_offset) < + (reg_cfg_cmd->u.dmi_info.len - + sizeof(uint32_t))) || + ((reg_cfg_cmd->u.dmi_info.hi_tbl_offset + + reg_cfg_cmd->u.dmi_info.len - + sizeof(uint32_t)) > cmd_len)) { + pr_err("%s:%d hi_tbl_offset %d len %d cmd %d\n", + __func__, __LINE__, + reg_cfg_cmd->u.dmi_info.hi_tbl_offset, + reg_cfg_cmd->u.dmi_info.len, cmd_len); + return -EINVAL; + } + } + if ((reg_cfg_cmd->u.dmi_info.lo_tbl_offset > + (UINT_MAX - reg_cfg_cmd->u.dmi_info.len)) || + ((reg_cfg_cmd->u.dmi_info.lo_tbl_offset + + reg_cfg_cmd->u.dmi_info.len) > cmd_len)) { + pr_err("%s:%d lo_tbl_offset %d len %d cmd_len %d\n", + __func__, __LINE__, + reg_cfg_cmd->u.dmi_info.lo_tbl_offset, + reg_cfg_cmd->u.dmi_info.len, cmd_len); + return -EINVAL; + } + break; + } + default: break; } @@ -956,39 +1009,27 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, break; } case VFE_WRITE_MB: { - uint32_t *data_ptr = cfg_data + - reg_cfg_cmd->u.rw_info.cmd_data_offset/4; - - if ((UINT_MAX - sizeof(*data_ptr) < - reg_cfg_cmd->u.rw_info.reg_offset) || - (resource_size(vfe_dev->vfe_mem) < - reg_cfg_cmd->u.rw_info.reg_offset + - sizeof(*data_ptr))) { - pr_err("%s: VFE_WRITE_MB: Invalid length\n", __func__); - return -EINVAL; - } - msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base + - reg_cfg_cmd->u.rw_info.reg_offset); + msm_camera_io_memcpy_mb(vfe_dev->vfe_base + + reg_cfg_cmd->u.rw_info.reg_offset, + cfg_data + reg_cfg_cmd->u.rw_info.cmd_data_offset/4, + reg_cfg_cmd->u.rw_info.len); break; } case VFE_CFG_MASK: { uint32_t temp; - if (resource_size(vfe_dev->vfe_mem) < - reg_cfg_cmd->u.mask_info.reg_offset) - return -EINVAL; - temp = msm_camera_io_r(vfe_dev->vfe_base + - reg_cfg_cmd->u.mask_info.reg_offset); - - temp &= ~reg_cfg_cmd->u.mask_info.mask; - temp |= reg_cfg_cmd->u.mask_info.val; if ((UINT_MAX - sizeof(temp) < - reg_cfg_cmd->u.mask_info.reg_offset) || + reg_cfg_cmd->u.mask_info.reg_offset) || (resource_size(vfe_dev->vfe_mem) < reg_cfg_cmd->u.mask_info.reg_offset + sizeof(temp))) { pr_err("%s: VFE_CFG_MASK: Invalid length\n", __func__); return -EINVAL; } + temp = msm_camera_io_r(vfe_dev->vfe_base + + reg_cfg_cmd->u.mask_info.reg_offset); + + temp &= ~reg_cfg_cmd->u.mask_info.mask; + temp |= reg_cfg_cmd->u.mask_info.val; msm_camera_io_w(temp, vfe_dev->vfe_base + reg_cfg_cmd->u.mask_info.reg_offset); break; @@ -1000,24 +1041,9 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL; uint32_t hi_val, lo_val, lo_val1; if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { - if ((UINT_MAX - reg_cfg_cmd->u.dmi_info.hi_tbl_offset < - reg_cfg_cmd->u.dmi_info.len - - sizeof(uint32_t)) || - (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + - reg_cfg_cmd->u.dmi_info.len - - sizeof(uint32_t) > cmd_len)) { - pr_err("Invalid Hi Table out of bounds\n"); - return -EINVAL; - } hi_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4; } - - if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset + - reg_cfg_cmd->u.dmi_info.len > cmd_len) { - pr_err("Invalid Lo Table out of bounds\n"); - return -EINVAL; - } lo_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4; if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) @@ -1050,24 +1076,17 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL; uint32_t hi_val, lo_val, lo_val1; if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) { - if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + - reg_cfg_cmd->u.dmi_info.len - - sizeof(uint32_t) > cmd_len) { - pr_err("Invalid Hi Table out of bounds\n"); - return -EINVAL; - } hi_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4; } - if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset + - reg_cfg_cmd->u.dmi_info.len > cmd_len) { - pr_err("Invalid Lo Table out of bounds\n"); - return -EINVAL; - } lo_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4; + if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) + reg_cfg_cmd->u.dmi_info.len = + reg_cfg_cmd->u.dmi_info.len / 2; + for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) { lo_val = msm_camera_io_r(vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset + 0x4); @@ -1121,7 +1140,7 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, if ((data_ptr < cfg_data) || (UINT_MAX / sizeof(*data_ptr) < (data_ptr - cfg_data)) || - (sizeof(*data_ptr) * (data_ptr - cfg_data) > + (sizeof(*data_ptr) * (data_ptr - cfg_data) >= cmd_len)) return -EINVAL; *data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base + @@ -1187,6 +1206,13 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, case SET_WM_UB_SIZE: break; case SET_UB_POLICY: { + + if (cmd_len < sizeof(vfe_dev->vfe_ub_policy)) { + pr_err("%s:%d failed: invalid cmd len %u exp %zu\n", + __func__, __LINE__, cmd_len, + sizeof(vfe_dev->vfe_ub_policy)); + return -EINVAL; + } vfe_dev->vfe_ub_policy = *cfg_data; break; } diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c index 78b9148..41c784a 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c @@ -102,6 +102,17 @@ void msm_camera_io_memcpy(void __iomem *dest_addr, msm_camera_io_dump(dest_addr, len); } +void msm_camera_io_memcpy_mb(void __iomem *dest_addr, + void __iomem *src_addr, u32 len) +{ + int i; + u32 *d = (u32 *) dest_addr; + u32 *s = (u32 *) src_addr; + + for (i = 0; i < (len / 4); i++) + msm_camera_io_w_mb(*s++, d++); +} + int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info, struct msm_cam_clk_info *clk_src_info, int num_clk) { diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h index fa9a283..2a0e21c 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h +++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h @@ -38,6 +38,8 @@ u32 msm_camera_io_r_mb(void __iomem *addr); void msm_camera_io_dump(void __iomem *addr, int size); void msm_camera_io_memcpy(void __iomem *dest_addr, void __iomem *src_addr, u32 len); +void msm_camera_io_memcpy_mb(void __iomem *dest_addr, + void __iomem *src_addr, u32 len); int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info, struct msm_cam_clk_info *clk_src_info, int num_clk); int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info, -- cgit v1.1