DivestOS/Patches/Linux_CVEs/CVE-2014-4324/ANY/0001.patch
2017-11-07 17:32:46 -05:00

309 lines
10 KiB
Diff

From 8ad163e831a2b2c30551edb360f168a604cdb0bb Mon Sep 17 00:00:00 2001
From: Alok Kediya <kediya@codeaurora.org>
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: Alok Kediya <kediya@codeaurora.org>
---
.../platform/msm/camera_v2/isp/msm_isp_util.c | 162 ++++++++++++++-------
.../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, 119 insertions(+), 56 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 620c01a..e1b79ce 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
@@ -494,9 +494,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 +
@@ -522,6 +537,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;
}
@@ -535,39 +602,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;
@@ -579,22 +634,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) ||
- (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;
if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT)
@@ -627,30 +669,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);
@@ -660,6 +690,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;
}
@@ -698,7 +735,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 +
@@ -707,9 +744,16 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
}
break;
}
- case GET_SOC_HW_VER:
- *cfg_data = vfe_dev->soc_hw_version;
- break;
+ case GET_SOC_HW_VER: {
+ if (cmd_len < sizeof(uint32_t)) {
+ pr_err("%s:%d failed: invalid cmd len %u exp %zu\n",
+ __func__, __LINE__, cmd_len,
+ sizeof(uint32_t));
+ return -EINVAL;
+ }
+ *cfg_data = vfe_dev->soc_hw_version;
+ break;
+ }
case GET_MAX_CLK_RATE: {
int rc = 0;
@@ -728,6 +772,12 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
break;
}
case SET_WM_UB_SIZE: {
+ if (cmd_len < sizeof(uint32_t)) {
+ pr_err("%s:%d failed: invalid cmd len %u exp %zu\n",
+ __func__, __LINE__, cmd_len,
+ sizeof(uint32_t));
+ return -EINVAL;
+ }
vfe_dev->vfe_ub_size = *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 46a0542..7d369ff 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
@@ -107,6 +107,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 2e6f809..90925a9 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
@@ -28,6 +28,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