Skip to content

Commit 71f2195

Browse files
haiyangzdavem330
authored andcommitted
hv_netvsc: Fix offset usage in netvsc_send_table()
To reach the data region, the existing code adds offset in struct nvsp_5_send_indirect_table on the beginning of this struct. But the offset should be based on the beginning of its container, struct nvsp_message. This bug causes the first table entry missing, and adds an extra zero from the zero pad after the data region. This can put extra burden on the channel 0. So, correct the offset usage. Also add a boundary check to ensure not reading beyond data region. 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 35fc59c commit 71f2195

File tree

2 files changed

+20
-9
lines changed

2 files changed

+20
-9
lines changed

drivers/net/hyperv/hyperv_net.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,8 @@ struct nvsp_5_send_indirect_table {
609609
/* The number of entries in the send indirection table */
610610
u32 count;
611611

612-
/* The offset of the send indirection table from top of this struct.
612+
/* The offset of the send indirection table from the beginning of
613+
* struct nvsp_message.
613614
* The send indirection table tells which channel to put the send
614615
* traffic on. Each entry is a channel number.
615616
*/

drivers/net/hyperv/netvsc.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,20 +1178,28 @@ static int netvsc_receive(struct net_device *ndev,
11781178
}
11791179

11801180
static void netvsc_send_table(struct net_device *ndev,
1181-
const struct nvsp_message *nvmsg)
1181+
const struct nvsp_message *nvmsg,
1182+
u32 msglen)
11821183
{
11831184
struct net_device_context *net_device_ctx = netdev_priv(ndev);
1184-
u32 count, *tab;
1185+
u32 count, offset, *tab;
11851186
int i;
11861187

11871188
count = nvmsg->msg.v5_msg.send_table.count;
1189+
offset = nvmsg->msg.v5_msg.send_table.offset;
1190+
11881191
if (count != VRSS_SEND_TAB_SIZE) {
11891192
netdev_err(ndev, "Received wrong send-table size:%u\n", count);
11901193
return;
11911194
}
11921195

1193-
tab = (u32 *)((unsigned long)&nvmsg->msg.v5_msg.send_table +
1194-
nvmsg->msg.v5_msg.send_table.offset);
1196+
if (offset > msglen - count * sizeof(u32)) {
1197+
netdev_err(ndev, "Received send-table offset too big:%u\n",
1198+
offset);
1199+
return;
1200+
}
1201+
1202+
tab = (void *)nvmsg + offset;
11951203

11961204
for (i = 0; i < count; i++)
11971205
net_device_ctx->tx_table[i] = tab[i];
@@ -1209,12 +1217,13 @@ static void netvsc_send_vf(struct net_device *ndev,
12091217
net_device_ctx->vf_alloc ? "added" : "removed");
12101218
}
12111219

1212-
static void netvsc_receive_inband(struct net_device *ndev,
1213-
const struct nvsp_message *nvmsg)
1220+
static void netvsc_receive_inband(struct net_device *ndev,
1221+
const struct nvsp_message *nvmsg,
1222+
u32 msglen)
12141223
{
12151224
switch (nvmsg->hdr.msg_type) {
12161225
case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
1217-
netvsc_send_table(ndev, nvmsg);
1226+
netvsc_send_table(ndev, nvmsg, msglen);
12181227
break;
12191228

12201229
case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
@@ -1232,6 +1241,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
12321241
{
12331242
struct vmbus_channel *channel = nvchan->channel;
12341243
const struct nvsp_message *nvmsg = hv_pkt_data(desc);
1244+
u32 msglen = hv_pkt_datalen(desc);
12351245

12361246
trace_nvsp_recv(ndev, channel, nvmsg);
12371247

@@ -1247,7 +1257,7 @@ static int netvsc_process_raw_pkt(struct hv_device *device,
12471257
break;
12481258

12491259
case VM_PKT_DATA_INBAND:
1250-
netvsc_receive_inband(ndev, nvmsg);
1260+
netvsc_receive_inband(ndev, nvmsg, msglen);
12511261
break;
12521262

12531263
default:

0 commit comments

Comments
 (0)