Skip to content

Commit 211f514

Browse files
rpedgecoliuw
authored andcommitted
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 <[email protected]> Signed-off-by: Michael Kelley <[email protected]> Reviewed-by: Kuppuswamy Sathyanarayanan <[email protected]> Acked-by: Kirill A. Shutemov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]> Message-ID: <[email protected]>
1 parent 03f5a99 commit 211f514

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

drivers/hv/channel.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,18 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
436436
(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
437437

438438
ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
439-
if (ret)
439+
if (ret) {
440+
gpadl->decrypted = false;
440441
return ret;
442+
}
441443

444+
/*
445+
* Set the "decrypted" flag to true for the set_memory_decrypted()
446+
* success case. In the failure case, the encryption state of the
447+
* memory is unknown. Leave "decrypted" as true to ensure the
448+
* memory will be leaked instead of going back on the free list.
449+
*/
450+
gpadl->decrypted = true;
442451
ret = set_memory_decrypted((unsigned long)kbuffer,
443452
PFN_UP(size));
444453
if (ret) {
@@ -527,9 +536,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
527536

528537
kfree(msginfo);
529538

530-
if (ret)
531-
set_memory_encrypted((unsigned long)kbuffer,
532-
PFN_UP(size));
539+
if (ret) {
540+
/*
541+
* If set_memory_encrypted() fails, the decrypted flag is
542+
* left as true so the memory is leaked instead of being
543+
* put back on the free list.
544+
*/
545+
if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size)))
546+
gpadl->decrypted = false;
547+
}
533548

534549
return ret;
535550
}
@@ -850,6 +865,8 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, struct vmbus_gpadl *gpad
850865
if (ret)
851866
pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
852867

868+
gpadl->decrypted = ret;
869+
853870
return ret;
854871
}
855872
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);

include/linux/hyperv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ struct vmbus_gpadl {
832832
u32 gpadl_handle;
833833
u32 size;
834834
void *buffer;
835+
bool decrypted;
835836
};
836837

837838
struct vmbus_channel {

0 commit comments

Comments
 (0)