DivestOS/Patches/Linux_CVEs/CVE-2014-9871/0.patch

147 lines
5.5 KiB
Diff

From f615e40c706708f74cd826d5b19c63025f54c041 Mon Sep 17 00:00:00 2001
From: Seemanta Dutta <seemanta@codeaurora.org>
Date: Tue, 23 Jul 2013 15:52:22 -0700
Subject: msm: camera: Fix potential memory overflow errors
Fix potential memory overflow errors in msm_isp_util.c which happen
under certain rare conditions.
CRs-fixed: 514717
Change-Id: I8c70e089df9bf1e7a364c5c8264b782c9c23bf0b
Signed-off-by: Seemanta Dutta <seemanta@codeaurora.org>
---
.../platform/msm/camera_v2/isp/msm_isp_util.c | 47 +++++++++++++++++++---
.../platform/msm/camera_v2/isp/msm_isp_util.h | 2 +-
2 files changed, 43 insertions(+), 6 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 3806213..9b9c5a3 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
@@ -366,7 +366,7 @@ long msm_isp_ioctl(struct v4l2_subdev *sd,
break;
case VIDIOC_MSM_ISP_SET_SRC_STATE:
mutex_lock(&vfe_dev->core_mutex);
- msm_isp_set_src_state(vfe_dev, arg);
+ rc = msm_isp_set_src_state(vfe_dev, arg);
mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_REQUEST_STATS_STREAM:
@@ -410,7 +410,7 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
if (resource_size(vfe_dev->vfe_mem) <
(reg_cfg_cmd->u.rw_info.reg_offset +
reg_cfg_cmd->u.rw_info.len)) {
- pr_err("%s: Invalid length\n", __func__);
+ pr_err("%s: VFE_WRITE: Invalid length\n", __func__);
return -EINVAL;
}
msm_camera_io_memcpy(vfe_dev->vfe_base +
@@ -422,16 +422,37 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
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);
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) ||
+ (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;
+ }
msm_camera_io_w(temp, vfe_dev->vfe_base +
reg_cfg_cmd->u.mask_info.reg_offset);
break;
@@ -443,8 +464,10 @@ 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) {
+ 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;
}
@@ -528,6 +551,12 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev,
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++) {
+ 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);
reg_cfg_cmd->u.rw_info.reg_offset += 4;
@@ -545,6 +574,11 @@ int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg)
struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd;
uint32_t *cfg_data;
+ if (!proc_cmd->num_cfg) {
+ pr_err("%s: Passed num_cfg as 0\n", __func__);
+ return -EINVAL;
+ }
+
reg_cfg_cmd = kzalloc(sizeof(struct msm_vfe_reg_cfg_cmd)*
proc_cmd->num_cfg, GFP_KERNEL);
if (!reg_cfg_cmd) {
@@ -856,11 +890,14 @@ void msm_isp_do_tasklet(unsigned long data)
}
}
-void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg)
+int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg)
{
struct msm_vfe_axi_src_state *src_state = arg;
+ if (src_state->input_src >= VFE_SRC_MAX)
+ return -EINVAL;
vfe_dev->axi_data.src_info[src_state->input_src].active =
src_state->src_active;
+ return 0;
}
int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index 34b9859..9d9558a 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -64,7 +64,7 @@ int msm_isp_cal_word_per_line(uint32_t output_format,
uint32_t pixel_per_line);
int msm_isp_get_bit_per_pixel(uint32_t output_format);
irqreturn_t msm_isp_process_irq(int irq_num, void *data);
-void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
void msm_isp_do_tasklet(unsigned long data);
void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev);
void msm_isp_process_error_info(struct vfe_device *vfe_dev);
--
cgit v1.1