]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/gpu/drm/nouveau/nouveau_gem.c
drm/nouveau: check pushbuffer bounds in ioctl
[linux-2.6.git] / drivers / gpu / drm / nouveau / nouveau_gem.c
index 2009db2426c3a87fa21be873a22001eed25e8c35..504833044080123b0082badc757f082b8f49d037 100644 (file)
@@ -466,13 +466,14 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
 static int
 nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
                                struct drm_nouveau_gem_pushbuf_bo *bo,
-                               int nr_relocs, uint64_t ptr_relocs,
-                               int nr_dwords, int first_dword,
+                               unsigned nr_relocs, uint64_t ptr_relocs,
+                               unsigned nr_dwords, unsigned first_dword,
                                uint32_t *pushbuf, bool is_iomem)
 {
        struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
        struct drm_device *dev = chan->dev;
-       int ret = 0, i;
+       int ret = 0;
+       unsigned i;
 
        reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
        if (IS_ERR(reloc))
@@ -667,6 +668,18 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
        }
        pbbo = nouveau_gem_object(gem);
 
+       if ((req->offset & 3) || req->nr_dwords < 2 ||
+           (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
+           (unsigned long)req->nr_dwords >
+            ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
+               NV_ERROR(dev, "pb call misaligned or out of bounds: "
+                             "%d + %d * 4 > %ld\n",
+                        req->offset, req->nr_dwords, pbbo->bo.mem.size);
+               ret = -EINVAL;
+               drm_gem_object_unreference(gem);
+               goto out;
+       }
+
        ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
                             chan->fence.sequence);
        if (ret) {