From: Greg Kroah-Hartman Date: Fri, 27 Sep 2013 21:11:50 +0000 (-0700) Subject: 3.11-stable patches X-Git-Tag: v3.0.98~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0c0acd1a2577959daf6101a67137c5e6bc42eb52;p=thirdparty%2Fkernel%2Fstable-queue.git 3.11-stable patches added patches: hid-lenovo-tpkbd-fix-leak-if-tpkbd_probe_tp-fails.patch hid-lenovo-tpkbd-validate-output-report-details.patch hid-lg-validate-hid-output-report-details.patch hid-logitech-dj-validate-output-report-details.patch hid-multitouch-validate-indexes-details.patch hid-sony-validate-hid-output-report-details.patch hid-steelseries-validate-output-report-details.patch hid-validate-feature-and-input-report-details.patch hid-zeroplus-validate-output-report-details.patch --- diff --git a/queue-3.11/hid-lenovo-tpkbd-fix-leak-if-tpkbd_probe_tp-fails.patch b/queue-3.11/hid-lenovo-tpkbd-fix-leak-if-tpkbd_probe_tp-fails.patch new file mode 100644 index 00000000000..e45d3c2e948 --- /dev/null +++ b/queue-3.11/hid-lenovo-tpkbd-fix-leak-if-tpkbd_probe_tp-fails.patch @@ -0,0 +1,58 @@ +From 0ccdd9e7476680c16113131264ad6597bd10299d Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Wed, 11 Sep 2013 21:56:59 +0200 +Subject: HID: lenovo-tpkbd: fix leak if tpkbd_probe_tp fails + +From: Benjamin Tissoires + +commit 0ccdd9e7476680c16113131264ad6597bd10299d upstream. + +If tpkbd_probe_tp() bails out, the probe() function return an error, +but hid_hw_stop() is never called. + +fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=1003998 + +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-lenovo-tpkbd.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/hid/hid-lenovo-tpkbd.c ++++ b/drivers/hid/hid-lenovo-tpkbd.c +@@ -406,22 +406,27 @@ static int tpkbd_probe(struct hid_device + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "hid_parse failed\n"); +- goto err_free; ++ goto err; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hid_hw_start failed\n"); +- goto err_free; ++ goto err; + } + + uhdev = (struct usbhid_device *) hdev->driver_data; + +- if (uhdev->ifnum == 1) +- return tpkbd_probe_tp(hdev); ++ if (uhdev->ifnum == 1) { ++ ret = tpkbd_probe_tp(hdev); ++ if (ret) ++ goto err_hid; ++ } + + return 0; +-err_free: ++err_hid: ++ hid_hw_stop(hdev); ++err: + return ret; + } + diff --git a/queue-3.11/hid-lenovo-tpkbd-validate-output-report-details.patch b/queue-3.11/hid-lenovo-tpkbd-validate-output-report-details.patch new file mode 100644 index 00000000000..dada7747a75 --- /dev/null +++ b/queue-3.11/hid-lenovo-tpkbd-validate-output-report-details.patch @@ -0,0 +1,47 @@ +From 0a9cd0a80ac559357c6a90d26c55270ed752aa26 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:55 +0200 +Subject: HID: lenovo-tpkbd: validate output report details + +From: Kees Cook + +commit 0a9cd0a80ac559357c6a90d26c55270ed752aa26 upstream. + +A HID device could send a malicious output report that would cause the +lenovo-tpkbd HID driver to write just beyond the output report allocation +during initialization, causing a heap overflow: + +[ 76.109807] usb 1-1: New USB device found, idVendor=17ef, idProduct=6009 +... +[ 80.462540] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +CVE-2013-2894 + +Signed-off-by: Kees Cook +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-lenovo-tpkbd.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- 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_dev + struct tpkbd_data_pointer *data_pointer; + size_t name_sz = strlen(dev_name(dev)) + 16; + char *name_mute, *name_micmute; +- int ret; ++ int i, ret; ++ ++ /* Validate required reports. */ ++ for (i = 0; i < 4; i++) { ++ if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1)) ++ return -ENODEV; ++ } ++ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2)) ++ return -ENODEV; + + if (sysfs_create_group(&hdev->dev.kobj, + &tpkbd_attr_group_pointer)) { diff --git a/queue-3.11/hid-lg-validate-hid-output-report-details.patch b/queue-3.11/hid-lg-validate-hid-output-report-details.patch new file mode 100644 index 00000000000..c7cd732386b --- /dev/null +++ b/queue-3.11/hid-lg-validate-hid-output-report-details.patch @@ -0,0 +1,188 @@ +From 0fb6bd06e06792469acc15bbe427361b56ada528 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:54 +0200 +Subject: HID: LG: validate HID output report details + +From: Kees Cook + +commit 0fb6bd06e06792469acc15bbe427361b56ada528 upstream. + +A HID device could send a malicious output report that would cause the +lg, lg3, and lg4 HID drivers to write beyond the output report allocation +during an event, causing a heap overflow: + +[ 325.245240] usb 1-1: New USB device found, idVendor=046d, idProduct=c287 +... +[ 414.518960] BUG kmalloc-4096 (Not tainted): Redzone overwritten + +Additionally, while lg2 did correctly validate the report details, it was +cleaned up and shortened. + +CVE-2013-2893 + +Signed-off-by: Kees Cook +Reviewed-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-lg2ff.c | 19 +++---------------- + drivers/hid/hid-lg3ff.c | 29 ++++++----------------------- + drivers/hid/hid-lg4ff.c | 20 +------------------- + drivers/hid/hid-lgff.c | 17 ++--------------- + 4 files changed, 12 insertions(+), 73 deletions(-) + +--- a/drivers/hid/hid-lg2ff.c ++++ b/drivers/hid/hid-lg2ff.c +@@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid) + struct hid_report *report; + struct hid_input *hidinput = list_entry(hid->inputs.next, + struct hid_input, list); +- struct list_head *report_list = +- &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; + int error; + +- if (list_empty(report_list)) { +- hid_err(hid, "no output report found\n"); ++ /* Check that the report looks ok */ ++ report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); ++ if (!report) + return -ENODEV; +- } +- +- report = list_entry(report_list->next, struct hid_report, list); +- +- if (report->maxfield < 1) { +- hid_err(hid, "output report is empty\n"); +- return -ENODEV; +- } +- if (report->field[0]->report_count < 7) { +- hid_err(hid, "not enough values in the field\n"); +- return -ENODEV; +- } + + lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); + if (!lg2ff) +--- a/drivers/hid/hid-lg3ff.c ++++ b/drivers/hid/hid-lg3ff.c +@@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_d + int x, y; + + /* +- * Maxusage should always be 63 (maximum fields) +- * likely a better way to ensure this data is clean ++ * Available values in the field should always be 63, but we only use up to ++ * 35. Instead, clear the entire area, however big it is. + */ +- memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); ++ memset(report->field[0]->value, 0, ++ sizeof(__s32) * report->field[0]->report_count); + + switch (effect->type) { + case FF_CONSTANT: +@@ -129,32 +130,14 @@ static const signed short ff3_joystick_a + int lg3ff_init(struct hid_device *hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + const signed short *ff_bits = ff3_joystick_ac; + int error; + int i; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- if (!report) { +- hid_err(hid, "NULL output report\n"); +- return -1; +- } +- +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); +- return -1; +- } ++ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) ++ return -ENODEV; + + /* Assume single fixed device G940 */ + for (i = 0; ff_bits[i] >= 0; i++) +--- a/drivers/hid/hid-lg4ff.c ++++ b/drivers/hid/hid-lg4ff.c +@@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get + int lg4ff_init(struct hid_device *hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + struct usb_device_descriptor *udesc; + int error, i, j; + __u16 bcdDevice, rev_maj, rev_min; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- if (!report) { +- hid_err(hid, "NULL output report\n"); +- return -1; +- } +- +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); ++ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -1; +- } + + /* Check what wheel has been connected */ + for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { +--- a/drivers/hid/hid-lgff.c ++++ b/drivers/hid/hid-lgff.c +@@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(stru + int lgff_init(struct hid_device* hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + const signed short *ff_bits = ff_joystick; + int error; + int i; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); +- return -1; +- } ++ if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) ++ return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(devices); i++) { + if (dev->id.vendor == devices[i].idVendor && diff --git a/queue-3.11/hid-logitech-dj-validate-output-report-details.patch b/queue-3.11/hid-logitech-dj-validate-output-report-details.patch new file mode 100644 index 00000000000..6c869e65cdd --- /dev/null +++ b/queue-3.11/hid-logitech-dj-validate-output-report-details.patch @@ -0,0 +1,62 @@ +From 297502abb32e225fb23801fcdb0e4f6f8e17099a Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:56 +0200 +Subject: HID: logitech-dj: validate output report details + +From: Kees Cook + +commit 297502abb32e225fb23801fcdb0e4f6f8e17099a upstream. + +A HID device could send a malicious output report that would cause the +logitech-dj HID driver to leak kernel memory contents to the device, or +trigger a NULL dereference during initialization: + +[ 304.424553] usb 1-1: New USB device found, idVendor=046d, idProduct=c52b +... +[ 304.780467] BUG: unable to handle kernel NULL pointer dereference at 0000000000000028 +[ 304.781409] IP: [] logi_dj_recv_send_report.isra.11+0x1a/0x90 + +CVE-2013-2895 + +Signed-off-by: Kees Cook +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-logitech-dj.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- 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(stru + struct hid_report *report; + struct hid_report_enum *output_report_enum; + u8 *data = (u8 *)(&dj_report->device_index); +- int i; ++ unsigned int i; + + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; +@@ -471,7 +471,7 @@ static int logi_dj_recv_send_report(stru + return -ENODEV; + } + +- for (i = 0; i < report->field[0]->report_count; i++) ++ for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++) + report->field[0]->value[i] = data[i]; + + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); +@@ -783,6 +783,12 @@ static int logi_dj_probe(struct hid_devi + goto hid_parse_fail; + } + ++ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, ++ 0, DJREPORT_SHORT_LENGTH - 1)) { ++ retval = -ENODEV; ++ goto hid_parse_fail; ++ } ++ + /* Starts the usb device and connects to upper interfaces hiddev and + * hidraw */ + retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); diff --git a/queue-3.11/hid-multitouch-validate-indexes-details.patch b/queue-3.11/hid-multitouch-validate-indexes-details.patch new file mode 100644 index 00000000000..f45539f4862 --- /dev/null +++ b/queue-3.11/hid-multitouch-validate-indexes-details.patch @@ -0,0 +1,85 @@ +From 8821f5dc187bdf16cfb32ef5aa8c3035273fa79a Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Wed, 11 Sep 2013 21:56:58 +0200 +Subject: HID: multitouch: validate indexes details + +From: Benjamin Tissoires + +commit 8821f5dc187bdf16cfb32ef5aa8c3035273fa79a upstream. + +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 + +Signed-off-by: Benjamin Tissoires +Acked-by: Kees Cook +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-multitouch.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -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 */ +@@ -317,20 +317,18 @@ static void mt_feature_mapping(struct hi + 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; +@@ -536,6 +534,10 @@ static int mt_touch_input_mapping(struct + 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; diff --git a/queue-3.11/hid-sony-validate-hid-output-report-details.patch b/queue-3.11/hid-sony-validate-hid-output-report-details.patch new file mode 100644 index 00000000000..ca7a94b3290 --- /dev/null +++ b/queue-3.11/hid-sony-validate-hid-output-report-details.patch @@ -0,0 +1,42 @@ +From 9446edb9a1740989cf6c20daf7510fb9a23be14a Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:52 +0200 +Subject: HID: sony: validate HID output report details + +From: Kees Cook + +commit 9446edb9a1740989cf6c20daf7510fb9a23be14a upstream. + +This driver must validate the availability of the HID output report and +its size before it can write LED states via buzz_set_leds(). This stops +a heap overflow that is possible if a device provides a malicious HID +output report: + +[ 108.171280] usb 1-1: New USB device found, idVendor=054c, idProduct=0002 +... +[ 117.507877] BUG kmalloc-192 (Not tainted): Redzone overwritten + +CVE-2013-2890 + +Signed-off-by: Kees Cook +Reviewed-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-sony.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -537,6 +537,10 @@ static int buzz_init(struct hid_device * + drv_data = hid_get_drvdata(hdev); + BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); + ++ /* Validate expected report characteristics. */ ++ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) ++ return -ENODEV; ++ + buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); + if (!buzz) { + hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); diff --git a/queue-3.11/hid-steelseries-validate-output-report-details.patch b/queue-3.11/hid-steelseries-validate-output-report-details.patch new file mode 100644 index 00000000000..93b48adbe74 --- /dev/null +++ b/queue-3.11/hid-steelseries-validate-output-report-details.patch @@ -0,0 +1,42 @@ +From 41df7f6d43723deb7364340b44bc5d94bf717456 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:53 +0200 +Subject: HID: steelseries: validate output report details + +From: Kees Cook + +commit 41df7f6d43723deb7364340b44bc5d94bf717456 upstream. + +A HID device could send a malicious output report that would cause the +steelseries HID driver to write beyond the output report allocation +during initialization, causing a heap overflow: + +[ 167.981534] usb 1-1: New USB device found, idVendor=1038, idProduct=1410 +... +[ 182.050547] BUG kmalloc-256 (Tainted: G W ): Redzone overwritten + +CVE-2013-2891 + +Signed-off-by: Kees Cook +Reviewed-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-steelseries.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/hid/hid-steelseries.c ++++ b/drivers/hid/hid-steelseries.c +@@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struc + goto err_free; + } + ++ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) { ++ ret = -ENODEV; ++ goto err_free; ++ } ++ + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hw start failed\n"); diff --git a/queue-3.11/hid-validate-feature-and-input-report-details.patch b/queue-3.11/hid-validate-feature-and-input-report-details.patch new file mode 100644 index 00000000000..eeaeda076c7 --- /dev/null +++ b/queue-3.11/hid-validate-feature-and-input-report-details.patch @@ -0,0 +1,134 @@ +From cc6b54aa54bf40b762cab45a9fc8aa81653146eb Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Wed, 11 Sep 2013 21:56:57 +0200 +Subject: HID: validate feature and input report details + +From: Benjamin Tissoires + +commit cc6b54aa54bf40b762cab45a9fc8aa81653146eb upstream. + +When dealing with usage_index, be sure to properly use unsigned instead of +int to avoid overflows. + +When working on report fields, always validate that their report_counts 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 + +CVE-2013-2897 + +Signed-off-by: Benjamin Tissoires +Acked-by: Kees Cook +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-core.c | 16 +++++++--------- + drivers/hid/hid-input.c | 11 ++++++++++- + 2 files changed, 17 insertions(+), 10 deletions(-) + +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -94,7 +94,6 @@ EXPORT_SYMBOL_GPL(hid_register_report); + static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) + { + struct hid_field *field; +- int i; + + if (report->maxfield == HID_MAX_FIELDS) { + hid_err(report->device, "too many fields in report\n"); +@@ -113,9 +112,6 @@ static struct hid_field *hid_register_fi + field->value = (s32 *)(field->usage + usages); + field->report = report; + +- for (i = 0; i < usages; i++) +- field->usage[i].usage_index = i; +- + return field; + } + +@@ -226,9 +222,9 @@ static int hid_add_field(struct hid_pars + { + struct hid_report *report; + struct hid_field *field; +- int usages; ++ unsigned usages; + unsigned offset; +- int i; ++ unsigned i; + + report = hid_register_report(parser->device, report_type, parser->global.report_id); + if (!report) { +@@ -255,7 +251,8 @@ static int hid_add_field(struct hid_pars + if (!parser->local.usage_index) /* Ignore padding fields */ + return 0; + +- usages = max_t(int, parser->local.usage_index, parser->global.report_count); ++ usages = max_t(unsigned, parser->local.usage_index, ++ parser->global.report_count); + + field = hid_register_field(report, usages, parser->global.report_count); + if (!field) +@@ -266,13 +263,14 @@ static int hid_add_field(struct hid_pars + field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); + + for (i = 0; i < usages; i++) { +- int j = i; ++ unsigned j = i; + /* Duplicate the last usage we parsed if we have excess values */ + if (i >= parser->local.usage_index) + j = parser->local.usage_index - 1; + field->usage[i].hid = parser->local.usage[j]; + field->usage[i].collection_index = + parser->local.collection_index[j]; ++ field->usage[i].usage_index = i; + } + + field->maxusage = usages; +@@ -1295,7 +1293,7 @@ int hid_report_raw_event(struct hid_devi + goto out; + } + +- if (hid->claimed != HID_CLAIMED_HIDRAW) { ++ if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) { + for (a = 0; a < report->maxfield; a++) + hid_input_field(hid, report->field[a], cdata, interrupt); + hdrv = hid->driver; +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -485,6 +485,10 @@ static void hidinput_configure_usage(str + if (field->flags & HID_MAIN_ITEM_CONSTANT) + goto ignore; + ++ /* Ignore if report count is out of bounds. */ ++ if (field->report_count < 1) ++ goto ignore; ++ + /* only LED usages are supported in output fields */ + if (field->report_type == HID_OUTPUT_REPORT && + (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { +@@ -1168,7 +1172,11 @@ static void report_features(struct hid_d + + rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; + list_for_each_entry(rep, &rep_enum->report_list, list) +- for (i = 0; i < rep->maxfield; i++) ++ for (i = 0; i < rep->maxfield; i++) { ++ /* Ignore if report count is out of bounds. */ ++ if (rep->field[i]->report_count < 1) ++ continue; ++ + for (j = 0; j < rep->field[i]->maxusage; j++) { + /* Verify if Battery Strength feature is available */ + hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); +@@ -1177,6 +1185,7 @@ static void report_features(struct hid_d + drv->feature_mapping(hid, rep->field[i], + rep->field[i]->usage + j); + } ++ } + } + + static struct hid_input *hidinput_allocate(struct hid_device *hid) diff --git a/queue-3.11/hid-zeroplus-validate-output-report-details.patch b/queue-3.11/hid-zeroplus-validate-output-report-details.patch new file mode 100644 index 00000000000..99a6e1846c3 --- /dev/null +++ b/queue-3.11/hid-zeroplus-validate-output-report-details.patch @@ -0,0 +1,58 @@ +From 78214e81a1bf43740ce89bb5efda78eac2f8ef83 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 11 Sep 2013 21:56:51 +0200 +Subject: HID: zeroplus: validate output report details + +From: Kees Cook + +commit 78214e81a1bf43740ce89bb5efda78eac2f8ef83 upstream. + +The zeroplus HID driver was not checking the size of allocated values +in fields it used. A HID device could send a malicious output report +that would cause the driver to write beyond the output report allocation +during initialization, causing a heap overflow: + +[ 1442.728680] usb 1-1: New USB device found, idVendor=0c12, idProduct=0005 +... +[ 1466.243173] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten + +CVE-2013-2889 + +Signed-off-by: Kees Cook +Reviewed-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-zpff.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +--- a/drivers/hid/hid-zpff.c ++++ b/drivers/hid/hid-zpff.c +@@ -68,21 +68,13 @@ static int zpff_init(struct hid_device * + struct hid_report *report; + struct hid_input *hidinput = list_entry(hid->inputs.next, + struct hid_input, list); +- struct list_head *report_list = +- &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- int error; ++ int i, error; + +- if (list_empty(report_list)) { +- hid_err(hid, "no output report found\n"); +- return -ENODEV; +- } +- +- report = list_entry(report_list->next, struct hid_report, list); +- +- if (report->maxfield < 4) { +- hid_err(hid, "not enough fields in report\n"); +- return -ENODEV; ++ for (i = 0; i < 4; i++) { ++ report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); ++ if (!report) ++ return -ENODEV; + } + + zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); diff --git a/queue-3.11/series b/queue-3.11/series index e781314267d..ee5a21e9528 100644 --- a/queue-3.11/series +++ b/queue-3.11/series @@ -9,3 +9,12 @@ timekeeping-fix-hrtick-related-deadlock-from-ntp-lock-changes.patch sched-cputime-do-not-scale-when-utime-0.patch sched-fair-fix-small-race-where-child-se.parent-cfs_rq-might-point-to-invalid-ones.patch hid-provide-a-helper-for-validating-hid-reports.patch +hid-validate-feature-and-input-report-details.patch +hid-multitouch-validate-indexes-details.patch +hid-lg-validate-hid-output-report-details.patch +hid-zeroplus-validate-output-report-details.patch +hid-lenovo-tpkbd-fix-leak-if-tpkbd_probe_tp-fails.patch +hid-steelseries-validate-output-report-details.patch +hid-sony-validate-hid-output-report-details.patch +hid-lenovo-tpkbd-validate-output-report-details.patch +hid-logitech-dj-validate-output-report-details.patch