[PATCH] usb/core/devio.c: Don't reject control message to endpoint with wrong direction bit

2013-09-24 Thread Kurt Garloff
Hi,

this has been discussed on linux-usb and Alan Stern provided very
helpful feedback.

Please merge this patch ...


From: Kurt Garloff 
Date: Mon, 23 Sep 2013 14:19:02 +0200
Subject: Tolerate wrong direction bit in endpoint address for control messages

Trying to read data from the Pegasus Technologies NoteTaker (0e20:0101)
[1] with the Windows App (EasyNote) works natively but fails when
Windows is running under KVM (and the USB device handed to KVM).

The reason is a USB control message
 usb 4-2.2: control urb: bRequestType=22 bRequest=09 wValue=0200 wIndex=0001 
wLength=0008
This goes to endpoint address 0x01 (wIndex); however, endpoint address 
0x01 does not exist. There is an endpoint 0x81 though (same number,
but other direction); the app may have meant that endpoint instead.
 
The kernel thus rejects the IO and thus we see the failure.

Apparently, Linux is more strict here than Windows ... we can't change
the Win app easily, so that's a problem.

It seems that the Win app/driver is buggy here and the driver does not
behave fully according to the USB HID class spec that it claims to 
belong to.  The device seems to happily deal with that though (and 
seems to not really care about this value much).

So the question is whether the Linux kernel should filter here.
Rejecting has the risk that somewhat non-compliant userspace apps/
drivers (most likely in a virtual machine) are prevented from working.
Not rejecting has the risk of confusing an overly sensitive device with
such a transfer. Given the fact that Windows does not filter it makes
this risk rather small though.

The patch makes the kernel more tolerant: If the endpoint address in
wIndex does not exist, but an endpoint with toggled direction bit does,
it will let the transfer through. (It does NOT change the message.)

With attached patch, the app in Windows in KVM works.
 usb 4-2.2: check_ctrlrecip: process 13073 (qemu-kvm) requesting ep 01 but 
needs 81

I suspect this will mostly affect apps in virtual environments; as on
Linux the apps would have been adapted to the stricter handling of the
kernel. I have done that for mine[2].
 
[1] http://www.pegatech.com/
[2] https://sourceforge.net/projects/notetakerpen/

Signed-off-by: Kurt Garloff 
Acked-by: Alan Stern 
Cc: sta...@vger.kernel.org
---
 drivers/usb/core/devio.c |   16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 737e3c1..71dc5d7 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -742,6 +742,22 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned 
int requesttype,
if ((index & ~USB_DIR_IN) == 0)
return 0;
ret = findintfep(ps->dev, index);
+   if (ret < 0) {
+   /*
+* Some not fully compliant Win apps seem to get
+* index wrong and have the endpoint number here
+* rather than the endpoint address (with the
+* correct direction). Win does let this through,
+* so we'll not reject it here but leave it to
+* the device to not break KVM. But we warn.
+*/
+   ret = findintfep(ps->dev, index ^ 0x80);
+   if (ret >= 0)
+   dev_info(&ps->dev->dev,
+   "%s: process %i (%s) requesting ep %02x 
but needs %02x\n",
+   __func__, task_pid_nr(current),
+   current->comm, index, index ^ 0x80);
+   }
if (ret >= 0)
    ret = checkintf(ps, ret);
break;


-- 
Kurt Garloff   [Koeln, Germany]

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] usb/core/devio.c:tolerate wrong direction flag in control endpoints

2013-09-23 Thread Kurt Garloff
Hi Alan,



Alan Stern  schrieb:
> On Mon, 23 Sep 2013, Kurt Garloff wrote:
> 
> > >> that qualifies as a bug or not. Maybe it should not claim to be a
> > >> HID device then?
> > > Maybe not.  This particular combination of bRequestType and
> bRequest 
> > > values (0x22, 0x09) is not defined in the HID 1.11 spec.  Do you
> know 
> > > if it is defined somewhere else?
> > These are custom commands, somewhat described at
> >
> http://pegatech.com/_Uploads/Downloads/Documents/Protocol_Definition_Rev_1.12.pdf
> 
> That document describes a UART protocol with no mention of USB at all.

Yep, probably they just took the serial protocol to USB... 
Beyond the spec,  I did watch the Win app a bit when implementing [2] ...

> > With behavior here I referred to the fact that I have not yet seen a
> USB
> > device that
> > has two endpoints with the same endpoint number (but different direction).
> 
> I have.  They aren't very common but they do exist.
> 
> > Let me try inline insert (by c'n'p: I switched from mutt to Thunderbird
> > recently and lack
> > experience whether this breaks formatting or so ...)
> 
> It did mangle the whitespace characters. 

Cr*p.

> That doesn't matter for 
> reviewing, but it is important when you submit the patch.  Take a look
> 
> at Documentation/email-clients.txt for some suggestions.

I'll go back to mutt then, I guess - used it for >10 years... 

> > 8<
> > 
> > From: Kurt Garloff 
> > Date: Mon, 23 Sep 2013 14:19:02 +0200
> > Subject: Tolerate wrong direction bit in endpoint address for control
> > messages
> >
> > Trying to read data from the Pegasus Technologies NoteTaker (0e20:0101)
> > [1] with the Windows App (EasyNote) works natively but fails when
> > Windows is running under KVM (and the USB device handed to KVM).
> >
> > The reason is a USB control message
> >  usb 4-2.2: control urb: bRequestType=22 bRequest=09 wValue=0200
> > wIndex=0001 wLength=0008
> > This goes to endpoint address 0x01 (wIndex); however, endpoint number 1
> > is an input endpoint and thus has endpoint address 0x81.
> 
> You should say something like:
> 
>   however, endpoint 0x01 doesn't exist.  There is an endpoint
>   0x81, though; perhaps the app meant that endpoint instead.

OK. 

> > The kernel thus rejects the IO and thus we see the failure.
> >
> > Apparently, Linux is more strict here than Windows ... we can't change
> > the Win app easily, so that's a problem.
> > 
> > It seems that the Win app/driver is buggy here and the driver does not
> > behave fully according to the USB HID class that it claims to belong to.
> > The device seems to happily deal with that though (and seems to not
> > really care about this value much).
> > 
> > So the question is whether the Linux kernel should filter here.
> > Rejecting has the risk that somewhat non-compliant userspace apps/
> > drivers (most likely in a virtual machine) are prevented from
> working.
> > Not rejecting has the risk of confusing an overly sensitive device with
> > such a transfer. Given the fact that Windows does not filter it makes
> > this risk rather small though.
> > 
> > The patch makes the kernel more tolerant: If the endpoint address in
> > wIndex does not exist, but an endpoint with toggled direction bit does,
> > it will let the transfer through. (It does NOT change the message.)
> > 
> > With attached patch, the app in Windows in KVM works.
> >  usb 4-2.2: check_ctrlrecip: process 13073 (qemu-kvm) requesting ep
> 01
> > but needs 81 (or 00)
> 
> You need to remove the "(or 00)" here.

Good catch! I changed the code but not the log... 

> > I suspect this will mostly affect apps in virtual environments; as on
> > Linux the apps would have been adapted to the stricter handling of the
> > kernel. I have done that for mine[2].
> >  
> > [1] http://www.pegatech.com/
> > [2] https://sourceforge.net/projects/notetakerpen/
> > 
> > Signed-off-by: Kurt Garloff 
> > Cc: sta...@vger.kernel.or
> 
> Fix the spelling (.org).

The second time in two days, my fingers are getting too slow... 

> > ---
> >  drivers/usb/core/devio.c |   16 
> >  1 file changed, 16 insertions(+)
> > 
> > diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
> > index 737e3c1..4ff61f9 100644
> > --- a/drivers/usb/core/devio.c
> > +++ b/drivers/usb/core/devio.c
> > @@ -742,6 +742,22 @@ static int check_ctrlrecip(struct dev_state *

Re: [PATCH] usb/core/devio.c:tolerate wrong direction flag in control endpoints

2013-09-23 Thread Kurt Garloff
Hi Alan,

On 09/23/2013 04:28 AM, Alan Stern wrote:
> On Sun, 22 Sep 2013, Kurt Garloff wrote:
>
>> Well, this seems to be a question of terminology, no?
>> I saw the endpoint byte as consisting of endpoint index plus the direction 
>> bit.
> See the entry for "Endpoint Address" in Chapter 2 (Terms and 
> Abbreviations) of the USB 2.0 specification.  The definition says:
>
>   The combination of an endpoint number and an endpoint direction
>   on a USB device. Each endpoint address supports data transfer
>   in one direction.

OK. This definitely helps me to use the correct terminology.
>> OK, you certainly know the USB specs better than I do.
>>
>> If the message is not according to spec because the windex byte (which
>> should reference the endpoint) has the endpoint direction flag wrong,
>> then the question may become whether the kernel should reject it or
>> leave that to the device.
>> Rejecting by the kernel has the risk that somewhat non-compliant devices
>> with somewhat non-compliant (userspace) drivers are prevented from working.
>> While not rejecting has the risk that overly sensitive devices might freak 
>> out
>> on receiving a non-compliant transfer. The fact that Win does not not seem to
>> filter here however might make that risk rather small.
>> (Long years have taught us that companies don't test against the spec but 
>> this
>>  "OS" from Redmond.)
> This is a good explanation of why the patch should be accepted.
OK, I added it into the patch header.
>> It seems to interpret wIndex differently indeed. Not sure whether
>> that qualifies as a bug or not. Maybe it should not claim to be a
>> HID device then?
> Maybe not.  This particular combination of bRequestType and bRequest 
> values (0x22, 0x09) is not defined in the HID 1.11 spec.  Do you know 
> if it is defined somewhere else?
These are custom commands, somewhat described at
http://pegatech.com/_Uploads/Downloads/Documents/Protocol_Definition_Rev_1.12.pdf
>> Hmmm, none of the devices I have show this.
>> My impression was that the EP byte is composed of 
>>   ep = epindex | (dir==in? 0x80: 0)
>> and that index alone must be unique already. But then again, I'm in no
>> way an expert in USB specs and may just have jumped to conclusions
>> from the wording.
> The spec is pretty clear about this.  For example, it says that in
> addition to endpoint 0, a device can have up to 15 input endpoints and 
> up to 15 output endpoints (section 5.3.1.2).
>
>> (And again the behavior might not be enforced by the spec, but maybe
>> by Windows?)
> More likely the behavior isn't enforced at all.  The device may simply 
> be buggy.
With behavior here I referred to the fact that I have not yet seen a USB
device that
has two endpoints with the same endpoint number (but different direction).
Anyway, that's not relevant to the patch ... We don't change the value of
wIndex, we just decide to let the transfer through and let the device
deal with it.
>> Based on the observation that uurb.endpoint = 0 (see above), I have
>> changed my code in the Linux program (at [2]) to use 0x00 as wIndex 
>> instead of 0x81 (or formerly 0x01). It still worked.
>> So it's questionable, whether wIndex should even point to an EP ...
>> and the hardware might just ignore it.
> It looks that way.  The request claims to be class-specific, so it 
> would be nice to know which class document defines the request's 
> format.
I guess none ...
I just dropped the (or 00), as it's not reflected in the code ...
>> Thanks for the review! I will submit a new patch.
> Good.

Find it here.
(Let me know if it should be sent again separately for some reason.)

Let me try inline insert (by c'n'p: I switched from mutt to Thunderbird
recently and lack
experience whether this breaks formatting or so ...)

8<

From: Kurt Garloff 
Date: Mon, 23 Sep 2013 14:19:02 +0200
Subject: Tolerate wrong direction bit in endpoint address for control
messages
   
Trying to read data from the Pegasus Technologies NoteTaker (0e20:0101)
[1] with the Windows App (EasyNote) works natively but fails when
Windows is running under KVM (and the USB device handed to KVM).
   
The reason is a USB control message
 usb 4-2.2: control urb: bRequestType=22 bRequest=09 wValue=0200
wIndex=0001 wLength=0008
This goes to endpoint address 0x01 (wIndex); however, endpoint number 1
is an input endpoint and thus has endpoint address 0x81.
   
The kernel thus rejects the IO and thus we see the failure.
   
Apparently, Linux is more strict here than Windows ... we can't change
the Win app easily, so that's a problem.

It seems that the Win app/driver is buggy he

Re: [PATCH] usb/core/devio.c:tolerate wrong direction flag in control endpoints

2013-09-22 Thread Kurt Garloff
Hi Alan,

thanks for your review and your constructive comments!



Alan Stern  schrieb:
>On Sun, 22 Sep 2013, Kurt Garloff wrote:
>
>> Hi,
>> 
>> USB devio rejects control messages when the index does not have the
>> direction bit set correctly.
>
>I wouldn't describe it that way.  It would be more accurate to say that
>the message is rejected when wIndex contains an invalid endpoint
>address.

Well, this seems to be a question of terminology, no?
I saw the endpoint byte as consisting of endpoint index plus the direction bit.

>> This breaks windows apps in KVM -- and might be overly strict
>according
>> to my reading of USB HID spec.
>
>It is not overly strict.

OK, you certainly know the USB specs better than I do.

If the message is not according to spec because the windex byte (which
should reference the endpoint) has the endpoint direction flag wrong,
then the question may become whether the kernel should reject it or
leave that to the device.
Rejecting by the kernel has the risk that somewhat non-compliant devices
with somewhat non-compliant (userspace) drivers are prevented from working.
While not rejecting has the risk that overly sensitive devices might freak out
on receiving a non-compliant transfer. The fact that Win does not not seem to
filter here however might make that risk rather small.
(Long years have taught us that companies don't test against the spec but this
 "OS" from Redmond.)

>> Attached patch makes the kernel tolerant against it and makes the app
>> work for me.
>> 
>> More details in the patch header.
>> 
>> USB experts: Please review this and judge whether this is correct,
>> applies more generically,
>> or maybe needs to be special cased (only for USB HID devices?) or
>> implemented as quirk
>> or module/kernel parameter.
>
>The patch seems reasonable enough, although the description needs 
>improvement and a couple of minor things should be fixed.  More 
>comments below.
>
>In the future, please put patches inline with the rest of the email
>message.  Don't make them attachments unless you have to; that way they
>become harder to read and comment on.

Seems I have not sent a patch for too long, so I failed to remember this
longstanding rule when sending. Sorry for this!

>> Once in the final form, this *might* be stable material.
>
>Yes, it should be.
>
>> commit bc1e4e1ae1d5a4f9b2d263f22c651dd5ba4f8ff9
>> Author: Kurt Garloff 
>> Date:   Sun Sep 22 11:54:59 2013 +0200
>> 
>> From: Kurt Garloff 
>> Subject: Tolerate wrong direction bit endpoint index for control messages
>> Signed-off-by: Kurt Garloff 
>> 
>> Trying to read data from the Pegasus Technologies NoteTaker (0e20:0101)
>> [1] with the Windows App (EasyNote) works natively but fails when
>> WIndows is running under KVM (and the USB device handed to KVM).
>> 
>> The reason is a USB control message
>>  usb 4-2.2: control urb: bRequestType=22 bRequest=09 wValue=0200 
>> wIndex=0001 wLength=0008
>> This goes to endpoint 1 (wIndex), however, the endpoint is an input
>> endpoint and thus enumerated 0x81.
>> 
>> The kernel thus rejects the IO and thus we see the failure.
>> 
>> Apparently, Linux is more strict here than Windows ... we can't change
>> the Win app easily, so that's a problem.
>
>Indeed, this indicates that the device itself is also buggy.  If it 
>worked correctly, it would reject the incorrect control message.

It seems to interpret wIndex differently indeed. Not sure whether
that qualifies as a bug or not. Maybe it should not claim to be a
HID device then?
Looking at the code, it seems that printers do something strange
here, and it might be that the device in question here is not 100%
HID in that it also assumes a non-standard meaning to this byte.

Strange enough, the app does want to talk to the control interface it seems:
Sep 19 09:47:21 nehalem kernel: [44539.730269] usb 4-2.2: usbdev_do_ioctl: 
SUBMITURB
Sep 19 09:47:21 nehalem kernel: [44539.730276] usb 4-2.2: proc_submiturb: URB 
02 00 0  01a83420 16 0
Sep 19 09:47:21 nehalem kernel: [44539.730280] usb 4-2.2: control urb: 
bRequestType=22 bRequest=09 wValue=0200 wIndex=0001 wLength=0008
Sep 19 09:47:21 nehalem kernel: [44539.730285] usb 4-2.2: check_ctrlrecip: 
process 13073 (qemu-kvm) requesting ep 01 but needs 81 (or 00)
Sep 19 09:47:21 nehalem kernel: [44539.730290] usb 4-2.2: userurb 
01b56f00, ep0 ctrl-out, length 8
Sep 19 09:47:21 nehalem kernel: [44539.730294] data: 02 01 b5 00 00 00 00 00
  
Sep 19 09:47:21 nehalem ker

[PATCH] usb/core/devio.c:tolerate wrong direction flag in control endpoints

2013-09-22 Thread Kurt Garloff
Hi,

USB devio rejects control messages when the index does not have the
direction bit set correctly.
This breaks windows apps in KVM -- and might be overly strict according
to my reading of USB HID spec.
Attached patch makes the kernel tolerant against it and makes the app
work for me.

More details in the patch header.

USB experts: Please review this and judge whether this is correct,
applies more generically,
or maybe needs to be special cased (only for USB HID devices?) or
implemented as quirk
or module/kernel parameter.

Once in the final form, this *might* be stable material.

Please keep me in copy for the discussion, my participation on LKML is
mostly reading summaries
from Jonathan and Thorsten these days, unfortunately.

-- 
Kurt Garloff 
Cologne, Germany

commit bc1e4e1ae1d5a4f9b2d263f22c651dd5ba4f8ff9
Author: Kurt Garloff 
Date:   Sun Sep 22 11:54:59 2013 +0200

From: Kurt Garloff 
Subject: Tolerate wrong direction bit endpoint index for control messages
Signed-off-by: Kurt Garloff 

Trying to read data from the Pegasus Technologies NoteTaker (0e20:0101)
[1] with the Windows App (EasyNote) works natively but fails when
WIndows is running under KVM (and the USB device handed to KVM).

The reason is a USB control message
 usb 4-2.2: control urb: bRequestType=22 bRequest=09 wValue=0200 wIndex=0001 wLength=0008
This goes to endpoint 1 (wIndex), however, the endpoint is an input
endpoint and thus enumerated 0x81.

The kernel thus rejects the IO and thus we see the failure.

Apparently, Linux is more strict here than Windows ... we can't change
the Win app easily, so that's a problem.

However, the app might not even be buggy here.  Browsing the USB HID
spec, there's a note that the bit for direction is ignored for control
endpoints ... so Linux might be overly strict?

With attached patch, everything works.
 usb 4-2.2: check_ctrlrecip: process 13073 (qemu-kvm) requesting ep 01 but needs 81 (or 00)

Notes:
- I have not checked whether the ignorance of the direction bit for
  control endpoints only applies to USB HID devices, thus I have not
  special-cased depending on the device type.
- We do output a warning into the kernel log, as this might still be
  caused by an application error.
- We don't risk sending to a wrong endpoint, as there can't be two
  endpoints with same index and just different direction.
- I suspect this will mostly affect apps in virtual environments; as on
  Linux the apps would have been adapted to the stricter handling of the
  kernel. I have done that for mine[2], although delaying the release by
  two years 

[1} http://www.pegatech.com/
[2] https://sourceforge.net/projects/notetakerpen/

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index c2f62a3..8acbc2f 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -623,6 +623,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
 	switch (requesttype & USB_RECIP_MASK) {
 	case USB_RECIP_ENDPOINT:
 		ret = findintfep(ps->dev, index);
+		if (ret < 0) {
+			/* OK, give it a second try -- user might have confused
+			 * direction -- this happens from virtualized win apps 
+			 * e.g. -- warn, but be graceful */
+			ret = findintfep(ps->dev, index ^ 0x80);
+			if (ret >= 0)
+dev_info(&ps->dev->dev , 
+	"%s: process %i (%s) requesting ep %02x but needs %02x (or 00)\n",
+	__func__, 
+	task_pid_nr(current),
+	current->comm,
+   	index, index ^ 0x80);
+		}
 		if (ret >= 0)
 			ret = checkintf(ps, ret);
 		break;