summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <unichrome@shipmail.org>2005-08-10 19:46:46 +0000
committerThomas Hellstrom <unichrome@shipmail.org>2005-08-10 19:46:46 +0000
commitd5e8ab13ff5399531eb1927dcd4535aeeed18c94 (patch)
treea6e2aacb12fbaec99c841b84dfdfc67293ed8243
parent0d81954b0e4430428eddc00c6097e614e51ba0b1 (diff)
Security fix on via: Checking that the specified context belongs to the
caller on fb / agp memory alloc and free. Otherwise malicious clients can register allocations on other clients or free memory used by other clients which will lead to severe memory manager inconsistensies.
-rw-r--r--linux-core/drmP.h1
-rw-r--r--linux-core/drm_context.c30
-rw-r--r--shared-core/via_drv.h4
-rw-r--r--shared-core/via_mm.c10
4 files changed, 43 insertions, 2 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 2b4dbcf6..8fed5e72 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -838,6 +838,7 @@ extern int drm_context_switch_complete(drm_device_t * dev, int new);
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);
diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c
index baa8437d..2f947191 100644
--- a/linux-core/drm_context.c
+++ b/linux-core/drm_context.c
@@ -576,4 +576,34 @@ int drm_rmctx(struct inode *inode, struct file *filp,
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;
+}
+
+
/*@}*/
diff --git a/shared-core/via_drv.h b/shared-core/via_drv.h
index c76674ee..95af8b9c 100644
--- a/shared-core/via_drv.h
+++ b/shared-core/via_drv.h
@@ -28,11 +28,11 @@
#define DRIVER_NAME "via"
#define DRIVER_DESC "VIA Unichrome / Pro"
-#define DRIVER_DATE "20050715"
+#define DRIVER_DATE "20050810"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 6
-#define DRIVER_PATCHLEVEL 4
+#define DRIVER_PATCHLEVEL 5
#include "via_verifier.h"
diff --git a/shared-core/via_mm.c b/shared-core/via_mm.c
index 13921f3c..89d762f1 100644
--- a/shared-core/via_mm.c
+++ b/shared-core/via_mm.c
@@ -192,11 +192,16 @@ int via_final_context(struct drm_device *dev, int context)
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 @@ static int via_agp_alloc(drm_via_mem_t * mem)
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: