diff options
| -rw-r--r-- | drivers/usb/core/devio.c | 56 | ||||
| -rw-r--r-- | fs/compat_ioctl.c | 1 | ||||
| -rw-r--r-- | include/linux/usbdevice_fs.h | 7 |
3 files changed, 50 insertions, 14 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 2bd742ba812d..ffb2e242b100 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
| @@ -1301,23 +1301,20 @@ static int proc_releaseinterface(struct dev_state *ps, void __user *arg) | |||
| 1301 | return 0; | 1301 | return 0; |
| 1302 | } | 1302 | } |
| 1303 | 1303 | ||
| 1304 | static int proc_ioctl (struct dev_state *ps, void __user *arg) | 1304 | static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) |
| 1305 | { | 1305 | { |
| 1306 | struct usbdevfs_ioctl ctrl; | ||
| 1307 | int size; | 1306 | int size; |
| 1308 | void *buf = NULL; | 1307 | void *buf = NULL; |
| 1309 | int retval = 0; | 1308 | int retval = 0; |
| 1310 | struct usb_interface *intf = NULL; | 1309 | struct usb_interface *intf = NULL; |
| 1311 | struct usb_driver *driver = NULL; | 1310 | struct usb_driver *driver = NULL; |
| 1312 | 1311 | ||
| 1313 | /* get input parameters and alloc buffer */ | 1312 | /* alloc buffer */ |
| 1314 | if (copy_from_user(&ctrl, arg, sizeof (ctrl))) | 1313 | if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) { |
| 1315 | return -EFAULT; | ||
| 1316 | if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) { | ||
| 1317 | if ((buf = kmalloc (size, GFP_KERNEL)) == NULL) | 1314 | if ((buf = kmalloc (size, GFP_KERNEL)) == NULL) |
| 1318 | return -ENOMEM; | 1315 | return -ENOMEM; |
| 1319 | if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) { | 1316 | if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) { |
| 1320 | if (copy_from_user (buf, ctrl.data, size)) { | 1317 | if (copy_from_user (buf, ctl->data, size)) { |
| 1321 | kfree(buf); | 1318 | kfree(buf); |
| 1322 | return -EFAULT; | 1319 | return -EFAULT; |
| 1323 | } | 1320 | } |
| @@ -1333,9 +1330,9 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg) | |||
| 1333 | 1330 | ||
| 1334 | if (ps->dev->state != USB_STATE_CONFIGURED) | 1331 | if (ps->dev->state != USB_STATE_CONFIGURED) |
| 1335 | retval = -EHOSTUNREACH; | 1332 | retval = -EHOSTUNREACH; |
| 1336 | else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno))) | 1333 | else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno))) |
| 1337 | retval = -EINVAL; | 1334 | retval = -EINVAL; |
| 1338 | else switch (ctrl.ioctl_code) { | 1335 | else switch (ctl->ioctl_code) { |
| 1339 | 1336 | ||
| 1340 | /* disconnect kernel driver from interface */ | 1337 | /* disconnect kernel driver from interface */ |
| 1341 | case USBDEVFS_DISCONNECT: | 1338 | case USBDEVFS_DISCONNECT: |
| @@ -1367,7 +1364,7 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg) | |||
| 1367 | if (driver == NULL || driver->ioctl == NULL) { | 1364 | if (driver == NULL || driver->ioctl == NULL) { |
| 1368 | retval = -ENOTTY; | 1365 | retval = -ENOTTY; |
| 1369 | } else { | 1366 | } else { |
| 1370 | retval = driver->ioctl (intf, ctrl.ioctl_code, buf); | 1367 | retval = driver->ioctl (intf, ctl->ioctl_code, buf); |
| 1371 | if (retval == -ENOIOCTLCMD) | 1368 | if (retval == -ENOIOCTLCMD) |
| 1372 | retval = -ENOTTY; | 1369 | retval = -ENOTTY; |
| 1373 | } | 1370 | } |
| @@ -1376,15 +1373,42 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg) | |||
| 1376 | 1373 | ||
| 1377 | /* cleanup and return */ | 1374 | /* cleanup and return */ |
| 1378 | if (retval >= 0 | 1375 | if (retval >= 0 |
| 1379 | && (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0 | 1376 | && (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0 |
| 1380 | && size > 0 | 1377 | && size > 0 |
| 1381 | && copy_to_user (ctrl.data, buf, size) != 0) | 1378 | && copy_to_user (ctl->data, buf, size) != 0) |
| 1382 | retval = -EFAULT; | 1379 | retval = -EFAULT; |
| 1383 | 1380 | ||
| 1384 | kfree(buf); | 1381 | kfree(buf); |
| 1385 | return retval; | 1382 | return retval; |
| 1386 | } | 1383 | } |
| 1387 | 1384 | ||
| 1385 | static int proc_ioctl_default(struct dev_state *ps, void __user *arg) | ||
| 1386 | { | ||
| 1387 | struct usbdevfs_ioctl ctrl; | ||
| 1388 | |||
| 1389 | if (copy_from_user(&ctrl, arg, sizeof (ctrl))) | ||
| 1390 | return -EFAULT; | ||
| 1391 | return proc_ioctl(ps, &ctrl); | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | #ifdef CONFIG_COMPAT | ||
| 1395 | static int proc_ioctl_compat(struct dev_state *ps, void __user *arg) | ||
| 1396 | { | ||
| 1397 | struct usbdevfs_ioctl32 __user *uioc; | ||
| 1398 | struct usbdevfs_ioctl ctrl; | ||
| 1399 | u32 udata; | ||
| 1400 | |||
| 1401 | uioc = compat_ptr(arg); | ||
| 1402 | if (get_user(ctrl.ifno, &uioc->ifno) || | ||
| 1403 | get_user(ctrl.ioctl_code, &uioc->ioctl_code) || | ||
| 1404 | __get_user(udata, &uioc->data)) | ||
| 1405 | return -EFAULT; | ||
| 1406 | ctrl.data = compat_ptr(udata); | ||
| 1407 | |||
| 1408 | return proc_ioctl(ps, &ctrl); | ||
| 1409 | } | ||
| 1410 | #endif | ||
| 1411 | |||
| 1388 | /* | 1412 | /* |
| 1389 | * NOTE: All requests here that have interface numbers as parameters | 1413 | * NOTE: All requests here that have interface numbers as parameters |
| 1390 | * are assuming that somehow the configuration has been prevented from | 1414 | * are assuming that somehow the configuration has been prevented from |
| @@ -1485,6 +1509,10 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 1485 | ret = proc_reapurbnonblock_compat(ps, p); | 1509 | ret = proc_reapurbnonblock_compat(ps, p); |
| 1486 | break; | 1510 | break; |
| 1487 | 1511 | ||
| 1512 | case USBDEVFS_IOCTL32: | ||
| 1513 | snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__); | ||
| 1514 | ret = proc_ioctl_compat(ps, p); | ||
| 1515 | break; | ||
| 1488 | #endif | 1516 | #endif |
| 1489 | 1517 | ||
| 1490 | case USBDEVFS_DISCARDURB: | 1518 | case USBDEVFS_DISCARDURB: |
| @@ -1519,7 +1547,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 1519 | 1547 | ||
| 1520 | case USBDEVFS_IOCTL: | 1548 | case USBDEVFS_IOCTL: |
| 1521 | snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__); | 1549 | snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__); |
| 1522 | ret = proc_ioctl(ps, p); | 1550 | ret = proc_ioctl_default(ps, p); |
| 1523 | break; | 1551 | break; |
| 1524 | } | 1552 | } |
| 1525 | usb_unlock_device(dev); | 1553 | usb_unlock_device(dev); |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index e28a74203f3b..a327e03753ac 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -3050,6 +3050,7 @@ HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl) | |||
| 3050 | HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) | 3050 | HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) |
| 3051 | HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) | 3051 | HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) |
| 3052 | HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) | 3052 | HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) |
| 3053 | COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) | ||
| 3053 | /* i2c */ | 3054 | /* i2c */ |
| 3054 | HANDLE_IOCTL(I2C_FUNCS, w_long) | 3055 | HANDLE_IOCTL(I2C_FUNCS, w_long) |
| 3055 | HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) | 3056 | HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) |
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h index 9facf733800c..8859f0b41543 100644 --- a/include/linux/usbdevice_fs.h +++ b/include/linux/usbdevice_fs.h | |||
| @@ -140,6 +140,12 @@ struct usbdevfs_urb32 { | |||
| 140 | compat_caddr_t usercontext; /* unused */ | 140 | compat_caddr_t usercontext; /* unused */ |
| 141 | struct usbdevfs_iso_packet_desc iso_frame_desc[0]; | 141 | struct usbdevfs_iso_packet_desc iso_frame_desc[0]; |
| 142 | }; | 142 | }; |
| 143 | |||
| 144 | struct usbdevfs_ioctl32 { | ||
| 145 | s32 ifno; | ||
| 146 | s32 ioctl_code; | ||
| 147 | compat_caddr_t data; | ||
| 148 | }; | ||
| 143 | #endif | 149 | #endif |
| 144 | 150 | ||
| 145 | #define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer) | 151 | #define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer) |
| @@ -160,6 +166,7 @@ struct usbdevfs_urb32 { | |||
| 160 | #define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int) | 166 | #define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int) |
| 161 | #define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo) | 167 | #define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo) |
| 162 | #define USBDEVFS_IOCTL _IOWR('U', 18, struct usbdevfs_ioctl) | 168 | #define USBDEVFS_IOCTL _IOWR('U', 18, struct usbdevfs_ioctl) |
| 169 | #define USBDEVFS_IOCTL32 _IOWR('U', 18, struct usbdevfs_ioctl32) | ||
| 163 | #define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo) | 170 | #define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo) |
| 164 | #define USBDEVFS_RESET _IO('U', 20) | 171 | #define USBDEVFS_RESET _IO('U', 20) |
| 165 | #define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int) | 172 | #define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int) |
