mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
HID: core: fix number/pointer type confusion on long items
commit28abce9513upstream. When fetch_item() is called by hid_scan_report() on an item with HID_ITEM_TAG_LONG, it stores a pointer to the item data in item->data.longdata instead of storing a value directly in item->data.{u8/u16/u32}. When item_udata() or item_sdata() encounters such an item, it incorrectly assumes that the item is in short format, and therefore returns the lower part of a kernel pointer reinterpreted as a number. When a HID device is connected whose descriptor contains a HID_GLOBAL_ITEM_TAG_REPORT_SIZE encoded in long format with size=4, this causes the lower half of a kernel pointer to be printed into dmesg as a number, like this: hid (null): invalid report_size 107953555 To fix it, let item_udata() and item_sdata() verify that the item is in short format. Note that this bug only affects hid_scan_report(), while the main parsing pass hid_parse_collections() will always bail out when encountering a long item. Sidenote: There are currently no users of data.longdata; maybe we should just remove any parsing of long-format descriptors as a follow-up. Fixes:3dc8fc083d("HID: Use hid_parser for pre-scanning the report descriptors") Cc: stable@vger.kernel.org Signed-off-by: Jann Horn <jannh@google.com> Signed-off-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
bd397c4123
commit
abec577de5
@@ -344,6 +344,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
|
||||
|
||||
static u32 item_udata(struct hid_item *item)
|
||||
{
|
||||
if (item->format != HID_ITEM_FORMAT_SHORT)
|
||||
return 0;
|
||||
|
||||
switch (item->size) {
|
||||
case 1: return item->data.u8;
|
||||
case 2: return item->data.u16;
|
||||
@@ -354,6 +357,9 @@ static u32 item_udata(struct hid_item *item)
|
||||
|
||||
static s32 item_sdata(struct hid_item *item)
|
||||
{
|
||||
if (item->format != HID_ITEM_FORMAT_SHORT)
|
||||
return 0;
|
||||
|
||||
switch (item->size) {
|
||||
case 1: return item->data.s8;
|
||||
case 2: return item->data.s16;
|
||||
|
||||
Reference in New Issue
Block a user