Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

switch compat_drm_mapbufs() to drm_ioctl_kernel()

Another horror like addbufs; this one is even uglier. With that
done, drm_ioc32.c should be sane.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 87d3ce11 6113252d

+77 -65
+39 -29
drivers/gpu/drm/drm_bufs.c
··· 1443 1443 * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls 1444 1444 * drm_mmap_dma(). 1445 1445 */ 1446 - int drm_legacy_mapbufs(struct drm_device *dev, void *data, 1447 - struct drm_file *file_priv) 1446 + int __drm_legacy_mapbufs(struct drm_device *dev, void *data, int *p, 1447 + void __user **v, 1448 + int (*f)(void *, int, unsigned long, 1449 + struct drm_buf *), 1450 + struct drm_file *file_priv) 1448 1451 { 1449 1452 struct drm_device_dma *dma = dev->dma; 1450 1453 int retcode = 0; 1451 - const int zero = 0; 1452 1454 unsigned long virtual; 1453 - unsigned long address; 1454 - struct drm_buf_map *request = data; 1455 1455 int i; 1456 1456 1457 1457 if (!drm_core_check_feature(dev, DRIVER_LEGACY)) ··· 1471 1471 dev->buf_use++; /* Can't allocate more after this call */ 1472 1472 spin_unlock(&dev->buf_lock); 1473 1473 1474 - if (request->count >= dma->buf_count) { 1474 + if (*p >= dma->buf_count) { 1475 1475 if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP)) 1476 1476 || (drm_core_check_feature(dev, DRIVER_SG) 1477 1477 && (dma->flags & _DRM_DMA_USE_SG))) { ··· 1496 1496 retcode = (signed long)virtual; 1497 1497 goto done; 1498 1498 } 1499 - request->virtual = (void __user *)virtual; 1499 + *v = (void __user *)virtual; 1500 1500 1501 1501 for (i = 0; i < dma->buf_count; i++) { 1502 - if (copy_to_user(&request->list[i].idx, 1503 - &dma->buflist[i]->idx, 1504 - sizeof(request->list[0].idx))) { 1505 - retcode = -EFAULT; 1506 - goto done; 1507 - } 1508 - if (copy_to_user(&request->list[i].total, 1509 - &dma->buflist[i]->total, 1510 - sizeof(request->list[0].total))) { 1511 - retcode = -EFAULT; 1512 - goto done; 1513 - } 1514 - if (copy_to_user(&request->list[i].used, 1515 - &zero, sizeof(zero))) { 1516 - retcode = -EFAULT; 1517 - goto done; 1518 - } 1519 - address = virtual + dma->buflist[i]->offset; /* *** */ 1520 - if (copy_to_user(&request->list[i].address, 1521 - &address, sizeof(address))) { 1502 + if (f(data, i, virtual, dma->buflist[i]) < 0) { 1522 1503 retcode = -EFAULT; 1523 1504 goto done; 1524 1505 } 1525 1506 } 1526 1507 } 1527 1508 done: 1528 - request->count = dma->buf_count; 1529 - DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode); 1509 + *p = dma->buf_count; 1510 + DRM_DEBUG("%d buffers, retcode = %d\n", *p, retcode); 1530 1511 1531 1512 return retcode; 1513 + } 1514 + 1515 + static int map_one_buf(void *data, int idx, unsigned long virtual, 1516 + struct drm_buf *buf) 1517 + { 1518 + struct drm_buf_map *request = data; 1519 + unsigned long address = virtual + buf->offset; /* *** */ 1520 + 1521 + if (copy_to_user(&request->list[idx].idx, &buf->idx, 1522 + sizeof(request->list[0].idx))) 1523 + return -EFAULT; 1524 + if (copy_to_user(&request->list[idx].total, &buf->total, 1525 + sizeof(request->list[0].total))) 1526 + return -EFAULT; 1527 + if (clear_user(&request->list[idx].used, sizeof(int))) 1528 + return -EFAULT; 1529 + if (copy_to_user(&request->list[idx].address, &address, 1530 + sizeof(address))) 1531 + return -EFAULT; 1532 + return 0; 1533 + } 1534 + 1535 + int drm_legacy_mapbufs(struct drm_device *dev, void *data, 1536 + struct drm_file *file_priv) 1537 + { 1538 + struct drm_buf_map *request = data; 1539 + return __drm_legacy_mapbufs(dev, data, &request->count, 1540 + &request->virtual, map_one_buf, 1541 + file_priv); 1532 1542 } 1533 1543 1534 1544 int drm_legacy_dma_ioctl(struct drm_device *dev, void *data,
+34 -36
drivers/gpu/drm/drm_ioc32.c
··· 415 415 u32 list; /**< Buffer information */ 416 416 } drm_buf_map32_t; 417 417 418 + static int map_one_buf32(void *data, int idx, unsigned long virtual, 419 + struct drm_buf *buf) 420 + { 421 + drm_buf_map32_t *request = data; 422 + drm_buf_pub32_t __user *to = compat_ptr(request->list) + idx; 423 + drm_buf_pub32_t v; 424 + 425 + v.idx = buf->idx; 426 + v.total = buf->total; 427 + v.used = 0; 428 + v.address = virtual + buf->offset; 429 + if (copy_to_user(to, &v, sizeof(v))) 430 + return -EFAULT; 431 + return 0; 432 + } 433 + 434 + static int drm_legacy_mapbufs32(struct drm_device *dev, void *data, 435 + struct drm_file *file_priv) 436 + { 437 + drm_buf_map32_t *request = data; 438 + void __user *v; 439 + int err = __drm_legacy_mapbufs(dev, data, &request->count, 440 + &v, map_one_buf32, 441 + file_priv); 442 + request->virtual = ptr_to_compat(v); 443 + return err; 444 + } 445 + 418 446 static int compat_drm_mapbufs(struct file *file, unsigned int cmd, 419 447 unsigned long arg) 420 448 { 421 449 drm_buf_map32_t __user *argp = (void __user *)arg; 422 450 drm_buf_map32_t req32; 423 - drm_buf_pub32_t __user *list32; 424 - struct drm_buf_map __user *request; 425 - struct drm_buf_pub __user *list; 426 - int i, err; 427 - int count, actual; 428 - size_t nbytes; 429 - void __user *addr; 451 + int err; 430 452 431 453 if (copy_from_user(&req32, argp, sizeof(req32))) 432 454 return -EFAULT; 433 - count = req32.count; 434 - list32 = (void __user *)(unsigned long)req32.list; 435 - 436 - if (count < 0) 455 + if (req32.count < 0) 437 456 return -EINVAL; 438 - nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub); 439 - request = compat_alloc_user_space(nbytes); 440 - if (!request) 441 - return -EFAULT; 442 - list = (struct drm_buf_pub *) (request + 1); 443 457 444 - if (__put_user(count, &request->count) 445 - || __put_user(list, &request->list)) 446 - return -EFAULT; 447 - 448 - err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request); 458 + err = drm_ioctl_kernel(file, drm_legacy_mapbufs32, &req32, DRM_AUTH); 449 459 if (err) 450 460 return err; 451 461 452 - if (__get_user(actual, &request->count)) 453 - return -EFAULT; 454 - if (count >= actual) 455 - for (i = 0; i < actual; ++i) 456 - if (__copy_in_user(&list32[i], &list[i], 457 - offsetof(struct drm_buf_pub, address)) 458 - || __get_user(addr, &list[i].address) 459 - || __put_user((unsigned long)addr, 460 - &list32[i].address)) 461 - return -EFAULT; 462 - 463 - if (__put_user(actual, &argp->count) 464 - || __get_user(addr, &request->virtual) 465 - || __put_user((unsigned long)addr, &argp->virtual)) 462 + if (put_user(req32.count, &argp->count) 463 + || put_user(req32.virtual, &argp->virtual)) 466 464 return -EFAULT; 467 465 468 466 return 0; ··· 908 910 DRM_IOCTL32_DEF(DRM_IOCTL_ADD_BUFS, compat_drm_addbufs), 909 911 DRM_IOCTL32_DEF(DRM_IOCTL_MARK_BUFS, compat_drm_markbufs), 910 912 DRM_IOCTL32_DEF(DRM_IOCTL_INFO_BUFS, compat_drm_infobufs), 911 - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)].fn = compat_drm_mapbufs, 913 + DRM_IOCTL32_DEF(DRM_IOCTL_MAP_BUFS, compat_drm_mapbufs), 912 914 DRM_IOCTL32_DEF(DRM_IOCTL_FREE_BUFS, compat_drm_freebufs), 913 915 DRM_IOCTL32_DEF(DRM_IOCTL_RM_MAP, compat_drm_rmmap), 914 916 DRM_IOCTL32_DEF(DRM_IOCTL_SET_SAREA_CTX, compat_drm_setsareactx),
+4
drivers/gpu/drm/drm_legacy.h
··· 76 76 77 77 int __drm_legacy_infobufs(struct drm_device *, void *, int *, 78 78 int (*)(void *, int, struct drm_buf_entry *)); 79 + int __drm_legacy_mapbufs(struct drm_device *, void *, int *, 80 + void __user **, 81 + int (*)(void *, int, unsigned long, struct drm_buf *), 82 + struct drm_file *); 79 83 80 84 #ifdef CONFIG_DRM_VM 81 85 void drm_legacy_vma_flush(struct drm_device *d);