Skip to content

Commit 7c39f48

Browse files
ribaldaHans Verkuil
authored andcommitted
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 <[email protected]> Closes: https://lore.kernel.org/linux-media/abycbXzYupZpGkvR@hyeyoo/T/#t Tested-by: Marek Marczykowski-Górecki <[email protected]> Fixes: c824345 ("media: uvcvideo: Pass allocation size directly to uvc_alloc_urb_buffer") Signed-off-by: Ricardo Ribalda <[email protected]> Reviewed-by: Laurent Pinchart <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Laurent Pinchart <[email protected]> Signed-off-by: Hans Verkuil <[email protected]>
1 parent e8d97c2 commit 7c39f48

1 file changed

Lines changed: 5 additions & 4 deletions

File tree

drivers/media/usb/uvc/uvc_video.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,7 +1751,8 @@ static void uvc_video_complete(struct urb *urb)
17511751
/*
17521752
* Free transfer buffers.
17531753
*/
1754-
static void uvc_free_urb_buffers(struct uvc_streaming *stream)
1754+
static void uvc_free_urb_buffers(struct uvc_streaming *stream,
1755+
unsigned int size)
17551756
{
17561757
struct usb_device *udev = stream->dev->udev;
17571758
struct uvc_urb *uvc_urb;
@@ -1760,7 +1761,7 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream)
17601761
if (!uvc_urb->buffer)
17611762
continue;
17621763

1763-
usb_free_noncoherent(udev, stream->urb_size, uvc_urb->buffer,
1764+
usb_free_noncoherent(udev, size, uvc_urb->buffer,
17641765
uvc_stream_dir(stream), uvc_urb->sgt);
17651766
uvc_urb->buffer = NULL;
17661767
uvc_urb->sgt = NULL;
@@ -1820,7 +1821,7 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
18201821

18211822
if (!uvc_alloc_urb_buffer(stream, uvc_urb, urb_size,
18221823
gfp_flags)) {
1823-
uvc_free_urb_buffers(stream);
1824+
uvc_free_urb_buffers(stream, urb_size);
18241825
break;
18251826
}
18261827

@@ -1868,7 +1869,7 @@ static void uvc_video_stop_transfer(struct uvc_streaming *stream,
18681869
}
18691870

18701871
if (free_buffers)
1871-
uvc_free_urb_buffers(stream);
1872+
uvc_free_urb_buffers(stream, stream->urb_size);
18721873
}
18731874

18741875
/*

0 commit comments

Comments
 (0)