All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] Input: bcm5974 - check endpoint type before starting traffic
@ 2023-10-12 16:51 Javier Carrasco
  2023-10-14  3:03 ` Dmitry Torokhov
  0 siblings, 1 reply; 3+ messages in thread
From: Javier Carrasco @ 2023-10-12 16:51 UTC (permalink / raw)
  To: John Horan, Henrik Rydberg, Dmitry Torokhov
  Cc: linux-input, linux-kernel, Javier Carrasco, syzbot+348331f63b034f89b622

syzbot has found a type mismatch between a USB pipe and the transfer
endpoint, which is triggered by the bcm5974 driver[1].

This driver expects the device to provide input interrupt endpoints and
if that is not the case, the driver registration should terminate.

Repros are available to reproduce this issue with a certain setup for
the dummy_hcd, leading to an interrupt/bulk mismatch which is caught in
the USB core after calling usb_submit_urb() with the following message:
"BOGUS urb xfer, pipe 1 != type 3"

Some other device drivers (like the appletouch driver bcm5974 is mainly
based on) provide some checking mechanism to make sure that an IN
interrupt endpoint is available. In this particular case the endpoint
addresses are provided by a config table, so the checking can be
targeted to the provided endpoints.

Add some basic checking to guarantee that the endpoints available match
the expected type for both the trackpad and button endpoints.

This issue was only found for the trackpad endpoint, but the checking
has been added to the button endpoint as well for the same reasons.

Given that there was never a check for the endpoint type, this bug has
been there since the first implementation of the driver (f89bd95c5c94).

[1] https://syzkaller.appspot.com/bug?extid=348331f63b034f89b622

Fixes: f89bd95c5c94 ("Input: bcm5974 - add driver for Macbook Air and Pro Penryn touchpads")
Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
Reported-and-tested-by: syzbot+348331f63b034f89b622@syzkaller.appspotmail.com
---
Changes in v2:
- Keep error = -ENOMEM for the rest of the probe and return -ENODEV if
  the endpoint check fails.
- Check function returns now bool and was renamed (_is_ for
  bool-returning functions).
- Link to v1: https://lore.kernel.org/r/20231007-topic-bcm5974_bulk-v1-1-355be9f8ad80@gmail.com
---
 drivers/input/mouse/bcm5974.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index ca150618d32f..9fc9dd96c96a 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -891,6 +891,21 @@ static int bcm5974_resume(struct usb_interface *iface)
 	return error;
 }
 
+static bool bcm5974_ep_is_int_in(struct usb_host_interface *iface, int addr)
+{
+	struct usb_endpoint_descriptor *endpoint;
+	int i;
+
+	for (i = 0; i < iface->desc.bNumEndpoints; i++) {
+		endpoint = &iface->endpoint[i].desc;
+		if (endpoint->bEndpointAddress == addr) {
+			if (usb_endpoint_is_int_in(endpoint))
+				return true;
+		}
+	}
+	return false;
+}
+
 static int bcm5974_probe(struct usb_interface *iface,
 			 const struct usb_device_id *id)
 {
@@ -903,6 +918,18 @@ static int bcm5974_probe(struct usb_interface *iface,
 	/* find the product index */
 	cfg = bcm5974_get_config(udev);
 
+	if (cfg->tp_type == TYPE1) {
+		if (!bcm5974_ep_is_int_in(iface->cur_altsetting, cfg->bt_ep)) {
+			dev_err(&iface->dev, "No int-in endpoint for the button\n");
+			return -ENODEV;
+		}
+	}
+
+	if (!bcm5974_ep_is_int_in(iface->cur_altsetting, cfg->tp_ep)) {
+		dev_err(&iface->dev, "No int-in endpoint for the trackpad\n");
+		return -ENODEV;
+	}
+
 	/* allocate memory for our device state and initialize it */
 	dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL);
 	input_dev = input_allocate_device();

---
base-commit: 401644852d0b2a278811de38081be23f74b5bb04
change-id: 20231007-topic-bcm5974_bulk-c66b743ba7ba

Best regards,
-- 
Javier Carrasco <javier.carrasco.cruz@gmail.com>


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

* Re: [PATCH v2] Input: bcm5974 - check endpoint type before starting traffic
  2023-10-12 16:51 [PATCH v2] Input: bcm5974 - check endpoint type before starting traffic Javier Carrasco
@ 2023-10-14  3:03 ` Dmitry Torokhov
  2023-10-14  7:57   ` Javier Carrasco
  0 siblings, 1 reply; 3+ messages in thread
From: Dmitry Torokhov @ 2023-10-14  3:03 UTC (permalink / raw)
  To: Javier Carrasco
  Cc: John Horan, Henrik Rydberg, linux-input, linux-kernel,
	syzbot+348331f63b034f89b622

Hi Javier,

On Thu, Oct 12, 2023 at 06:51:49PM +0200, Javier Carrasco wrote:
>  
> +static bool bcm5974_ep_is_int_in(struct usb_host_interface *iface, int addr)
> +{
> +	struct usb_endpoint_descriptor *endpoint;
> +	int i;
> +
> +	for (i = 0; i < iface->desc.bNumEndpoints; i++) {
> +		endpoint = &iface->endpoint[i].desc;
> +		if (endpoint->bEndpointAddress == addr) {
> +			if (usb_endpoint_is_int_in(endpoint))
> +				return true;
> +		}
> +	}
> +	return false;
> +}

This essentially reimplements usb_find_endpoint() in a sense, so can we
instead do:

	ep = usb_find_endpoint(iface, addr);
	if (!ep || !usb_endpoint_is_int_in(ep)) {
		dev_err(...);
		return ...;
	}


Also it looks like the handling of button endpoint is interleaved with
the trackpad endpoint, I wonder if it would not be better if we have a
separate "if (cfg->tp_type == TYPE1)" where we would do the check,
allocate URB, and did all the rest of set up for button transfers.

Thanks.

-- 
Dmitry

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

* Re: [PATCH v2] Input: bcm5974 - check endpoint type before starting traffic
  2023-10-14  3:03 ` Dmitry Torokhov
@ 2023-10-14  7:57   ` Javier Carrasco
  0 siblings, 0 replies; 3+ messages in thread
From: Javier Carrasco @ 2023-10-14  7:57 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: John Horan, Henrik Rydberg, linux-input, linux-kernel,
	syzbot+348331f63b034f89b622

Hi Dmitry,

On 14.10.23 05:03, Dmitry Torokhov wrote:
> Hi Javier,
> 
> On Thu, Oct 12, 2023 at 06:51:49PM +0200, Javier Carrasco wrote:
>>  
>> +static bool bcm5974_ep_is_int_in(struct usb_host_interface *iface, int addr)
>> +{
>> +	struct usb_endpoint_descriptor *endpoint;
>> +	int i;
>> +
>> +	for (i = 0; i < iface->desc.bNumEndpoints; i++) {
>> +		endpoint = &iface->endpoint[i].desc;
>> +		if (endpoint->bEndpointAddress == addr) {
>> +			if (usb_endpoint_is_int_in(endpoint))
>> +				return true;
>> +		}
>> +	}
>> +	return false;
>> +}
> 
> This essentially reimplements usb_find_endpoint() in a sense, so can we
> instead do:
> 
> 	ep = usb_find_endpoint(iface, addr);
> 	if (!ep || !usb_endpoint_is_int_in(ep)) {
> 		dev_err(...);
> 		return ...;
> 	}
> 
Thanks for your feedback. usb_find_endpoint is a static function from
the usb core and in principle is not available here, but your code
snippet seems to reinterpret usb_check_int_endpoints() for a single
address. I would suggest using usb_check_int_endpoints and pass both
addresses at the same time (if both exist, of course).
> 
> Also it looks like the handling of button endpoint is interleaved with
> the trackpad endpoint, I wonder if it would not be better if we have a
> separate "if (cfg->tp_type == TYPE1)" where we would do the check,
> allocate URB, and did all the rest of set up for button transfers.
Using usb_check_int_endpoints would solve this immediately.
> 
> Thanks.
> 
Thanks and best regards,
Javier Carrasco

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

end of thread, other threads:[~2023-10-14  7:58 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-12 16:51 [PATCH v2] Input: bcm5974 - check endpoint type before starting traffic Javier Carrasco
2023-10-14  3:03 ` Dmitry Torokhov
2023-10-14  7:57   ` Javier Carrasco

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.