Hi!

Attached is a patch that stops a drm client from registering a fb / agp memory block under an arbitrary context handle, which will lead to heap memory leaks if the client dies.

It also stops malicious clients from freeing other clients fb / agp memory blocks.

Works fine with via, but it will break sis bsd, so I'll hold off with commiting. Could someone test on SiS hardware?

/Thomas



? ccheck_diff
? drmpatch
? linux-core/.ati_pcigart.o.cmd
? linux-core/.drm.ko.cmd
? linux-core/.drm.mod.o.cmd
? linux-core/.drm.o.cmd
? linux-core/.drm_agpsupport.o.cmd
? linux-core/.drm_auth.o.cmd
? linux-core/.drm_bufs.o.cmd
? linux-core/.drm_context.o.cmd
? linux-core/.drm_dma.o.cmd
? linux-core/.drm_drawable.o.cmd
? linux-core/.drm_drv.o.cmd
? linux-core/.drm_fops.o.cmd
? linux-core/.drm_ioc32.o.cmd
? linux-core/.drm_ioctl.o.cmd
? linux-core/.drm_irq.o.cmd
? linux-core/.drm_lock.o.cmd
? linux-core/.drm_memory.o.cmd
? linux-core/.drm_memory_debug.o.cmd
? linux-core/.drm_pci.o.cmd
? linux-core/.drm_proc.o.cmd
? linux-core/.drm_scatter.o.cmd
? linux-core/.drm_stub.o.cmd
? linux-core/.drm_sysfs.o.cmd
? linux-core/.drm_vm.o.cmd
? linux-core/.sis.ko.cmd
? linux-core/.sis.mod.o.cmd
? linux-core/.sis.o.cmd
? linux-core/.sis_drv.o.cmd
? linux-core/.sis_ds.o.cmd
? linux-core/.sis_mm.o.cmd
? linux-core/.tmp_versions
? linux-core/.via.ko.cmd
? linux-core/.via.mod.o.cmd
? linux-core/.via.o.cmd
? linux-core/.via_dma.o.cmd
? linux-core/.via_drv.o.cmd
? linux-core/.via_ds.o.cmd
? linux-core/.via_irq.o.cmd
? linux-core/.via_map.o.cmd
? linux-core/.via_mm.o.cmd
? linux-core/.via_verifier.o.cmd
? linux-core/.via_video.o.cmd
? linux-core/drm.ko
? linux-core/drm.mod.c
? linux-core/drm_pciids.h
? linux-core/sis.ko
? linux-core/sis.mod.c
? linux-core/via.ko
? linux-core/via.mod.c
Index: linux-core/drmP.h
===================================================================
RCS file: /cvs/dri/drm/linux-core/drmP.h,v
retrieving revision 1.156
diff -u -r1.156 drmP.h
--- linux-core/drmP.h   3 Jul 2005 18:07:03 -0000       1.156
+++ linux-core/drmP.h   17 Jul 2005 11:04:32 -0000
@@ -831,6 +831,7 @@
 extern int drm_ctxbitmap_init(drm_device_t * dev);
 extern void drm_ctxbitmap_cleanup(drm_device_t * dev);
 extern void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle);
+extern int drm_check_context(drm_file_t *priv, drm_context_t handle);
 
 extern int drm_setsareactx(struct inode *inode, struct file *filp,
                           unsigned int cmd, unsigned long arg);
Index: linux-core/drm_context.c
===================================================================
RCS file: /cvs/dri/drm/linux-core/drm_context.c,v
retrieving revision 1.31
diff -u -r1.31 drm_context.c
--- linux-core/drm_context.c    4 Jun 2005 06:18:11 -0000       1.31
+++ linux-core/drm_context.c    17 Jul 2005 11:04:32 -0000
@@ -576,4 +576,34 @@
        return 0;
 }
 
+/**
+ * Check that a context is registered for a caller.
+ *
+ * \param priv file pointer private structure.
+ * \param handle context handle.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return one if the context is registered with the file pointer. Zero 
otherwise.
+ */
+
+int drm_check_context(drm_file_t *priv, drm_context_t handle)
+{
+       drm_device_t *dev = priv->head->dev;
+       int ret = 0;
+
+       down(&dev->ctxlist_sem);
+       if (dev->ctxlist && !list_empty(&dev->ctxlist->head)) {
+               drm_ctx_list_t *pos, *n;
+
+               list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+                       if (pos->handle == handle) {
+                               ret = (pos->tag == priv);
+                               break;
+                       }
+               }
+       }
+       up(&dev->ctxlist_sem);
+       return ret;
+}
+       
+
 /[EMAIL PROTECTED]/
Index: shared-core/sis_mm.c
===================================================================
RCS file: /cvs/dri/drm/shared-core/sis_mm.c,v
retrieving revision 1.15
diff -u -r1.15 sis_mm.c
--- shared-core/sis_mm.c        7 Mar 2005 09:40:18 -0000       1.15
+++ shared-core/sis_mm.c        17 Jul 2005 11:04:32 -0000
@@ -88,6 +88,7 @@
 
 static int sis_fb_alloc(DRM_IOCTL_ARGS)
 {
+       drm_file_t *priv = filp->private_data;
        drm_sis_mem_t fb;
        struct sis_memreq req;
        drm_sis_mem_t __user *argp = (void __user *)data;
@@ -95,6 +96,10 @@
 
        DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
 
+       if (!drm_check_context(priv, fb.context)) {
+               return DRM_ERR(EINVAL);
+       }
+       
        req.size = fb.size;
        sis_malloc(&req);
        if (req.offset) {
@@ -121,11 +126,16 @@
 
 static int sis_fb_free(DRM_IOCTL_ARGS)
 {
+       drm_file_t *priv = filp->private_data;
        drm_sis_mem_t fb;
        int retval = 0;
 
        DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
 
+       if (!drm_check_context(priv, fb.context)) {
+               return DRM_ERR(EINVAL);
+       }
+       
        if (!fb.free)
                return DRM_ERR(EINVAL);
 
@@ -190,6 +200,10 @@
 
        DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
 
+       if (!drm_check_context(priv, fb.context)) {
+               return DRM_ERR(EINVAL);
+       }
+
        block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
        if (block) {
                /* TODO */
@@ -224,6 +238,10 @@
 
        DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
 
+       if (!drm_check_context(priv, fb.context)) {
+               return DRM_ERR(EINVAL);
+       }
+       
        if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free))
                return DRM_ERR(EINVAL);
 
Index: shared-core/via_mm.c
===================================================================
RCS file: /cvs/dri/drm/shared-core/via_mm.c,v
retrieving revision 1.18
diff -u -r1.18 via_mm.c
--- shared-core/via_mm.c        15 Jul 2005 21:22:51 -0000      1.18
+++ shared-core/via_mm.c        17 Jul 2005 11:04:32 -0000
@@ -192,11 +192,16 @@
 
 int via_mem_alloc(DRM_IOCTL_ARGS)
 {
+       drm_file_t *priv = filp->private_data;
        drm_via_mem_t mem;
 
        DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
                                 sizeof(mem));
 
+       if (!drm_check_context(priv, mem.context)) {
+               return DRM_ERR(EINVAL);
+       }
+
        switch (mem.type) {
        case VIDEO:
                if (via_fb_alloc(&mem) < 0)
@@ -289,11 +294,16 @@
 
 int via_mem_free(DRM_IOCTL_ARGS)
 {
+       drm_file_t *priv = filp->private_data;
        drm_via_mem_t mem;
 
        DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
                                 sizeof(mem));
 
+       if (!drm_check_context(priv, mem.context)) {
+               return DRM_ERR(EINVAL);
+       }
+
        switch (mem.type) {
 
        case VIDEO:

Reply via email to