diff options
author | Thomas Hellstrom <unichrome@shipmail.org> | 2005-08-10 19:46:46 +0000 |
---|---|---|
committer | Thomas Hellstrom <unichrome@shipmail.org> | 2005-08-10 19:46:46 +0000 |
commit | d5e8ab13ff5399531eb1927dcd4535aeeed18c94 (patch) | |
tree | a6e2aacb12fbaec99c841b84dfdfc67293ed8243 | |
parent | 0d81954b0e4430428eddc00c6097e614e51ba0b1 (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.h | 1 | ||||
-rw-r--r-- | linux-core/drm_context.c | 30 | ||||
-rw-r--r-- | shared-core/via_drv.h | 4 | ||||
-rw-r--r-- | shared-core/via_mm.c | 10 |
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: |