video: tegra: host: fix possible overflow with num_syncpt_incrs
Deepak Nibade [Mon, 27 Jun 2016 08:33:15 +0000 (13:33 +0530)]
We allocate below without checking if num_syncpt_incrs
is valid or not
struct nvhost_ctrl_sync_fence_info pts[num_syncpt_incrs];

If UMD passes a negative value in num_syncpt_incrs, then
it is possible to corrupt the stack

Hence, first check if num_syncpt_incrs is valid (i.e.
not negative)
And then allocate the array dynamically using kzalloc
instead of allocating it on stack

Bug 1781393

Change-Id: I5389fd271149b457f63831a41c104c9814299ddf
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/1171747
(cherry picked from commit 07fb347b4060a888b19df3524f36fcf7974a79d1)
Reviewed-on: http://git-master/r/1190751
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>

drivers/video/tegra/host/bus_client.c

index add6ac6..6ff53b6 100644 (file)
@@ -535,6 +535,9 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
        u32 *local_class_ids = NULL;
        int err, i;
 
+       if (num_cmdbufs < 0 || num_syncpt_incrs < 0)
+               return -EINVAL;
+
        job = nvhost_job_alloc(ctx->ch,
                        num_cmdbufs,
                        num_relocs,
@@ -702,7 +705,15 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
         * syncpoint is used. */
 
        if (args->flags & BIT(NVHOST_SUBMIT_FLAG_SYNC_FENCE_FD)) {
-               struct nvhost_ctrl_sync_fence_info pts[num_syncpt_incrs];
+               struct nvhost_ctrl_sync_fence_info *pts;
+
+               pts = kzalloc(num_syncpt_incrs *
+                             sizeof(struct nvhost_ctrl_sync_fence_info),
+                             GFP_KERNEL);
+               if (!pts) {
+                       err = -ENOMEM;
+                       goto fail;
+               }
 
                for (i = 0; i < num_syncpt_incrs; i++) {
                        pts[i].id = job->sp[i].id;
@@ -711,6 +722,7 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
 
                err = nvhost_sync_create_fence_fd(ctx->pdev,
                                pts, num_syncpt_incrs, "fence", &args->fence);
+               kfree(pts);
                if (err)
                        goto fail;
        } else if (num_syncpt_incrs == 1)