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

usbdevfs: move compat_ioctl handling to devio.c

Half the compat_ioctl handling is in devio.c, the other
half is in fs/compat_ioctl.c. This moves everything into
one place for consistency.

As a positive side-effect, push down the BKL into the
ioctl methods.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Oliver Neukum <oliver@neukum.org>
Cc: Alon Bar-Lev <alon.barlev@gmail.com>
Cc: David Vrabel <david.vrabel@csr.com>
Cc: linux-usb@vger.kernel.org

+125 -123
+99 -11
drivers/usb/core/devio.c
··· 1388 1388 } 1389 1389 1390 1390 #ifdef CONFIG_COMPAT 1391 + static int proc_control_compat(struct dev_state *ps, 1392 + struct usbdevfs_ctrltransfer32 __user *p32) 1393 + { 1394 + struct usbdevfs_ctrltransfer __user *p; 1395 + __u32 udata; 1396 + p = compat_alloc_user_space(sizeof(*p)); 1397 + if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || 1398 + get_user(udata, &p32->data) || 1399 + put_user(compat_ptr(udata), &p->data)) 1400 + return -EFAULT; 1401 + return proc_control(ps, p); 1402 + } 1403 + 1404 + static int proc_bulk_compat(struct dev_state *ps, 1405 + struct usbdevfs_bulktransfer32 __user *p32) 1406 + { 1407 + struct usbdevfs_bulktransfer __user *p; 1408 + compat_uint_t n; 1409 + compat_caddr_t addr; 1410 + 1411 + p = compat_alloc_user_space(sizeof(*p)); 1412 + 1413 + if (get_user(n, &p32->ep) || put_user(n, &p->ep) || 1414 + get_user(n, &p32->len) || put_user(n, &p->len) || 1415 + get_user(n, &p32->timeout) || put_user(n, &p->timeout) || 1416 + get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data)) 1417 + return -EFAULT; 1418 + 1419 + return proc_bulk(ps, p); 1420 + } 1421 + static int proc_disconnectsignal_compat(struct dev_state *ps, void __user *arg) 1422 + { 1423 + struct usbdevfs_disconnectsignal32 ds; 1424 + 1425 + if (copy_from_user(&ds, arg, sizeof(ds))) 1426 + return -EFAULT; 1427 + ps->discsignr = ds.signr; 1428 + ps->disccontext = compat_ptr(ds.context); 1429 + return 0; 1430 + } 1391 1431 1392 1432 static int get_urb32(struct usbdevfs_urb *kurb, 1393 1433 struct usbdevfs_urb32 __user *uurb) ··· 1521 1481 return -EAGAIN; 1522 1482 return processcompl_compat(as, (void __user * __user *)arg); 1523 1483 } 1484 + 1524 1485 1525 1486 #endif 1526 1487 ··· 1689 1648 * are assuming that somehow the configuration has been prevented from 1690 1649 * changing. But there's no mechanism to ensure that... 1691 1650 */ 1692 - static int usbdev_ioctl(struct inode *inode, struct file *file, 1693 - unsigned int cmd, unsigned long arg) 1651 + static long usbdev_do_ioctl(struct file *file, unsigned int cmd, 1652 + void __user *p) 1694 1653 { 1695 1654 struct dev_state *ps = file->private_data; 1655 + struct inode *inode = file->f_path.dentry->d_inode; 1696 1656 struct usb_device *dev = ps->dev; 1697 - void __user *p = (void __user *)arg; 1698 1657 int ret = -ENOTTY; 1699 1658 1700 1659 if (!(file->f_mode & FMODE_WRITE)) ··· 1767 1726 break; 1768 1727 1769 1728 #ifdef CONFIG_COMPAT 1729 + case USBDEVFS_CONTROL32: 1730 + snoop(&dev->dev, "%s: CONTROL32\n", __func__); 1731 + ret = proc_control_compat(ps, p); 1732 + if (ret >= 0) 1733 + inode->i_mtime = CURRENT_TIME; 1734 + break; 1735 + 1736 + case USBDEVFS_BULK32: 1737 + snoop(&dev->dev, "%s: BULK32\n", __func__); 1738 + ret = proc_bulk_compat(ps, p); 1739 + if (ret >= 0) 1740 + inode->i_mtime = CURRENT_TIME; 1741 + break; 1742 + 1743 + case USBDEVFS_DISCSIGNAL32: 1744 + snoop(&dev->dev, "%s: DISCSIGNAL32\n", __func__); 1745 + ret = proc_disconnectsignal_compat(ps, p); 1746 + break; 1770 1747 1771 1748 case USBDEVFS_SUBMITURB32: 1772 1749 snoop(&dev->dev, "%s: SUBMITURB32\n", __func__); ··· 1804 1745 break; 1805 1746 1806 1747 case USBDEVFS_IOCTL32: 1807 - snoop(&dev->dev, "%s: IOCTL\n", __func__); 1748 + snoop(&dev->dev, "%s: IOCTL32\n", __func__); 1808 1749 ret = proc_ioctl_compat(ps, ptr_to_compat(p)); 1809 1750 break; 1810 1751 #endif ··· 1860 1801 return ret; 1861 1802 } 1862 1803 1804 + static long usbdev_ioctl(struct file *file, unsigned int cmd, 1805 + unsigned long arg) 1806 + { 1807 + int ret; 1808 + 1809 + lock_kernel(); 1810 + ret = usbdev_do_ioctl(file, cmd, (void __user *)arg); 1811 + unlock_kernel(); 1812 + 1813 + return ret; 1814 + } 1815 + 1816 + #ifdef CONFIG_COMPAT 1817 + static long usbdev_compat_ioctl(struct file *file, unsigned int cmd, 1818 + unsigned long arg) 1819 + { 1820 + int ret; 1821 + 1822 + lock_kernel(); 1823 + ret = usbdev_do_ioctl(file, cmd, compat_ptr(arg)); 1824 + unlock_kernel(); 1825 + 1826 + return ret; 1827 + } 1828 + #endif 1829 + 1863 1830 /* No kernel lock - fine */ 1864 1831 static unsigned int usbdev_poll(struct file *file, 1865 1832 struct poll_table_struct *wait) ··· 1902 1817 } 1903 1818 1904 1819 const struct file_operations usbdev_file_operations = { 1905 - .owner = THIS_MODULE, 1906 - .llseek = usbdev_lseek, 1907 - .read = usbdev_read, 1908 - .poll = usbdev_poll, 1909 - .ioctl = usbdev_ioctl, 1910 - .open = usbdev_open, 1911 - .release = usbdev_release, 1820 + .owner = THIS_MODULE, 1821 + .llseek = usbdev_lseek, 1822 + .read = usbdev_read, 1823 + .poll = usbdev_poll, 1824 + .unlocked_ioctl = usbdev_ioctl, 1825 + #ifdef CONFIG_COMPAT 1826 + .compat_ioctl = usbdev_compat_ioctl, 1827 + #endif 1828 + .open = usbdev_open, 1829 + .release = usbdev_release, 1912 1830 }; 1913 1831 1914 1832 static void usbdev_remove(struct usb_device *udev)
-112
fs/compat_ioctl.c
··· 742 742 return err; 743 743 } 744 744 745 - struct usbdevfs_ctrltransfer32 { 746 - u8 bRequestType; 747 - u8 bRequest; 748 - u16 wValue; 749 - u16 wIndex; 750 - u16 wLength; 751 - u32 timeout; /* in milliseconds */ 752 - compat_caddr_t data; 753 - }; 754 - 755 - #define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) 756 - 757 - static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, 758 - struct usbdevfs_ctrltransfer32 __user *p32) 759 - { 760 - struct usbdevfs_ctrltransfer __user *p; 761 - __u32 udata; 762 - p = compat_alloc_user_space(sizeof(*p)); 763 - if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) || 764 - get_user(udata, &p32->data) || 765 - put_user(compat_ptr(udata), &p->data)) 766 - return -EFAULT; 767 - return sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)p); 768 - } 769 - 770 - 771 - struct usbdevfs_bulktransfer32 { 772 - compat_uint_t ep; 773 - compat_uint_t len; 774 - compat_uint_t timeout; /* in milliseconds */ 775 - compat_caddr_t data; 776 - }; 777 - 778 - #define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) 779 - 780 - static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, 781 - struct usbdevfs_bulktransfer32 __user *p32) 782 - { 783 - struct usbdevfs_bulktransfer __user *p; 784 - compat_uint_t n; 785 - compat_caddr_t addr; 786 - 787 - p = compat_alloc_user_space(sizeof(*p)); 788 - 789 - if (get_user(n, &p32->ep) || put_user(n, &p->ep) || 790 - get_user(n, &p32->len) || put_user(n, &p->len) || 791 - get_user(n, &p32->timeout) || put_user(n, &p->timeout) || 792 - get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data)) 793 - return -EFAULT; 794 - 795 - return sys_ioctl(fd, USBDEVFS_BULK, (unsigned long)p); 796 - } 797 - 798 - 799 - /* 800 - * USBDEVFS_SUBMITURB, USBDEVFS_REAPURB and USBDEVFS_REAPURBNDELAY 801 - * are handled in usbdevfs core. -Christopher Li 802 - */ 803 - 804 - struct usbdevfs_disconnectsignal32 { 805 - compat_int_t signr; 806 - compat_caddr_t context; 807 - }; 808 - 809 - #define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) 810 - 811 - static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, 812 - struct usbdevfs_disconnectsignal32 __user *udis) 813 - { 814 - struct usbdevfs_disconnectsignal kdis; 815 - mm_segment_t old_fs; 816 - u32 uctx; 817 - int err; 818 - 819 - if (get_user(kdis.signr, &udis->signr) || 820 - __get_user(uctx, &udis->context)) 821 - return -EFAULT; 822 - 823 - kdis.context = compat_ptr(uctx); 824 - 825 - old_fs = get_fs(); 826 - set_fs(KERNEL_DS); 827 - err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis); 828 - set_fs(old_fs); 829 - 830 - return err; 831 - } 832 - 833 745 /* 834 746 * I2C layer ioctls 835 747 */ ··· 1383 1471 COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) 1384 1472 COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) 1385 1473 COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) 1386 - /* USB */ 1387 - COMPATIBLE_IOCTL(USBDEVFS_RESETEP) 1388 - COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE) 1389 - COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION) 1390 - COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER) 1391 - COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB) 1392 - COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE) 1393 - COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE) 1394 - COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO) 1395 - COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO) 1396 - COMPATIBLE_IOCTL(USBDEVFS_RESET) 1397 - COMPATIBLE_IOCTL(USBDEVFS_SUBMITURB32) 1398 - COMPATIBLE_IOCTL(USBDEVFS_REAPURB32) 1399 - COMPATIBLE_IOCTL(USBDEVFS_REAPURBNDELAY32) 1400 - COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT) 1401 1474 /* NBD */ 1402 1475 COMPATIBLE_IOCTL(NBD_DO_IT) 1403 1476 COMPATIBLE_IOCTL(NBD_CLEAR_SOCK) ··· 1501 1604 COMPATIBLE_IOCTL(TIOCSTART) 1502 1605 COMPATIBLE_IOCTL(TIOCSTOP) 1503 1606 #endif 1504 - /* Usbdevfs */ 1505 - COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) 1506 1607 1507 1608 /* fat 'r' ioctls. These are handled by fat with ->compat_ioctl, 1508 1609 but we don't want warnings on other file systems. So declare ··· 1572 1677 case TIOCGSERIAL: 1573 1678 case TIOCSSERIAL: 1574 1679 return serial_struct_ioctl(fd, cmd, argp); 1575 - /* Usbdevfs */ 1576 - case USBDEVFS_CONTROL32: 1577 - return do_usbdevfs_control(fd, cmd, argp); 1578 - case USBDEVFS_BULK32: 1579 - return do_usbdevfs_bulk(fd, cmd, argp); 1580 - case USBDEVFS_DISCSIGNAL32: 1581 - return do_usbdevfs_discsignal(fd, cmd, argp); 1582 1680 /* i2c */ 1583 1681 case I2C_FUNCS: 1584 1682 return w_long(fd, cmd, argp);
+26
include/linux/usbdevice_fs.h
··· 128 128 #ifdef __KERNEL__ 129 129 #ifdef CONFIG_COMPAT 130 130 #include <linux/compat.h> 131 + 132 + struct usbdevfs_ctrltransfer32 { 133 + u8 bRequestType; 134 + u8 bRequest; 135 + u16 wValue; 136 + u16 wIndex; 137 + u16 wLength; 138 + u32 timeout; /* in milliseconds */ 139 + compat_caddr_t data; 140 + }; 141 + 142 + struct usbdevfs_bulktransfer32 { 143 + compat_uint_t ep; 144 + compat_uint_t len; 145 + compat_uint_t timeout; /* in milliseconds */ 146 + compat_caddr_t data; 147 + }; 148 + 149 + struct usbdevfs_disconnectsignal32 { 150 + compat_int_t signr; 151 + compat_caddr_t context; 152 + }; 153 + 131 154 struct usbdevfs_urb32 { 132 155 unsigned char type; 133 156 unsigned char endpoint; ··· 176 153 #endif /* __KERNEL__ */ 177 154 178 155 #define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer) 156 + #define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) 179 157 #define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer) 158 + #define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) 180 159 #define USBDEVFS_RESETEP _IOR('U', 3, unsigned int) 181 160 #define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface) 182 161 #define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int) ··· 191 166 #define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *) 192 167 #define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, __u32) 193 168 #define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal) 169 + #define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) 194 170 #define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int) 195 171 #define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int) 196 172 #define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo)