Olaf Hering d1425d
From: Haiyang Zhang <haiyangz@microsoft.com>
Olaf Hering d1425d
Date: Thu, 21 Nov 2019 13:33:41 -0800
Olaf Hering d1425d
Patch-mainline: v5.4
Olaf Hering d1425d
Subject: hv_netvsc: Fix send_table offset in case of a host bug
Olaf Hering d1425d
Git-commit: 171c1fd98df3d5948d9a9eb755274850fa5e59c6
Olaf Hering d1425d
References: bsc#1164598
Olaf Hering d1425d
Olaf Hering d1425d
If negotiated NVSP version <= NVSP_PROTOCOL_VERSION_6, the offset may
Olaf Hering d1425d
be wrong (too small) due to a host bug. This can cause missing the
Olaf Hering d1425d
end of the send indirection table, and add multiple zero entries from
Olaf Hering d1425d
leading zeros before the data region. This bug adds extra burden on
Olaf Hering d1425d
channel 0.
Olaf Hering d1425d
Olaf Hering d1425d
So fix the offset by computing it from the data structure sizes. This
Olaf Hering d1425d
will ensure netvsc driver runs normally on unfixed hosts, and future
Olaf Hering d1425d
fixed hosts.
Olaf Hering d1425d
Olaf Hering d1425d
Fixes: 5b54dac856cb ("hyperv: Add support for virtual Receive Side Scaling (vRSS)")
Olaf Hering d1425d
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Olaf Hering d1425d
Signed-off-by: David S. Miller <davem@davemloft.net>
Olaf Hering d1425d
Acked-by: Olaf Hering <ohering@suse.de>
Olaf Hering d1425d
---
Olaf Hering d1425d
 drivers/net/hyperv/netvsc.c | 16 ++++++++++++++--
Olaf Hering d1425d
 1 file changed, 14 insertions(+), 2 deletions(-)
Olaf Hering d1425d
Olaf Hering d1425d
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
Olaf Hering d1425d
--- a/drivers/net/hyperv/netvsc.c
Olaf Hering d1425d
+++ b/drivers/net/hyperv/netvsc.c
Olaf Hering d1425d
@@ -1178,6 +1178,7 @@ static int netvsc_receive(struct net_device *ndev,
Olaf Hering d1425d
 }
Olaf Hering d1425d
 
Olaf Hering d1425d
 static void netvsc_send_table(struct net_device *ndev,
Olaf Hering d1425d
+			      struct netvsc_device *nvscdev,
Olaf Hering d1425d
 			      const struct nvsp_message *nvmsg,
Olaf Hering d1425d
 			      u32 msglen)
Olaf Hering d1425d
 {
Olaf Hering d1425d
@@ -1193,6 +1194,16 @@ static void netvsc_send_table(struct net_device *ndev,
Olaf Hering d1425d
 		return;
Olaf Hering d1425d
 	}
Olaf Hering d1425d
 
Olaf Hering d1425d
+	/* If negotiated version <= NVSP_PROTOCOL_VERSION_6, the offset may be
Olaf Hering d1425d
+	 * wrong due to a host bug. So fix the offset here.
Olaf Hering d1425d
+	 */
Olaf Hering d1425d
+	if (nvscdev->nvsp_version <= NVSP_PROTOCOL_VERSION_6 &&
Olaf Hering d1425d
+	    msglen >= sizeof(struct nvsp_message_header) +
Olaf Hering d1425d
+	    sizeof(union nvsp_6_message_uber) + count * sizeof(u32))
Olaf Hering d1425d
+		offset = sizeof(struct nvsp_message_header) +
Olaf Hering d1425d
+			 sizeof(union nvsp_6_message_uber);
Olaf Hering d1425d
+
Olaf Hering d1425d
+	/* Boundary check for all versions */
Olaf Hering d1425d
 	if (offset > msglen - count * sizeof(u32)) {
Olaf Hering d1425d
 		netdev_err(ndev, "Received send-table offset too big:%u\n",
Olaf Hering d1425d
 			   offset);
Olaf Hering d1425d
@@ -1218,12 +1229,13 @@ static void netvsc_send_vf(struct net_device *ndev,
Olaf Hering d1425d
 }
Olaf Hering d1425d
 
Olaf Hering d1425d
 static void netvsc_receive_inband(struct net_device *ndev,
Olaf Hering d1425d
+				  struct netvsc_device *nvscdev,
Olaf Hering d1425d
 				  const struct nvsp_message *nvmsg,
Olaf Hering d1425d
 				  u32 msglen)
Olaf Hering d1425d
 {
Olaf Hering d1425d
 	switch (nvmsg->hdr.msg_type) {
Olaf Hering d1425d
 	case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
Olaf Hering d1425d
-		netvsc_send_table(ndev, nvmsg, msglen);
Olaf Hering d1425d
+		netvsc_send_table(ndev, nvscdev, nvmsg, msglen);
Olaf Hering d1425d
 		break;
Olaf Hering d1425d
 
Olaf Hering d1425d
 	case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
Olaf Hering d1425d
@@ -1257,7 +1269,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
Olaf Hering d1425d
 		break;
Olaf Hering d1425d
 
Olaf Hering d1425d
 	case VM_PKT_DATA_INBAND:
Olaf Hering d1425d
-		netvsc_receive_inband(ndev, nvmsg, msglen);
Olaf Hering d1425d
+		netvsc_receive_inband(ndev, net_device, nvmsg, msglen);
Olaf Hering d1425d
 		break;
Olaf Hering d1425d
 
Olaf Hering d1425d
 	default: