In vmbus_teardown_gpadl(), the return value from vmbus_post_msg() is overwritten by the logic that decides if set_memory_encrypted() should run. A failure from vmbus_post_msg() is lost and vmbus_teardown_gpadl() may incorrectly report success. Furthermore, if vmbus_post_msg() fails, the GPADL remains active on the Hyper-V side, yet in a CoCo VM the buffer will be re-encrypted anyway.
Fix this by gating buffer re-encryption on success from vmbus_post_msg(). And if either function fails, mark the buffer as decrypted so the memory will be leaked. The decrypted flag does double-duty: in a CoCo VM it indicates the decryption status, but at buffer cleanup time in all VMs it is a "should be leaked due to error" flag. Reported-by: Sashiko <[email protected]> Closes: https://lore.kernel.org/linux-hyperv/[email protected]/ Fixes: d4dccf353db8 ("Drivers: hv: vmbus: Mark vmbus ring buffer visible to host in Isolation VM") Signed-off-by: Michael Kelley <[email protected]> --- drivers/hv/channel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index f4370617deac..cc86e8505ad0 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -1059,14 +1059,14 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, struct vmbus_gpadl *gpad kfree(info); - if (gpadl->decrypted) + if (!ret && gpadl->decrypted) { ret = set_memory_encrypted((unsigned long)gpadl->buffer, PFN_UP(gpadl->size)); - else - ret = 0; - if (ret) - pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret); + if (ret) + pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret); + } + /* If error in ret, mark buffer decrypted so it is leaked */ gpadl->decrypted = ret; return ret; -- 2.25.1

