diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2017-07-04 13:31:18 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-07-04 13:31:18 -0400 |
| commit | f2cffa223afaca0c8297793581bb857dc364542c (patch) | |
| tree | c1658666414d1c89d8aecd65340c33c132c81a45 | |
| parent | 8d1a81a852f58c5708cd607dcbe36eb32da5cbeb (diff) | |
| parent | aeba03903063e9fea885d32318e1546d9b7e83a8 (diff) | |
| download | linux-f2cffa223afaca0c8297793581bb857dc364542c.tar.gz linux-f2cffa223afaca0c8297793581bb857dc364542c.tar.bz2 linux-f2cffa223afaca0c8297793581bb857dc364542c.zip | |
Merge branch 'work.drm' into work.__copy_in_user
| -rw-r--r-- | drivers/gpu/drm/drm_bufs.c | 116 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_internal.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_ioc32.c | 750 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_ioctl.c | 48 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_legacy.h | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/mga/mga_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/mga/mga_ioc32.c | 149 | ||||
| -rw-r--r-- | drivers/gpu/drm/mga/mga_state.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/Makefile | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_ioc32.c | 424 | ||||
| -rw-r--r-- | include/drm/drm_ioctl.h | 1 |
12 files changed, 476 insertions, 1045 deletions
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index adb1dd7fde5f..1ee84dd802d4 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -1258,11 +1258,11 @@ int drm_legacy_addbufs(struct drm_device *dev, void *data, * lock, preventing of allocating more buffers after this call. Information * about each requested buffer is then copied into user space. */ -int drm_legacy_infobufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int __drm_legacy_infobufs(struct drm_device *dev, + void *data, int *p, + int (*f)(void *, int, struct drm_buf_entry *)) { struct drm_device_dma *dma = dev->dma; - struct drm_buf_info *request = data; int i; int count; @@ -1290,26 +1290,12 @@ int drm_legacy_infobufs(struct drm_device *dev, void *data, DRM_DEBUG("count = %d\n", count); - if (request->count >= count) { + if (*p >= count) { for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) { - if (dma->bufs[i].buf_count) { - struct drm_buf_desc __user *to = - &request->list[count]; - struct drm_buf_entry *from = &dma->bufs[i]; - if (copy_to_user(&to->count, - &from->buf_count, - sizeof(from->buf_count)) || - copy_to_user(&to->size, - &from->buf_size, - sizeof(from->buf_size)) || - copy_to_user(&to->low_mark, - &from->low_mark, - sizeof(from->low_mark)) || - copy_to_user(&to->high_mark, - &from->high_mark, - sizeof(from->high_mark))) + struct drm_buf_entry *from = &dma->bufs[i]; + if (from->buf_count) { + if (f(data, count, from) < 0) return -EFAULT; - DRM_DEBUG("%d %d %d %d %d\n", i, dma->bufs[i].buf_count, @@ -1320,11 +1306,29 @@ int drm_legacy_infobufs(struct drm_device *dev, void *data, } } } - request->count = count; + *p = count; return 0; } +static int copy_one_buf(void *data, int count, struct drm_buf_entry *from) +{ + struct drm_buf_info *request = data; + struct drm_buf_desc __user *to = &request->list[count]; + struct drm_buf_desc v = {.count = from->buf_count, + .size = from->buf_size, + .low_mark = from->low_mark, + .high_mark = from->high_mark}; + return copy_to_user(to, &v, offsetof(struct drm_buf_desc, flags)); +} + +int drm_legacy_infobufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_buf_info *request = data; + return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf); +} + /** * Specifies a low and high water mark for buffer allocation * @@ -1439,15 +1443,15 @@ int drm_legacy_freebufs(struct drm_device *dev, void *data, * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls * drm_mmap_dma(). */ -int drm_legacy_mapbufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int __drm_legacy_mapbufs(struct drm_device *dev, void *data, int *p, + void __user **v, + int (*f)(void *, int, unsigned long, + struct drm_buf *), + struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; int retcode = 0; - const int zero = 0; unsigned long virtual; - unsigned long address; - struct drm_buf_map *request = data; int i; if (!drm_core_check_feature(dev, DRIVER_LEGACY)) @@ -1467,7 +1471,7 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data, dev->buf_use++; /* Can't allocate more after this call */ spin_unlock(&dev->buf_lock); - if (request->count >= dma->buf_count) { + if (*p >= dma->buf_count) { if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP)) || (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG))) { @@ -1492,41 +1496,51 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data, retcode = (signed long)virtual; goto done; } - request->virtual = (void __user *)virtual; + *v = (void __user *)virtual; for (i = 0; i < dma->buf_count; i++) { - if (copy_to_user(&request->list[i].idx, - &dma->buflist[i]->idx, - sizeof(request->list[0].idx))) { - retcode = -EFAULT; - goto done; - } - if (copy_to_user(&request->list[i].total, - &dma->buflist[i]->total, - sizeof(request->list[0].total))) { - retcode = -EFAULT; - goto done; - } - if (copy_to_user(&request->list[i].used, - &zero, sizeof(zero))) { - retcode = -EFAULT; - goto done; - } - address = virtual + dma->buflist[i]->offset; /* *** */ - if (copy_to_user(&request->list[i].address, - &address, sizeof(address))) { + if (f(data, i, virtual, dma->buflist[i]) < 0) { retcode = -EFAULT; goto done; } } } done: - request->count = dma->buf_count; - DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode); + *p = dma->buf_count; + DRM_DEBUG("%d buffers, retcode = %d\n", *p, retcode); return retcode; } +static int map_one_buf(void *data, int idx, unsigned long virtual, + struct drm_buf *buf) +{ + struct drm_buf_map *request = data; + unsigned long address = virtual + buf->offset; /* *** */ + + if (copy_to_user(&request->list[idx].idx, &buf->idx, + sizeof(request->list[0].idx))) + return -EFAULT; + if (copy_to_user(&request->list[idx].total, &buf->total, + sizeof(request->list[0].total))) + return -EFAULT; + if (clear_user(&request->list[idx].used, sizeof(int))) + return -EFAULT; + if (copy_to_user(&request->list[idx].address, &address, + sizeof(address))) + return -EFAULT; + return 0; +} + +int drm_legacy_mapbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_buf_map *request = data; + return __drm_legacy_mapbufs(dev, data, &request->count, + &request->virtual, map_one_buf, + file_priv); +} + int drm_legacy_dma_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 3d8e8f878924..14dfa9c83d1d 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -143,3 +143,6 @@ static inline int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) return 0; } #endif +drm_ioctl_t drm_version; +drm_ioctl_t drm_getunique; +drm_ioctl_t drm_getclient; diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index ae386783e3ea..94acf5109235 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -32,6 +32,9 @@ #include <linux/export.h> #include <drm/drmP.h> +#include "drm_legacy.h" +#include "drm_internal.h" +#include "drm_crtc_internal.h" #define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t) #define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t) @@ -87,39 +90,28 @@ static int compat_drm_version(struct file *file, unsigned int cmd, unsigned long arg) { drm_version32_t v32; - struct drm_version __user *version; + struct drm_version v; int err; if (copy_from_user(&v32, (void __user *)arg, sizeof(v32))) return -EFAULT; - version = compat_alloc_user_space(sizeof(*version)); - if (!version) - return -EFAULT; - if (__put_user(v32.name_len, &version->name_len) - || __put_user((void __user *)(unsigned long)v32.name, - &version->name) - || __put_user(v32.date_len, &version->date_len) - || __put_user((void __user *)(unsigned long)v32.date, - &version->date) - || __put_user(v32.desc_len, &version->desc_len) - || __put_user((void __user *)(unsigned long)v32.desc, - &version->desc)) - return -EFAULT; - - err = drm_ioctl(file, - DRM_IOCTL_VERSION, (unsigned long)version); + v = (struct drm_version) { + .name_len = v32.name_len, + .name = compat_ptr(v32.name), + .date_len = v32.date_len, + .date = compat_ptr(v32.date), + .desc_len = v32.desc_len, + .desc = compat_ptr(v32.desc), + }; + err = drm_ioctl_kernel(file, drm_version, &v, + DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW); if (err) return err; - if (__get_user(v32.version_major, &version->version_major) - || __get_user(v32.version_minor, &version->version_minor) - || __get_user(v32.version_patchlevel, &version->version_patchlevel) - || __get_user(v32.name_len, &version->name_len) - || __get_user(v32.date_len, &version->date_len) - || __get_user(v32.desc_len, &version->desc_len)) - return -EFAULT; - + v32.version_major = v.version_major; + v32.version_minor = v.version_minor; + v32.version_patchlevel = v.version_patchlevel; if (copy_to_user((void __user *)arg, &v32, sizeof(v32))) return -EFAULT; return 0; @@ -134,26 +126,21 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, unsigned long arg) { drm_unique32_t uq32; - struct drm_unique __user *u; + struct drm_unique uq; int err; if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32))) return -EFAULT; + uq = (struct drm_unique){ + .unique_len = uq32.unique_len, + .unique = compat_ptr(uq32.unique), + }; - u = compat_alloc_user_space(sizeof(*u)); - if (!u) - return -EFAULT; - if (__put_user(uq32.unique_len, &u->unique_len) - || __put_user((void __user *)(unsigned long)uq32.unique, - &u->unique)) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u); + err = drm_ioctl_kernel(file, drm_getunique, &uq, DRM_UNLOCKED); if (err) return err; - if (__get_user(uq32.unique_len, &u->unique_len)) - return -EFAULT; + uq32.unique_len = uq.unique_len; if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32))) return -EFAULT; return 0; @@ -162,21 +149,8 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, static int compat_drm_setunique(struct file *file, unsigned int cmd, unsigned long arg) { - drm_unique32_t uq32; - struct drm_unique __user *u; - - if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32))) - return -EFAULT; - - u = compat_alloc_user_space(sizeof(*u)); - if (!u) - return -EFAULT; - if (__put_user(uq32.unique_len, &u->unique_len) - || __put_user((void __user *)(unsigned long)uq32.unique, - &u->unique)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u); + /* it's dead */ + return -EINVAL; } typedef struct drm_map32 { @@ -193,32 +167,23 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd, { drm_map32_t __user *argp = (void __user *)arg; drm_map32_t m32; - struct drm_map __user *map; - int idx, err; - void *handle; - - if (get_user(idx, &argp->offset)) - return -EFAULT; + struct drm_map map; + int err; - map = compat_alloc_user_space(sizeof(*map)); - if (!map) - return -EFAULT; - if (__put_user(idx, &map->offset)) + if (copy_from_user(&m32, argp, sizeof(m32))) return -EFAULT; - err = drm_ioctl(file, DRM_IOCTL_GET_MAP, (unsigned long)map); + map.offset = m32.offset; + err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, DRM_UNLOCKED); if (err) return err; - if (__get_user(m32.offset, &map->offset) - || __get_user(m32.size, &map->size) - || __get_user(m32.type, &map->type) - || __get_user(m32.flags, &map->flags) - || __get_user(handle, &map->handle) - || __get_user(m32.mtrr, &map->mtrr)) - return -EFAULT; - - m32.handle = (unsigned long)handle; + m32.offset = map.offset; + m32.size = map.size; + m32.type = map.type; + m32.flags = map.flags; + m32.handle = ptr_to_compat(map.handle); + m32.mtrr = map.mtrr; if (copy_to_user(argp, &m32, sizeof(m32))) return -EFAULT; return 0; @@ -230,35 +195,28 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd, { drm_map32_t __user *argp = (void __user *)arg; drm_map32_t m32; - struct drm_map __user *map; + struct drm_map map; int err; - void *handle; if (copy_from_user(&m32, argp, sizeof(m32))) return -EFAULT; - map = compat_alloc_user_space(sizeof(*map)); - if (!map) - return -EFAULT; - if (__put_user(m32.offset, &map->offset) - || __put_user(m32.size, &map->size) - || __put_user(m32.type, &map->type) - || __put_user(m32.flags, &map->flags)) - return -EFAULT; + map.offset = m32.offset; + map.size = m32.size; + map.type = m32.type; + map.flags = m32.flags; - err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map); + err = drm_ioctl_kernel(file, drm_legacy_addmap_ioctl, &map, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); if (err) return err; - if (__get_user(m32.offset, &map->offset) - || __get_user(m32.mtrr, &map->mtrr) - || __get_user(handle, &map->handle)) - return -EFAULT; - - m32.handle = (unsigned long)handle; - if (m32.handle != (unsigned long)handle) + m32.offset = map.offset; + m32.mtrr = map.mtrr; + m32.handle = ptr_to_compat(map.handle); + if (map.handle != compat_ptr(m32.handle)) pr_err_ratelimited("compat_drm_addmap truncated handle %p for type %d offset %x\n", - handle, m32.type, m32.offset); + map.handle, m32.type, m32.offset); if (copy_to_user(argp, &m32, sizeof(m32))) return -EFAULT; @@ -270,19 +228,13 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd, unsigned long arg) { drm_map32_t __user *argp = (void __user *)arg; - struct drm_map __user *map; + struct drm_map map; u32 handle; if (get_user(handle, &argp->handle)) return -EFAULT; - - map = compat_alloc_user_space(sizeof(*map)); - if (!map) - return -EFAULT; - if (__put_user((void *)(unsigned long)handle, &map->handle)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map); + map.handle = compat_ptr(handle); + return drm_ioctl_kernel(file, drm_legacy_rmmap_ioctl, &map, DRM_AUTH); } typedef struct drm_client32 { @@ -299,29 +251,24 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, { drm_client32_t c32; drm_client32_t __user *argp = (void __user *)arg; - struct drm_client __user *client; - int idx, err; + struct drm_client client; + int err; - if (get_user(idx, &argp->idx)) + if (copy_from_user(&c32, argp, sizeof(c32))) return -EFAULT; - client = compat_alloc_user_space(sizeof(*client)); - if (!client) - return -EFAULT; - if (__put_user(idx, &client->idx)) - return -EFAULT; + client.idx = c32.idx; - err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client); + err = drm_ioctl_kernel(file, drm_getclient, &client, DRM_UNLOCKED); if (err) return err; - if (__get_user(c32.idx, &client->idx) - || __get_user(c32.auth, &client->auth) - || __get_user(c32.pid, &client->pid) - || __get_user(c32.uid, &client->uid) - || __get_user(c32.magic, &client->magic) - || __get_user(c32.iocs, &client->iocs)) - return -EFAULT; + c32.idx = client.idx; + c32.auth = client.auth; + c32.pid = client.pid; + c32.uid = client.uid; + c32.magic = client.magic; + c32.iocs = client.iocs; if (copy_to_user(argp, &c32, sizeof(c32))) return -EFAULT; @@ -339,28 +286,14 @@ typedef struct drm_stats32 { static int compat_drm_getstats(struct file *file, unsigned int cmd, unsigned long arg) { - drm_stats32_t s32; drm_stats32_t __user *argp = (void __user *)arg; - struct drm_stats __user *stats; - int i, err; - - memset(&s32, 0, sizeof(drm_stats32_t)); - stats = compat_alloc_user_space(sizeof(*stats)); - if (!stats) - return -EFAULT; + int err; - err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats); + err = drm_ioctl_kernel(file, drm_noop, NULL, DRM_UNLOCKED); if (err) return err; - if (__get_user(s32.count, &stats->count)) - return -EFAULT; - for (i = 0; i < 15; ++i) - if (__get_user(s32.data[i].value, &stats->data[i].value) - || __get_user(s32.data[i].type, &stats->data[i].type)) - return -EFAULT; - - if (copy_to_user(argp, &s32, sizeof(s32))) + if (clear_user(argp, sizeof(drm_stats32_t))) return -EFAULT; return 0; } @@ -378,26 +311,28 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_desc32_t __user *argp = (void __user *)arg; - struct drm_buf_desc __user *buf; + drm_buf_desc32_t desc32; + struct drm_buf_desc desc; int err; - unsigned long agp_start; - buf = compat_alloc_user_space(sizeof(*buf)); - if (!buf || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))) + if (copy_from_user(&desc32, argp, sizeof(drm_buf_desc32_t))) return -EFAULT; - if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start)) - || __get_user(agp_start, &argp->agp_start) - || __put_user(agp_start, &buf->agp_start)) - return -EFAULT; + desc = (struct drm_buf_desc){ + desc32.count, desc32.size, desc32.low_mark, desc32.high_mark, + desc32.flags, desc32.agp_start + }; - err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf); + err = drm_ioctl_kernel(file, drm_legacy_addbufs, &desc, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); if (err) return err; - if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start)) - || __get_user(agp_start, &buf->agp_start) - || __put_user(agp_start, &argp->agp_start)) + desc32 = (drm_buf_desc32_t){ + desc.count, desc.size, desc.low_mark, desc.high_mark, + desc.flags, desc.agp_start + }; + if (copy_to_user(argp, &desc32, sizeof(drm_buf_desc32_t))) return -EFAULT; return 0; @@ -408,21 +343,17 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd, { drm_buf_desc32_t b32; drm_buf_desc32_t __user *argp = (void __user *)arg; - struct drm_buf_desc __user *buf; + struct drm_buf_desc __user buf; if (copy_from_user(&b32, argp, sizeof(b32))) return -EFAULT; - buf = compat_alloc_user_space(sizeof(*buf)); - if (!buf) - return -EFAULT; - - if (__put_user(b32.size, &buf->size) - || __put_user(b32.low_mark, &buf->low_mark) - || __put_user(b32.high_mark, &buf->high_mark)) - return -EFAULT; + buf.size = b32.size; + buf.low_mark = b32.low_mark; + buf.high_mark = b32.high_mark; - return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf); + return drm_ioctl_kernel(file, drm_legacy_markbufs, &buf, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } typedef struct drm_buf_info32 { @@ -430,52 +361,42 @@ typedef struct drm_buf_info32 { u32 list; } drm_buf_info32_t; +static int copy_one_buf32(void *data, int count, struct drm_buf_entry *from) +{ + drm_buf_info32_t *request = data; + drm_buf_desc32_t __user *to = compat_ptr(request->list); + drm_buf_desc32_t v = {.count = from->buf_count, + .size = from->buf_size, + .low_mark = from->low_mark, + .high_mark = from->high_mark}; + return copy_to_user(to + count, &v, offsetof(drm_buf_desc32_t, flags)); +} + +static int drm_legacy_infobufs32(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + drm_buf_info32_t *request = data; + return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf32); +} + static int compat_drm_infobufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_info32_t req32; drm_buf_info32_t __user *argp = (void __user *)arg; - drm_buf_desc32_t __user *to; - struct drm_buf_info __user *request; - struct drm_buf_desc __user *list; - size_t nbytes; - int i, err; - int count, actual; + int err; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - count = req32.count; - to = (drm_buf_desc32_t __user *) (unsigned long)req32.list; - if (count < 0) - count = 0; - if (count > 0 - && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t))) - return -EFAULT; - - nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc); - request = compat_alloc_user_space(nbytes); - if (!request) - return -EFAULT; - list = (struct drm_buf_desc *) (request + 1); - - if (__put_user(count, &request->count) - || __put_user(list, &request->list)) - return -EFAULT; + if (req32.count < 0) + req32.count = 0; - err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request); + err = drm_ioctl_kernel(file, drm_legacy_infobufs32, &req32, DRM_AUTH); if (err) return err; - if (__get_user(actual, &request->count)) - return -EFAULT; - if (count >= actual) - for (i = 0; i < actual; ++i) - if (__copy_in_user(&to[i], &list[i], - offsetof(struct drm_buf_desc, flags))) - return -EFAULT; - - if (__put_user(actual, &argp->count)) + if (put_user(req32.count, &argp->count)) return -EFAULT; return 0; @@ -494,54 +415,52 @@ typedef struct drm_buf_map32 { u32 list; /**< Buffer information */ } drm_buf_map32_t; +static int map_one_buf32(void *data, int idx, unsigned long virtual, + struct drm_buf *buf) +{ + drm_buf_map32_t *request = data; + drm_buf_pub32_t __user *to = compat_ptr(request->list) + idx; + drm_buf_pub32_t v; + + v.idx = buf->idx; + v.total = buf->total; + v.used = 0; + v.address = virtual + buf->offset; + if (copy_to_user(to, &v, sizeof(v))) + return -EFAULT; + return 0; +} + +static int drm_legacy_mapbufs32(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + drm_buf_map32_t *request = data; + void __user *v; + int err = __drm_legacy_mapbufs(dev, data, &request->count, + &v, map_one_buf32, + file_priv); + request->virtual = ptr_to_compat(v); + return err; +} + static int compat_drm_mapbufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_map32_t __user *argp = (void __user *)arg; drm_buf_map32_t req32; - drm_buf_pub32_t __user *list32; - struct drm_buf_map __user *request; - struct drm_buf_pub __user *list; - int i, err; - int count, actual; - size_t nbytes; - void __user *addr; + int err; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - count = req32.count; - list32 = (void __user *)(unsigned long)req32.list; - - if (count < 0) + if (req32.count < 0) return -EINVAL; - nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub); - request = compat_alloc_user_space(nbytes); - if (!request) - return -EFAULT; - list = (struct drm_buf_pub *) (request + 1); - - if (__put_user(count, &request->count) - || __put_user(list, &request->list)) - return -EFAULT; - err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request); + err = drm_ioctl_kernel(file, drm_legacy_mapbufs32, &req32, DRM_AUTH); if (err) return err; - if (__get_user(actual, &request->count)) - return -EFAULT; - if (count >= actual) - for (i = 0; i < actual; ++i) - if (__copy_in_user(&list32[i], &list[i], - offsetof(struct drm_buf_pub, address)) - || __get_user(addr, &list[i].address) - || __put_user((unsigned long)addr, - &list32[i].address)) - return -EFAULT; - - if (__put_user(actual, &argp->count) - || __get_user(addr, &request->virtual) - || __put_user((unsigned long)addr, &argp->virtual)) + if (put_user(req32.count, &argp->count) + || put_user(req32.virtual, &argp->virtual)) return -EFAULT; return 0; @@ -556,21 +475,15 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd, unsigned long arg) { drm_buf_free32_t req32; - struct drm_buf_free __user *request; + struct drm_buf_free request; drm_buf_free32_t __user *argp = (void __user *)arg; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request) - return -EFAULT; - if (__put_user(req32.count, &request->count) - || __put_user((int __user *)(unsigned long)req32.list, - &request->list)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request); + request.count = req32.count; + request.list = compat_ptr(req32.list); + return drm_ioctl_kernel(file, drm_legacy_freebufs, &request, DRM_AUTH); } typedef struct drm_ctx_priv_map32 { @@ -582,48 +495,36 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd, unsigned long arg) { drm_ctx_priv_map32_t req32; - struct drm_ctx_priv_map __user *request; + struct drm_ctx_priv_map request; drm_ctx_priv_map32_t __user *argp = (void __user *)arg; if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request) - return -EFAULT; - if (__put_user(req32.ctx_id, &request->ctx_id) - || __put_user((void *)(unsigned long)req32.handle, - &request->handle)) - return -EFAULT; - - return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request); + request.ctx_id = req32.ctx_id; + request.handle = compat_ptr(req32.handle); + return drm_ioctl_kernel(file, drm_legacy_setsareactx, &request, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } static int compat_drm_getsareactx(struct file *file, unsigned int cmd, unsigned long arg) { - struct drm_ctx_priv_map __user *request; + struct drm_ctx_priv_map req; + drm_ctx_priv_map32_t req32; drm_ctx_priv_map32_t __user *argp = (void __user *)arg; int err; - unsigned int ctx_id; - void *handle; - - if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp)) - || __get_user(ctx_id, &argp->ctx_id)) - return -EFAULT; - request = compat_alloc_user_space(sizeof(*request)); - if (!request) - return -EFAULT; - if (__put_user(ctx_id, &request->ctx_id)) + if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; - err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request); + req.ctx_id = req32.ctx_id; + err = drm_ioctl_kernel(file, drm_legacy_getsareactx, &req, DRM_AUTH); if (err) return err; - if (__get_user(handle, &request->handle) - || __put_user((unsigned long)handle, &argp->handle)) + req32.handle = ptr_to_compat(req.handle); + if (copy_to_user(argp, &req32, sizeof(req32))) return -EFAULT; return 0; @@ -639,26 +540,20 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd, { drm_ctx_res32_t __user *argp = (void __user *)arg; drm_ctx_res32_t res32; - struct drm_ctx_res __user *res; + struct drm_ctx_res res; int err; if (copy_from_user(&res32, argp, sizeof(res32))) return -EFAULT; - res = compat_alloc_user_space(sizeof(*res)); - if (!res) - return -EFAULT; - if (__put_user(res32.count, &res->count) - || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts, - &res->contexts)) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res); + res.count = res32.count; + res.contexts = compat_ptr(res32.contexts); + err = drm_ioctl_kernel(file, drm_legacy_resctx, &res, DRM_AUTH); if (err) return err; - if (__get_user(res32.count, &res->count) - || __put_user(res32.count, &argp->count)) + res32.count = res.count; + if (copy_to_user(argp, &res32, sizeof(res32))) return -EFAULT; return 0; @@ -682,38 +577,26 @@ static int compat_drm_dma(struct file *file, unsigned int cmd, { drm_dma32_t d32; drm_dma32_t __user *argp = (void __user *)arg; - struct drm_dma __user *d; + struct drm_dma d; int err; if (copy_from_user(&d32, argp, sizeof(d32))) return -EFAULT; - d = compat_alloc_user_space(sizeof(*d)); - if (!d) - return -EFAULT; - - if (__put_user(d32.context, &d->context) - || __put_user(d32.send_count, &d->send_count) - || __put_user((int __user *)(unsigned long)d32.send_indices, - &d->send_indices) - || __put_user((int __user *)(unsigned long)d32.send_sizes, - &d->send_sizes) - || __put_user(d32.flags, &d->flags) - || __put_user(d32.request_count, &d->request_count) - || __put_user((int __user *)(unsigned long)d32.request_indices, - &d->request_indices) - || __put_user((int __user *)(unsigned long)d32.request_sizes, - &d->request_sizes)) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d); + d.context = d32.context; + d.send_count = d32.send_count; + d.send_indices = compat_ptr(d32.send_indices); + d.send_sizes = compat_ptr(d32.send_sizes); + d.flags = d32.flags; + d.request_count = d32.request_count; + d.request_indices = compat_ptr(d32.request_indices); + d.request_sizes = compat_ptr(d32.request_sizes); + err = drm_ioctl_kernel(file, drm_legacy_dma_ioctl, &d, DRM_AUTH); if (err) return err; - if (__get_user(d32.request_size, &d->request_size) - || __get_user(d32.granted_count, &d->granted_count) - || __put_user(d32.request_size, &argp->request_size) - || __put_user(d32.granted_count, &argp->granted_count)) + if (put_user(d.request_size, &argp->request_size) + || put_user(d.granted_count, &argp->granted_count)) return -EFAULT; return 0; @@ -728,17 +611,13 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd, unsigned long arg) { drm_agp_mode32_t __user *argp = (void __user *)arg; - drm_agp_mode32_t m32; - struct drm_agp_mode __user *mode; - - if (get_user(m32.mode, &argp->mode)) - return -EFAULT; + struct drm_agp_mode mode; - mode = compat_alloc_user_space(sizeof(*mode)); - if (put_user(m32.mode, &mode->mode)) + if (get_user(mode.mode, &argp->mode)) return -EFAULT; - return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode); + return drm_ioctl_kernel(file, drm_agp_enable_ioctl, &mode, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); } typedef struct drm_agp_info32 { @@ -760,28 +639,22 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd, { drm_agp_info32_t __user *argp = (void __user *)arg; drm_agp_info32_t i32; - struct drm_agp_info __user *info; + struct drm_agp_info info; int err; - info = compat_alloc_user_space(sizeof(*info)); - if (!info) - return -EFAULT; - - err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info); + err = drm_ioctl_kernel(file, drm_agp_info_ioctl, &info, DRM_AUTH); if (err) return err; - if (__get_user(i32.agp_version_major, &info->agp_version_major) - || __get_user(i32.agp_version_minor, &info->agp_version_minor) - || __get_user(i32.mode, &info->mode) - || __get_user(i32.aperture_base, &info->aperture_base) - || __get_user(i32.aperture_size, &info->aperture_size) - || __get_user(i32.memory_allowed, &info->memory_allowed) - || __get_user(i32.memory_used, &info->memory_used) - || __get_user(i32.id_vendor, &info-> |
