Path: news.gmane.org!not-for-mail From: Jiri Kosina Newsgroups: gmane.linux.kernel.input Subject: [PATCH 02/14] HID: provide a helper for validating hid reports Date: Wed, 28 Aug 2013 22:30:06 +0200 (CEST) Lines: 99 Approved: news@gmane.org Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: ger.gmane.org 1377721810 9564 80.91.229.3 (28 Aug 2013 20:30:10 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:10 +0000 (UTC) Cc: Kees Cook To: linux-input@vger.kernel.org Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:12 2013 Return-path: Envelope-to: glki-linux-input-2@plane.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VEmNX-0008U8-Cg for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:11 +0200 Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754750Ab3H1UaK (ORCPT ); Wed, 28 Aug 2013 16:30:10 -0400 Original-Received: from cantor2.suse.de ([195.135.220.15]:57911 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752748Ab3H1UaK (ORCPT ); Wed, 28 Aug 2013 16:30:10 -0400 Original-Received: from relay1.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 3C054A531D; Wed, 28 Aug 2013 22:30:09 +0200 (CEST) User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) Original-Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Xref: news.gmane.org gmane.linux.kernel.input:31653 Archived-At: From: Kees Cook Many drivers need to validate the characteristics of their HID report during initialization to avoid misusing the reports. This adds a common helper to perform validation of the report, its field count, and the value count within the fields. Signed-off-by: Kees Cook Cc: stable@kernel.org --- drivers/hid/hid-core.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/hid.h | 4 ++++ 2 files changed, 54 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 5ea7d51..55798b2 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -759,6 +759,56 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) } EXPORT_SYMBOL_GPL(hid_parse_report); +static const char * const hid_report_names[] = { + "HID_INPUT_REPORT", + "HID_OUTPUT_REPORT", + "HID_FEATURE_REPORT", +}; +/** + * hid_validate_report - validate existing device report + * + * @device: hid device + * @type: which report type to examine + * @id: which report ID to examine (0 for first) + * @fields: expected number of fields + * @report_counts: expected number of values per field + * + * Validate the report details after parsing. + */ +struct hid_report *hid_validate_report(struct hid_device *hid, + unsigned int type, unsigned int id, + unsigned int fields, + unsigned int report_counts) +{ + struct hid_report *report; + unsigned int i; + + if (type > HID_FEATURE_REPORT) { + hid_err(hid, "invalid HID report %u\n", type); + return NULL; + } + + report = hid->report_enum[type].report_id_hash[id]; + if (!report) { + hid_err(hid, "missing %s %u\n", hid_report_names[type], id); + return NULL; + } + if (report->maxfield < fields) { + hid_err(hid, "not enough fields in %s %u\n", + hid_report_names[type], id); + return NULL; + } + for (i = 0; i < fields; i++) { + if (report->field[i]->report_count < report_counts) { + hid_err(hid, "not enough values in %s %u fields\n", + hid_report_names[type], id); + return NULL; + } + } + return report; +} +EXPORT_SYMBOL_GPL(hid_validate_report); + /** * hid_open_report - open a driver-specific device report * diff --git a/include/linux/hid.h b/include/linux/hid.h index ff545cc..76e41d8 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -749,6 +749,10 @@ void hid_output_report(struct hid_report *report, __u8 *data); struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); +struct hid_report *hid_validate_report(struct hid_device *hid, + unsigned int type, unsigned int id, + unsigned int fields, + unsigned int report_counts); int hid_open_report(struct hid_device *device); int hid_check_keys_pressed(struct hid_device *hid); int hid_connect(struct hid_device *hid, unsigned int connect_mask); -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Path: news.gmane.org!not-for-mail From: Jiri Kosina Newsgroups: gmane.linux.kernel.input Subject: [PATCH 03/14] HID: zeroplus: validate output report details Date: Wed, 28 Aug 2013 22:30:15 +0200 (CEST) Lines: 57 Approved: news@gmane.org Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: ger.gmane.org 1377721819 9648 80.91.229.3 (28 Aug 2013 20:30:19 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:19 +0000 (UTC) Cc: Kees Cook To: linux-input@vger.kernel.org Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:21 2013 Return-path: Envelope-to: glki-linux-input-2@plane.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VEmNg-0008U8-24 for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:21 +0200 Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754896Ab3H1UaT (ORCPT ); Wed, 28 Aug 2013 16:30:19 -0400 Original-Received: from cantor2.suse.de ([195.135.220.15]:57913 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752748Ab3H1UaS (ORCPT ); Wed, 28 Aug 2013 16:30:18 -0400 Original-Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id A94ACA531D; Wed, 28 Aug 2013 22:30:17 +0200 (CEST) User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) Original-Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Xref: news.gmane.org gmane.linux.kernel.input:31654 Archived-At: From: Kees Cook 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 Cc: stable@kernel.org --- drivers/hid/hid-zpff.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index 6ec28a3..b124991 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c @@ -68,22 +68,12 @@ static int zpff_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"); + report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 4, 1); + if (!report) 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; - } zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); if (!zpff) -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Path: news.gmane.org!not-for-mail From: Jiri Kosina Newsgroups: gmane.linux.kernel.input Subject: [PATCH 04/14] HID: sony: validate HID output report details Date: Wed, 28 Aug 2013 22:30:23 +0200 (CEST) Lines: 43 Approved: news@gmane.org Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: ger.gmane.org 1377721826 9710 80.91.229.3 (28 Aug 2013 20:30:26 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:26 +0000 (UTC) Cc: Kees Cook To: linux-input@vger.kernel.org Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:28 2013 Return-path: Envelope-to: glki-linux-input-2@plane.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VEmNn-0008U8-JR for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:27 +0200 Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754899Ab3H1Ua1 (ORCPT ); Wed, 28 Aug 2013 16:30:27 -0400 Original-Received: from cantor2.suse.de ([195.135.220.15]:57919 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753936Ab3H1Ua0 (ORCPT ); Wed, 28 Aug 2013 16:30:26 -0400 Original-Received: from relay1.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 02DB9A531D; Wed, 28 Aug 2013 22:30:26 +0200 (CEST) User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) Original-Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Xref: news.gmane.org gmane.linux.kernel.input:31655 Archived-At: From: Kees Cook 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 Cc: stable@kernel.org --- drivers/hid/hid-sony.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 87fbe29..b987926 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) drv_data = hid_get_drvdata(hdev); BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); + /* Validate expected report characteristics. */ + if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 0, 1, 7)) + return -ENODEV; + buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); if (!buzz) { hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Path: news.gmane.org!not-for-mail From: Jiri Kosina Newsgroups: gmane.linux.kernel.input Subject: [PATCH 05/14] HID: steelseries: validate output report details Date: Wed, 28 Aug 2013 22:30:37 +0200 (CEST) Lines: 43 Approved: news@gmane.org Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: ger.gmane.org 1377721849 9885 80.91.229.3 (28 Aug 2013 20:30:49 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 28 Aug 2013 20:30:49 +0000 (UTC) Cc: Kees Cook , Simon Wood To: linux-input@vger.kernel.org Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:30:51 2013 Return-path: Envelope-to: glki-linux-input-2@plane.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VEmO7-0000cl-Po for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:30:48 +0200 Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755238Ab3H1Uam (ORCPT ); Wed, 28 Aug 2013 16:30:42 -0400 Original-Received: from cantor2.suse.de ([195.135.220.15]:57942 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754222Ab3H1Uak (ORCPT ); Wed, 28 Aug 2013 16:30:40 -0400 Original-Received: from relay1.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id EFDE1A531D; Wed, 28 Aug 2013 22:30:39 +0200 (CEST) User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) Original-Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Xref: news.gmane.org gmane.linux.kernel.input:31656 Archived-At: From: Kees Cook 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 Cc: stable@kernel.org --- drivers/hid/hid-steelseries.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c index d164911..ef42e86 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, goto err_free; } + if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 0, 1, 16)) { + ret = -ENODEV; + goto err_free; + } + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { hid_err(hdev, "hw start failed\n"); -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Path: news.gmane.org!not-for-mail From: Jiri Kosina Newsgroups: gmane.linux.kernel.input Subject: [PATCH 07/14] HID: LG: validate HID output report details Date: Wed, 28 Aug 2013 22:31:00 +0200 (CEST) Lines: 194 Approved: news@gmane.org Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: ger.gmane.org 1377721865 10099 80.91.229.3 (28 Aug 2013 20:31:05 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:05 +0000 (UTC) Cc: Kees Cook To: linux-input@vger.kernel.org Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:07 2013 Return-path: Envelope-to: glki-linux-input-2@plane.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VEmOQ-0000cl-Fi for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:06 +0200 Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753468Ab3H1UbF (ORCPT ); Wed, 28 Aug 2013 16:31:05 -0400 Original-Received: from cantor2.suse.de ([195.135.220.15]:57957 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752780Ab3H1UbE (ORCPT ); Wed, 28 Aug 2013 16:31:04 -0400 Original-Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 5F1F5A531D; Wed, 28 Aug 2013 22:31:03 +0200 (CEST) User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) Original-Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Xref: news.gmane.org gmane.linux.kernel.input:31658 Archived-At: From: Kees Cook 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 Cc: stable@kernel.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(-) diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index b3cd150..9805197 100644 --- 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_report(hid, HID_OUTPUT_REPORT, 0, 1, 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) diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c index e52f181..53ac79b 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, 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_ac[] = { 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_report(hid, HID_OUTPUT_REPORT, 0, 1, 35)) + return -ENODEV; /* Assume single fixed device G940 */ for (i = 0; ff_bits[i] >= 0; i++) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 0ddae2a..8b89f0f 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 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"); + if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } /* Check what wheel has been connected */ for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index d7ea8c8..a84fb40 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) 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_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) + return -ENODEV; for (i = 0; i < ARRAY_SIZE(devices); i++) { if (dev->id.vendor == devices[i].idVendor && -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Path: news.gmane.org!not-for-mail From: Jiri Kosina Newsgroups: gmane.linux.kernel.input Subject: [PATCH 08/14] HID: lenovo-tpkbd: validate output report details Date: Wed, 28 Aug 2013 22:31:10 +0200 (CEST) Lines: 42 Approved: news@gmane.org Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: ger.gmane.org 1377721874 10167 80.91.229.3 (28 Aug 2013 20:31:14 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:14 +0000 (UTC) Cc: Kees Cook , Bernhard Seibold To: linux-input@vger.kernel.org Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:16 2013 Return-path: Envelope-to: glki-linux-input-2@plane.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VEmOY-0000cl-HM for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:14 +0200 Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754122Ab3H1UbN (ORCPT ); Wed, 28 Aug 2013 16:31:13 -0400 Original-Received: from cantor2.suse.de ([195.135.220.15]:57965 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752780Ab3H1UbN (ORCPT ); Wed, 28 Aug 2013 16:31:13 -0400 Original-Received: from relay1.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 982A1A531D; Wed, 28 Aug 2013 22:31:12 +0200 (CEST) User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) Original-Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Xref: news.gmane.org gmane.linux.kernel.input:31659 Archived-At: From: Kees Cook 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 Cc: stable@kernel.org --- drivers/hid/hid-lenovo-tpkbd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c index 07837f5..b697ada 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c @@ -341,6 +341,11 @@ static int tpkbd_probe_tp(struct hid_device *hdev) char *name_mute, *name_micmute; int ret; + /* Validate required reports. */ + if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 4, 4, 1) || + !hid_validate_report(hdev, HID_OUTPUT_REPORT, 3, 1, 2)) + return -ENODEV; + if (sysfs_create_group(&hdev->dev.kobj, &tpkbd_attr_group_pointer)) { hid_warn(hdev, "Could not create sysfs group\n"); -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Path: news.gmane.org!not-for-mail From: Jiri Kosina Newsgroups: gmane.linux.kernel.input Subject: [PATCH 09/14] HID: logitech-dj: validate output report details Date: Wed, 28 Aug 2013 22:31:18 +0200 (CEST) Lines: 65 Approved: news@gmane.org Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: ger.gmane.org 1377721883 10249 80.91.229.3 (28 Aug 2013 20:31:23 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:23 +0000 (UTC) Cc: Kees Cook , Nestor Lopez Casado To: linux-input@vger.kernel.org Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:25 2013 Return-path: Envelope-to: glki-linux-input-2@plane.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VEmOg-0000cl-O9 for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:23 +0200 Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752780Ab3H1UbW (ORCPT ); Wed, 28 Aug 2013 16:31:22 -0400 Original-Received: from cantor2.suse.de ([195.135.220.15]:57976 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751971Ab3H1UbV (ORCPT ); Wed, 28 Aug 2013 16:31:21 -0400 Original-Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id D53F8A531D; Wed, 28 Aug 2013 22:31:20 +0200 (CEST) User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) Original-Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Xref: news.gmane.org gmane.linux.kernel.input:31660 Archived-At: From: Kees Cook 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 Cc: stable@kernel.org --- drivers/hid/hid-logitech-dj.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index cd33084..7b99c2a 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, struct hid_report *report; struct hid_report_enum *output_report_enum; u8 *data = (u8 *)(&dj_report->device_index); - int i; + unsigned int i, length; output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; @@ -471,7 +471,9 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, return -ENODEV; } - for (i = 0; i < report->field[0]->report_count; i++) + length = min_t(size_t, sizeof(*dj_report) - 1, + report->field[0]->report_count); + for (i = 0; i < length; i++) report->field[0]->value[i] = data[i]; hid_hw_request(hdev, report, HID_REQ_SET_REPORT); @@ -783,6 +785,12 @@ static int logi_dj_probe(struct hid_device *hdev, goto hid_parse_fail; } + if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, + 1, 3)) { + 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); -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Path: news.gmane.org!not-for-mail From: Jiri Kosina Newsgroups: gmane.linux.kernel.input Subject: [PATCH 11/14] HID: multitouch: validate feature report details Date: Wed, 28 Aug 2013 22:31:37 +0200 (CEST) Lines: 77 Approved: news@gmane.org Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Trace: ger.gmane.org 1377721900 10409 80.91.229.3 (28 Aug 2013 20:31:40 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 28 Aug 2013 20:31:40 +0000 (UTC) Cc: Kees Cook , Henrik Rydberg , Benjamin Tissoires To: linux-input@vger.kernel.org Original-X-From: linux-input-owner@vger.kernel.org Wed Aug 28 22:31:42 2013 Return-path: Envelope-to: glki-linux-input-2@plane.gmane.org Original-Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VEmOz-0000cl-Ku for glki-linux-input-2@plane.gmane.org; Wed, 28 Aug 2013 22:31:42 +0200 Original-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754253Ab3H1Ubl (ORCPT ); Wed, 28 Aug 2013 16:31:41 -0400 Original-Received: from cantor2.suse.de ([195.135.220.15]:57991 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754222Ab3H1Ubk (ORCPT ); Wed, 28 Aug 2013 16:31:40 -0400 Original-Received: from relay1.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id BA511A535B; Wed, 28 Aug 2013 22:31:39 +0200 (CEST) User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) Original-Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Xref: news.gmane.org gmane.linux.kernel.input:31662 Archived-At: From: Kees Cook 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 CVE-2013-2897 Signed-off-by: Kees Cook Cc: stable@kernel.org --- drivers/hid/hid-multitouch.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index cb0e361..2aa275e 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -330,9 +330,18 @@ static void mt_feature_mapping(struct hid_device *hdev, break; } } + /* Ignore if value index is out of bounds. */ + if (td->inputmode_index < 0 || + td->inputmode_index >= field->report_count) { + dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); + td->inputmode = -1; + } break; case HID_DG_CONTACTMAX: + /* Ignore if value count is out of bounds. */ + if (field->report_count < 1) + break; td->maxcontact_report_id = field->report->id; td->maxcontacts = field->value[0]; if (!td->maxcontacts && @@ -743,15 +752,21 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) unsigned count; int r, n; + if (report->maxfield == 0) + return; + /* * Includes multi-packet support where subsequent * packets are sent with zero contactcount. */ - if (td->cc_index >= 0) { - struct hid_field *field = report->field[td->cc_index]; - int value = field->value[td->cc_value_index]; - if (value) - td->num_expected = value; + if (td->cc_index >= 0 && td->cc_index < report->maxfield) { + field = report->field[td->cc_index]; + if (td->cc_value_index >= 0 && + td->cc_value_index < field->report_count) { + int value = field->value[td->cc_value_index]; + if (value) + td->num_expected = value; + } } for (r = 0; r < report->maxfield; r++) { -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html