mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
HID: hyperv: validate initial device info bounds
The Hyper-V synthetic HID host supplies SYNTH_HID_INITIAL_DEVICE_INFO
messages that contain a HID descriptor followed by the report descriptor
bytes. mousevsc_on_receive_device_info() trusts bLength and
wDescriptorLength without checking that the received packet contains both
byte ranges.
A malformed host or backend message can therefore make the guest read
past the received VMBus packet while copying the report descriptor. Pass
the received initial-device-info size into the parser and reject
descriptor lengths that exceed the packet.
Impact: A malicious Hyper-V host or backend can crash a guest by sending
a short initial device-info message with an oversized HID report
descriptor length.
Fixes: b95f5bcb81 ("HID: Move the hid-hyperv driver out of staging")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5-5-xhigh
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
parent
091c05c184
commit
934b7778aa
|
|
@ -171,18 +171,32 @@ static void mousevsc_free_device(struct mousevsc_dev *device)
|
|||
}
|
||||
|
||||
static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
|
||||
struct synthhid_device_info *device_info)
|
||||
struct synthhid_device_info *device_info,
|
||||
u32 device_info_size)
|
||||
{
|
||||
int ret = 0;
|
||||
struct hid_descriptor *desc;
|
||||
struct mousevsc_prt_msg ack;
|
||||
size_t desc_offset;
|
||||
size_t desc_size;
|
||||
|
||||
input_device->dev_info_status = -ENOMEM;
|
||||
|
||||
if (device_info_size < sizeof(*device_info)) {
|
||||
input_device->dev_info_status = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
input_device->hid_dev_info = device_info->hid_dev_info;
|
||||
desc = &device_info->hid_descriptor;
|
||||
desc_offset = offsetof(struct synthhid_device_info, hid_descriptor);
|
||||
desc_size = device_info_size - desc_offset;
|
||||
if (desc->bLength == 0)
|
||||
goto cleanup;
|
||||
if (desc->bLength < sizeof(*desc) || desc->bLength > desc_size) {
|
||||
input_device->dev_info_status = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* The pointer is not NULL when we resume from hibernation */
|
||||
kfree(input_device->hid_desc);
|
||||
|
|
@ -197,6 +211,10 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
|
|||
input_device->dev_info_status = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
if (input_device->report_desc_size > desc_size - desc->bLength) {
|
||||
input_device->dev_info_status = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* The pointer is not NULL when we resume from hibernation */
|
||||
kfree(input_device->report_desc);
|
||||
|
|
@ -273,14 +291,17 @@ static void mousevsc_on_receive(struct hv_device *device,
|
|||
break;
|
||||
|
||||
case SYNTH_HID_INITIAL_DEVICE_INFO:
|
||||
WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info));
|
||||
if (WARN_ON_ONCE(pipe_msg->size <
|
||||
sizeof(struct synthhid_device_info)))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Parse out the device info into device attr,
|
||||
* hid desc and report desc
|
||||
*/
|
||||
mousevsc_on_receive_device_info(input_dev,
|
||||
(struct synthhid_device_info *)pipe_msg->data);
|
||||
(struct synthhid_device_info *)pipe_msg->data,
|
||||
pipe_msg->size);
|
||||
break;
|
||||
case SYNTH_HID_INPUT_REPORT:
|
||||
input_report =
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user