Re: [PATCH RFC v2] usb: gadget: uvc: check endpoint enabled state in uvcg_video_enable()
Aleksandr Nogikh <[email protected]>
| Newsgroups | dev.linux.lists.syzbot |
|---|---|
| Message-ID | <CANp29Y5fCex2aQqPZyr7UKvPR-F+S1pccsK-yYa4epPqTkDQyw@mail.gmail.com> |
On Wed, Aug 12, 2026 at 3:28 PM syzbot <[email protected]> wrote: > > A NULL pointer dereference can occur in uvc_video_prep_requests() if > userspace issues a VIDIOC_STREAMON ioctl before the USB host has fully > configured the streaming endpoint. > > When userspace calls VIDIOC_STREAMON, the driver handles it in > uvc_v4l2_streamon(), which in turn calls uvcg_video_enable(). Currently, > uvcg_video_enable() only checks if the endpoint pointer is allocated > (video->ep == NULL), but it fails to check if the endpoint is actually > enabled (video->ep->enabled). > > The endpoint descriptor (video->ep->desc) is only assigned when the USB > host explicitly selects the streaming alternate setting via a SET_INTERFACE > control request. If userspace prematurely calls VIDIOC_STREAMON before the > host has selected the streaming alternate setting, video->ep->desc will > still be NULL. > > Because uvcg_video_enable() does not verify the endpoint's enabled state, > it proceeds to call uvc_video_alloc_requests() and then > uvc_video_prep_requests(). Inside uvc_video_prep_requests(), the code > unconditionally dereferences video->ep->desc, resulting in a KASAN > null-ptr-deref / general protection fault: > > Oops: general protection fault, probably for non-canonical address > 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI > KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] > RIP: 0010:usb_endpoint_xfer_isoc include/uapi/linux/usb/ch9.h:571 [inline] > RIP: 0010:uvc_video_prep_requests > drivers/usb/gadget/function/uvc_video.c:508 [inline] > RIP: 0010:uvc_video_alloc_requests > drivers/usb/gadget/function/uvc_video.c:559 [inline] > RIP: 0010:uvcg_video_enable+0x142/0xe70 > drivers/usb/gadget/function/uvc_video.c:784 > Call Trace: > <TASK> > uvc_v4l2_streamon+0x7e/0x110 drivers/usb/gadget/function/uvc_v4l2.c:531 > __video_do_ioctl+0x8af/0xc70 drivers/media/v4l2-core/v4l2-ioctl.c:3133 > video_usercopy+0x860/0x1430 drivers/media/v4l2-core/v4l2-ioctl.c:3475 > v4l2_ioctl+0x18d/0x1e0 drivers/media/v4l2-core/v4l2-dev.c:366 > vfs_ioctl fs/ioctl.c:51 [inline] > __do_sys_ioctl fs/ioctl.c:597 [inline] > __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583 > > To fix this, update uvcg_video_enable() to also verify that the endpoint is > enabled (!video->ep->enabled). This ensures that if userspace prematurely > calls VIDIOC_STREAMON, the driver will safely reject the request with > -ENODEV instead of crashing the kernel. > > Fixes: 48dbe731171e ("usb: gadget: uvc: set req_size and n_requests based on the frame interval") > Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot > Reported-by: [email protected] > Closes: https://syzkaller.appspot.com/bug?extid=44835f0858f11e3e923c > Link: https://syzkaller.appspot.com/ai_job?id=e3902952-fe28-4ca4-a910-c485a9927925 > To: "Greg Kroah-Hartman" <[email protected]> > To: <[email protected]> > To: "Michael Grzeschik" <[email protected]> > Cc: "Frank Li" <[email protected]> > Cc: "Jimmy Hu" <[email protected]> > Cc: "Hans Verkuil" <[email protected]> > Cc: "Kees Cook" <[email protected]> > Cc: "Laurent Pinchart" <[email protected]> > Cc: <[email protected]> > Cc: "Muhammad Bilal" <[email protected]> > Cc: "Junzhong Pan" <[email protected]> > Cc: "Xu Yang" <[email protected]> > > --- > v2: > - Check that uvc->state is UVC_STATE_CONNECTED in uvc_v4l2_streamon() before allowing streaming. > - Update uvc->state to UVC_STATE_STREAMING before calling uvcg_video_enable(), and revert it on failure. > - Check video->ep->desc in addition to video->ep->enabled in uvcg_video_enable(). > - Add safety checks for video->ep, video->ep->enabled, and video->ep->desc in uvc_video_alloc_requests(). > > v1: > https://lore.kernel.org/all/[email protected]/T/ > --- > diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c > index dfa0521a2..a80663c9a 100644 > --- a/drivers/usb/gadget/function/uvc_v4l2.c > +++ b/drivers/usb/gadget/function/uvc_v4l2.c > @@ -527,17 +527,24 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) > if (type != video->queue.queue.type) > return -EINVAL; > > + if (uvc->state != UVC_STATE_CONNECTED) > + return -ENODEV; > + > + uvc->state = UVC_STATE_STREAMING; > + > /* Enable UVC video. */ > ret = uvcg_video_enable(video); > - if (ret < 0) > + if (ret < 0) { > + if (uvc->state == UVC_STATE_STREAMING) > + uvc->state = UVC_STATE_CONNECTED; > return ret; > + } > > /* > * Complete the alternate setting selection setup phase now that > * userspace is ready to provide video frames. > */ > uvc_function_setup_continue(uvc, 0); > - uvc->state = UVC_STATE_STREAMING; Instead of all that changes, would just this suffice (at the right place)? if (uvc->state != UVC_STATE_CONNECTED) return -ENODEV; > > return 0; > } > diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c > index 2f9700b3f..bd67a9d80 100644 > --- a/drivers/usb/gadget/function/uvc_video.c > +++ b/drivers/usb/gadget/function/uvc_video.c > @@ -551,6 +551,9 @@ uvc_video_alloc_requests(struct uvc_video *video) > unsigned int i; > int ret = -ENOMEM; > > + if (video->ep == NULL || !video->ep->enabled || !video->ep->desc) > + return -ENODEV; > + > /* > * calculate in uvc_video_prep_requests > * - video->uvc_num_requests > @@ -764,7 +767,7 @@ int uvcg_video_enable(struct uvc_video *video) > { > int ret; > > - if (video->ep == NULL) { > + if (video->ep == NULL || !video->ep->enabled || !video->ep->desc) { > uvcg_info(&video->uvc->func, > "Video enable failed, device is uninitialized.\n"); > return -ENODEV; > > > base-commit: db2ddb87143519e20a95aa36c60b36107b736a58 > -- > This is an AI-generated patch subject to moderation. > Reply with '#syz upstream' to Sign-off the patch as a human author > and send it to the upstream kernel mailing lists. > Reply with '#syz reject' to reject it ('#syz unreject' to undo). > > See https://goo.gle/syzbot-ai-patches for information about AI-generated patches. > You can comment on the patch as usual, syzbot will try to address > the comments and send a new version of the patch if necessary. > syzbot engineers can be reached at [email protected].