Commit 8821f5dc authored by Benjamin Tissoires's avatar Benjamin Tissoires Committed by Jiri Kosina

HID: multitouch: validate indexes details

When working on report indexes, always validate that they are in bounds.
Without this, a HID device could report a malicious feature report that
could trick the driver into a heap overflow:

[  634.885003] usb 1-1: New USB device found, idVendor=0596, idProduct=0500
...
[  676.469629] BUG kmalloc-192 (Tainted: G        W   ): Redzone overwritten

Note that we need to change the indexes from s8 to s16 as they can
be between -1 and 255.

CVE-2013-2897

Cc: stable@vger.kernel.org
Signed-off-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 297502ab
...@@ -101,9 +101,9 @@ struct mt_device { ...@@ -101,9 +101,9 @@ struct mt_device {
unsigned last_slot_field; /* the last field of a slot */ unsigned last_slot_field; /* the last field of a slot */
unsigned mt_report_id; /* the report ID of the multitouch device */ unsigned mt_report_id; /* the report ID of the multitouch device */
unsigned pen_report_id; /* the report ID of the pen device */ unsigned pen_report_id; /* the report ID of the pen device */
__s8 inputmode; /* InputMode HID feature, -1 if non-existent */ __s16 inputmode; /* InputMode HID feature, -1 if non-existent */
__s8 inputmode_index; /* InputMode HID feature index in the report */ __s16 inputmode_index; /* InputMode HID feature index in the report */
__s8 maxcontact_report_id; /* Maximum Contact Number HID feature, __s16 maxcontact_report_id; /* Maximum Contact Number HID feature,
-1 if non-existent */ -1 if non-existent */
__u8 num_received; /* how many contacts we received */ __u8 num_received; /* how many contacts we received */
__u8 num_expected; /* expected last contact index */ __u8 num_expected; /* expected last contact index */
...@@ -312,20 +312,18 @@ static void mt_feature_mapping(struct hid_device *hdev, ...@@ -312,20 +312,18 @@ static void mt_feature_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage) struct hid_field *field, struct hid_usage *usage)
{ {
struct mt_device *td = hid_get_drvdata(hdev); struct mt_device *td = hid_get_drvdata(hdev);
int i;
switch (usage->hid) { switch (usage->hid) {
case HID_DG_INPUTMODE: case HID_DG_INPUTMODE:
td->inputmode = field->report->id; /* Ignore if value index is out of bounds. */
td->inputmode_index = 0; /* has to be updated below */ if (usage->usage_index >= field->report_count) {
dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n");
for (i=0; i < field->maxusage; i++) { break;
if (field->usage[i].hid == usage->hid) {
td->inputmode_index = i;
break;
}
} }
td->inputmode = field->report->id;
td->inputmode_index = usage->usage_index;
break; break;
case HID_DG_CONTACTMAX: case HID_DG_CONTACTMAX:
td->maxcontact_report_id = field->report->id; 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,6 +509,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
return 1; return 1;
case HID_DG_CONTACTCOUNT: case HID_DG_CONTACTCOUNT:
/* Ignore if indexes are out of bounds. */
if (field->index >= field->report->maxfield ||
usage->usage_index >= field->report_count)
return 1;
td->cc_index = field->index; td->cc_index = field->index;
td->cc_value_index = usage->usage_index; td->cc_value_index = usage->usage_index;
return 1; return 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment