media: uvcvideo: Fix bug in error path of uvc_alloc_urb_buffers
Recent cleanup introduced a bug in the error path of
uvc_alloc_urb_buffers(). If there is not enough memory for the
allocation the following error will be triggered:
[ 739.196672] UBSAN: shift-out-of-bounds in mm/page_alloc.c:1403:22
[ 739.196710] shift exponent 52 is too large for 32-bit type 'int'
Resulting in:
[ 740.464422] BUG: unable to handle page fault for address: fffffac1c0800000
The reason for the bug is that usb_free_noncoherent is called with an
invalid size (0) instead of the actual size of the urb.
This patch takes care of that.
Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Closes: https://lore.kernel.org/linux-media/abycbXzYupZpGkvR@hyeyoo/T/#t
Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Fixes: c824345288 ("media: uvcvideo: Pass allocation size directly to uvc_alloc_urb_buffer")
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patch.msgid.link/20260320-uvc-urb-free-error-v1-1-b12cc3762a19@chromium.org
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
parent
e8d97c270c
commit
7c39f48568
|
|
@ -1751,7 +1751,8 @@ static void uvc_video_complete(struct urb *urb)
|
|||
/*
|
||||
* Free transfer buffers.
|
||||
*/
|
||||
static void uvc_free_urb_buffers(struct uvc_streaming *stream)
|
||||
static void uvc_free_urb_buffers(struct uvc_streaming *stream,
|
||||
unsigned int size)
|
||||
{
|
||||
struct usb_device *udev = stream->dev->udev;
|
||||
struct uvc_urb *uvc_urb;
|
||||
|
|
@ -1760,7 +1761,7 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream)
|
|||
if (!uvc_urb->buffer)
|
||||
continue;
|
||||
|
||||
usb_free_noncoherent(udev, stream->urb_size, uvc_urb->buffer,
|
||||
usb_free_noncoherent(udev, size, uvc_urb->buffer,
|
||||
uvc_stream_dir(stream), uvc_urb->sgt);
|
||||
uvc_urb->buffer = NULL;
|
||||
uvc_urb->sgt = NULL;
|
||||
|
|
@ -1820,7 +1821,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
|
|||
|
||||
if (!uvc_alloc_urb_buffer(stream, uvc_urb, urb_size,
|
||||
gfp_flags)) {
|
||||
uvc_free_urb_buffers(stream);
|
||||
uvc_free_urb_buffers(stream, urb_size);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1868,7 +1869,7 @@ static void uvc_video_stop_transfer(struct uvc_streaming *stream,
|
|||
}
|
||||
|
||||
if (free_buffers)
|
||||
uvc_free_urb_buffers(stream);
|
||||
uvc_free_urb_buffers(stream, stream->urb_size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue