Linux Media Controller development
 help / color / mirror / Atom feed
* [PATCH] media: gspca: fix stack overrun in build_isoc_ep_tb()
@ 2026-09-28 11:07 pwngets
  2026-11-13  8:28 ` Hans Verkuil
  0 siblings, 1 reply; 2+ messages in thread
From: pwngets @ 2026-09-28 11:07 UTC (permalink / raw)
  To: hverkuil; +Cc: linux-media, pwngets

build_isoc_ep_tb() fills the ep_tb[] table that gspca_init_transfer()
declares as "struct ep_tb_s ep_tb[MAX_ALT]".  The bandwidth sentinel is
stored at the top of the loop, i.e. before the "found" test that decides
whether the pass produced a usable entry:

	for (;;) {
		ep_tb->bandwidth = 2000 * 2000 * 120;
		found = 0;
		for (j = 0; j < nbalt; j++) {
			...
		}
		if (!found)
			break;
		last_bw = ep_tb->bandwidth;
		i++;
		ep_tb++;
	}

Every pass that does not break raises last_bw, and the candidates are
the bandwidths of the nbalt altsettings, so at most MAX_ALT passes fill
an entry.  The pass that ends the loop has already written
ep_tb[MAX_ALT].bandwidth by then -- one element past the end of the
array.

A device that presents MAX_ALT (16) alternate settings carrying
isochronous IN endpoints with pairwise distinct, increasing bandwidths
reaches that pass with nbalt == MAX_ALT.  On x86-64 the store is 4
bytes at ep_tb + 132, which is the upper half of the stack canary, so
kernels built with CONFIG_STACKPROTECTOR_STRONG (the default on the
major distributions) panic in __stack_chk_fail() when
gspca_init_transfer() returns.

Only the device descriptors are needed: the store happens while
VIDIOC_STREAMON is being handled, before any isochronous transfer takes
place.

Give the table room for the terminating entry as well.

Assisted-by: Claude Code
---
 drivers/media/usb/gspca/gspca.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index 594d73e..64bb818 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -753,7 +753,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
 	struct usb_interface *intf;
 	struct usb_host_endpoint *ep;
 	struct urb *urb;
-	struct ep_tb_s ep_tb[MAX_ALT];
+	struct ep_tb_s ep_tb[MAX_ALT + 1];
 	int n, ret, xfer, alt, alt_idx;
 
 	/* reset the streaming variables */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] media: gspca: fix stack overrun in build_isoc_ep_tb()
  2026-09-28 11:07 [PATCH] media: gspca: fix stack overrun in build_isoc_ep_tb() pwngets
@ 2026-11-13  8:28 ` Hans Verkuil
  0 siblings, 0 replies; 2+ messages in thread
From: Hans Verkuil @ 2026-11-13  8:28 UTC (permalink / raw)
  To: pwngets, hverkuil; +Cc: linux-media

On 28/09/2026 13:07, pwngets wrote:
> build_isoc_ep_tb() fills the ep_tb[] table that gspca_init_transfer()
> declares as "struct ep_tb_s ep_tb[MAX_ALT]".  The bandwidth sentinel is
> stored at the top of the loop, i.e. before the "found" test that decides
> whether the pass produced a usable entry:
> 
> 	for (;;) {
> 		ep_tb->bandwidth = 2000 * 2000 * 120;
> 		found = 0;
> 		for (j = 0; j < nbalt; j++) {
> 			...
> 		}
> 		if (!found)
> 			break;
> 		last_bw = ep_tb->bandwidth;
> 		i++;
> 		ep_tb++;
> 	}
> 
> Every pass that does not break raises last_bw, and the candidates are
> the bandwidths of the nbalt altsettings, so at most MAX_ALT passes fill
> an entry.  The pass that ends the loop has already written
> ep_tb[MAX_ALT].bandwidth by then -- one element past the end of the
> array.
> 
> A device that presents MAX_ALT (16) alternate settings carrying
> isochronous IN endpoints with pairwise distinct, increasing bandwidths
> reaches that pass with nbalt == MAX_ALT.  On x86-64 the store is 4
> bytes at ep_tb + 132, which is the upper half of the stack canary, so
> kernels built with CONFIG_STACKPROTECTOR_STRONG (the default on the
> major distributions) panic in __stack_chk_fail() when
> gspca_init_transfer() returns.
> 
> Only the device descriptors are needed: the store happens while
> VIDIOC_STREAMON is being handled, before any isochronous transfer takes
> place.
> 
> Give the table room for the terminating entry as well.
> 
> Assisted-by: Claude Code

No Signed-off-by and incomprehensible AI prose.

Rejected.

Regards,

	Hans

> ---
>  drivers/media/usb/gspca/gspca.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
> index 594d73e..64bb818 100644
> --- a/drivers/media/usb/gspca/gspca.c
> +++ b/drivers/media/usb/gspca/gspca.c
> @@ -753,7 +753,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
>  	struct usb_interface *intf;
>  	struct usb_host_endpoint *ep;
>  	struct urb *urb;
> -	struct ep_tb_s ep_tb[MAX_ALT];
> +	struct ep_tb_s ep_tb[MAX_ALT + 1];
>  	int n, ret, xfer, alt, alt_idx;
>  
>  	/* reset the streaming variables */


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-13  8:28 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-28 11:07 [PATCH] media: gspca: fix stack overrun in build_isoc_ep_tb() pwngets
2026-11-13  8:28 ` Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox