summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-05-03 23:32:07 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-05-03 23:32:06 -0700
commita1e1d01429ac1fb8cc68c546a82a220b77ca4dd7 (patch)
treecb29cc3034ec42bfd1aecf83f7f122e60adf82c2 /drivers
parent9d0c2b4690a9e2bf526cb91a3bd5ba8272d34f1d (diff)
parentfab64410d005a7dee8ed02557a0ca26e4c5242ff (diff)
Merge "msm: camera2: cpp: Fix out-of-bounds frame or command buffer access"
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c82
1 files changed, 64 insertions, 18 deletions
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 8402e31364b9..b7feb126f707 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -2542,9 +2542,29 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev,
return -EINVAL;
}
- if (stripe_base == UINT_MAX || new_frame->num_strips >
- (UINT_MAX - 1 - stripe_base) / stripe_size) {
- pr_err("Invalid frame message,num_strips %d is large\n",
+ /* Stripe index starts at zero */
+ if ((!new_frame->num_strips) ||
+ (new_frame->first_stripe_index >= new_frame->num_strips) ||
+ (new_frame->last_stripe_index >= new_frame->num_strips) ||
+ (new_frame->first_stripe_index >
+ new_frame->last_stripe_index)) {
+ pr_err("Invalid frame message, #stripes=%d, stripe indices=[%d,%d]\n",
+ new_frame->num_strips,
+ new_frame->first_stripe_index,
+ new_frame->last_stripe_index);
+ return -EINVAL;
+ }
+
+ if (!stripe_size) {
+ pr_err("Invalid frame message, invalid stripe_size (%d)!\n",
+ stripe_size);
+ return -EINVAL;
+ }
+
+ if ((stripe_base == UINT_MAX) ||
+ (new_frame->num_strips >
+ (UINT_MAX - 1 - stripe_base) / stripe_size)) {
+ pr_err("Invalid frame message, num_strips %d is large\n",
new_frame->num_strips);
return -EINVAL;
}
@@ -2785,13 +2805,14 @@ static int msm_cpp_cfg(struct cpp_device *cpp_dev,
struct msm_cpp_frame_info_t *frame = NULL;
struct msm_cpp_frame_info_t k_frame_info;
int32_t rc = 0;
- int32_t i = 0;
- int32_t num_buff = sizeof(k_frame_info.output_buffer_info)/
+ uint32_t i = 0;
+ uint32_t num_buff = sizeof(k_frame_info.output_buffer_info) /
sizeof(struct msm_cpp_buffer_info_t);
+
if (copy_from_user(&k_frame_info,
(void __user *)ioctl_ptr->ioctl_ptr,
sizeof(k_frame_info)))
- return -EFAULT;
+ return -EFAULT;
frame = msm_cpp_get_frame(ioctl_ptr);
if (!frame) {
@@ -2953,8 +2974,9 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg,
}
*ioctl_ptr = arg;
- if ((*ioctl_ptr == NULL) ||
- ((*ioctl_ptr)->ioctl_ptr == NULL)) {
+ if (((*ioctl_ptr) == NULL) ||
+ ((*ioctl_ptr)->ioctl_ptr == NULL) ||
+ ((*ioctl_ptr)->len == 0)) {
pr_err("Error invalid ioctl argument cmd %u", cmd);
return -EINVAL;
}
@@ -3503,13 +3525,18 @@ STREAM_BUFF_END:
if (cpp_dev->iommu_state == CPP_IOMMU_STATE_DETACHED) {
struct msm_camera_smmu_attach_type cpp_attach_info;
+ if (ioctl_ptr->len !=
+ sizeof(struct msm_camera_smmu_attach_type)) {
+ rc = -EINVAL;
+ break;
+ }
+
memset(&cpp_attach_info, 0, sizeof(cpp_attach_info));
rc = msm_cpp_copy_from_ioctl_ptr(&cpp_attach_info,
ioctl_ptr);
if (rc < 0) {
pr_err("CPP_IOMMU_ATTACH copy from user fail");
- ERR_COPY_FROM_USER();
- return -EINVAL;
+ break;
}
cpp_dev->security_mode = cpp_attach_info.attach;
@@ -3538,16 +3565,20 @@ STREAM_BUFF_END:
case VIDIOC_MSM_CPP_IOMMU_DETACH: {
if ((cpp_dev->iommu_state == CPP_IOMMU_STATE_ATTACHED) &&
(cpp_dev->stream_cnt == 0)) {
-
struct msm_camera_smmu_attach_type cpp_attach_info;
+ if (ioctl_ptr->len !=
+ sizeof(struct msm_camera_smmu_attach_type)) {
+ rc = -EINVAL;
+ break;
+ }
+
memset(&cpp_attach_info, 0, sizeof(cpp_attach_info));
rc = msm_cpp_copy_from_ioctl_ptr(&cpp_attach_info,
ioctl_ptr);
if (rc < 0) {
pr_err("CPP_IOMMU_DETTACH copy from user fail");
- ERR_COPY_FROM_USER();
- return -EINVAL;
+ break;
}
cpp_dev->security_mode = cpp_attach_info.attach;
@@ -3568,6 +3599,7 @@ STREAM_BUFF_END:
} else {
pr_err("%s:%d IOMMMU attach triggered in invalid state\n",
__func__, __LINE__);
+ rc = -EINVAL;
}
break;
}
@@ -3883,6 +3915,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file,
struct msm_cpp_stream_buff_info_t k_cpp_buff_info;
struct msm_cpp_frame_info32_t k32_frame_info;
struct msm_cpp_frame_info_t k64_frame_info;
+ struct msm_camera_smmu_attach_type kb_cpp_smmu_attach_info;
uint32_t identity_k = 0;
bool is_copytouser_req = true;
void __user *up = (void __user *)arg;
@@ -4187,11 +4220,23 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file,
break;
}
case VIDIOC_MSM_CPP_IOMMU_ATTACH32:
- cmd = VIDIOC_MSM_CPP_IOMMU_ATTACH;
- break;
case VIDIOC_MSM_CPP_IOMMU_DETACH32:
- cmd = VIDIOC_MSM_CPP_IOMMU_DETACH;
+ {
+ if ((kp_ioctl.len != sizeof(struct msm_camera_smmu_attach_type))
+ || (copy_from_user(&kb_cpp_smmu_attach_info,
+ (void __user *)kp_ioctl.ioctl_ptr,
+ sizeof(kb_cpp_smmu_attach_info)))) {
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ kp_ioctl.ioctl_ptr = (void *)&kb_cpp_smmu_attach_info;
+ is_copytouser_req = false;
+ cmd = (cmd == VIDIOC_MSM_CPP_IOMMU_ATTACH32) ?
+ VIDIOC_MSM_CPP_IOMMU_ATTACH :
+ VIDIOC_MSM_CPP_IOMMU_DETACH;
break;
+ }
case MSM_SD_NOTIFY_FREEZE:
break;
case MSM_SD_UNNOTIFY_FREEZE:
@@ -4202,7 +4247,8 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file,
default:
pr_err_ratelimited("%s: unsupported compat type :%x LOAD %lu\n",
__func__, cmd, VIDIOC_MSM_CPP_LOAD_FIRMWARE);
- break;
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
}
mutex_unlock(&cpp_dev->mutex);
@@ -4233,7 +4279,7 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file,
default:
pr_err_ratelimited("%s: unsupported compat type :%d\n",
__func__, cmd);
- break;
+ return -EINVAL;
}
if (is_copytouser_req) {