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.
main
Thomas Hellstrom 2005-08-10 19:46:46 +00:00
parent 0d81954b0e
commit d5e8ab13ff
4 changed files with 43 additions and 2 deletions

View File

@ -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);

View File

@ -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;
}
/*@}*/

View File

@ -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"

View File

@ -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: