]>
Commit | Line | Data |
---|---|---|
01e02d84 GKH |
1 | From 1b15d2e5b8077670b1e6a33250a0d9577efff4a5 Mon Sep 17 00:00:00 2001 |
2 | From: Kees Cook <keescook@chromium.org> | |
3 | Date: Thu, 17 Apr 2014 13:22:09 -0700 | |
4 | Subject: HID: core: fix validation of report id 0 | |
5 | ||
6 | From: Kees Cook <keescook@chromium.org> | |
7 | ||
8 | commit 1b15d2e5b8077670b1e6a33250a0d9577efff4a5 upstream. | |
9 | ||
10 | Some drivers use the first HID report in the list instead of using an | |
11 | index. In these cases, validation uses ID 0, which was supposed to mean | |
12 | "first known report". This fixes the problem, which was causing at least | |
13 | the lgff family of devices to stop working since hid_validate_values | |
14 | was being called with ID 0, but the devices used single numbered IDs | |
15 | for their reports: | |
16 | ||
17 | 0x05, 0x01, /* Usage Page (Desktop), */ | |
18 | 0x09, 0x05, /* Usage (Gamepad), */ | |
19 | 0xA1, 0x01, /* Collection (Application), */ | |
20 | 0xA1, 0x02, /* Collection (Logical), */ | |
21 | 0x85, 0x01, /* Report ID (1), */ | |
22 | ... | |
23 | ||
24 | Reported-by: Simon Wood <simon@mungewell.org> | |
25 | Signed-off-by: Kees Cook <keescook@chromium.org> | |
26 | Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | |
27 | Signed-off-by: Jiri Kosina <jkosina@suse.cz> | |
28 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
29 | ||
30 | --- | |
31 | drivers/hid/hid-core.c | 12 +++++++++++- | |
32 | 1 file changed, 11 insertions(+), 1 deletion(-) | |
33 | ||
34 | --- a/drivers/hid/hid-core.c | |
35 | +++ b/drivers/hid/hid-core.c | |
36 | @@ -861,7 +861,17 @@ struct hid_report *hid_validate_values(s | |
37 | * ->numbered being checked, which may not always be the case when | |
38 | * drivers go to access report values. | |
39 | */ | |
40 | - report = hid->report_enum[type].report_id_hash[id]; | |
41 | + if (id == 0) { | |
42 | + /* | |
43 | + * Validating on id 0 means we should examine the first | |
44 | + * report in the list. | |
45 | + */ | |
46 | + report = list_entry( | |
47 | + hid->report_enum[type].report_list.next, | |
48 | + struct hid_report, list); | |
49 | + } else { | |
50 | + report = hid->report_enum[type].report_id_hash[id]; | |
51 | + } | |
52 | if (!report) { | |
53 | hid_err(hid, "missing %s %u\n", hid_report_names[type], id); | |
54 | return NULL; |