diff options
author | Kees Cook <keescook@chromium.org> | 2014-04-17 13:22:09 -0700 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-05-20 16:39:00 +0200 |
commit | 1b15d2e5b8077670b1e6a33250a0d9577efff4a5 (patch) | |
tree | ce5ca1f217c59a604ea6378afc68710d65c4f5de /drivers/hid/hid-core.c | |
parent | 825747bb85634a2a7b7dce4e373831e211ab1644 (diff) | |
download | lwn-1b15d2e5b8077670b1e6a33250a0d9577efff4a5.tar.gz lwn-1b15d2e5b8077670b1e6a33250a0d9577efff4a5.zip |
HID: core: fix validation of report id 0
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), */
...
Cc: stable@vger.kernel.org
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>
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r-- | drivers/hid/hid-core.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index da52279de939..a5c7927c9bd2 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -842,7 +842,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; |