RE: Potential trouble in usbhid

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

The snippet I quoted was from the Ubuntu 10.04 LTS we're using. Apparently, this issue (among others) was fixed in the latest 2.6 kernel, so please ignore this report.

Regards,

Robert 

> -----Original Message-----
> From: Robert Lukassen 
> Sent: Thursday, January 13, 2011 1:56 PM
> To: linux-usb@xxxxxxxxxxxxxxx
> Subject: Potential trouble in usbhid
> 
> 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
> 
> 
> 
--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux