forked from Minki/linux
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: Benjamin Tissoires <benjamin.tissoires@redhat.com> Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
297502abb3
commit
8821f5dc18
@ -101,9 +101,9 @@ struct mt_device {
|
||||
unsigned last_slot_field; /* the last field of a slot */
|
||||
unsigned mt_report_id; /* the report ID of the multitouch device */
|
||||
unsigned pen_report_id; /* the report ID of the pen device */
|
||||
__s8 inputmode; /* InputMode HID feature, -1 if non-existent */
|
||||
__s8 inputmode_index; /* InputMode HID feature index in the report */
|
||||
__s8 maxcontact_report_id; /* Maximum Contact Number HID feature,
|
||||
__s16 inputmode; /* InputMode HID feature, -1 if non-existent */
|
||||
__s16 inputmode_index; /* InputMode HID feature index in the report */
|
||||
__s16 maxcontact_report_id; /* Maximum Contact Number HID feature,
|
||||
-1 if non-existent */
|
||||
__u8 num_received; /* how many contacts we received */
|
||||
__u8 num_expected; /* expected last contact index */
|
||||
@ -312,20 +312,18 @@ static void mt_feature_mapping(struct hid_device *hdev,
|
||||
struct hid_field *field, struct hid_usage *usage)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hdev);
|
||||
int i;
|
||||
|
||||
switch (usage->hid) {
|
||||
case HID_DG_INPUTMODE:
|
||||
td->inputmode = field->report->id;
|
||||
td->inputmode_index = 0; /* has to be updated below */
|
||||
|
||||
for (i=0; i < field->maxusage; i++) {
|
||||
if (field->usage[i].hid == usage->hid) {
|
||||
td->inputmode_index = i;
|
||||
break;
|
||||
}
|
||||
/* Ignore if value index is out of bounds. */
|
||||
if (usage->usage_index >= field->report_count) {
|
||||
dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n");
|
||||
break;
|
||||
}
|
||||
|
||||
td->inputmode = field->report->id;
|
||||
td->inputmode_index = usage->usage_index;
|
||||
|
||||
break;
|
||||
case HID_DG_CONTACTMAX:
|
||||
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,
|
||||
mt_store_field(usage, td, hi);
|
||||
return 1;
|
||||
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_value_index = usage->usage_index;
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user