video: tegra: host: Add submit checks
Mikko Perttunen [Tue, 25 Oct 2016 09:31:15 +0000 (12:31 +0300)]
Currently nvhost performs minimal checking for submits it passes
to hardware: The kernel does not check if job syncpoints are allocated
and the gather classes are not verified currently.

This patch adds checks for syncpoint ids and gather classes.

Adapted from 0abcbd69c4cbd0093e223b6c248fdd53c2886951.

Bug 1831406

Change-Id: Ifb9d2090009d16d0f56bc11546036167c7f72228
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Reviewed-on: http://git-master/r/1242190
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Tested-by: Winnie Hsu <whsu@nvidia.com>

drivers/video/tegra/host/bus_client.c

index 4a5e2f5..eabb09f 100644 (file)
@@ -398,6 +398,7 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
        u32 __user *waitbases = (u32 *)(uintptr_t)args->waitbases;
        u32 __user *fences = (u32 *)(uintptr_t)args->fences;
        u32 __user *class_ids = (u32 *)(uintptr_t)args->class_ids;
+       struct nvhost_device_data *pdata = platform_get_drvdata(ctx->ch->dev);
 
        struct nvhost_master *host = nvhost_get_host(ctx->ch->dev);
        u32 *local_waitbases = NULL, *local_class_ids = NULL;
@@ -457,6 +458,13 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
                if (err)
                        cmdbuf_ext.pre_fence = -1;
 
+               if (class_id &&
+                   class_id != pdata->class &&
+                   class_id != NV_HOST1X_CLASS_ID) {
+                       err = -EINVAL;
+                       goto fail;
+               }
+
                nvhost_job_add_gather(job, cmdbuf.mem, cmdbuf.words,
                                      cmdbuf.offset, class_id,
                                      cmdbuf_ext.pre_fence);
@@ -512,6 +520,8 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
        for (i = 0; i < num_syncpt_incrs; ++i) {
                u32 waitbase;
                struct nvhost_syncpt_incr sp;
+               bool found = false;
+               int j;
 
                /* Copy */
                err = copy_from_user(&sp, syncpt_incrs + i, sizeof(sp));
@@ -519,7 +529,19 @@ static int nvhost_ioctl_channel_submit(struct nvhost_channel_userctx *ctx,
                        goto fail;
 
                /* Validate */
-               if (sp.syncpt_id >= host->info.nb_pts) {
+               if (sp.syncpt_id == 0) {
+                       err = -EINVAL;
+                       goto fail;
+               }
+
+               for (j = 0; j < NVHOST_MODULE_MAX_SYNCPTS; ++j) {
+                       if (pdata->syncpts[j] == sp.syncpt_id) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               if (!found) {
                        err = -EINVAL;
                        goto fail;
                }