aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-17 21:54:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-17 21:54:05 -0400
commit84fca9f38c5d646e95cdeef70e41cf15db549b95 (patch)
treec904715c9b70a2f0716c84931e2d58b1a226a1e0
parent03e1261778cca782d41a3d8e3945ca88cf93e01e (diff)
parent0ccdd9e7476680c16113131264ad6597bd10299d (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: "Fixes for CVE-2013-2897, CVE-2013-2895, CVE-2013-2897, CVE-2013-2894, CVE-2013-2893, CVE-2013-2891, CVE-2013-2890, CVE-2013-2889. All the bugs are triggerable only by specially crafted evil-on-purpose HW devices. Fixes by Kees Cook and Benjamin Tissoires" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: HID: lenovo-tpkbd: fix leak if tpkbd_probe_tp fails HID: multitouch: validate indexes details HID: logitech-dj: validate output report details HID: validate feature and input report details HID: lenovo-tpkbd: validate output report details HID: LG: validate HID output report details HID: steelseries: validate output report details HID: sony: validate HID output report details HID: zeroplus: validate output report details HID: provide a helper for validating hid reports
-rw-r--r--drivers/hid/hid-core.c74
-rw-r--r--drivers/hid/hid-input.c11
-rw-r--r--drivers/hid/hid-lenovo-tpkbd.c25
-rw-r--r--drivers/hid/hid-lg2ff.c19
-rw-r--r--drivers/hid/hid-lg3ff.c29
-rw-r--r--drivers/hid/hid-lg4ff.c20
-rw-r--r--drivers/hid/hid-lgff.c17
-rw-r--r--drivers/hid/hid-logitech-dj.c10
-rw-r--r--drivers/hid/hid-multitouch.c26
-rw-r--r--drivers/hid/hid-sony.c4
-rw-r--r--drivers/hid/hid-steelseries.c5
-rw-r--r--drivers/hid/hid-zpff.c18
-rw-r--r--include/linux/hid.h4
13 files changed, 146 insertions, 116 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index ae88a97f976e..b8470b1a10fe 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -94,7 +94,6 @@ EXPORT_SYMBOL_GPL(hid_register_report);
94static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) 94static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
95{ 95{
96 struct hid_field *field; 96 struct hid_field *field;
97 int i;
98 97
99 if (report->maxfield == HID_MAX_FIELDS) { 98 if (report->maxfield == HID_MAX_FIELDS) {
100 hid_err(report->device, "too many fields in report\n"); 99 hid_err(report->device, "too many fields in report\n");
@@ -113,9 +112,6 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
113 field->value = (s32 *)(field->usage + usages); 112 field->value = (s32 *)(field->usage + usages);
114 field->report = report; 113 field->report = report;
115 114
116 for (i = 0; i < usages; i++)
117 field->usage[i].usage_index = i;
118
119 return field; 115 return field;
120} 116}
121 117
@@ -226,9 +222,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
226{ 222{
227 struct hid_report *report; 223 struct hid_report *report;
228 struct hid_field *field; 224 struct hid_field *field;
229 int usages; 225 unsigned usages;
230 unsigned offset; 226 unsigned offset;
231 int i; 227 unsigned i;
232 228
233 report = hid_register_report(parser->device, report_type, parser->global.report_id); 229 report = hid_register_report(parser->device, report_type, parser->global.report_id);
234 if (!report) { 230 if (!report) {
@@ -255,7 +251,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
255 if (!parser->local.usage_index) /* Ignore padding fields */ 251 if (!parser->local.usage_index) /* Ignore padding fields */
256 return 0; 252 return 0;
257 253
258 usages = max_t(int, parser->local.usage_index, parser->global.report_count); 254 usages = max_t(unsigned, parser->local.usage_index,
255 parser->global.report_count);
259 256
260 field = hid_register_field(report, usages, parser->global.report_count); 257 field = hid_register_field(report, usages, parser->global.report_count);
261 if (!field) 258 if (!field)
@@ -266,13 +263,14 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
266 field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); 263 field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
267 264
268 for (i = 0; i < usages; i++) { 265 for (i = 0; i < usages; i++) {
269 int j = i; 266 unsigned j = i;
270 /* Duplicate the last usage we parsed if we have excess values */ 267 /* Duplicate the last usage we parsed if we have excess values */
271 if (i >= parser->local.usage_index) 268 if (i >= parser->local.usage_index)
272 j = parser->local.usage_index - 1; 269 j = parser->local.usage_index - 1;
273 field->usage[i].hid = parser->local.usage[j]; 270 field->usage[i].hid = parser->local.usage[j];
274 field->usage[i].collection_index = 271 field->usage[i].collection_index =
275 parser->local.collection_index[j]; 272 parser->local.collection_index[j];
273 field->usage[i].usage_index = i;
276 } 274 }
277 275
278 field->maxusage = usages; 276 field->maxusage = usages;
@@ -801,6 +799,64 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size)
801} 799}
802EXPORT_SYMBOL_GPL(hid_parse_report); 800EXPORT_SYMBOL_GPL(hid_parse_report);
803 801
802static const char * const hid_report_names[] = {
803 "HID_INPUT_REPORT",
804 "HID_OUTPUT_REPORT",
805 "HID_FEATURE_REPORT",
806};
807/**
808 * hid_validate_values - validate existing device report's value indexes
809 *
810 * @device: hid device
811 * @type: which report type to examine
812 * @id: which report ID to examine (0 for first)
813 * @field_index: which report field to examine
814 * @report_counts: expected number of values
815 *
816 * Validate the number of values in a given field of a given report, after
817 * parsing.
818 */
819struct hid_report *hid_validate_values(struct hid_device *hid,
820 unsigned int type, unsigned int id,
821 unsigned int field_index,
822 unsigned int report_counts)
823{
824 struct hid_report *report;
825
826 if (type > HID_FEATURE_REPORT) {
827 hid_err(hid, "invalid HID report type %u\n", type);
828 return NULL;
829 }
830
831 if (id >= HID_MAX_IDS) {
832 hid_err(hid, "invalid HID report id %u\n", id);
833 return NULL;
834 }
835
836 /*
837 * Explicitly not using hid_get_report() here since it depends on
838 * ->numbered being checked, which may not always be the case when
839 * drivers go to access report values.
840 */
841 report = hid->report_enum[type].report_id_hash[id];
842 if (!report) {
843 hid_err(hid, "missing %s %u\n", hid_report_names[type], id);
844 return NULL;
845 }
846 if (report->maxfield <= field_index) {
847 hid_err(hid, "not enough fields in %s %u\n",
848 hid_report_names[type], id);
849 return NULL;
850 }
851 if (report->field[field_index]->report_count < report_counts) {
852 hid_err(hid, "not enough values in %s %u field %u\n",
853 hid_report_names[type], id, field_index);
854 return NULL;
855 }
856 return report;
857}
858EXPORT_SYMBOL_GPL(hid_validate_values);
859
804/** 860/**
805 * hid_open_report - open a driver-specific device report 861 * hid_open_report - open a driver-specific device report
806 * 862 *
@@ -1296,7 +1352,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
1296 goto out; 1352 goto out;
1297 } 1353 }
1298 1354
1299 if (hid->claimed != HID_CLAIMED_HIDRAW) { 1355 if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) {
1300 for (a = 0; a < report->maxfield; a++) 1356 for (a = 0; a < report->maxfield; a++)
1301 hid_input_field(hid, report->field[a], cdata, interrupt); 1357 hid_input_field(hid, report->field[a], cdata, interrupt);
1302 hdrv = hid->driver; 1358 hdrv = hid->driver;
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index b420f4a0fd28..8741d953dcc8 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -485,6 +485,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
485 if (field->flags & HID_MAIN_ITEM_CONSTANT) 485 if (field->flags & HID_MAIN_ITEM_CONSTANT)
486 goto ignore; 486 goto ignore;
487 487
488 /* Ignore if report count is out of bounds. */
489 if (field->report_count < 1)
490 goto ignore;
491
488 /* only LED usages are supported in output fields */ 492 /* only LED usages are supported in output fields */
489 if (field->report_type == HID_OUTPUT_REPORT && 493 if (field->report_type == HID_OUTPUT_REPORT &&
490 (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { 494 (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) {
@@ -1236,7 +1240,11 @@ static void report_features(struct hid_device *hid)
1236 1240
1237 rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; 1241 rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
1238 list_for_each_entry(rep, &rep_enum->report_list, list) 1242 list_for_each_entry(rep, &rep_enum->report_list, list)
1239 for (i = 0; i < rep->maxfield; i++) 1243 for (i = 0; i < rep->maxfield; i++) {
1244 /* Ignore if report count is out of bounds. */
1245 if (rep->field[i]->report_count < 1)
1246 continue;
1247
1240 for (j = 0; j < rep->field[i]->maxusage; j++) { 1248 for (j = 0; j < rep->field[i]->maxusage; j++) {
1241 /* Verify if Battery Strength feature is available */ 1249 /* Verify if Battery Strength feature is available */
1242 hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); 1250 hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]);
@@ -1245,6 +1253,7 @@ static void report_features(struct hid_device *hid)
1245 drv->feature_mapping(hid, rep->field[i], 1253 drv->feature_mapping(hid, rep->field[i],
1246 rep->field[i]->usage + j); 1254 rep->field[i]->usage + j);
1247 } 1255 }
1256 }
1248} 1257}
1249 1258
1250static struct hid_input *hidinput_allocate(struct hid_device *hid) 1259static struct hid_input *hidinput_allocate(struct hid_device *hid)
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c
index 07837f5a4eb8..31cf29a6ba17 100644
--- a/drivers/hid/hid-lenovo-tpkbd.c
+++ b/drivers/hid/hid-lenovo-tpkbd.c
@@ -339,7 +339,15 @@ static int tpkbd_probe_tp(struct hid_device *hdev)
339 struct tpkbd_data_pointer *data_pointer; 339 struct tpkbd_data_pointer *data_pointer;
340 size_t name_sz = strlen(dev_name(dev)) + 16; 340 size_t name_sz = strlen(dev_name(dev)) + 16;
341 char *name_mute, *name_micmute; 341 char *name_mute, *name_micmute;
342 int ret; 342 int i, ret;
343
344 /* Validate required reports. */
345 for (i = 0; i < 4; i++) {
346 if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
347 return -ENODEV;
348 }
349 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
350 return -ENODEV;
343 351
344 if (sysfs_create_group(&hdev->dev.kobj, 352 if (sysfs_create_group(&hdev->dev.kobj,
345 &tpkbd_attr_group_pointer)) { 353 &tpkbd_attr_group_pointer)) {
@@ -406,22 +414,27 @@ static int tpkbd_probe(struct hid_device *hdev,
406 ret = hid_parse(hdev); 414 ret = hid_parse(hdev);
407 if (ret) { 415 if (ret) {
408 hid_err(hdev, "hid_parse failed\n"); 416 hid_err(hdev, "hid_parse failed\n");
409 goto err_free; 417 goto err;
410 } 418 }
411 419
412 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 420 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
413 if (ret) { 421 if (ret) {
414 hid_err(hdev, "hid_hw_start failed\n"); 422 hid_err(hdev, "hid_hw_start failed\n");
415 goto err_free; 423 goto err;
416 } 424 }
417 425
418 uhdev = (struct usbhid_device *) hdev->driver_data; 426 uhdev = (struct usbhid_device *) hdev->driver_data;
419 427
420 if (uhdev->ifnum == 1) 428 if (uhdev->ifnum == 1) {
421 return tpkbd_probe_tp(hdev); 429 ret = tpkbd_probe_tp(hdev);
430 if (ret)
431 goto err_hid;
432 }
422 433
423 return 0; 434 return 0;
424err_free: 435err_hid:
436 hid_hw_stop(hdev);
437err:
425 return ret; 438 return ret;
426} 439}
427 440
diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
index b3cd1507dda2..1a42eaa6ca02 100644
--- a/drivers/hid/hid-lg2ff.c
+++ b/drivers/hid/hid-lg2ff.c
@@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid)
64 struct hid_report *report; 64 struct hid_report *report;
65 struct hid_input *hidinput = list_entry(hid->inputs.next, 65 struct hid_input *hidinput = list_entry(hid->inputs.next,
66 struct hid_input, list); 66 struct hid_input, list);
67 struct list_head *report_list =
68 &hid->report_enum[HID_OUTPUT_REPORT].report_list;
69 struct input_dev *dev = hidinput->input; 67 struct input_dev *dev = hidinput->input;
70 int error; 68 int error;
71 69
72 if (list_empty(report_list)) { 70 /* Check that the report looks ok */
73 hid_err(hid, "no output report found\n"); 71 report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
72 if (!report)
74 return -ENODEV; 73 return -ENODEV;
75 }
76
77 report = list_entry(report_list->next, struct hid_report, list);
78
79 if (report->maxfield < 1) {
80 hid_err(hid, "output report is empty\n");
81 return -ENODEV;
82 }
83 if (report->field[0]->report_count < 7) {
84 hid_err(hid, "not enough values in the field\n");
85 return -ENODEV;
86 }
87 74
88 lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); 75 lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
89 if (!lg2ff) 76 if (!lg2ff)
diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c
index e52f181f6aa1..8c2da183d3bc 100644
--- a/drivers/hid/hid-lg3ff.c
+++ b/drivers/hid/hid-lg3ff.c
@@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data,
66 int x, y; 66 int x, y;
67 67
68/* 68/*
69 * Maxusage should always be 63 (maximum fields) 69 * Available values in the field should always be 63, but we only use up to
70 * likely a better way to ensure this data is clean 70 * 35. Instead, clear the entire area, however big it is.
71 */ 71 */
72 memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); 72 memset(report->field[0]->value, 0,
73 sizeof(__s32) * report->field[0]->report_count);
73 74
74 switch (effect->type) { 75 switch (effect->type) {
75 case FF_CONSTANT: 76 case FF_CONSTANT:
@@ -129,32 +130,14 @@ static const signed short ff3_joystick_ac[] = {
129int lg3ff_init(struct hid_device *hid) 130int lg3ff_init(struct hid_device *hid)
130{ 131{
131 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); 132 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
132 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
133 struct input_dev *dev = hidinput->input; 133 struct input_dev *dev = hidinput->input;
134 struct hid_report *report;
135 struct hid_field *field;
136 const signed short *ff_bits = ff3_joystick_ac; 134 const signed short *ff_bits = ff3_joystick_ac;
137 int error; 135 int error;
138 int i; 136 int i;
139 137
140 /* Find the report to use */
141 if (list_empty(report_list)) {
142 hid_err(hid, "No output report found\n");
143 return -1;
144 }
145
146 /* Check that the report looks ok */ 138 /* Check that the report looks ok */
147 report = list_entry(report_list->next, struct hid_report, list); 139 if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35))
148 if (!report) { 140 return -ENODEV;
149 hid_err(hid, "NULL output report\n");
150 return -1;
151 }
152
153 field = report->field[0];
154 if (!field) {
155 hid_err(hid, "NULL field\n");
156 return -1;
157 }
158 141
159 /* Assume single fixed device G940 */ 142 /* Assume single fixed device G940 */
160 for (i = 0; ff_bits[i] >= 0; i++) 143 for (i = 0; ff_bits[i] >= 0; i++)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 0ddae2a00d59..8782fe1aaa07 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde
484int lg4ff_init(struct hid_device *hid) 484int lg4ff_init(struct hid_device *hid)
485{ 485{
486 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); 486 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
487 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
488 struct input_dev *dev = hidinput->input; 487 struct input_dev *dev = hidinput->input;
489 struct hid_report *report;
490 struct hid_field *field;
491 struct lg4ff_device_entry *entry; 488 struct lg4ff_device_entry *entry;
492 struct lg_drv_data *drv_data; 489 struct lg_drv_data *drv_data;
493 struct usb_device_descriptor *udesc; 490 struct usb_device_descriptor *udesc;
494 int error, i, j; 491 int error, i, j;
495 __u16 bcdDevice, rev_maj, rev_min; 492 __u16 bcdDevice, rev_maj, rev_min;
496 493
497 /* Find the report to use */
498 if (list_empty(report_list)) {
499 hid_err(hid, "No output report found\n");
500 return -1;
501 }
502
503 /* Check that the report looks ok */ 494 /* Check that the report looks ok */
504 report = list_entry(report_list->next, struct hid_report, list); 495 if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
505 if (!report) {
506 hid_err(hid, "NULL output report\n");
507 return -1; 496 return -1;
508 }
509
510 field = report->field[0];
511 if (!field) {
512 hid_err(hid, "NULL field\n");
513 return -1;
514 }
515 497
516 /* Check what wheel has been connected */ 498 /* Check what wheel has been connected */
517 for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { 499 for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) {
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
index d7ea8c845b40..e1394af0ae7b 100644
--- a/drivers/hid/hid-lgff.c
+++ b/drivers/hid/hid-lgff.c
@@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
128int lgff_init(struct hid_device* hid) 128int lgff_init(struct hid_device* hid)
129{ 129{
130 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); 130 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
131 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
132 struct input_dev *dev = hidinput->input; 131 struct input_dev *dev = hidinput->input;
133 struct hid_report *report;
134 struct hid_field *field;
135 const signed short *ff_bits = ff_joystick; 132 const signed short *ff_bits = ff_joystick;
136 int error; 133 int error;
137 int i; 134 int i;
138 135
139 /* Find the report to use */
140 if (list_empty(report_list)) {
141 hid_err(hid, "No output report found\n");
142 return -1;
143 }
144
145 /* Check that the report looks ok */ 136 /* Check that the report looks ok */
146 report = list_entry(report_list->next, struct hid_report, list); 137 if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
147 field = report->field[0]; 138 return -ENODEV;
148 if (!field) {
149 hid_err(hid, "NULL field\n");
150 return -1;
151 }
152 139
153 for (i = 0; i < ARRAY_SIZE(devices); i++) { 140 for (i = 0; i < ARRAY_SIZE(devices); i++) {
154 if (dev->id.vendor == devices[i].idVendor && 141 if (dev->id.vendor == devices[i].idVendor &&
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 7800b1410562..2e5302462efb 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -461,7 +461,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
461 struct hid_report *report; 461 struct hid_report *report;
462 struct hid_report_enum *output_report_enum; 462 struct hid_report_enum *output_report_enum;
463 u8 *data = (u8 *)(&dj_report->device_index); 463 u8 *data = (u8 *)(&dj_report->device_index);
464 int i; 464 unsigned int i;
465 465
466 output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; 466 output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
467 report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; 467 report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
@@ -471,7 +471,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
471 return -ENODEV; 471 return -ENODEV;
472 } 472 }
473 473
474 for (i = 0; i < report->field[0]->report_count; i++) 474 for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++)
475 report->field[0]->value[i] = data[i]; 475 report->field[0]->value[i] = data[i];
476 476
477 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 477 hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
@@ -791,6 +791,12 @@ static int logi_dj_probe(struct hid_device *hdev,
791 goto hid_parse_fail; 791 goto hid_parse_fail;
792 } 792 }
793 793
794 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT,
795 0, DJREPORT_SHORT_LENGTH - 1)) {
796 retval = -ENODEV;
797 goto hid_parse_fail;
798 }
799
794 /* Starts the usb device and connects to upper interfaces hiddev and 800 /* Starts the usb device and connects to upper interfaces hiddev and
795 * hidraw */ 801 * hidraw */
796 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 802 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index ac28f08c3866..5e5fe1b8eebb 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -101,9 +101,9 @@ struct mt_device {
101 unsigned last_slot_field; /* the last field of a slot */ 101 unsigned last_slot_field; /* the last field of a slot */
102 unsigned mt_report_id; /* the report ID of the multitouch device */ 102 unsigned mt_report_id; /* the report ID of the multitouch device */
103 unsigned pen_report_id; /* the report ID of the pen device */ 103 unsigned pen_report_id; /* the report ID of the pen device */
104 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ 104 __s16 inputmode; /* InputMode HID feature, -1 if non-existent */
105 __s8 inputmode_index; /* InputMode HID feature index in the report */ 105 __s16 inputmode_index; /* InputMode HID feature index in the report */
106 __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, 106 __s16 maxcontact_report_id; /* Maximum Contact Number HID feature,
107 -1 if non-existent */ 107 -1 if non-existent */
108 __u8 num_received; /* how many contacts we received */ 108 __u8 num_received; /* how many contacts we received */
109 __u8 num_expected; /* expected last contact index */ 109 __u8 num_expected; /* expected last contact index */
@@ -312,20 +312,18 @@ static void mt_feature_mapping(struct hid_device *hdev,
312 struct hid_field *field, struct hid_usage *usage) 312 struct hid_field *field, struct hid_usage *usage)
313{ 313{
314 struct mt_device *td = hid_get_drvdata(hdev); 314 struct mt_device *td = hid_get_drvdata(hdev);
315 int i;
316 315
317 switch (usage->hid) { 316 switch (usage->hid) {
318 case HID_DG_INPUTMODE: 317 case HID_DG_INPUTMODE:
319 td->inputmode = field->report->id; 318 /* Ignore if value index is out of bounds. */
320 td->inputmode_index = 0; /* has to be updated below */ 319 if (usage->usage_index >= field->report_count) {
321 320 dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n");
322 for (i=0; i < field->maxusage; i++) { 321 break;
323 if (field->usage[i].hid == usage->hid) {
324 td->inputmode_index = i;
325 break;
326 }
327 } 322 }
328 323
324 td->inputmode = field->report->id;
325 td->inputmode_index = usage->usage_index;
326
329 break; 327 break;
330 case HID_DG_CONTACTMAX: 328 case HID_DG_CONTACTMAX:
331 td->maxcontact_report_id = field->report->id; 329 td->maxcontact_report_id = field->report->id;
@@ -511,6 +509,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
511 mt_store_field(usage, td, hi); 509 mt_store_field(usage, td, hi);
512 return 1; 510 return 1;
513 case HID_DG_CONTACTCOUNT: 511 case HID_DG_CONTACTCOUNT:
512 /* Ignore if indexes are out of bounds. */
513 if (field->index >= field->report->maxfield ||
514 usage->usage_index >= field->report_count)
515 return 1;
514 td->cc_index = field->index; 516 td->cc_index = field->index;
515 td->cc_value_index = usage->usage_index; 517 td->cc_value_index = usage->usage_index;
516 return 1; 518 return 1;
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 30dbb6b40bbf..b18320db5f7d 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -537,6 +537,10 @@ static int buzz_init(struct hid_device *hdev)
537 drv_data = hid_get_drvdata(hdev); 537 drv_data = hid_get_drvdata(hdev);
538 BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); 538 BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER));
539 539
540 /* Validate expected report characteristics. */
541 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
542 return -ENODEV;
543
540 buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); 544 buzz = kzalloc(sizeof(*buzz), GFP_KERNEL);
541 if (!buzz) { 545 if (!buzz) {
542 hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); 546 hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index d16491192112..29f328f411fb 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struct hid_device *hdev,
249 goto err_free; 249 goto err_free;
250 } 250 }
251 251
252 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) {
253 ret = -ENODEV;
254 goto err_free;
255 }
256
252 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 257 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
253 if (ret) { 258 if (ret) {
254 hid_err(hdev, "hw start failed\n"); 259 hid_err(hdev, "hw start failed\n");
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c
index 6ec28a37c146..a29756c6ca02 100644
--- a/drivers/hid/hid-zpff.c
+++ b/drivers/hid/hid-zpff.c
@@ -68,21 +68,13 @@ static int zpff_init(struct hid_device *hid)
68 struct hid_report *report; 68 struct hid_report *report;
69 struct hid_input *hidinput = list_entry(hid->inputs.next, 69 struct hid_input *hidinput = list_entry(hid->inputs.next,
70 struct hid_input, list); 70 struct hid_input, list);
71 struct list_head *report_list =
72 &hid->report_enum[HID_OUTPUT_REPORT].report_list;
73 struct input_dev *dev = hidinput->input; 71 struct input_dev *dev = hidinput->input;
74 int error; 72 int i, error;
75 73
76 if (list_empty(report_list)) { 74 for (i = 0; i < 4; i++) {
77 hid_err(hid, "no output report found\n"); 75 report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1);
78 return -ENODEV; 76 if (!report)
79 } 77 return -ENODEV;
80
81 report = list_entry(report_list->next, struct hid_report, list);
82
83 if (report->maxfield < 4) {
84 hid_err(hid, "not enough fields in report\n");
85 return -ENODEV;
86 } 78 }
87 79
88 zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); 80 zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL);
diff --git a/include/linux/hid.h b/include/linux/hid.h
index ee1ffc5e19c9..31b9d299ef6c 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -756,6 +756,10 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
756struct hid_device *hid_allocate_device(void); 756struct hid_device *hid_allocate_device(void);
757struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); 757struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
758int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); 758int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
759struct hid_report *hid_validate_values(struct hid_device *hid,
760 unsigned int type, unsigned int id,
761 unsigned int field_index,
762 unsigned int report_counts);
759int hid_open_report(struct hid_device *device); 763int hid_open_report(struct hid_device *device);
760int hid_check_keys_pressed(struct hid_device *hid); 764int hid_check_keys_pressed(struct hid_device *hid);
761int hid_connect(struct hid_device *hid, unsigned int connect_mask); 765int hid_connect(struct hid_device *hid, unsigned int connect_mask);