diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2008-06-03 17:21:23 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2008-06-03 17:21:23 +0000 |
commit | f477a7be1a11212b343d8d9a83976683c4f6f10f (patch) | |
tree | ff1149e184151907bfc8ce826a425d8e72272f93 /sys/dev/pci/drm | |
parent | f85e7f6f471cf857331d4b96043121305d4db1a1 (diff) |
Make *drm(4) use D_CLONE so that the per-open data actually works. Since
i'm modifying this code anyway, prepare for privsep by making it so that
"master" openers must be root, and remove some spurious suser() checks.
For example, every DRM_ROOT_ONLY ioctl is also DRM_MASTER. Without this
change, privsep wouldn't work since the fd is no longer root owned.
With this, X privsep should work as soon as the userland bits are done
(currently unwritten).
Looked over by kettenis@, ok thib@.
Diffstat (limited to 'sys/dev/pci/drm')
-rw-r--r-- | sys/dev/pci/drm/drmP.h | 18 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_bufs.c | 13 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_drv.c | 37 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_fops.c | 32 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_vm.c | 8 |
5 files changed, 73 insertions, 35 deletions
diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h index ae3842c596a..6248fedfaec 100644 --- a/sys/dev/pci/drm/drmP.h +++ b/sys/dev/pci/drm/drmP.h @@ -322,11 +322,18 @@ enum { #elif defined(__NetBSD__) #define drm_get_device_from_kdev(_kdev) device_lookup(&drm_cd, minor(_kdev)) #elif defined(__OpenBSD__) +/* D_CLONE only supports one device, this will be fixed eventually */ +#define drm_get_device_from_kdev(_kdev) \ + drm_units[0] + +#if 0 /* D_CLONE only supports on device for now */ #define drm_get_device_from_kdev(_kdev) \ (minor(kdev) < DRM_MAXUNITS) ? \ drm_units[minor(kdev)] : NULL #endif +#endif /* __FreeBSD__ / __NetBSD__ / __OpenBSD__ */ + #ifdef __FreeBSD__ #define PAGE_ALIGN(addr) round_page(addr) #if __FreeBSD_version >= 700000 @@ -968,10 +975,13 @@ dev_type_mmap(drm_mmap); extern drm_local_map_t *drm_getsarea(drm_device_t *dev); /* File operations helpers (drm_fops.c) */ -int drm_open_helper(DRM_CDEV kdev, int flags, int fmt, - DRM_STRUCTPROC *p, drm_device_t *dev); -extern drm_file_t *drm_find_file_by_proc(drm_device_t *dev, - DRM_STRUCTPROC *p); +int drm_open_helper(DRM_CDEV, int, int, + DRM_STRUCTPROC *, drm_device_t *); +#ifdef __OpenBSD__ +drm_file_t *drm_find_file_by_minor(drm_device_t *, int); +#else +drm_file_t *drm_find_file_by_proc(drm_device_t *, DRM_STRUCTPROC *); +#endif /* Memory management support (drm_memory.c) */ void drm_mem_init(void); diff --git a/sys/dev/pci/drm/drm_bufs.c b/sys/dev/pci/drm/drm_bufs.c index e98da50ceb6..0102327beee 100644 --- a/sys/dev/pci/drm/drm_bufs.c +++ b/sys/dev/pci/drm/drm_bufs.c @@ -348,9 +348,6 @@ drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv) if (!(dev->flags & (FREAD|FWRITE))) return EACCES; /* Require read/write */ - if (!DRM_SUSER(DRM_CURPROC) && request->type != _DRM_AGP) - return EACCES; - DRM_LOCK(); err = drm_addmap(dev, request->offset, request->size, request->type, request->flags, &map); @@ -944,11 +941,6 @@ drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request) DRM_SPINLOCK(&dev->dma_lock); - if (!DRM_SUSER(DRM_CURPROC)) { - DRM_SPINUNLOCK(&dev->dma_lock); - return EACCES; - } - if (request->count < 0 || request->count > 4096) { DRM_SPINUNLOCK(&dev->dma_lock); return EINVAL; @@ -985,11 +977,6 @@ drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request) DRM_SPINLOCK(&dev->dma_lock); - if (!DRM_SUSER(DRM_CURPROC)) { - DRM_SPINUNLOCK(&dev->dma_lock); - return EACCES; - } - if (request->count < 0 || request->count > 4096) { DRM_SPINUNLOCK(&dev->dma_lock); return EINVAL; diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c index bb0dcc82b7c..4ea99a8b63b 100644 --- a/sys/dev/pci/drm/drm_drv.c +++ b/sys/dev/pci/drm/drm_drv.c @@ -580,15 +580,16 @@ error: void drm_unload(drm_device_t *dev) { +#ifdef __FreeBSD__ int i; - DRM_DEBUG( "\n" ); -#ifdef __FreeBSD__ drm_sysctl_cleanup(dev); destroy_dev(dev->devnode); #endif + DRM_DEBUG( "\n" ); + drm_ctxbitmap_cleanup(dev); #if !defined(DRM_NO_MTRR) && !defined(DRM_NO_AGP) @@ -618,21 +619,6 @@ drm_unload(drm_device_t *dev) dev->pcirid[i], dev->pcir[i]); dev->pcir[i] = NULL; } -#elif defined(__NetBSD__) || defined(__OpenBSD__) - for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) { - if (dev->pcir[i] == NULL) - continue; - if (dev->pcir[i]->mapped) - { - bus_space_unmap(dev->pa.pa_memt, - dev->pcir[i]->bsh, - dev->pcir[i]->size); - dev->pcir[i]->mapped = 0; - } - free(dev->pcir[i], M_DRM); - dev->pcir[i] = NULL; - } -#endif if ( dev->agp ) { free(dev->agp, M_DRM); @@ -721,7 +707,11 @@ drm_close(DRM_CDEV kdev, int flags, int fmt, DRM_STRUCTPROC *p) DRM_LOCK(); +#ifdef __OpenBSD__ + file_priv = drm_find_file_by_minor(dev, minor(kdev)); +#else file_priv = drm_find_file_by_proc(dev, p); +#endif if (!file_priv) { DRM_UNLOCK(); DRM_ERROR("can't find authenticator\n"); @@ -843,7 +833,11 @@ drm_ioctl(DRM_CDEV kdev, u_long cmd, caddr_t data, int flags, return ENODEV; DRM_LOCK(); +#ifdef __OpenBSD__ + file_priv = drm_find_file_by_minor(dev, minor(kdev)); +#else file_priv = drm_find_file_by_proc(dev, p); +#endif DRM_UNLOCK(); if (file_priv == NULL) { DRM_ERROR("can't find authenticator\n"); @@ -926,9 +920,18 @@ drm_ioctl(DRM_CDEV kdev, u_long cmd, caddr_t data, int flags, return EINVAL; } +#ifdef __OpenBSD__ + /* + * master must be root, and all ioctls that are ROOT_ONLY are + * also DRM_MASTER. + */ + if (((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || + ((ioctl->flags & DRM_MASTER) && !file_priv->master)) +#else if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) || ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || ((ioctl->flags & DRM_MASTER) && !file_priv->master)) +#endif return EACCES; if (is_driver_ioctl) { diff --git a/sys/dev/pci/drm/drm_fops.c b/sys/dev/pci/drm/drm_fops.c index 0c982f88959..6c7334eb727 100644 --- a/sys/dev/pci/drm/drm_fops.c +++ b/sys/dev/pci/drm/drm_fops.c @@ -36,6 +36,23 @@ #include "drmP.h" +#ifdef __OpenBSD__ + +drm_file_t * +drm_find_file_by_minor(struct drm_device *dev, int minor) +{ + drm_file_t *priv; + + DRM_SPINLOCK_ASSERT(&dev->dev_lock); + + TAILQ_FOREACH(priv, &dev->files, link) + if (priv->minor == minor) + return (priv); + return (NULL); +} + +#else + drm_file_t * drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p) { @@ -51,6 +68,7 @@ drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p) return priv; return NULL; } +#endif /* drm_open_helper is called whenever a process opens /dev/drm. */ int @@ -68,7 +86,11 @@ drm_open_helper(DRM_CDEV kdev, int flags, int fmt, DRM_STRUCTPROC *p, DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m); DRM_LOCK(); +#ifdef __OpenBSD__ + priv = drm_find_file_by_minor(dev, m); +#else priv = drm_find_file_by_proc(dev, p); +#endif if (priv) { priv->refs++; } else { @@ -97,7 +119,15 @@ drm_open_helper(DRM_CDEV kdev, int flags, int fmt, DRM_STRUCTPROC *p, } } - /* first opener automatically becomes master */ + /* first opener automatically becomes master if root */ +#ifdef __OpenBSD__ + if (TAILQ_EMPTY(&dev->files) && !DRM_SUSER(p)) { + free(priv, M_DRM); + DRM_UNLOCK(); + return (EPERM); + } +#endif + priv->master = TAILQ_EMPTY(&dev->files); TAILQ_INSERT_TAIL(&dev->files, priv, link); diff --git a/sys/dev/pci/drm/drm_vm.c b/sys/dev/pci/drm/drm_vm.c index 550f7b9a14f..09a4879a647 100644 --- a/sys/dev/pci/drm/drm_vm.c +++ b/sys/dev/pci/drm/drm_vm.c @@ -51,7 +51,11 @@ drm_mmap(dev_t kdev, off_t offset, int prot) #endif DRM_LOCK(); +#ifdef __OpenBSD__ + priv = drm_find_file_by_minor(dev, minor(kdev)); +#else priv = drm_find_file_by_proc(dev, DRM_CURPROC); +#endif DRM_UNLOCK(); if (priv == NULL) { DRM_ERROR("can't find authenticator\n"); @@ -104,7 +108,11 @@ drm_mmap(dev_t kdev, off_t offset, int prot) DRM_DEBUG("can't find map\n"); return -1; } +#ifdef __OpenBSD__ + if (((map->flags&_DRM_RESTRICTED) && priv->master == 0)) { +#else if (((map->flags&_DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) { +#endif DRM_UNLOCK(); DRM_DEBUG("restricted map\n"); return -1; |