| From: Johan Hovold <johan@kernel.org> |
| Date: Fri, 3 Jan 2020 17:35:10 +0100 |
| Subject: media: stv06xx: add missing descriptor sanity checks |
| |
| commit 485b06aadb933190f4bc44e006076bc27a23f205 upstream. |
| |
| Make sure to check that we have two alternate settings and at least one |
| endpoint before accessing the second altsetting structure and |
| dereferencing the endpoint arrays. |
| |
| This specifically avoids dereferencing NULL-pointers or corrupting |
| memory when a device does not have the expected descriptors. |
| |
| Note that the sanity checks in stv06xx_start() and pb0100_start() are |
| not redundant as the driver is mixing looking up altsettings by index |
| and by number, which may not coincide. |
| |
| Fixes: 8668d504d72c ("V4L/DVB (12082): gspca_stv06xx: Add support for st6422 bridge and sensor") |
| Fixes: c0b33bdc5b8d ("[media] gspca-stv06xx: support bandwidth changing") |
| Cc: Hans de Goede <hdegoede@redhat.com> |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/media/usb/gspca/stv06xx/stv06xx.c | 19 ++++++++++++++++++- |
| .../media/usb/gspca/stv06xx/stv06xx_pb0100.c | 4 ++++ |
| 2 files changed, 22 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/media/usb/gspca/stv06xx/stv06xx.c |
| +++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c |
| @@ -293,6 +293,9 @@ static int stv06xx_start(struct gspca_de |
| return -EIO; |
| } |
| |
| + if (alt->desc.bNumEndpoints < 1) |
| + return -ENODEV; |
| + |
| packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); |
| err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); |
| if (err < 0) |
| @@ -317,11 +320,21 @@ out: |
| |
| static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) |
| { |
| + struct usb_interface_cache *intfc; |
| struct usb_host_interface *alt; |
| struct sd *sd = (struct sd *) gspca_dev; |
| |
| + intfc = gspca_dev->dev->actconfig->intf_cache[0]; |
| + |
| + if (intfc->num_altsetting < 2) |
| + return -ENODEV; |
| + |
| + alt = &intfc->altsetting[1]; |
| + |
| + if (alt->desc.bNumEndpoints < 1) |
| + return -ENODEV; |
| + |
| /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ |
| - alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; |
| alt->endpoint[0].desc.wMaxPacketSize = |
| cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); |
| |
| @@ -334,6 +347,10 @@ static int stv06xx_isoc_nego(struct gspc |
| struct usb_host_interface *alt; |
| struct sd *sd = (struct sd *) gspca_dev; |
| |
| + /* |
| + * Existence of altsetting and endpoint was verified in |
| + * stv06xx_isoc_init() |
| + */ |
| alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; |
| packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); |
| min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; |
| --- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c |
| +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c |
| @@ -198,6 +198,10 @@ static int pb0100_start(struct sd *sd) |
| alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); |
| if (!alt) |
| return -ENODEV; |
| + |
| + if (alt->desc.bNumEndpoints < 1) |
| + return -ENODEV; |
| + |
| packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); |
| |
| /* If we don't have enough bandwidth use a lower framerate */ |