Home / exploits Linux HID security flaws
Posted on 01 September 2013
<pre> I've found several issues in the Linux HID code. They are making their way into the Linux kernel via the linux-input tree now: http://marc.info/?l=linux-input&m=137772180514608&w=1 0001-HID-validate-HID-report-id-size.patch Signed-off-by: Kees Cook <keescook@chromium.org> Cc: stable@kernel.org --- drivers/hid/hid-core.c | 10 +++++++--- include/linux/hid.h | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 36668d1..5ea7d51 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -63,6 +63,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, struct hid_report_enum *report_enum = device->report_enum + type; struct hid_report *report; + if (id >= HID_MAX_IDS) + return NULL; if (report_enum->report_id_hash[id]) return report_enum->report_id_hash[id]; @@ -404,8 +406,10 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) case HID_GLOBAL_ITEM_TAG_REPORT_ID: parser->global.report_id = item_udata(item); - if (parser->global.report_id == 0) { - hid_err(parser->device, "report_id 0 is invalid "); + if (parser->global.report_id == 0 || + parser->global.report_id >= HID_MAX_IDS) { + hid_err(parser->device, "report_id %u is invalid ", + parser->global.report_id); return -1; } return 0; @@ -575,7 +579,7 @@ static void hid_close_report(struct hid_device *device) for (i = 0; i < HID_REPORT_TYPES; i++) { struct hid_report_enum *report_enum = device->report_enum + i; - for (j = 0; j < 256; j++) { + for (j = 0; j < HID_MAX_IDS; j++) { struct hid_report *report = report_enum->report_id_hash[j]; if (report) hid_free_report(report); diff --git a/include/linux/hid.h b/include/linux/hid.h index 0c48991..ff545cc 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -393,10 +393,12 @@ struct hid_report { struct hid_device *device; /* associated device */ }; +#define HID_MAX_IDS 256 + struct hid_report_enum { unsigned numbered; struct list_head report_list; - struct hid_report *report_id_hash[256]; + struct hid_report *report_id_hash[HID_MAX_IDS]; }; #define HID_REPORT_TYPES 3 CVE-2013-2888 Requires CONFIG_HID Memory write via arbitrary heap array index. This is the most serious, IMO, as it allows (on 32-bit) access to the entire memory range (the index is unsigned 32 bit). This is mitigated slightly by the fact that the starting address is at an "unknown" location on the heap, and that the value written is an "arbitrary" kernel pointer. Still, this could almost certainly be turned into full kernel execution given enough study. http://marc.info/?l=linux-input&m=137772181214612&w=1 0002-HID-provide-a-helper-for-validating-hid-reports.patch Routine that many of the driver fixes use to verify their report sanity. http://marc.info/?l=linux-input&m=137772182014614&w=1 0003-HID-zeroplus-validate-output-report-details.patch CVE-2013-2889 Requires CONFIG_HID_ZEROPLUS Small past-end-of-heap-alloc zeroing. http://marc.info/?l=linux-input&m=137772182814616&w=1 0004-HID-sony-validate-HID-output-report-details.patch CVE-2013-2890 Requires CONFIG_HID_SONY Small past-end-of-heap-alloc zeroing http://marc.info/?l=linux-input&m=137772184614622&w=1 0005-HID-steelseries-validate-output-report-details.patch CVE-2013-2891 Requires CONFIG_HID_STEELSERIES 16 byte past-end-of-heap-alloc zeroing http://marc.info/?l=linux-input&m=137772185414625&w=1 0006-HID-pantherlord-validate-output-report-details.patch CVE-2013-2892 Requires CONFIG_HID_PANTHERLORD Small past-end-of-heap-alloc zeroing http://marc.info/?l=linux-input&m=137772186714627&w=1 0007-HID-LG-validate-HID-output-report-details.patch CVE-2013-2893 Requires CONFIG_LOGITECH_FF or CONFIG_LOGIG940_FF or CONFIG_LOGIWHEELS_FF Userspace-assisted small past-end-of-heap-alloc zeroing http://marc.info/?l=linux-input&m=137772187514628&w=1 0008-HID-lenovo-tpkbd-validate-output-report-details.patch CVE-2013-2894 Requires CONFIG_HID_LENOVO_TPKBD Small past-end-of-heap-alloc zeroing http://marc.info/?l=linux-input&m=137772188314631&w=1 0009-HID-logitech-dj-validate-output-report-details.patch CVE-2013-2895 Requires CONFIG_HID_LOGITECH_DJ Can leak up to 12K of kernel memory contents to device, or NULL deref Oops DoS http://marc.info/?l=linux-input&m=137772189314633&w=1 0010-HID-ntrig-validate-feature-report-details.patch CVE-2013-2896 Requires CONFIG_HID_NTRIG Triggers NULL deref Oops DoS http://marc.info/?l=linux-input&m=137772190214635&w=1 0011-HID-multitouch-validate-feature-report-details.patch CVE-2013-2897 Requires CONFIG_HID_MULTITOUCH Slightly flexible heap overwrite with static value 0x2, or NULL deref Oops DoS http://marc.info/?l=linux-input&m=137772191114645&w=1 0012-HID-sensor-hub-validate-feature-report-details.patch CVE-2013-2898 Requires CONFIG_HID_SENSOR_HUB Potential kernel caller confusion via past-end-of-heap-allocation read http://marc.info/?l=linux-input&m=137772191714649&w=1 0013-HID-picolcd_core-validate-output-report-details.patch CVE-2013-2899 Requires CONFIG_HID_PICOLCD Userspace-assisted NULL deref Oops DoS http://marc.info/?t=137772196600012&r=1&w=1 0014-HID-check-for-NULL-field-when-setting-values.patch Just a defensive change, since several drivers would have been less vulnerable with this check. -Kees -- Kees Cook Chrome OS Security </pre>
