Thread (14 messages) 14 messages, 3 authors, 2021-05-26

Re: [PATCH v2] USB: core: WARN if pipe direction != setup packet direction

From: Johan Hovold <johan@kernel.org>
Date: 2021-05-26 07:49:17

On Tue, May 25, 2021 at 11:12:08AM -0400, Alan Stern wrote:
On Tue, May 25, 2021 at 02:40:17PM +0200, Johan Hovold wrote:
quoted
On Mon, May 24, 2021 at 10:47:36AM -0400, Alan Stern wrote:
quoted
Do you think the check should be weakened for this case (i.e., ignore 
the direction bit in bRequestType when wLength is 0)?  So far it seems 
that the number of places getting this wrong isn't prohibitively large.
In a sense the request-type direction bit is already ignored when
wLength is zero. The question is if we should ignore the direction bit
of the pipe argument, or rather allow it to be IN, when wLength is
zero.

With the above check now merged, the following transfer triggers the
warning:

	usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
			0, USB_DIR_IN | USB_TYPE_VENDOR,
			0x0020, CMD_I2C_DA_RD,
			NULL, 0, 1000);

This request was used by a media driver to determine if a certain i2c
register was accessible by attempting to read it without really caring
about its value.

I changed the above to actually read the value, but this is an example
where allowing usb_rcvctrlpipe() might otherwise make sense was it not
for the possibility that some HCD could get confused.

Changing the above to use usb_sndctrlpipe() while either keeping
USB_DIR_IN or dropping USB_DIR_IN (for an I2C read request) does not
seem right. The latter could potentially even confuse some firmware even
if the direction bit is supposed to be ignored.

So far this is the only example I've found where changing to
usb_sndctrlpipe() and USB_DIR_OUT isn't obviously correct, but on the
other hand just reading the register in question is straight-forward
enough and does not require any exceptions in usb_submit_urb().
Okay, yes.  This seems like a sufficiently unusual edge case that we 
don't need to add special code to cater for it.

In fact, the direction bit in the pipe for a control transfer is never 
exposed to the USB device.  All the device sees is bRequestType and the 
data/status packet tokens (IN or OUT), which are dictated by the USB 
protocol.  So the fact that we insist on usb_sndctrlpipe for what will 
ultimately become an I2C read request is unimportant.
Right, it just looks a bit weird to use usb_sndctrlpipe() with
USB_DIR_IN, but that should be fine especially as such cases appears to
be rare.
quoted
We could perhaps even go the other way and strengthen the check to warn
if USB_DIR_IN is set when wLength is zero...
Given that the spec says the direction bit is ignored when wLength is 
zero, I think we shouldn't do this.
I agree, let's just allow this.
quoted
quoted
PS: Another check we could add is to make sure that the 
transfer_buffer_length value agrees with wLength.  Should I add such a 
check?
That sounds sensible as some of the HCDs only appears to check
transfer_buffer_length when handling the data stage and a mismatch could
amount to undefined behaviour (OUT) or perhaps even buffer overruns
(IN).

Judging from a quick check we don't seem to have any such cases
currently so this could be implemented as a submission failure rather
than another warning.
All right; I'll make the submission fail with a -EBADR (invalid request 
descriptor) error; that seems like a good choice of an obscure and 
otherwise unused value to match this case.  But I'll put in a debugging 
message, so that anyone who wants to know if this is occurring will have 
a way to find out.
Sounds good.

Johan
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help