diff options
author | Adrian Dudau <adrian.dudau@enea.com> | 2015-11-02 10:57:44 +0100 |
---|---|---|
committer | Adrian Dudau <adrian.dudau@enea.com> | 2015-11-02 11:20:41 +0100 |
commit | a130fba56f34391c7e921b2e2fd2ba174002e6a5 (patch) | |
tree | 5f50afba2f2ff1f9f524e8cb7c24b90b8212cb77 /recipes-kernel/linux/files/HID_CVE_patches/0007-HID-LG-validate-HID-output-report-details.patch | |
download | meta-nfv-access-bsp-arm-a130fba56f34391c7e921b2e2fd2ba174002e6a5.tar.gz |
Initial commit
result of splitting up meta-enea
Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
Diffstat (limited to 'recipes-kernel/linux/files/HID_CVE_patches/0007-HID-LG-validate-HID-output-report-details.patch')
-rw-r--r-- | recipes-kernel/linux/files/HID_CVE_patches/0007-HID-LG-validate-HID-output-report-details.patch | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/recipes-kernel/linux/files/HID_CVE_patches/0007-HID-LG-validate-HID-output-report-details.patch b/recipes-kernel/linux/files/HID_CVE_patches/0007-HID-LG-validate-HID-output-report-details.patch new file mode 100644 index 0000000..9376c42 --- /dev/null +++ b/recipes-kernel/linux/files/HID_CVE_patches/0007-HID-LG-validate-HID-output-report-details.patch | |||
@@ -0,0 +1,195 @@ | |||
1 | From 0fb6bd06e06792469acc15bbe427361b56ada528 Mon Sep 17 00:00:00 2001 | ||
2 | From: Kees Cook <keescook@chromium.org> | ||
3 | Date: Wed, 11 Sep 2013 21:56:54 +0200 | ||
4 | Subject: [PATCH] HID: LG: validate HID output report details | ||
5 | |||
6 | A HID device could send a malicious output report that would cause the | ||
7 | lg, lg3, and lg4 HID drivers to write beyond the output report allocation | ||
8 | during an event, causing a heap overflow: | ||
9 | |||
10 | [ 325.245240] usb 1-1: New USB device found, idVendor=046d, idProduct=c287 | ||
11 | ... | ||
12 | [ 414.518960] BUG kmalloc-4096 (Not tainted): Redzone overwritten | ||
13 | |||
14 | Additionally, while lg2 did correctly validate the report details, it was | ||
15 | cleaned up and shortened. | ||
16 | |||
17 | CVE-2013-2893 | ||
18 | |||
19 | Signed-off-by: Kees Cook <keescook@chromium.org> | ||
20 | Cc: stable@vger.kernel.org | ||
21 | Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | ||
22 | Signed-off-by: Jiri Kosina <jkosina@suse.cz> | ||
23 | Signed-off-by: Adrian Dudau <adrian.dudau@enea.com> | ||
24 | --- | ||
25 | drivers/hid/hid-lg2ff.c | 19 +++---------------- | ||
26 | drivers/hid/hid-lg3ff.c | 29 ++++++----------------------- | ||
27 | drivers/hid/hid-lg4ff.c | 20 +------------------- | ||
28 | drivers/hid/hid-lgff.c | 17 ++--------------- | ||
29 | 4 files changed, 12 insertions(+), 73 deletions(-) | ||
30 | |||
31 | diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c | ||
32 | index b3cd150..1a42eaa 100644 | ||
33 | --- a/drivers/hid/hid-lg2ff.c | ||
34 | +++ b/drivers/hid/hid-lg2ff.c | ||
35 | @@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid) | ||
36 | struct hid_report *report; | ||
37 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
38 | struct hid_input, list); | ||
39 | - struct list_head *report_list = | ||
40 | - &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
41 | struct input_dev *dev = hidinput->input; | ||
42 | int error; | ||
43 | |||
44 | - if (list_empty(report_list)) { | ||
45 | - hid_err(hid, "no output report found\n"); | ||
46 | + /* Check that the report looks ok */ | ||
47 | + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); | ||
48 | + if (!report) | ||
49 | return -ENODEV; | ||
50 | - } | ||
51 | - | ||
52 | - report = list_entry(report_list->next, struct hid_report, list); | ||
53 | - | ||
54 | - if (report->maxfield < 1) { | ||
55 | - hid_err(hid, "output report is empty\n"); | ||
56 | - return -ENODEV; | ||
57 | - } | ||
58 | - if (report->field[0]->report_count < 7) { | ||
59 | - hid_err(hid, "not enough values in the field\n"); | ||
60 | - return -ENODEV; | ||
61 | - } | ||
62 | |||
63 | lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); | ||
64 | if (!lg2ff) | ||
65 | diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c | ||
66 | index e52f181..8c2da18 100644 | ||
67 | --- a/drivers/hid/hid-lg3ff.c | ||
68 | +++ b/drivers/hid/hid-lg3ff.c | ||
69 | @@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, | ||
70 | int x, y; | ||
71 | |||
72 | /* | ||
73 | - * Maxusage should always be 63 (maximum fields) | ||
74 | - * likely a better way to ensure this data is clean | ||
75 | + * Available values in the field should always be 63, but we only use up to | ||
76 | + * 35. Instead, clear the entire area, however big it is. | ||
77 | */ | ||
78 | - memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); | ||
79 | + memset(report->field[0]->value, 0, | ||
80 | + sizeof(__s32) * report->field[0]->report_count); | ||
81 | |||
82 | switch (effect->type) { | ||
83 | case FF_CONSTANT: | ||
84 | @@ -129,32 +130,14 @@ static const signed short ff3_joystick_ac[] = { | ||
85 | int lg3ff_init(struct hid_device *hid) | ||
86 | { | ||
87 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
88 | - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
89 | struct input_dev *dev = hidinput->input; | ||
90 | - struct hid_report *report; | ||
91 | - struct hid_field *field; | ||
92 | const signed short *ff_bits = ff3_joystick_ac; | ||
93 | int error; | ||
94 | int i; | ||
95 | |||
96 | - /* Find the report to use */ | ||
97 | - if (list_empty(report_list)) { | ||
98 | - hid_err(hid, "No output report found\n"); | ||
99 | - return -1; | ||
100 | - } | ||
101 | - | ||
102 | /* Check that the report looks ok */ | ||
103 | - report = list_entry(report_list->next, struct hid_report, list); | ||
104 | - if (!report) { | ||
105 | - hid_err(hid, "NULL output report\n"); | ||
106 | - return -1; | ||
107 | - } | ||
108 | - | ||
109 | - field = report->field[0]; | ||
110 | - if (!field) { | ||
111 | - hid_err(hid, "NULL field\n"); | ||
112 | - return -1; | ||
113 | - } | ||
114 | + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) | ||
115 | + return -ENODEV; | ||
116 | |||
117 | /* Assume single fixed device G940 */ | ||
118 | for (i = 0; ff_bits[i] >= 0; i++) | ||
119 | diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c | ||
120 | index 0ddae2a..8782fe1 100644 | ||
121 | --- a/drivers/hid/hid-lg4ff.c | ||
122 | +++ b/drivers/hid/hid-lg4ff.c | ||
123 | @@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde | ||
124 | int lg4ff_init(struct hid_device *hid) | ||
125 | { | ||
126 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
127 | - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
128 | struct input_dev *dev = hidinput->input; | ||
129 | - struct hid_report *report; | ||
130 | - struct hid_field *field; | ||
131 | struct lg4ff_device_entry *entry; | ||
132 | struct lg_drv_data *drv_data; | ||
133 | struct usb_device_descriptor *udesc; | ||
134 | int error, i, j; | ||
135 | __u16 bcdDevice, rev_maj, rev_min; | ||
136 | |||
137 | - /* Find the report to use */ | ||
138 | - if (list_empty(report_list)) { | ||
139 | - hid_err(hid, "No output report found\n"); | ||
140 | - return -1; | ||
141 | - } | ||
142 | - | ||
143 | /* Check that the report looks ok */ | ||
144 | - report = list_entry(report_list->next, struct hid_report, list); | ||
145 | - if (!report) { | ||
146 | - hid_err(hid, "NULL output report\n"); | ||
147 | + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) | ||
148 | return -1; | ||
149 | - } | ||
150 | - | ||
151 | - field = report->field[0]; | ||
152 | - if (!field) { | ||
153 | - hid_err(hid, "NULL field\n"); | ||
154 | - return -1; | ||
155 | - } | ||
156 | |||
157 | /* Check what wheel has been connected */ | ||
158 | for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { | ||
159 | diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c | ||
160 | index d7ea8c8..e1394af 100644 | ||
161 | --- a/drivers/hid/hid-lgff.c | ||
162 | +++ b/drivers/hid/hid-lgff.c | ||
163 | @@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) | ||
164 | int lgff_init(struct hid_device* hid) | ||
165 | { | ||
166 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
167 | - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
168 | struct input_dev *dev = hidinput->input; | ||
169 | - struct hid_report *report; | ||
170 | - struct hid_field *field; | ||
171 | const signed short *ff_bits = ff_joystick; | ||
172 | int error; | ||
173 | int i; | ||
174 | |||
175 | - /* Find the report to use */ | ||
176 | - if (list_empty(report_list)) { | ||
177 | - hid_err(hid, "No output report found\n"); | ||
178 | - return -1; | ||
179 | - } | ||
180 | - | ||
181 | /* Check that the report looks ok */ | ||
182 | - report = list_entry(report_list->next, struct hid_report, list); | ||
183 | - field = report->field[0]; | ||
184 | - if (!field) { | ||
185 | - hid_err(hid, "NULL field\n"); | ||
186 | - return -1; | ||
187 | - } | ||
188 | + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) | ||
189 | + return -ENODEV; | ||
190 | |||
191 | for (i = 0; i < ARRAY_SIZE(devices); i++) { | ||
192 | if (dev->id.vendor == devices[i].idVendor && | ||
193 | -- | ||
194 | 1.7.9.5 | ||
195 | |||