[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <87eebh9qhd.fsf@vitty.brq.redhat.com>
Date: Thu, 29 Jul 2021 15:52:46 +0200
From: Vitaly Kuznetsov <vkuznets@...hat.com>
To: Siddharth Chandrasekaran <sidcha@...zon.de>
Cc: Siddharth Chandrasekaran <sidcha.dev@...il.com>,
Liran Alon <liran@...zon.com>,
Ioannis Aslanidis <iaslan@...zon.de>,
linux-hyperv@...r.kernel.org, linux-arch@...r.kernel.org,
linux-kernel@...r.kernel.org,
Siddharth Chandrasekaran <sidcha@...zon.de>,
"K. Y. Srinivasan" <kys@...rosoft.com>,
Haiyang Zhang <haiyangz@...rosoft.com>,
Stephen Hemminger <sthemmin@...rosoft.com>,
Wei Liu <wei.liu@...nel.org>, Dexuan Cui <decui@...rosoft.com>,
Arnd Bergmann <arnd@...db.de>
Subject: Re: [PATCH] asm-generic/hyperv: Fix struct hv_message_header ordering
Siddharth Chandrasekaran <sidcha@...zon.de> writes:
> According to Hyper-V TLFS Version 6.0b, struct hv_message_header members
> should be defined in the order:
>
> message_type, reserved, message_flags, payload_size
>
> but we have it defined in the order:
>
> message_type, payload_size, message_flags, reserved
>
> that is, the payload_size and reserved members swapped.
Indeed,
typedef struct
{
HV_MESSAGE_TYPE MessageType;
UINT16 Reserved;
HV_MESSAGE_FLAGS MessageFlags;
UINT8 PayloadSize;
union
{
UINT64 OriginationId;
HV_PARTITION_ID Sender;
HV_PORT_ID Port;
};
} HV_MESSAGE_HEADER;
> Due to this mix
> up, we were inadvertently causing two issues:
>
> - The payload_size field has invalid data; it didn't cause an issue
> so far because we are delivering only timer messages which has fixed
> size payloads the guest probably did a sizeof(payload) instead
> relying on the value of payload_size member.
>
> - The message_flags was always delivered as 0 to the guest;
> fortunately, according to section 13.3.1 message_flags is also
> treated as a reserved field.
>
> Although this is not causing an issue now, it might in future (we are
> adding more message types in our VSM implementation) so fix it to
> reflect the specification.
I'm wondering how this works for Linux-on-Hyper-V as
e.g. vmbus_on_msg_dpc() checks for mininum and maximum payload length:
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;
}
entry = &channel_message_table[msgtype];
if (!entry->message_handler)
goto msg_handled;
if (payload_size < entry->min_payload_len) {
WARN_ONCE(1, "message too short: msgtype=%d len=%d\n", msgtype, payload_size);
goto msg_handled;
}
Maybe it's vice versa, the header is correct and the documentation is wrong?
>
> Signed-off-by: Siddharth Chandrasekaran <sidcha@...zon.de>
> ---
> include/asm-generic/hyperv-tlfs.h | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h
> index 56348a541c50..a5540e9b171f 100644
> --- a/include/asm-generic/hyperv-tlfs.h
> +++ b/include/asm-generic/hyperv-tlfs.h
> @@ -284,9 +284,9 @@ union hv_port_id {
> /* Define synthetic interrupt controller message header. */
> struct hv_message_header {
> __u32 message_type;
> - __u8 payload_size;
> - union hv_message_flags message_flags;
> __u8 reserved[2];
> + union hv_message_flags message_flags;
> + __u8 payload_size;
> union {
> __u64 sender;
> union hv_port_id port;
--
Vitaly
Powered by blists - more mailing lists