* [PATCH 0/2] hv_netvsc: Fix leaking of send/receive buffers after GPADL teardown error
@ 2026-09-03 16:06 Michael Kelley
2026-09-03 16:06 ` [PATCH 1/2] Drivers: hv: Add vmbus_leak_buffer() Michael Kelley
2026-09-03 16:06 ` [PATCH net 2/2] hv_netvsc: Leak send/recv buffers if GPADL teardown fails Michael Kelley
0 siblings, 2 replies; 3+ messages in thread
From: Michael Kelley @ 2026-09-03 16:06 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
edumazet, kuba, pabeni
Cc: linux-hyperv, linux-kernel, netdev
When a Hyper-V netvsc device is shutdown, the GPADLs for the device's
large send and receive buffers are torn down. If the teardown fails,
Hyper-V retain access to the buffers and may continue to read or write
them. Consequently the buffers should be leaked after such an error.
Leaking the buffers used to work correctly, but was broken by a
commit applied in the 4.16 kernel. This patch series restores the
correct leaking behavior.
Because the large buffers are allocated with wrapper functions
that allow allocations larger than MAX_ORDER_NR_PAGES, leaking the
memory is not as simple as setting the memory pointer to NULL so
vfree() or kfree() does nothing. Patch 1 introduces a new
vmbus_leak_buffer() function that causes vmbus_free_buffer() to
properly leak the buffers. Then Patch 2 uses this function in
the netvsc driver.
Michael Kelley (2):
Drivers: hv: Add vmbus_leak_buffer()
hv_netvsc: Leak send/recv buffers if GPADL teardown fails
drivers/hv/channel.c | 26 ++++++++++++++++++++++++++
drivers/net/hyperv/netvsc.c | 6 ++++++
include/linux/hyperv.h | 4 ++++
3 files changed, 36 insertions(+)
--
2.25.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] Drivers: hv: Add vmbus_leak_buffer()
2026-09-03 16:06 [PATCH 0/2] hv_netvsc: Fix leaking of send/receive buffers after GPADL teardown error Michael Kelley
@ 2026-09-03 16:06 ` Michael Kelley
2026-09-03 16:06 ` [PATCH net 2/2] hv_netvsc: Leak send/recv buffers if GPADL teardown fails Michael Kelley
1 sibling, 0 replies; 3+ messages in thread
From: Michael Kelley @ 2026-09-03 16:06 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
edumazet, kuba, pabeni
Cc: linux-hyperv, linux-kernel, netdev
If an error case needs to leak the buffer memory allocated by
vmbus_alloc_buffer(), doing so requires knowledge of how
vmbus_free_buffer() works. In a CoCo VM buffers are allocated
differently from a normal VM, and vmbus_free_buffer() handles
the difference.
Encapsulate this knowledge in a new function, vmbus_leak_buffer(),
that error paths can call. After calling vmbus_leak_buffer(), a
subsequent call to vmbus_free_buffer() frees the additional
resources used in the CoCo VM case but does not free the actual
buffer memory. As such, vmbus_leak_buffer() is callable in a
context where accesses to the buffer memory may be in flight.
Signed-off-by: Michael Kelley <mhklinux@outlook.com>
---
drivers/hv/channel.c | 26 ++++++++++++++++++++++++++
include/linux/hyperv.h | 4 ++++
2 files changed, 30 insertions(+)
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index f4370617deac..d5d20e322831 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -648,6 +648,32 @@ void vmbus_free_buffer(void *addr, struct page **chunks, u32 chunk_cnt)
}
EXPORT_SYMBOL_GPL(vmbus_free_buffer);
+/**
+ * vmbus_leak_buffer - set up a buffer to be leaked by vmbus_free_buffer().
+ *
+ * @addr: buffer address
+ * @chunks: chunks array from vmbus_alloc_buffer()
+ * @chunk_cnt: number of entries in @chunks
+ *
+ * When @chunks is NULL the buffer is a plain vzalloc() allocation and
+ * the buffer is leaked by setting @addr to NULL. Otherwise set
+ * @chunk_cnt to 0 so that vmbus_free_buffer() does not try to re-encrypt
+ * or free the buffer memory, but still releases the vmap address and
+ * the chunks memory.
+ *
+ * This function may be called in a context where the buffer is still
+ * being accessed. It must not remove any kernel virtual addresses of
+ * the buffer or change its encryption status.
+ */
+void vmbus_leak_buffer(void **addr, struct page ***chunks, u32 *chunk_cnt)
+{
+ if (*chunks)
+ *chunk_cnt = 0;
+ else
+ *addr = NULL;
+}
+EXPORT_SYMBOL_GPL(vmbus_leak_buffer);
+
/**
* vmbus_alloc_buffer - allocate a host-visible, virtually-contiguous buffer.
*
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index e61f9a4cb7c3..c55de4d01cbb 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1220,6 +1220,10 @@ extern void *vmbus_alloc_buffer(struct vmbus_channel *channel,
extern void vmbus_free_buffer(void *addr, struct page **chunks, u32 chunk_cnt);
+extern void vmbus_leak_buffer(void **addr,
+ struct page ***chunks,
+ u32 *chunk_cnt);
+
void vmbus_reset_channel_cb(struct vmbus_channel *channel);
extern int vmbus_recvpacket(struct vmbus_channel *channel,
--
2.25.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH net 2/2] hv_netvsc: Leak send/recv buffers if GPADL teardown fails
2026-09-03 16:06 [PATCH 0/2] hv_netvsc: Fix leaking of send/receive buffers after GPADL teardown error Michael Kelley
2026-09-03 16:06 ` [PATCH 1/2] Drivers: hv: Add vmbus_leak_buffer() Michael Kelley
@ 2026-09-03 16:06 ` Michael Kelley
1 sibling, 0 replies; 3+ messages in thread
From: Michael Kelley @ 2026-09-03 16:06 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, andrew+netdev, davem,
edumazet, kuba, pabeni
Cc: linux-hyperv, linux-kernel, netdev
If GPADL teardown fails for the send or receive buffers, the Hyper-V
host retains access to the buffers and might continue to access them.
Per the code comments, the intent is to be safe by leaking the buffers
instead of freeing them.
The intended behavior existed prior to commit 02400fcee254 ("hv_netvsc:
use RCU to fix concurrent rx and queue changes") because freeing
the buffers was done in the same function as the GPADL teardown.
The "return" statement in the error path effectively skipped freeing
the memory. But commit 02400fcee254 moved the freeing to a separate
function that is called later. It has no knowledge of the GPADL teardown
error, and so frees the memory regardless.
Fix this by calling vmbus_leak_buffer() if the respective GPADL
teardown fails. The later call to vmbus_free_buffer() then skips
freeing of the actual buffer, including any re-encryption required
in a CoCo VM.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/linux-hyperv/20260731201210.3653C1F00AC4@smtp.kernel.org/
Fixes: 02400fcee254 ("hv_netvsc: use RCU to fix concurrent rx and queue changes")
Signed-off-by: Michael Kelley <mhklinux@outlook.com>
---
drivers/net/hyperv/netvsc.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 5cd084e5696c..449dc928cc44 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -316,6 +316,9 @@ static void netvsc_teardown_recv_gpadl(struct hv_device *device,
* rather than continue and a bugchk
*/
if (ret != 0) {
+ vmbus_leak_buffer(&net_device->recv_buf,
+ &net_device->recv_buf_chunks,
+ &net_device->recv_buf_chunk_cnt);
netdev_err(ndev,
"unable to teardown receive buffer's gpadl\n");
return;
@@ -337,6 +340,9 @@ static void netvsc_teardown_send_gpadl(struct hv_device *device,
* rather than continue and a bugchk
*/
if (ret != 0) {
+ vmbus_leak_buffer(&net_device->send_buf,
+ &net_device->send_buf_chunks,
+ &net_device->send_buf_chunk_cnt);
netdev_err(ndev,
"unable to teardown send buffer's gpadl\n");
return;
--
2.25.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-03 16:07 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 16:06 [PATCH 0/2] hv_netvsc: Fix leaking of send/receive buffers after GPADL teardown error Michael Kelley
2026-09-03 16:06 ` [PATCH 1/2] Drivers: hv: Add vmbus_leak_buffer() Michael Kelley
2026-09-03 16:06 ` [PATCH net 2/2] hv_netvsc: Leak send/recv buffers if GPADL teardown fails Michael Kelley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox