Skip to content

Commit 171c1fd

Browse files
haiyangzdavem330
authored andcommitted
hv_netvsc: Fix send_table offset in case of a host bug
If negotiated NVSP version <= NVSP_PROTOCOL_VERSION_6, the offset may be wrong (too small) due to a host bug. This can cause missing the end of the send indirection table, and add multiple zero entries from leading zeros before the data region. This bug adds extra burden on channel 0. So fix the offset by computing it from the data structure sizes. This will ensure netvsc driver runs normally on unfixed hosts, and future fixed hosts. Fixes: 5b54dac ("hyperv: Add support for virtual Receive Side Scaling (vRSS)") Signed-off-by: Haiyang Zhang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 71f2195 commit 171c1fd

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

drivers/net/hyperv/netvsc.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,7 @@ static int netvsc_receive(struct net_device *ndev,
11781178
}
11791179

11801180
static void netvsc_send_table(struct net_device *ndev,
1181+
struct netvsc_device *nvscdev,
11811182
const struct nvsp_message *nvmsg,
11821183
u32 msglen)
11831184
{
@@ -1193,6 +1194,16 @@ static void netvsc_send_table(struct net_device *ndev,
11931194
return;
11941195
}
11951196

1197+
/* If negotiated version <= NVSP_PROTOCOL_VERSION_6, the offset may be
1198+
* wrong due to a host bug. So fix the offset here.
1199+
*/
1200+
if (nvscdev->nvsp_version <= NVSP_PROTOCOL_VERSION_6 &&
1201+
msglen >= sizeof(struct nvsp_message_header) +
1202+
sizeof(union nvsp_6_message_uber) + count * sizeof(u32))
1203+
offset = sizeof(struct nvsp_message_header) +
1204+
sizeof(union nvsp_6_message_uber);
1205+
1206+
/* Boundary check for all versions */
11961207
if (offset > msglen - count * sizeof(u32)) {
11971208
netdev_err(ndev, "Received send-table offset too big:%u\n",
11981209
offset);
@@ -1218,12 +1229,13 @@ static void netvsc_send_vf(struct net_device *ndev,
12181229
}
12191230

12201231
static void netvsc_receive_inband(struct net_device *ndev,
1232+
struct netvsc_device *nvscdev,
12211233
const struct nvsp_message *nvmsg,
12221234
u32 msglen)
12231235
{
12241236
switch (nvmsg->hdr.msg_type) {
12251237
case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
1226-
netvsc_send_table(ndev, nvmsg, msglen);
1238+
netvsc_send_table(ndev, nvscdev, nvmsg, msglen);
12271239
break;
12281240

12291241
case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
@@ -1257,7 +1269,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
12571269
break;
12581270

12591271
case VM_PKT_DATA_INBAND:
1260-
netvsc_receive_inband(ndev, nvmsg, msglen);
1272+
netvsc_receive_inband(ndev, net_device, nvmsg, msglen);
12611273
break;
12621274

12631275
default:

0 commit comments

Comments
 (0)