]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Sep 2013 21:11:50 +0000 (14:11 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Sep 2013 21:11:50 +0000 (14:11 -0700)
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

queue-3.11/hid-lenovo-tpkbd-fix-leak-if-tpkbd_probe_tp-fails.patch [new file with mode: 0644]
queue-3.11/hid-lenovo-tpkbd-validate-output-report-details.patch [new file with mode: 0644]
queue-3.11/hid-lg-validate-hid-output-report-details.patch [new file with mode: 0644]
queue-3.11/hid-logitech-dj-validate-output-report-details.patch [new file with mode: 0644]
queue-3.11/hid-multitouch-validate-indexes-details.patch [new file with mode: 0644]
queue-3.11/hid-sony-validate-hid-output-report-details.patch [new file with mode: 0644]
queue-3.11/hid-steelseries-validate-output-report-details.patch [new file with mode: 0644]
queue-3.11/hid-validate-feature-and-input-report-details.patch [new file with mode: 0644]
queue-3.11/hid-zeroplus-validate-output-report-details.patch [new file with mode: 0644]
queue-3.11/series

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 (file)
index 0000000..e45d3c2
--- /dev/null
@@ -0,0 +1,58 @@
+From 0ccdd9e7476680c16113131264ad6597bd10299d Mon Sep 17 00:00:00 2001
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Date: Wed, 11 Sep 2013 21:56:59 +0200
+Subject: HID: lenovo-tpkbd: fix leak if tpkbd_probe_tp fails
+
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+
+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 <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..dada774
--- /dev/null
@@ -0,0 +1,47 @@
+From 0a9cd0a80ac559357c6a90d26c55270ed752aa26 Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 11 Sep 2013 21:56:55 +0200
+Subject: HID: lenovo-tpkbd: validate output report details
+
+From: Kees Cook <keescook@chromium.org>
+
+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 <keescook@chromium.org>
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..c7cd732
--- /dev/null
@@ -0,0 +1,188 @@
+From 0fb6bd06e06792469acc15bbe427361b56ada528 Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 11 Sep 2013 21:56:54 +0200
+Subject: HID: LG: validate HID output report details
+
+From: Kees Cook <keescook@chromium.org>
+
+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 <keescook@chromium.org>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..6c869e6
--- /dev/null
@@ -0,0 +1,62 @@
+From 297502abb32e225fb23801fcdb0e4f6f8e17099a Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 11 Sep 2013 21:56:56 +0200
+Subject: HID: logitech-dj: validate output report details
+
+From: Kees Cook <keescook@chromium.org>
+
+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: [<ffffffff815d50aa>] logi_dj_recv_send_report.isra.11+0x1a/0x90
+
+CVE-2013-2895
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..f45539f
--- /dev/null
@@ -0,0 +1,85 @@
+From 8821f5dc187bdf16cfb32ef5aa8c3035273fa79a Mon Sep 17 00:00:00 2001
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Date: Wed, 11 Sep 2013 21:56:58 +0200
+Subject: HID: multitouch: validate indexes details
+
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+
+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 <benjamin.tissoires@redhat.com>
+Acked-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..ca7a94b
--- /dev/null
@@ -0,0 +1,42 @@
+From 9446edb9a1740989cf6c20daf7510fb9a23be14a Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 11 Sep 2013 21:56:52 +0200
+Subject: HID: sony: validate HID output report details
+
+From: Kees Cook <keescook@chromium.org>
+
+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 <keescook@chromium.org>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..93b48ad
--- /dev/null
@@ -0,0 +1,42 @@
+From 41df7f6d43723deb7364340b44bc5d94bf717456 Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 11 Sep 2013 21:56:53 +0200
+Subject: HID: steelseries: validate output report details
+
+From: Kees Cook <keescook@chromium.org>
+
+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 <keescook@chromium.org>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..eeaeda0
--- /dev/null
@@ -0,0 +1,134 @@
+From cc6b54aa54bf40b762cab45a9fc8aa81653146eb Mon Sep 17 00:00:00 2001
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Date: Wed, 11 Sep 2013 21:56:57 +0200
+Subject: HID: validate feature and input report details
+
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+
+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 <benjamin.tissoires@redhat.com>
+Acked-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..99a6e18
--- /dev/null
@@ -0,0 +1,58 @@
+From 78214e81a1bf43740ce89bb5efda78eac2f8ef83 Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 11 Sep 2013 21:56:51 +0200
+Subject: HID: zeroplus: validate output report details
+
+From: Kees Cook <keescook@chromium.org>
+
+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 <keescook@chromium.org>
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
index e781314267de4f79f08885704b1375351878b24f..ee5a21e952861ec76c0df51ebd9ef2f75dade31c 100644 (file)
@@ -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