summaryrefslogtreecommitdiffstats
path: root/drivers/hv/channel.c
diff options
context:
space:
mode:
authorRick Edgecombe <rick.p.edgecombe@intel.com>2024-03-11 17:15:55 +0100
committerWei Liu <wei.liu@kernel.org>2024-04-10 23:33:32 +0200
commit211f514ebf1ef5de37b1cf6df9d28a56cfd242ca (patch)
tree80525894c4dc489e615d7a9ae83765c0a5ceb57d /drivers/hv/channel.c
parentDrivers: hv: vmbus: Leak pages if set_memory_encrypted() fails (diff)
downloadlinux-211f514ebf1ef5de37b1cf6df9d28a56cfd242ca.tar.xz
linux-211f514ebf1ef5de37b1cf6df9d28a56cfd242ca.zip
Drivers: hv: vmbus: Track decrypted status in vmbus_gpadl
In CoCo VMs it is possible for the untrusted host to cause set_memory_encrypted() or set_memory_decrypted() to fail such that an error is returned and the resulting memory is shared. Callers need to take care to handle these errors to avoid returning decrypted (shared) memory to the page allocator, which could lead to functional or security issues. In order to make sure callers of vmbus_establish_gpadl() and vmbus_teardown_gpadl() don't return decrypted/shared pages to allocators, add a field in struct vmbus_gpadl to keep track of the decryption status of the buffers. This will allow the callers to know if they should free or leak the pages. Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> Signed-off-by: Michael Kelley <mhklinux@outlook.com> Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Link: https://lore.kernel.org/r/20240311161558.1310-3-mhklinux@outlook.com Signed-off-by: Wei Liu <wei.liu@kernel.org> Message-ID: <20240311161558.1310-3-mhklinux@outlook.com>
Diffstat (limited to 'drivers/hv/channel.c')
-rw-r--r--drivers/hv/channel.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index adbf674355b2..98259b492502 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -436,9 +436,18 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
- if (ret)
+ if (ret) {
+ gpadl->decrypted = false;
return ret;
+ }
+ /*
+ * Set the "decrypted" flag to true for the set_memory_decrypted()
+ * success case. In the failure case, the encryption state of the
+ * memory is unknown. Leave "decrypted" as true to ensure the
+ * memory will be leaked instead of going back on the free list.
+ */
+ gpadl->decrypted = true;
ret = set_memory_decrypted((unsigned long)kbuffer,
PFN_UP(size));
if (ret) {
@@ -527,9 +536,15 @@ cleanup:
kfree(msginfo);
- if (ret)
- set_memory_encrypted((unsigned long)kbuffer,
- PFN_UP(size));
+ if (ret) {
+ /*
+ * If set_memory_encrypted() fails, the decrypted flag is
+ * left as true so the memory is leaked instead of being
+ * put back on the free list.
+ */
+ if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size)))
+ gpadl->decrypted = false;
+ }
return ret;
}
@@ -850,6 +865,8 @@ post_msg_err:
if (ret)
pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
+ gpadl->decrypted = ret;
+
return ret;
}
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);