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