Hi all, We've experienced some issues with an application that uses hiddev devices. This application regularly performs ioctl syscalls on a hiddev device (/dev/usb/hiddev0) with the intent to get report information. This works fine, until the device is physically disconnected. For context, here's a snippet from drivers/hid/usb/hiddev.c: ------- static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct hiddev_list *list = file->private_data; struct hiddev *hiddev = list->hiddev; struct hid_device *hid = hiddev->hid; struct usb_device *dev = hid_to_usb_dev(hid); struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; struct hiddev_devinfo dinfo; struct hid_report *report; struct hid_field *field; struct usbhid_device *usbhid = hid->driver_data; void __user *user_arg = (void __user *)arg; int i, r; /* Called without BKL by compat methods so no BKL taken */ /* FIXME: Who or what stop this racing with a disconnect ?? */ if (!hiddev->exist) return -EIO; ------- We found that in rare circumstances, the deference in the third line fails, i.e. list->hiddev does not hold a valid pointer. Here's the trace from the kernel: Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637584] EIP: 0060:[<f80d4d7c>] EFLAGS: 00010292 CPU: 0 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637596] EIP is at hiddev_ioctl+0x2c/0x680 [usbhid] Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637601] EAX: 00000000 EBX: ee538000 ECX: bf8d78a8 EDX: 4018480c Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637607] ESI: ee24dd80 EDI: f08e0000 EBP: f5663f50 ESP: f5663ec8 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637612] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637627] 00000000 f5663ed8 bf8d78a8 00000000 00000001 ffffffff f3b64300 00000000 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637641] <0> 00000000 00000000 00000000 f6bd9980 00000000 00000000 00000000 f6bd9980 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637657] <0> c0167b50 f5663f0c f5663f0c 00000000 00000000 f5663e70 f5663f28 c03bb5dd Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637687] [<c0167b50>] ? autoremove_wake_function+0x0/0x50 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637697] [<c03bb5dd>] ? tty_ldisc_deref+0xd/0x10 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637707] [<c02f5c14>] ? security_file_permission+0x14/0x20 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637717] [<c0208a24>] ? rw_verify_area+0x64/0xe0 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637743] [<f80d4d50>] ? hiddev_ioctl+0x0/0x680 [usbhid] Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637756] [<c0217211>] ? vfs_ioctl+0x21/0x90 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637764] [<c0171b96>] ? getnstimeofday+0x56/0x110 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637771] [<c02174f9>] ? do_vfs_ioctl+0x79/0x310 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637779] [<c03549a9>] ? copy_to_user+0x39/0x130 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637786] [<c02177f7>] ? sys_ioctl+0x67/0x80 Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.637794] [<c01033ec>] ? syscall_call+0x7/0xb Jan 13 10:32:31 ehv-nb-001 kernel: [ 7525.638001] ---[ end trace beb5a9ffee100cae ]--- hiddev_ioctl+0x2c is a dereference of EAX, which is 00000000. It seems to be a problem related to the 'unbinding' of hiddev from the list, resulting in list->hiddev being 0, while 'file' still refers to a valid file. We suspect that the 'FIXME' mentioned is also related, except that in our case sometimes the 'hiddev' is gone. We've patched these lines: ------ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct hiddev_list *list = file->private_data; struct hiddev *hiddev = list->hiddev; struct hid_device *hid; struct usb_device *dev; struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; struct hiddev_devinfo dinfo; struct hid_report *report; struct hid_field *field; struct usbhid_device *usbhid; void __user *user_arg; int i, r; if (hiddev == NULL) return -EIO; hid = hiddev->hid; if (hid == NULL || &(hid->dev) == NULL || hid->dev.parent == NULL) return -EIO; dev = hid_to_usb_dev(hid); usbhid = hid->driver_data; user_arg = (void __user *)arg; ------ This seems to be enough to solve the symptom. Not sure whether the same caution should be applied to the dereferencing of 'list', or even 'file' for that matter. Regards, Robert Lukassen This e-mail message contains information which is confidential and may be privileged. It is intended for use by the addressee only. If you are not the intended addressee, we request that you notify the sender immediately and delete or destroy this e-mail message and any attachment(s), without copying, saving, forwarding, disclosing or using its contents in any other way. TomTom N.V., TomTom International BV or any other company belonging to the TomTom group of companies will not be liable for damage relating to the communication by e-mail of data, documents or any other information. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html