lkml.org 
[lkml]   [2020]   [Dec]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 3/6] Drivers: hv: vmbus: Copy the hv_message in vmbus_on_msg_dpc()
    Date
    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>
    ---
    Changes since v2:
    - Revisit commit message and inline comment

    drivers/hv/vmbus_drv.c | 19 ++++++++++++++-----
    1 file changed, 14 insertions(+), 5 deletions(-)

    diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
    index 44bcf9ccdaf5f..b1c5a89d75f9d 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
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-12-09 08:13    [W:3.390 / U:23.492 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site