Comment 0 for bug 331106

Revision history for this message
Colin Ian King (colin-king) wrote :

Playing audio through a Bluetooth headset and then suspending the machine on Hardy, Intrepid and Jaunty causes a kernel panic. I've captured the location of the panic below in hci_usb_tx_complete.

00000750 <hci_usb_tx_complete>:
     750: 83 ec 14 sub $0x14,%esp
     753: 89 5c 24 04 mov %ebx,0x4(%esp)
     757: 89 c3 mov %eax,%ebx
     759: 89 74 24 08 mov %esi,0x8(%esp)
     75d: 89 6c 24 10 mov %ebp,0x10(%esp)
     761: 8d 68 ec lea -0x14(%eax),%ebp
     764: 89 7c 24 0c mov %edi,0xc(%esp)
     768: 8b 78 64 mov 0x64(%eax),%edi
     76b: 8b 07 mov (%edi),%eax
     76d: 8d 77 68 lea 0x68(%edi),%esi
     770: 89 04 24 mov %eax,(%esp)
     773: 8b 45 0c mov 0xc(%ebp),%eax
     776: f0 ff 0c 86 lock decl (%esi,%eax,4)
     77a: c7 43 3c 00 00 00 00 movl $0x0,0x3c(%ebx)
     781: 8b 45 10 mov 0x10(%ebp),%eax
     784: e8 fc ff ff ff call 785 <hci_usb_tx_complete+0x35>
     789: 8b 14 24 mov (%esp),%edx
     78c: 8b 42 18 mov 0x18(%edx),%eax
     78f: a8 04 test $0x4,%al
     791: 0f 84 9d 00 00 00 je 834 <hci_usb_tx_complete+0xe4>
     797: 8b 4b 34 mov 0x34(%ebx),%ecx
     79a: 85 c9 test %ecx,%ecx
     79c: 0f 84 a6 00 00 00 je 848 <hci_usb_tx_complete+0xf8>
     7a2: 8b 04 24 mov (%esp),%eax
     7a5: 83 80 74 02 00 00 01 addl $0x1,0x274(%eax)
     7ac: 89 f0 mov %esi,%eax
     7ae: e8 fc ff ff ff call 7af <hci_usb_tx_complete+0x5f>
     7b3: 8b 45 08 mov 0x8(%ebp),%eax
     7b6: 85 c0 test %eax,%eax
     7b8: 74 33 je 7ed <hci_usb_tx_complete+0x9d>
     7ba: 8d 58 08 lea 0x8(%eax),%ebx
     7bd: 89 d8 mov %ebx,%eax
     7bf: e8 fc ff ff ff call 7c0 <hci_usb_tx_complete+0x70>
     7c4: 8b 55 04 mov 0x4(%ebp),%edx
     7c7: 8b 4d 00 mov 0x0(%ebp),%ecx
     7ca: 89 51 04 mov %edx,0x4(%ecx) <-- panic occurs here

The panic occurs when hci_usb_tx_complete() calls _urb_unlink() on an _urb which has been previously been removed from a list - basically _urb->list.prev and _urb->list.next are invalid pointers at this point and this causes a panic on the _urb_unlink().

It seems to me that the bug occurs because hci_usb_suspend() dequeues the _urb and then calls usb_kill_urb() - I believe it should put the _urb on the killed list first before killing the urb.

My testing confirms this fix works fine every time (and I've checked the _urb activity throughout the stack to verify that this is the root cause of the panic).

Attached - the patch