* [PATCH] hv: hv_balloon: validate unballoon range count
@ 2026-07-10 2:29 Michael Bommarito
2026-07-11 18:09 ` Michael Kelley
0 siblings, 1 reply; 2+ messages in thread
From: Michael Bommarito @ 2026-07-10 2:29 UTC (permalink / raw)
To: kys, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li
Cc: Greg Kroah-Hartman, linux-hyperv, linux-kernel, stable
The Hyper-V dynamic memory host supplies DM_UNBALLOON_REQUEST messages
with a header size and a range_count field. balloon_down() trusts
range_count and walks req->range_array without checking that the received
message contains that many ranges.
A malformed host or backend message can therefore make the guest read
past the received VMBus packet while freeing balloon ranges. Validate the
received message size and reject range_count values that exceed the
present range array before walking it.
Impact: A malicious Hyper-V host or backend can crash a guest by sending
a short unballoon request with an oversized range_count.
Fixes: 9aa8b50b2b3d ("Drivers: hv: Add Hyper-V balloon driver")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5-5-xhigh
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/hv/hv_balloon.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index a848400a59a2d..f5bc8c9fea7b9 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -1337,8 +1337,23 @@ static void balloon_up(struct work_struct *dummy)
}
}
+static bool unballoon_request_valid(struct dm_unballoon_request *req,
+ u32 msg_size)
+{
+ u32 max_ranges;
+
+ if (msg_size < sizeof(*req) || req->hdr.size < sizeof(*req) ||
+ req->hdr.size > msg_size)
+ return false;
+
+ max_ranges = (req->hdr.size - sizeof(*req)) /
+ sizeof(req->range_array[0]);
+
+ return req->range_count <= max_ranges;
+}
+
static void balloon_down(struct hv_dynmem_device *dm,
- struct dm_unballoon_request *req)
+ struct dm_unballoon_request *req, u32 msg_size)
{
union dm_mem_page_range *range_array = req->range_array;
int range_count = req->range_count;
@@ -1346,6 +1361,12 @@ static void balloon_down(struct hv_dynmem_device *dm,
int i;
unsigned int prev_pages_ballooned = dm->num_pages_ballooned;
+ if (!unballoon_request_valid(req, msg_size)) {
+ pr_warn_ratelimited("Invalid unballoon request: size %u, header size %u, range count %u\n",
+ msg_size, req->hdr.size, req->range_count);
+ return;
+ }
+
for (i = 0; i < range_count; i++) {
free_balloon_pages(dm, &range_array[i]);
complete(&dm_device.config_event);
@@ -1527,7 +1548,8 @@ static void balloon_onchannelcallback(void *context)
dm->state = DM_BALLOON_DOWN;
balloon_down(dm,
- (struct dm_unballoon_request *)recv_buffer);
+ (struct dm_unballoon_request *)recv_buffer,
+ recvlen);
break;
case DM_MEM_HOT_ADD_REQUEST:
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* RE: [PATCH] hv: hv_balloon: validate unballoon range count
2026-07-10 2:29 [PATCH] hv: hv_balloon: validate unballoon range count Michael Bommarito
@ 2026-07-11 18:09 ` Michael Kelley
0 siblings, 0 replies; 2+ messages in thread
From: Michael Kelley @ 2026-07-11 18:09 UTC (permalink / raw)
To: Michael Bommarito, kys@microsoft.com, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li
Cc: Greg Kroah-Hartman, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org
From: Michael Bommarito <michael.bommarito@gmail.com> Sent: Thursday, July 9, 2026 7:29 PM
>
> The Hyper-V dynamic memory host supplies DM_UNBALLOON_REQUEST messages
> with a header size and a range_count field. balloon_down() trusts
> range_count and walks req->range_array without checking that the received
> message contains that many ranges.
>
> A malformed host or backend message can therefore make the guest read
> past the received VMBus packet while freeing balloon ranges. Validate the
> received message size and reject range_count values that exceed the
> present range array before walking it.
Same comment applies here as I wrote for your proposed validations for
the Hyper-V mouse driver. The balloon driver also has .allowed_in_isolated
set to false, so it isn't loaded in a CoCo VM and it hasn't been hardened
for the "untrusted host" threat model.
Michael
>
> Impact: A malicious Hyper-V host or backend can crash a guest by sending
> a short unballoon request with an oversized range_count.
>
> Fixes: 9aa8b50b2b3d ("Drivers: hv: Add Hyper-V balloon driver")
> Cc: stable@vger.kernel.org
> Assisted-by: Codex:gpt-5-5-xhigh
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
> ---
> drivers/hv/hv_balloon.c | 26 ++++++++++++++++++++++++--
> 1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
> index a848400a59a2d..f5bc8c9fea7b9 100644
> --- a/drivers/hv/hv_balloon.c
> +++ b/drivers/hv/hv_balloon.c
> @@ -1337,8 +1337,23 @@ static void balloon_up(struct work_struct *dummy)
> }
> }
>
> +static bool unballoon_request_valid(struct dm_unballoon_request *req,
> + u32 msg_size)
> +{
> + u32 max_ranges;
> +
> + if (msg_size < sizeof(*req) || req->hdr.size < sizeof(*req) ||
> + req->hdr.size > msg_size)
> + return false;
> +
> + max_ranges = (req->hdr.size - sizeof(*req)) /
> + sizeof(req->range_array[0]);
> +
> + return req->range_count <= max_ranges;
> +}
> +
> static void balloon_down(struct hv_dynmem_device *dm,
> - struct dm_unballoon_request *req)
> + struct dm_unballoon_request *req, u32 msg_size)
> {
> union dm_mem_page_range *range_array = req->range_array;
> int range_count = req->range_count;
> @@ -1346,6 +1361,12 @@ static void balloon_down(struct hv_dynmem_device *dm,
> int i;
> unsigned int prev_pages_ballooned = dm->num_pages_ballooned;
>
> + if (!unballoon_request_valid(req, msg_size)) {
> + pr_warn_ratelimited("Invalid unballoon request: size %u, header size
> %u, range count %u\n",
> + msg_size, req->hdr.size, req->range_count);
> + return;
> + }
> +
> for (i = 0; i < range_count; i++) {
> free_balloon_pages(dm, &range_array[i]);
> complete(&dm_device.config_event);
> @@ -1527,7 +1548,8 @@ static void balloon_onchannelcallback(void *context)
>
> dm->state = DM_BALLOON_DOWN;
> balloon_down(dm,
> - (struct dm_unballoon_request *)recv_buffer);
> + (struct dm_unballoon_request *)recv_buffer,
> + recvlen);
> break;
>
> case DM_MEM_HOT_ADD_REQUEST:
> --
> 2.53.0
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-11 18:09 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-10 2:29 [PATCH] hv: hv_balloon: validate unballoon range count Michael Bommarito
2026-07-11 18:09 ` Michael Kelley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox