diff options
-rw-r--r-- | bsd-core/drmP.h | 8 | ||||
-rw-r--r-- | bsd-core/drm_bufs.c | 58 | ||||
-rw-r--r-- | bsd-core/drm_context.c | 5 | ||||
-rw-r--r-- | bsd-core/drm_drv.c | 13 | ||||
-rw-r--r-- | bsd-core/drm_fops.c | 7 | ||||
-rw-r--r-- | bsd-core/drm_vm.c | 7 |
6 files changed, 81 insertions, 17 deletions
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index 7e16fe66..d5907355 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -229,7 +229,8 @@ enum { int flags, DRM_STRUCTPROC *p, DRMFILE filp #define PAGE_ALIGN(addr) round_page(addr) -#define DRM_SUSER(p) suser(p) +/* DRM_SUSER returns true if the user is superuser */ +#define DRM_SUSER(p) (suser(p) == 0) #define DRM_AGP_FIND_DEVICE() agp_find_device() #define DRM_MTRR_WC MDF_WRITECOMBINE #define jiffies ticks @@ -249,7 +250,8 @@ enum { #define CDEV_MAJOR 34 #define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) -#define DRM_SUSER(p) suser(p->p_ucred, &p->p_acflag) +/* DRM_SUSER returns true if the user is superuser */ +#define DRM_SUSER(p) (suser(p->p_ucred, &p->p_acflag) == 0) #define DRM_AGP_FIND_DEVICE() agp_find_device(0) #define DRM_MTRR_WC MTRR_TYPE_WC #define jiffies hardclock_ticks @@ -524,6 +526,7 @@ typedef TAILQ_HEAD(drm_file_list, drm_file) drm_file_list_t; struct drm_file { TAILQ_ENTRY(drm_file) link; int authenticated; + int master; int minor; pid_t pid; uid_t uid; @@ -585,6 +588,7 @@ typedef struct drm_agp_head { typedef struct drm_sg_mem { unsigned long handle; + void *virtual; int pages; dma_addr_t *busaddr; drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */ diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c index b00ecda2..5ce2d4de 100644 --- a/bsd-core/drm_bufs.c +++ b/bsd-core/drm_bufs.c @@ -113,11 +113,12 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, /* Check if this is just another version of a kernel-allocated map, and * just hand that back if so. */ - if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER) - { + if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER || + type == _DRM_SHM) { DRM_LOCK(); TAILQ_FOREACH(map, &dev->maplist, link) { - if (map->type == type && map->offset == offset) { + if (map->type == type && + (map->offset == offset || map->type == _DRM_SHM)) { map->size = size; DRM_DEBUG("Found kernel map %d\n", type); goto done; @@ -171,8 +172,25 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, } break; case _DRM_AGP: - map->offset += dev->agp->base; - map->mtrr = dev->agp->mtrr; /* for getmap */ + { + drm_agp_mem_t *entry; + int valid = 0; + + map->offset += dev->agp->base; + map->mtrr = dev->agp->mtrr; /* for getmap */ + for (entry = dev->agp->memory; entry; + entry = entry->next) + if ((map->offset >= entry->bound) && + (map->offset + map->size <= + entry->bound + entry->pages * PAGE_SIZE)) { + valid = 1; + break; + } + if (!valid) { + free(map, M_DRM); + return DRM_ERR(EACCES); + } + } break; case _DRM_SCATTER_GATHER: if (!dev->sg) { @@ -186,7 +204,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, 0xfffffffful); if (map->dmah == NULL) { free(map, M_DRM); - return ENOMEM; + return DRM_ERR(ENOMEM); } map->handle = map->dmah->vaddr; map->offset = map->dmah->busaddr; @@ -223,6 +241,9 @@ int drm_addmap_ioctl(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(request, (drm_map_t *)data, sizeof(drm_map_t)); + if (!DRM_SUSER(p) && request.type != _DRM_AGP) + return DRM_ERR(EACCES); + err = drm_addmap(dev, request.offset, request.size, request.type, request.flags, &map); if (err != 0) @@ -342,6 +363,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) { drm_device_dma_t *dma = dev->dma; drm_buf_entry_t *entry; + drm_agp_mem_t *agp_entry; drm_buf_t *buf; unsigned long offset; unsigned long agp_offset; @@ -352,7 +374,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) int page_order; int total; int byte_count; - int i; + int i, valid; drm_buf_t **temp_buflist; count = request->count; @@ -375,6 +397,22 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request) DRM_DEBUG( "page_order: %d\n", page_order ); DRM_DEBUG( "total: %d\n", total ); + /* Make sure buffers are located in AGP memory that we own */ + valid = 0; + for (agp_entry = dev->agp->memory; agp_entry; + agp_entry = agp_entry->next) { + if ((agp_offset >= agp_entry->bound) && + (agp_offset + total * count <= + agp_entry->bound + agp_entry->pages * PAGE_SIZE)) { + valid = 1; + break; + } + } + if (!valid) { + DRM_DEBUG("zone invalid\n"); + return DRM_ERR(EINVAL); + } + entry = &dma->bufs[order]; entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM, @@ -742,6 +780,9 @@ int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) DRM_SPINLOCK(&dev->dma_lock); + if (!DRM_SUSER(DRM_CURPROC)) + return DRM_ERR(EACCES); + if (request->count < 0 || request->count > 4096) return DRM_ERR(EINVAL); @@ -773,6 +814,9 @@ int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request) DRM_SPINLOCK(&dev->dma_lock); + if (!DRM_SUSER(DRM_CURPROC)) + return DRM_ERR(EACCES); + if (request->count < 0 || request->count > 4096) return DRM_ERR(EINVAL); diff --git a/bsd-core/drm_context.c b/bsd-core/drm_context.c index 11d23c6f..8e009540 100644 --- a/bsd-core/drm_context.c +++ b/bsd-core/drm_context.c @@ -228,14 +228,17 @@ int drm_context_switch_complete(drm_device_t *dev, int new) int drm_resctx(DRM_IOCTL_ARGS) { drm_ctx_res_t res; + drm_ctx_t ctx; int i; DRM_COPY_FROM_USER_IOCTL( res, (drm_ctx_res_t *)data, sizeof(res) ); if ( res.count >= DRM_RESERVED_CONTEXTS ) { + bzero(&ctx, sizeof(ctx)); for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) { + ctx.handle = i; if ( DRM_COPY_TO_USER( &res.contexts[i], - &i, sizeof(i) ) ) + &ctx, sizeof(ctx) ) ) return DRM_ERR(EFAULT); } } diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index d9784073..c4ee39cb 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -33,6 +33,7 @@ #include "drmP.h" #include "drm.h" +#include "drm_sarea.h" int drm_debug_flag = 0; @@ -357,10 +358,17 @@ drm_pci_id_list_t *drm_find_description(int vendor, int device, static int drm_firstopen(drm_device_t *dev) { + drm_local_map_t *map; int i; DRM_SPINLOCK_ASSERT(&dev->dev_lock); + /* prebuild the SAREA */ + i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, + _DRM_CONTAINS_LOCK, &map); + if (i != 0) + return i; + if (dev->driver.firstopen) dev->driver.firstopen(dev); @@ -388,7 +396,6 @@ static int drm_firstopen(drm_device_t *dev) dev->magiclist[i].tail = NULL; } - dev->lock.hw_lock = NULL; dev->lock.lock_queue = 0; dev->irq_enabled = 0; dev->context_flag = 0; @@ -851,9 +858,9 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, /* ioctl->master check should be against something in the filp set up * for the first opener, but it doesn't matter yet. */ - if ((ioctl->root_only && DRM_SUSER(p)) || + if ((ioctl->root_only && !DRM_SUSER(p)) || (ioctl->auth_needed && !priv->authenticated) || - (ioctl->master && !DRM_SUSER(p))) + (ioctl->master && !priv->master)) return EACCES; if (is_driver_ioctl) diff --git a/bsd-core/drm_fops.c b/bsd-core/drm_fops.c index b15fd056..f5c9349b 100644 --- a/bsd-core/drm_fops.c +++ b/bsd-core/drm_fops.c @@ -88,7 +88,9 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p, priv->refs = 1; priv->minor = m; priv->ioctl_count = 0; - priv->authenticated = !DRM_SUSER(p); + + /* for compatibility root is always authenticated */ + priv->authenticated = DRM_SUSER(p); if (dev->driver.open) { retcode = dev->driver.open(dev, priv); @@ -99,6 +101,9 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p, } } + /* first opener automatically becomes master */ + priv->master = TAILQ_EMPTY(&dev->files); + TAILQ_INSERT_TAIL(&dev->files, priv, link); } DRM_UNLOCK(); diff --git a/bsd-core/drm_vm.c b/bsd-core/drm_vm.c index 419b3cb1..05ac7b15 100644 --- a/bsd-core/drm_vm.c +++ b/bsd-core/drm_vm.c @@ -49,10 +49,11 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) if (!priv->authenticated) return DRM_ERR(EACCES); - DRM_SPINLOCK(&dev->dma_lock); if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) { drm_device_dma_t *dma = dev->dma; + DRM_SPINLOCK(&dev->dma_lock); + if (dma->pagelist != NULL) { unsigned long page = offset >> PAGE_SHIFT; unsigned long phys = dma->pagelist[page]; @@ -68,8 +69,8 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) DRM_SPINUNLOCK(&dev->dma_lock); return -1; } + DRM_SPINUNLOCK(&dev->dma_lock); } - DRM_SPINUNLOCK(&dev->dma_lock); /* A sequential search of a linked list is fine here because: 1) there will only be @@ -89,7 +90,7 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot) DRM_DEBUG("can't find map\n"); return -1; } - if (((map->flags&_DRM_RESTRICTED) && DRM_SUSER(DRM_CURPROC))) { + if (((map->flags&_DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) { DRM_UNLOCK(); DRM_DEBUG("restricted map\n"); return -1; |