mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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. Bug: 19141655 Conflicts: drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h Change-Id: If3719de65b32773c2b6ff904da76a951dbfb11eb Signed-off-by: Alok Kediya <kediya@codeaurora.org> Signed-off-by: Patrick Tjin <pattjin@google.com> Signed-off-by: Patrick Tjin <pattjin@google.com>
This commit is contained in:
parent
41dda3638b
commit
18d456d3b2
3 changed files with 143 additions and 34 deletions
|
@ -402,9 +402,24 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
|
|||
struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd,
|
||||
uint32_t *cfg_data, uint32_t cmd_len)
|
||||
{
|
||||
if (!vfe_dev || !reg_cfg_cmd) {
|
||||
pr_err("%s:%d failed: vfe_dev %p reg_cfg_cmd %p\n", __func__,
|
||||
__LINE__, vfe_dev, reg_cfg_cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((reg_cfg_cmd->cmd_type != VFE_CFG_MASK) &&
|
||||
(!cfg_data || !cmd_len)) {
|
||||
pr_err("%s:%d failed: cmd type %d cfg_data %p cmd_len %d\n",
|
||||
__func__, __LINE__, reg_cfg_cmd->cmd_type, cfg_data,
|
||||
cmd_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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 +
|
||||
|
@ -430,6 +445,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;
|
||||
}
|
||||
|
@ -443,16 +510,25 @@ 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;
|
||||
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 ((UINT_MAX - sizeof(temp) <
|
||||
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 +
|
||||
|
@ -466,20 +542,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 (reg_cfg_cmd->u.dmi_info.hi_tbl_offset +
|
||||
reg_cfg_cmd->u.dmi_info.len > 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;
|
||||
|
||||
|
@ -510,30 +575,18 @@ 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 > 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;
|
||||
|
||||
for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) {
|
||||
if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) {
|
||||
hi_val = msm_camera_io_r(vfe_dev->vfe_base +
|
||||
vfe_dev->hw_info->dmi_reg_offset);
|
||||
*hi_tbl_ptr++ = hi_val;
|
||||
}
|
||||
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);
|
||||
|
||||
|
@ -543,6 +596,13 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
|
|||
lo_val |= lo_val1 << 16;
|
||||
}
|
||||
*lo_tbl_ptr++ = lo_val;
|
||||
if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) {
|
||||
hi_val = msm_camera_io_r(vfe_dev->vfe_base +
|
||||
vfe_dev->hw_info->dmi_reg_offset);
|
||||
*hi_tbl_ptr = hi_val;
|
||||
hi_tbl_ptr += 2;
|
||||
lo_tbl_ptr++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -550,9 +610,16 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
|
|||
int i;
|
||||
uint32_t *data_ptr = cfg_data +
|
||||
reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
|
||||
for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++)
|
||||
for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++) {
|
||||
if ((data_ptr < cfg_data) ||
|
||||
(UINT_MAX / 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 +
|
||||
reg_cfg_cmd->u.rw_info.reg_offset++);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,45 @@ 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)
|
||||
{
|
||||
int i;
|
||||
int rc = 0;
|
||||
struct clk *mux_clk = NULL;
|
||||
struct clk *src_clk = NULL;
|
||||
|
||||
for (i = 0; i < num_clk; i++) {
|
||||
if (clk_src_info[i].clk_name) {
|
||||
mux_clk = clk_get(dev, clk_info[i].clk_name);
|
||||
if (IS_ERR(mux_clk)) {
|
||||
pr_err("%s get failed\n",
|
||||
clk_info[i].clk_name);
|
||||
continue;
|
||||
}
|
||||
src_clk = clk_get(dev, clk_src_info[i].clk_name);
|
||||
if (IS_ERR(src_clk)) {
|
||||
pr_err("%s get failed\n",
|
||||
clk_src_info[i].clk_name);
|
||||
continue;
|
||||
}
|
||||
clk_set_parent(mux_clk, src_clk);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
|
||||
struct clk **clk_ptr, int num_clk, int enable)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,10 @@ 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,
|
||||
struct clk **clk_ptr, int num_clk, int enable);
|
||||
|
||||
|
|
Loading…
Reference in a new issue