New: nullpointer dereference in uvc_video_stop_streaming
https://bugzilla.kernel.org/show_bug.cgi?id=207871
Bug ID: 207871
Summary: nullpointer dereference in uvc_video_stop_streaming
Product: Drivers
Version: 2.5
Kernel Version: 5.4.26
Hardware: x86-64
OS: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: USB
Assignee: [email protected]
Reporter: [email protected]
Regression: Nonullpointer dereference in V4L2CaptureThread when in-use USB3 uvcvideo device drops of the bus:
[5473614.803782] usb 4-4.4: New USB device strings: Mfr=6, Product=7, SerialNumber=3 [5473614.803784] usb 4-4.4: Product: HDMI to U3 capture [5473614.803785] usb 4-4.4: Manufacturer: Video Grabber [5473614.803787] usb 4-4.4: SerialNumber: 20000130041415 [5473614.804178] uvcvideo: Found UVC 1.00 device HDMI to U3 capture (1e4e:701f) [5473614.818515] uvcvideo: UVC non compliance - GET_DEF(PROBE) not supported. Enabling workaround. [5473614.818716] uvcvideo 4-4.4:1.0: Entity type for entity Extension 4 was not initialized! [5473614.818718] uvcvideo 4-4.4:1.0: Entity type for entity Processing 3 was not initialized! [5473614.818720] uvcvideo 4-4.4:1.0: Entity type for entity Camera 1 was not initialized! [5473614.869980] systemd-udevd[16462]: Process '/usr/sbin/alsactl -E
HOME=/run/alsa restore 3' failed with exit code 99.
[5473633.057731] usb 4-4.4: reset SuperSpeed Gen 1 USB device number 58 using xhci_hcd [5473635.636401] usb 4-4.4: USB disconnect, device number 58 [5473635.642127] BUG: kernel NULL pointer dereference, address: 0000000000000000 [5473635.642132] #PF: supervisor read access in kernel mode [5473635.642133] #PF: error_code(0x0000) - not-present page [5473635.642135] PGD 0 P4D 0 [5473635.642139] Oops: 0000 [#1] SMP [5473635.642142] CPU: 0 PID: 16509 Comm: V4L2CaptureThre Not tainted 5.4.26 #2 [5473635.642144] Hardware name: Gigabyte Technology Co., Ltd. AB350M-D3H/AB350M-D3H-CF, BIOS F31 05/06/2019 [5473635.642151] RIP: 0010:usb_ifnum_to_if+0x21/0x37 [5473635.642153] Code: ff ff 5b 5d 41 5c 41 5d c3 48 8b 87 98 03 00 00 48 85 c0 74 2a 0f b6 78 04 31 d2 39 d7 7e 1d 48 8b 8c d0 98 00 00 00 48 ff c2 <4c> 8b 01 45 0f b6 40 02 41 39 f0 75 e4 48 89 c8 eb 03 31 c0 c3 c3 [5473635.642155] RSP: 0018:ffffa140c109fb98 EFLAGS: 00010202 [5473635.642157] RAX: ffff89f4e64d2c00 RBX: ffff89f60d4b1000 RCX: 0000000000000000 [5473635.642159] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 0000000000000004 [5473635.642160] RBP: ffff89f5b095fa88 R08: 00000000ffffffed R09: 0000000000000001 [5473635.642162] R10: 000000000000000b R11: 0045e025810cb2e0 R12: 0000000000000000 [5473635.642163] R13: ffff89f5b095fa88 R14: ffff89f5b095fad8 R15: ffff89f3d2f60000 [5473635.642165] FS: 00007f9a5c6ce700(0000) GS:ffff89f61ee00000(0000) knlGS:0000000000000000 [5473635.642167] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [5473635.642168] CR2: 0000000000000000 CR3: 00000003c193f000 CR4: 00000000003406f0 [5473635.642170] Call Trace: [5473635.642175] usb_hcd_alloc_bandwidth+0x1e8/0x2d9 [5473635.642179] usb_set_interface+0x1b4/0x290 [5473635.642187] uvc_video_stop_streaming+0x2f/0x75 [uvcvideo] [5473635.642192] uvc_stop_streaming+0x17/0x43 [uvcvideo] [5473635.642196] __vb2_queue_cancel+0x6c/0x2fd [videobuf2_common] [5473635.642201] vb2_core_streamoff+0x2b/0x73 [videobuf2_common] [5473635.642205] uvc_queue_streamoff+0x25/0x39 [uvcvideo] [5473635.642209] uvc_ioctl_streamoff+0x38/0x47 [uvcvideo] [5473635.642213] __video_do_ioctl+0x279/0x3c1 [5473635.642219] ? _raw_spin_unlock_irqrestore+0xd/0xe [5473635.642222] ? try_to_wake_up+0x290/0x363 [5473635.642225] video_usercopy+0x28b/0x46d [5473635.642227] ? v4l_g_ctrl+0x11f/0x11f [5473635.642230] ? vtime_delta.isra.10+0x9/0x1e [5473635.642233] v4l2_ioctl+0x42/0x48 [5473635.642236] vfs_ioctl+0x19/0x26 [5473635.642238] do_vfs_ioctl+0x526/0x54e [5473635.642241] ? finish_task_switch+0x1d4/0x218 [5473635.642245] ? timekeeping_get_ns+0x19/0x2c [5473635.642248] ? paravirt_sched_clock+0x5/0x8 [5473635.642250] ksys_ioctl+0x39/0x58 [5473635.642252] __x64_sys_ioctl+0x11/0x14 [5473635.642255] do_syscall_64+0x83/0x91 [5473635.642258] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [5473635.642261] RIP: 0033:0x7f9a614a5427 [5473635.642264] Code: 00 00 90 48 8b 05 69 aa 0c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 39 aa 0c 00 f7 d8 64 89 01 48 [5473635.642265] RSP: 002b:00007f9a5c6cd258 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [5473635.642268] RAX: ffffffffffffffda RBX: 00002059db1a35f0 RCX: 00007f9a614a5427 [5473635.642269] RDX: 00007f9a5c6cd2ac RSI: 0000000040045613 RDI: 0000000000000017 [5473635.642270] RBP: 00007f9a5c6cd2f0 R08: 0000000000000000 R09: 00007f9a5c6cd3d8 [5473635.642272] R10: 00007ffeaab6e090 R11: 0000000000000246 R12: 00002059db230158 [5473635.642273] R13: 00002059db230000 R14: 00002059db230000 R15: 00007f9a5c6cd2ac [5473635.642275] Modules linked in: cfg80211 snd_usb_audio bnep bluetooth uvcvideo videobuf2_vmalloc videobuf2_memops snd_usbmidi_lib videobuf2_v4l2 snd_rawmidi videobuf2_common [last unloaded: snd_usb_audio] [5473635.642282] CR2: 0000000000000000 [5473635.642284] ---[ end trace cbc4d60c1db09b1c ]--- [5473635.642287] RIP: 0010:usb_ifnum_to_if+0x21/0x37 [5473635.642289] Code: ff ff 5b 5d 41 5c 41 5d c3 48 8b 87 98 03 00 00 48 85 c0 74 2a 0f b6 78 04 31 d2 39 d7 7e 1d 48 8b 8c d0 98 00 00 00 48 ff c2 <4c> 8b 01 45 0f b6 40 02 41 39 f0 75 e4 48 89 c8 eb 03 31 c0 c3 c3 [5473635.642291] RSP: 0018:ffffa140c109fb98 EFLAGS: 00010202 [5473635.642292] RAX: ffff89f4e64d2c00 RBX: ffff89f60d4b1000 RCX: 0000000000000000 [5473635.642293] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 0000000000000004 [5473635.642295] RBP: ffff89f5b095fa88 R08: 00000000ffffffed R09: 0000000000000001 [5473635.642296] R10: 000000000000000b R11: 0045e025810cb2e0 R12: 0000000000000000 [5473635.642297] R13: ffff89f5b095fa88 R14: ffff89f5b095fad8 R15: ffff89f3d2f60000 [5473635.642299] FS: 00007f9a5c6ce700(0000) GS:ffff89f61ee00000(0000) knlGS:0000000000000000 [5473635.642300] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [5473635.642302] CR2: 0000000000000000 CR3: 00000003c193f000 CR4: 00000000003406f0 [5473635.700061] show_signal_msg: 3729 callbacks suppressed [5473635.700065] chrome[16497]: segfault at 0 ip 000056399a1110f4 sp 00007ffeaaa675c0 error 4 in chrome[563997639000+7349000] [5473635.700080] Code: 48 89 de 31 d2 4c 89 f1 e8 b9 20 fa ff eb 07 48 8b 1d b0
fd 10 05 48 89 df 5b 41 5e 5d e9 64 2e 00 00 cc cc cc cc 55 48 89 e5 <48> 8b 0f 4c 8b 47 08 4c 89 c0 48 29 c8 74 41 48 c1 f8 03 48 bf ab
Signature · 2 lines
You are receiving this mail because: You are watching the assignee of the bug.
[Bug 207871] nullpointer dereference in uvc_video_stop_streaming
https://bugzilla.kernel.org/show_bug.cgi?id=207871
--- Comment #2 from Tobias Diedrich ([email protected]) --- Interestingly, usb_set_interface() already calls usb_ifnum_to_if() once, which did not fail. Then after calling usb_disable_interface() it calls usb_hcd_alloc_bandwidth(), which does another call to usb_ifnum_to_if(), which faulted with the null deref.
The fault is at:
mov rax, [rdx + 0x398]
test rax, rax
jz early_exit_since_config_is_null
[...]
mov rcx, [rax + rdx*8 + 0x98]
inc rdx-> mov r8, [rcx]
movzx r8d, byte ptr [r8 + 2]
[...]
So I think the fault is at
[...]
for (i = 0; i < config->desc.bNumInterfaces; i++)
-> if (config->interface[i]->altsetting[0].desc.bInterfaceNumber == ifnum)
^^^^^^^^^^^^nullptr
return config->interface[i];[...]
usb_set_interface() only checks for dev->state == USB_STATE_SUSPENDED, maybe it also needs to check for dev->state == USB_STATE_NOTATTACHED?
The disconnect message indicates this would have been the state the device was in, from usb_disconnect():
[...]
usb_set_device_state(udev, USB_STATE_NOTATTACHED); dev_info(&udev->dev, "USB disconnect, device number %d\n", udev->devnum); [...]
Signature · 2 lines
You are receiving this mail because: You are watching the assignee of the bug.
[Bug 207871] nullpointer dereference in uvc_video_stop_streaming
In reply to [email protected]https://bugzilla.kernel.org/show_bug.cgi?id=207871
--- Comment #3 from Alan Stern ([email protected]) --- The problem is not that usb_set_interface() does inadequate checking; the problem is that the uvc_video driver calls usb_set_interface() at an inappropriate time -- i.e., after its remove routine has returned.
(I don't know this for certain, but it seems likely given the context of the bug.)
Signature · 2 lines
You are receiving this mail because: You are watching the assignee of the bug.
[Bug 207871] nullpointer dereference in uvc_video_stop_streaming
In reply to [email protected]https://bugzilla.kernel.org/show_bug.cgi?id=207871
--- Comment #4 from Tobias Diedrich ([email protected]) --- I'm guessing that's the device disconnect callback?
static void uvc_disconnect(struct usb_interface *intf)
{
struct uvc_device *dev = usb_get_intfdata(intf);
/* Set the USB interface data to NULL. This can be done outside the
* lock, as there's no other reader.
*/
usb_set_intfdata(intf, NULL);
if (intf->cur_altsetting->desc.bInterfaceSubClass ==
UVC_SC_VIDEOSTREAMING)
return;
uvc_unregister_video(dev);
kref_put(&dev->ref, uvc_delete);
}Meanwhile uvc_stop_streaming is a vb2_ops (videobuf2) callback from the V4L2CaptureThread.
I'm guessing then that uvc_disconnect() should wait for videobufs to be stopped before returning?
Signature · 2 lines
You are receiving this mail because: You are watching the assignee of the bug.
[Bug 207871] nullpointer dereference in uvc_video_stop_streaming
In reply to [email protected]https://bugzilla.kernel.org/show_bug.cgi?id=207871
Alan Stern ([email protected]) changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |[email protected]
--- Comment #5 from Alan Stern ([email protected]) --- Yes. I'm not familiar with this driver, but it looks like uvc_unregister_video() (or one of the routines it calls) is supposed to do the waiting.
Signature · 2 lines
You are receiving this mail because: You are watching the assignee of the bug.