summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Bommarito <michael.bommarito@gmail.com>2026-07-09 22:28:53 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-08-27 14:34:40 +0200
commit2529737763cb4bcfcaf397beeea2664656c865b4 (patch)
tree6836b358dfb6f2b8082a107f14a7b8b4a97fb3b0
parentf1b3ca06380531f49f988f4721d3ed30b0d7a5d2 (diff)
downloadlinux-2529737763cb4bcfcaf397beeea2664656c865b4.tar.gz
linux-2529737763cb4bcfcaf397beeea2664656c865b4.zip
HID: hyperv: validate initial device info bounds
commit 934b7778aa7b7c8f6bb073d2a73ba3674885bae0 upstream. 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: b95f5bcb811e ("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/hid/hid-hyperv.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index 7d2b0063df15..fd90196430e2 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -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 =