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) |