Re: [PATCH v2] USB: serial: Enforce USB driver and USB serial driver match

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

 



On Wed, May 30, 2012 at 10:00:14AM +0200, Bjørn Mork wrote:
> We need to make sure that the USB serial driver we find
> matches the USB driver whose probe we are currently
> executing. Otherwise we will end up with USB serial
> devices bound to the correct serial driver but wrong
> USB driver.
> 
> An example of such cross-probing, where the usbserial_generic
> USB driver has found the sierra serial driver:
> 
> May 29 18:26:15 nemi kernel: [ 4442.559246] usbserial_generic 4-4:1.0: Sierra USB modem converter detected
> May 29 18:26:20 nemi kernel: [ 4447.556747] usbserial_generic 4-4:1.2: Sierra USB modem converter detected
> May 29 18:26:25 nemi kernel: [ 4452.557288] usbserial_generic 4-4:1.3: Sierra USB modem converter detected
> 
> sysfs view of the same problem:
> 
> bjorn@nemi:~$ ls -l /sys/bus/usb/drivers/sierra/
> total 0
> --w------- 1 root root 4096 May 29 18:23 bind
> lrwxrwxrwx 1 root root    0 May 29 18:23 module -> ../../../../module/usbserial
> --w------- 1 root root 4096 May 29 18:23 uevent
> --w------- 1 root root 4096 May 29 18:23 unbind
> bjorn@nemi:~$ ls -l /sys/bus/usb-serial/drivers/sierra/
> total 0
> --w------- 1 root root 4096 May 29 18:23 bind
> lrwxrwxrwx 1 root root    0 May 29 18:23 module -> ../../../../module/sierra
> -rw-r--r-- 1 root root 4096 May 29 18:23 new_id
> lrwxrwxrwx 1 root root    0 May 29 18:32 ttyUSB0 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.0/ttyUSB0
> lrwxrwxrwx 1 root root    0 May 29 18:32 ttyUSB1 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.2/ttyUSB1
> lrwxrwxrwx 1 root root    0 May 29 18:32 ttyUSB2 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.3/ttyUSB2
> --w------- 1 root root 4096 May 29 18:23 uevent
> --w------- 1 root root 4096 May 29 18:23 unbind
> 
> bjorn@nemi:~$ ls -l /sys/bus/usb/drivers/usbserial_generic/
> total 0
> lrwxrwxrwx 1 root root    0 May 29 18:33 4-4:1.0 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.0
> lrwxrwxrwx 1 root root    0 May 29 18:33 4-4:1.2 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.2
> lrwxrwxrwx 1 root root    0 May 29 18:33 4-4:1.3 -> ../../../../devices/pci0000:00/0000:00:1d.7/usb4/4-4/4-4:1.3
> --w------- 1 root root 4096 May 29 18:33 bind
> lrwxrwxrwx 1 root root    0 May 29 18:33 module -> ../../../../module/usbserial
> --w------- 1 root root 4096 May 29 18:22 uevent
> --w------- 1 root root 4096 May 29 18:33 unbind
> bjorn@nemi:~$ ls -l /sys/bus/usb-serial/drivers/generic/
> total 0
> --w------- 1 root root 4096 May 29 18:33 bind
> lrwxrwxrwx 1 root root    0 May 29 18:33 module -> ../../../../module/usbserial
> -rw-r--r-- 1 root root 4096 May 29 18:33 new_id
> --w------- 1 root root 4096 May 29 18:22 uevent
> --w------- 1 root root 4096 May 29 18:33 unbind
> 
> So we end up with a mismatch between the USB driver and the
> USB serial driver.  The reason for the above is simple: The
> USB driver probe will succeed if *any* registered serial
> driver matches, and will use that serial driver for all
> serial driver functions.
> 
> This makes ref counting go wrong. We count the USB driver
> as used, but not the USB serial driver.  This may result
> in Oops'es as demonstrated by Johan Hovold <jhovold@xxxxxxxxx>:
> 
> [11811.646396] drivers/usb/serial/usb-serial.c: get_free_serial 1
> [11811.646443] drivers/usb/serial/usb-serial.c: get_free_serial - minor base = 0
> [11811.646460] drivers/usb/serial/usb-serial.c: usb_serial_probe - registering ttyUSB0
> [11811.646766] usb 6-1: pl2303 converter now attached to ttyUSB0
> [11812.264197] USB Serial deregistering driver FTDI USB Serial Device
> [11812.264865] usbcore: deregistering interface driver ftdi_sio
> [11812.282180] USB Serial deregistering driver pl2303
> [11812.283141] pl2303 ttyUSB0: pl2303 converter now disconnected from ttyUSB0
> [11812.283272] usbcore: deregistering interface driver pl2303
> [11812.301056] USB Serial deregistering driver generic
> [11812.301186] usbcore: deregistering interface driver usbserial_generic
> [11812.301259] drivers/usb/serial/usb-serial.c: usb_serial_disconnect
> [11812.301823] BUG: unable to handle kernel paging request at f8e7438c
> [11812.301845] IP: [<f8e38445>] usb_serial_disconnect+0xb5/0x100 [usbserial]
> [11812.301871] *pde = 357ef067 *pte = 00000000
> [11812.301957] Oops: 0000 [#1] PREEMPT SMP
> [11812.301983] Modules linked in: usbserial(-) [last unloaded: pl2303]
> [11812.302008]
> [11812.302019] Pid: 1323, comm: modprobe Tainted: G        W    3.4.0-rc7+ #101 Dell Inc. Vostro 1520/0T816J
> [11812.302115] EIP: 0060:[<f8e38445>] EFLAGS: 00010246 CPU: 1
> [11812.302130] EIP is at usb_serial_disconnect+0xb5/0x100 [usbserial]
> [11812.302141] EAX: f508a180 EBX: f508a180 ECX: 00000000 EDX: f8e74300
> [11812.302151] ESI: f5050800 EDI: 00000001 EBP: f5141e78 ESP: f5141e58
> [11812.302160]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
> [11812.302170] CR0: 8005003b CR2: f8e7438c CR3: 34848000 CR4: 000007d0
> [11812.302180] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
> [11812.302189] DR6: ffff0ff0 DR7: 00000400
> [11812.302199] Process modprobe (pid: 1323, ti=f5140000 task=f61e2bc0 task.ti=f5140000)
> [11812.302209] Stack:
> [11812.302216]  f8e3be0f f8e3b29c f8e3ae00 00000000 f513641c f5136400 f513641c f507a540
> [11812.302325]  f5141e98 c133d2c1 00000000 00000000 f509c400 f513641c f507a590 f5136450
> [11812.302372]  f5141ea8 c12f0344 f513641c f507a590 f5141ebc c12f0c67 00000000 f507a590
> [11812.302419] Call Trace:
> [11812.302439]  [<c133d2c1>] usb_unbind_interface+0x51/0x190
> [11812.302456]  [<c12f0344>] __device_release_driver+0x64/0xb0
> [11812.302469]  [<c12f0c67>] driver_detach+0x97/0xa0
> [11812.302483]  [<c12f001c>] bus_remove_driver+0x6c/0xe0
> [11812.302500]  [<c145938d>] ? __mutex_unlock_slowpath+0xcd/0x140
> [11812.302514]  [<c12f0ff9>] driver_unregister+0x49/0x80
> [11812.302528]  [<c1457df6>] ? printk+0x1d/0x1f
> [11812.302540]  [<c133c50d>] usb_deregister+0x5d/0xb0
> [11812.302557]  [<f8e37c55>] ? usb_serial_deregister+0x45/0x50 [usbserial]
> [11812.302575]  [<f8e37c8d>] usb_serial_deregister_drivers+0x2d/0x40 [usbserial]
> [11812.302593]  [<f8e3a6e2>] usb_serial_generic_deregister+0x12/0x20 [usbserial]
> [11812.302611]  [<f8e3acf0>] usb_serial_exit+0x8/0x32 [usbserial]
> [11812.302716]  [<c1080b48>] sys_delete_module+0x158/0x260
> [11812.302730]  [<c110594e>] ? mntput+0x1e/0x30
> [11812.302746]  [<c145c3c3>] ? sysenter_exit+0xf/0x18
> [11812.302746]  [<c107777c>] ? trace_hardirqs_on_caller+0xec/0x170
> [11812.302746]  [<c145c390>] sysenter_do_call+0x12/0x36
> [11812.302746] Code: 24 02 00 00 e8 dd f3 20 c8 f6 86 74 02 00 00 02 74 b4 8d 86 4c 02 00 00 47 e8 78 55 4b c8 0f b6 43 0e 39 f8 7f a9 8b 53 04 89 d8 <ff> 92 8c 00 00 00 89 d8 e8 0e ff ff ff 8b 45 f0 c7 44 24 04 2f
> [11812.302746] EIP: [<f8e38445>] usb_serial_disconnect+0xb5/0x100 [usbserial] SS:ESP 0068:f5141e58
> [11812.302746] CR2: 00000000f8e7438c
> 
> Fix by only evaluating serial drivers pointing back to the
> USB driver we are currently probing.  This still allows two
> or more drivers to match the same device, running their
> serial driver probes to sort out which one to use.
> 
> Cc: stable@xxxxxxxxxxxxxxx # 3.0, 3.2, 3.3, 3.4
> Cc: Johan Hovold <jhovold@xxxxxxxxx>
> Signed-off-by: Bjørn Mork <bjorn@xxxxxxx>

This looks fine to my eyes, FWIW:

Reviewed-by: Felipe Balbi <balbi@xxxxxx>

> ---
> > So search_serial_device needs to do the match.  Does anyone see a
> > problem with that?  I guess noone here does, unless I express it in code
> > :-)  So I'll go do that now.
> 
> Here it is.  Changes in
> v2:
>   - moved driver matching to search_serial_device to allow two drivers
>     to match the same device
>   - much more verbose patch description including relevant parts of my
>     previous comment as suggested by Felipe Balbi
>   - including example Oops from Johan Hovold in description
> 
> This problem became evident when the generic serial driver probe was
> removed, but has been in the code "forever".  I believe it can be
> triggered on older kernels by using new_id on serial drivers trusting
> device matching. I have verified that the fix applies unmodified to
>  stable/linux-3.0.y
>  stable/linux-3.2.y
>  stable/linux-3.3.y
>  stable/linux-3.4.y
> and I believe it should go into all of them.  I have not verified the
> end result on these kernels, but the affected logic has not changed so
> it should work.
> 
> 
>  drivers/usb/serial/usb-serial.c |    6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
> index 6a1b609..6e8c527 100644
> --- a/drivers/usb/serial/usb-serial.c
> +++ b/drivers/usb/serial/usb-serial.c
> @@ -659,12 +659,14 @@ exit:
>  static struct usb_serial_driver *search_serial_device(
>  					struct usb_interface *iface)
>  {
> -	const struct usb_device_id *id;
> +	const struct usb_device_id *id = NULL;
>  	struct usb_serial_driver *drv;
> +	struct usb_driver *driver = to_usb_driver(iface->dev.driver);
>  
>  	/* Check if the usb id matches a known device */
>  	list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
> -		id = get_iface_id(drv, iface);
> +		if (drv->usb_driver == driver)
> +			id = get_iface_id(drv, iface);
>  		if (id)
>  			return drv;
>  	}
> -- 
> 1.7.10
> 

-- 
balbi

Attachment: signature.asc
Description: Digital signature


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

  Powered by Linux