1*4882a593SmuzhiyunFrom 623e2a995d156e115c91f56a3ec691bdc333df8b Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Chris Dickens <christopher.a.dickens@gmail.com> 3*4882a593SmuzhiyunDate: Sun, 13 Dec 2020 15:49:19 -0800 4*4882a593SmuzhiyunSubject: [PATCH 1/1] linux_usbfs: Fix parsing of descriptors for 5*4882a593Smuzhiyun multi-configuration devices 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunCommit e2be556bd2 ("linux_usbfs: Parse config descriptors during device 8*4882a593Smuzhiyuninitialization") introduced a regression for devices with multiple 9*4882a593Smuzhiyunconfigurations. The logic that verifies the reported length of the 10*4882a593Smuzhiyunconfiguration descriptors failed to count the length of the 11*4882a593Smuzhiyunconfiguration descriptor itself and would truncate the actual length by 12*4882a593Smuzhiyun9 bytes, leading to a parsing error for subsequent descriptors. 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunCloses #825 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunSigned-off-by: Chris Dickens <christopher.a.dickens@gmail.com> 17*4882a593Smuzhiyun(cherry picked from commit f6d2cb561402c3b6d3627c0eb89e009b503d9067) 18*4882a593SmuzhiyunSigned-off-by: John Keeping <john@metanate.com> 19*4882a593Smuzhiyun--- 20*4882a593Smuzhiyun libusb/os/linux_usbfs.c | 12 ++++++++---- 21*4882a593Smuzhiyun 1 file changed, 8 insertions(+), 4 deletions(-) 22*4882a593Smuzhiyun 23*4882a593Smuzhiyundiff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c 24*4882a593Smuzhiyunindex fb2ed53..4d2dc8d 100644 25*4882a593Smuzhiyun--- a/libusb/os/linux_usbfs.c 26*4882a593Smuzhiyun+++ b/libusb/os/linux_usbfs.c 27*4882a593Smuzhiyun@@ -641,7 +641,12 @@ static int seek_to_next_config(struct libusb_context *ctx, 28*4882a593Smuzhiyun uint8_t *buffer, size_t len) 29*4882a593Smuzhiyun { 30*4882a593Smuzhiyun struct usbi_descriptor_header *header; 31*4882a593Smuzhiyun- int offset = 0; 32*4882a593Smuzhiyun+ int offset; 33*4882a593Smuzhiyun+ 34*4882a593Smuzhiyun+ /* Start seeking past the config descriptor */ 35*4882a593Smuzhiyun+ offset = LIBUSB_DT_CONFIG_SIZE; 36*4882a593Smuzhiyun+ buffer += LIBUSB_DT_CONFIG_SIZE; 37*4882a593Smuzhiyun+ len -= LIBUSB_DT_CONFIG_SIZE; 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun while (len > 0) { 40*4882a593Smuzhiyun if (len < 2) { 41*4882a593Smuzhiyun@@ -718,7 +723,7 @@ static int parse_config_descriptors(struct libusb_device *dev) 42*4882a593Smuzhiyun } 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun if (priv->sysfs_dir) { 45*4882a593Smuzhiyun- /* 46*4882a593Smuzhiyun+ /* 47*4882a593Smuzhiyun * In sysfs wTotalLength is ignored, instead the kernel returns a 48*4882a593Smuzhiyun * config descriptor with verified bLength fields, with descriptors 49*4882a593Smuzhiyun * with an invalid bLength removed. 50*4882a593Smuzhiyun@@ -727,8 +732,7 @@ static int parse_config_descriptors(struct libusb_device *dev) 51*4882a593Smuzhiyun int offset; 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun if (num_configs > 1 && idx < num_configs - 1) { 54*4882a593Smuzhiyun- offset = seek_to_next_config(ctx, buffer + LIBUSB_DT_CONFIG_SIZE, 55*4882a593Smuzhiyun- remaining - LIBUSB_DT_CONFIG_SIZE); 56*4882a593Smuzhiyun+ offset = seek_to_next_config(ctx, buffer, remaining); 57*4882a593Smuzhiyun if (offset < 0) 58*4882a593Smuzhiyun return offset; 59*4882a593Smuzhiyun sysfs_config_len = (uint16_t)offset; 60*4882a593Smuzhiyun-- 61*4882a593Smuzhiyun2.30.1 62*4882a593Smuzhiyun 63