diff options
author | John Keeping <john@metanate.com> | 2017-11-27 13:15:40 -0500 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2017-11-28 06:05:31 -0500 |
commit | a3acc696085e112733d191a77b106e67a4fa110b (patch) | |
tree | 149aa791fe110d309dfcba8db474c2b74e0ed3ca | |
parent | a4f0927ef588cf62bb864707261482c874352942 (diff) |
usb: f_fs: Force Reserved1=1 in OS_DESC_EXT_COMPAT
The specification says that the Reserved1 field in OS_DESC_EXT_COMPAT
must have the value "1", but when this feature was first implemented we
rejected any non-zero values.
This was adjusted to accept all non-zero values (while now rejecting
zero) in commit 53642399aa71 ("usb: gadget: f_fs: Fix wrong check on
reserved1 of OS_DESC_EXT_COMPAT"), but that breaks any userspace
programs that worked previously by returning EINVAL when Reserved1 == 0
which was previously the only value that succeeded!
If we just set the field to "1" ourselves, both old and new userspace
programs continue to work correctly and, as a bonus, old programs are
now compliant with the specification without having to fix anything
themselves.
Fixes: 53642399aa71 ("usb: gadget: f_fs: Fix wrong check on reserved1 of OS_DESC_EXT_COMPAT")
Cc: <stable@vger.kernel.org>
Signed-off-by: John Keeping <john@metanate.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 9aa457b53e01..b6cf5ab5a0a1 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -2282,9 +2282,18 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, | |||
2282 | int i; | 2282 | int i; |
2283 | 2283 | ||
2284 | if (len < sizeof(*d) || | 2284 | if (len < sizeof(*d) || |
2285 | d->bFirstInterfaceNumber >= ffs->interfaces_count || | 2285 | d->bFirstInterfaceNumber >= ffs->interfaces_count) |
2286 | !d->Reserved1) | ||
2287 | return -EINVAL; | 2286 | return -EINVAL; |
2287 | if (d->Reserved1 != 1) { | ||
2288 | /* | ||
2289 | * According to the spec, Reserved1 must be set to 1 | ||
2290 | * but older kernels incorrectly rejected non-zero | ||
2291 | * values. We fix it here to avoid returning EINVAL | ||
2292 | * in response to values we used to accept. | ||
2293 | */ | ||
2294 | pr_debug("usb_ext_compat_desc::Reserved1 forced to 1\n"); | ||
2295 | d->Reserved1 = 1; | ||
2296 | } | ||
2288 | for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i) | 2297 | for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i) |
2289 | if (d->Reserved2[i]) | 2298 | if (d->Reserved2[i]) |
2290 | return -EINVAL; | 2299 | return -EINVAL; |