summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2014-04-17 13:22:09 -0700
committerBen Hutchings <ben@decadent.org.uk>2014-07-11 13:33:35 +0100
commit40b81e0d1a79c4770cc353bea225668a74e1493f (patch)
treeffc23c0b15ef9000da01c8ef9ef5adc652f742e6 /drivers/hid
parent164b63e6a46aae261210faf970f6f04cf512adf5 (diff)
HID: core: fix validation of report id 0
commit 1b15d2e5b8077670b1e6a33250a0d9577efff4a5 upstream. Some drivers use the first HID report in the list instead of using an index. In these cases, validation uses ID 0, which was supposed to mean "first known report". This fixes the problem, which was causing at least the lgff family of devices to stop working since hid_validate_values was being called with ID 0, but the devices used single numbered IDs for their reports: 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x05, /* Usage (Gamepad), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0x01, /* Report ID (1), */ ... Reported-by: Simon Wood <simon@mungewell.org> Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-core.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9ac4389ecfa2..64d79d2a0318 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -754,7 +754,17 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
* ->numbered being checked, which may not always be the case when
* drivers go to access report values.
*/
- report = hid->report_enum[type].report_id_hash[id];
+ if (id == 0) {
+ /*
+ * Validating on id 0 means we should examine the first
+ * report in the list.
+ */
+ report = list_entry(
+ hid->report_enum[type].report_list.next,
+ struct hid_report, list);
+ } else {
+ report = hid->report_enum[type].report_id_hash[id];
+ }
if (!report) {
hid_err(hid, "missing %s %u\n", hid_report_names[type], id);
return NULL;