On Mon, 30 Nov 2015, Vladis Dronov wrote: > Hello, Alan, all. Hello. > > > Yes for the normal USB device. This case is a weird USB device (with no > > > endpoints) specially designed to be weird. My point here is that even a > > > weird device probing should not crash a kernel by a NULL-deref. > > > > True. However, a weird device that didn't have any endpoint 0 would > > not crash the kernel, because the kernel wouldn't be able to > > communicate with it at all. > > I'm afraid, I do not get you here. A device in question _does_ crash the kernel > (or driver only) as this call trace shows (see attached for the full call trace), > and that's why the patch is proposed: > > [ 622.444650] BUG: unable to handle kernel NULL pointer dereference at 0000000000000002 > [ 622.445019] IP: [<ffffffffa0395303>] aiptek_probe+0x463/0x658 [aiptek] > [ 622.445019] RIP: 0010:[<ffffffffa0395303>] aiptek_probe+0x463/0x658 [aiptek] > [ 622.445019] RAX: 0000000000000000 RBX: ffff88000bd67800 RCX: ffff88000bcd0800 > ^^^ rax is NULL, it is being dereferenced This is the result of a bug in the aiptek driver. See below. > Kernel does not communicates with the device, Yes it does. Otherwise how would the kernel know that the aiptek driver was the one which should be probed for this device? > but the driver tries to access > a kernel structure, which was not allocated (thus, a null-deref): > > endpoint = &intf->altsetting[0].endpoint[0].desc; // the structure endpoint[0] > // was not kzalloc()ed, thus NULL > usb_rcvintpipe(aiptek->usbdev, endpoint->bEndpointAddress) // NULL deref Right. That's the bug; aiptek should not try to access a data structure that was never allocated. > > Drivers do not have to check whether endpoint 0 exists; it always does. > > But they do have to check any other endpoint they use. > > As the above example shows, endpoint 0 does not always exists. A specially > crafted weird USB device can advertise absence of endpoint 0 and the kernel > will accept this: The example above has nothing to do with endpoint 0. The entries in the altsetting[n].endpoint array are not stored in numerical order; entry 0 in this array does not refer to endpoint 0. (See the comment for the endpoint field in the definition of struct usb_host_interface in include/linux/usb.h.) In fact, endpoint 0 is treated specially and isn't part of this array at all. > [drivers/usb/core/config.c] > num_ep = num_ep_orig = alt->desc.bNumEndpoints; // weird device can have 0 here > alt->desc.bNumEndpoints = 0; > if (num_ep > 0) { > /* Can't allocate 0 bytes */ > len = sizeof(struct usb_host_endpoint) * num_ep; > alt->endpoint = kzalloc(len, GFP_KERNEL); > > As far as I understand, this is a question we discuss here: whose responsibility > is to handle situations of endpoint 0 absence in an altconfig? num_ep counts the number of endpoints _other_ than endpoint 0. There's no point counting endpoint 0 because it is always present. Not to mention that it doesn't get stored in this array, since endpoint 0 has no descriptor. > - if it is driver's job, a driver much check this, as in the patch I propose > > - if it is a kernel job not to allow devices with no endpoint 0 in one the > configurations, the current USB device detection implementation (in > drivers/usb/core/config.c) should be modified, as currently it allows such. > > I do not have much expertise in the Linux USB stack, so I'm asking you and > the community for an advise on this. My advice is to fix aiptek's probe routine. It should check that intf->altsetting[0].desc.bNumEndpoints > 0 before trying to accessing the endpoint array. > > > btw, indeed, this is not the only driver with this problem, I've met 2 more. > > > > In fact, there's no way to check whether endpoint 0 exists. Where > > would you look to find out? There isn't any endpoint descriptor for it. > > I believe, there is a configuration descriptor for that, probably, I'm wrong: > > if (intf->altsetting[0].desc.bNumEndpoints < 1) { ... That value is the number of endpoints _other_ than endpoint 0. This is documented in the USB-2.0 specification, Table 9-12. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html