diff options
author | Andrea Parri (Microsoft) <parri.andrea@gmail.com> | 2020-12-09 08:08:24 +0100 |
---|---|---|
committer | Wei Liu <wei.liu@kernel.org> | 2021-02-05 09:55:42 +0000 |
commit | fe8c1b18a27de4d6ca5d99b3ffb3125dc69a5b76 (patch) | |
tree | dd42a4e48da160d4dc2c8a6636350dcfc59117e5 /drivers/hv/vmbus_drv.c | |
parent | 9c400d3548c39378327268fb18112b229f91b220 (diff) | |
download | linux-next-fe8c1b18a27de4d6ca5d99b3ffb3125dc69a5b76.tar.gz |
Drivers: hv: vmbus: Copy the hv_message in vmbus_on_msg_dpc()
Since the message is in memory shared with the host, an erroneous or a
malicious Hyper-V could 'corrupt' the message while vmbus_on_msg_dpc()
or individual message handlers are executing. To prevent it, copy the
message into private memory.
Reported-by: Juan Vazquez <juvazq@microsoft.com>
Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/20201209070827.29335-4-parri.andrea@gmail.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Diffstat (limited to 'drivers/hv/vmbus_drv.c')
-rw-r--r-- | drivers/hv/vmbus_drv.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 9749cbce33d4..4b0f2065a4bd 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1054,14 +1054,14 @@ void vmbus_on_msg_dpc(unsigned long data) { struct hv_per_cpu_context *hv_cpu = (void *)data; void *page_addr = hv_cpu->synic_message_page; - struct hv_message *msg = (struct hv_message *)page_addr + + struct hv_message msg_copy, *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; struct vmbus_channel_message_header *hdr; enum vmbus_channel_message_type msgtype; const struct vmbus_channel_message_table_entry *entry; struct onmessage_work_context *ctx; - u32 message_type = msg->header.message_type; __u8 payload_size; + u32 message_type; /* * 'enum vmbus_channel_message_type' is supposed to always be 'u32' as @@ -1070,11 +1070,20 @@ void vmbus_on_msg_dpc(unsigned long data) */ BUILD_BUG_ON(sizeof(enum vmbus_channel_message_type) != sizeof(u32)); + /* + * Since the message is in memory shared with the host, an erroneous or + * malicious Hyper-V could modify the message while vmbus_on_msg_dpc() + * or individual message handlers are executing; to prevent this, copy + * the message into private memory. + */ + memcpy(&msg_copy, msg, sizeof(struct hv_message)); + + message_type = msg_copy.header.message_type; if (message_type == HVMSG_NONE) /* no msg */ return; - hdr = (struct vmbus_channel_message_header *)msg->u.payload; + hdr = (struct vmbus_channel_message_header *)msg_copy.u.payload; msgtype = hdr->msgtype; trace_vmbus_on_msg_dpc(hdr); @@ -1084,7 +1093,7 @@ void vmbus_on_msg_dpc(unsigned long data) goto msg_handled; } - payload_size = msg->header.payload_size; + payload_size = msg_copy.header.payload_size; if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT) { WARN_ONCE(1, "payload size is too large (%d)\n", payload_size); goto msg_handled; @@ -1106,7 +1115,7 @@ void vmbus_on_msg_dpc(unsigned long data) return; INIT_WORK(&ctx->work, vmbus_onmessage_work); - memcpy(&ctx->msg, msg, sizeof(msg->header) + payload_size); + memcpy(&ctx->msg, &msg_copy, sizeof(msg->header) + payload_size); /* * The host can generate a rescind message while we |