hc
2024-05-16 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb
kernel/drivers/net/hyperv/netvsc.c
....@@ -1,17 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2009, Microsoft Corporation.
3
- *
4
- * This program is free software; you can redistribute it and/or modify it
5
- * under the terms and conditions of the GNU General Public License,
6
- * version 2, as published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11
- * more details.
12
- *
13
- * You should have received a copy of the GNU General Public License along with
14
- * this program; if not, see <http://www.gnu.org/licenses/>.
154 *
165 * Authors:
176 * Haiyang Zhang <haiyangz@microsoft.com>
....@@ -133,8 +122,10 @@
133122 vfree(nvdev->send_buf);
134123 kfree(nvdev->send_section_map);
135124
136
- for (i = 0; i < VRSS_CHANNEL_MAX; i++)
125
+ for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
126
+ xdp_rxq_info_unreg(&nvdev->chan_table[i].xdp_rxq);
137127 vfree(nvdev->chan_table[i].mrc.slots);
128
+ }
138129
139130 kfree(nvdev);
140131 }
....@@ -397,10 +388,20 @@
397388 net_device->recv_section_size = resp->sections[0].sub_alloc_size;
398389 net_device->recv_section_cnt = resp->sections[0].num_sub_allocs;
399390
400
- /* Setup receive completion ring */
401
- net_device->recv_completion_cnt
402
- = round_up(net_device->recv_section_cnt + 1,
403
- PAGE_SIZE / sizeof(u64));
391
+ /* Ensure buffer will not overflow */
392
+ if (net_device->recv_section_size < NETVSC_MTU_MIN || (u64)net_device->recv_section_size *
393
+ (u64)net_device->recv_section_cnt > (u64)buf_size) {
394
+ netdev_err(ndev, "invalid recv_section_size %u\n",
395
+ net_device->recv_section_size);
396
+ ret = -EINVAL;
397
+ goto cleanup;
398
+ }
399
+
400
+ /* Setup receive completion ring.
401
+ * Add 1 to the recv_section_cnt because at least one entry in a
402
+ * ring buffer has to be empty.
403
+ */
404
+ net_device->recv_completion_cnt = net_device->recv_section_cnt + 1;
404405 ret = netvsc_alloc_recv_comp_ring(net_device, 0);
405406 if (ret)
406407 goto cleanup;
....@@ -468,6 +469,12 @@
468469 /* Parse the response */
469470 net_device->send_section_size = init_packet->msg.
470471 v1_msg.send_send_buf_complete.section_size;
472
+ if (net_device->send_section_size < NETVSC_MTU_MIN) {
473
+ netdev_err(ndev, "invalid send_section_size %u\n",
474
+ net_device->send_section_size);
475
+ ret = -EINVAL;
476
+ goto cleanup;
477
+ }
471478
472479 /* Section count is simply the size divided by the section size. */
473480 net_device->send_section_cnt = buf_size / net_device->send_section_size;
....@@ -542,6 +549,9 @@
542549 /* Teaming bit is needed to receive link speed updates */
543550 init_packet->msg.v2_msg.send_ndis_config.capability.teaming = 1;
544551 }
552
+
553
+ if (nvsp_ver >= NVSP_PROTOCOL_VERSION_61)
554
+ init_packet->msg.v2_msg.send_ndis_config.capability.rsc = 1;
545555
546556 trace_nvsp_send(ndev, init_packet);
547557
....@@ -641,9 +651,12 @@
641651
642652 RCU_INIT_POINTER(net_device_ctx->nvdev, NULL);
643653
644
- /* And disassociate NAPI context from device */
645
- for (i = 0; i < net_device->num_chn; i++)
654
+ /* Disable NAPI and disassociate its context from the device. */
655
+ for (i = 0; i < net_device->num_chn; i++) {
656
+ /* See also vmbus_reset_channel_cb(). */
657
+ napi_disable(&net_device->chan_table[i].napi);
646658 netif_napi_del(&net_device->chan_table[i].napi);
659
+ }
647660
648661 /*
649662 * At this point, no one should be accessing net_device
....@@ -733,12 +746,49 @@
733746 int budget)
734747 {
735748 const struct nvsp_message *nvsp_packet = hv_pkt_data(desc);
749
+ u32 msglen = hv_pkt_datalen(desc);
750
+
751
+ /* Ensure packet is big enough to read header fields */
752
+ if (msglen < sizeof(struct nvsp_message_header)) {
753
+ netdev_err(ndev, "nvsp_message length too small: %u\n", msglen);
754
+ return;
755
+ }
736756
737757 switch (nvsp_packet->hdr.msg_type) {
738758 case NVSP_MSG_TYPE_INIT_COMPLETE:
759
+ if (msglen < sizeof(struct nvsp_message_header) +
760
+ sizeof(struct nvsp_message_init_complete)) {
761
+ netdev_err(ndev, "nvsp_msg length too small: %u\n",
762
+ msglen);
763
+ return;
764
+ }
765
+ fallthrough;
766
+
739767 case NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE:
768
+ if (msglen < sizeof(struct nvsp_message_header) +
769
+ sizeof(struct nvsp_1_message_send_receive_buffer_complete)) {
770
+ netdev_err(ndev, "nvsp_msg1 length too small: %u\n",
771
+ msglen);
772
+ return;
773
+ }
774
+ fallthrough;
775
+
740776 case NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE:
777
+ if (msglen < sizeof(struct nvsp_message_header) +
778
+ sizeof(struct nvsp_1_message_send_send_buffer_complete)) {
779
+ netdev_err(ndev, "nvsp_msg1 length too small: %u\n",
780
+ msglen);
781
+ return;
782
+ }
783
+ fallthrough;
784
+
741785 case NVSP_MSG5_TYPE_SUBCHANNEL:
786
+ if (msglen < sizeof(struct nvsp_message_header) +
787
+ sizeof(struct nvsp_5_subchannel_complete)) {
788
+ netdev_err(ndev, "nvsp_msg5 length too small: %u\n",
789
+ msglen);
790
+ return;
791
+ }
742792 /* Copy the response back */
743793 memcpy(&net_device->channel_init_pkt, nvsp_packet,
744794 sizeof(struct nvsp_message));
....@@ -796,7 +846,7 @@
796846 }
797847
798848 for (i = 0; i < page_count; i++) {
799
- char *src = phys_to_virt(pb[i].pfn << PAGE_SHIFT);
849
+ char *src = phys_to_virt(pb[i].pfn << HV_HYP_PAGE_SHIFT);
800850 u32 offset = pb[i].offset;
801851 u32 len = pb[i].len;
802852
....@@ -908,7 +958,8 @@
908958 struct hv_netvsc_packet *packet,
909959 struct rndis_message *rndis_msg,
910960 struct hv_page_buffer *pb,
911
- struct sk_buff *skb)
961
+ struct sk_buff *skb,
962
+ bool xdp_tx)
912963 {
913964 struct net_device_context *ndev_ctx = netdev_priv(ndev);
914965 struct netvsc_device *net_device
....@@ -931,10 +982,11 @@
931982 packet->send_buf_index = NETVSC_INVALID_INDEX;
932983 packet->cp_partial = false;
933984
934
- /* Send control message directly without accessing msd (Multi-Send
935
- * Data) field which may be changed during data packet processing.
985
+ /* Send a control message or XDP packet directly without accessing
986
+ * msd (Multi-Send Data) field which may be changed during data packet
987
+ * processing.
936988 */
937
- if (!skb)
989
+ if (!skb || xdp_tx)
938990 return netvsc_send_pkt(device, packet, net_device, pb, skb);
939991
940992 /* batch packets in send buffer if possible */
....@@ -966,7 +1018,7 @@
9661018 /* Keep aggregating only if stack says more data is coming
9671019 * and not doing mixed modes send and not flow blocked
9681020 */
969
- xmit_more = skb->xmit_more &&
1021
+ xmit_more = netdev_xmit_more() &&
9701022 !packet->cp_partial &&
9711023 !netif_xmit_stopped(netdev_get_tx_queue(ndev, packet->q_idx));
9721024
....@@ -1116,24 +1168,42 @@
11161168
11171169 static int netvsc_receive(struct net_device *ndev,
11181170 struct netvsc_device *net_device,
1119
- struct vmbus_channel *channel,
1120
- const struct vmpacket_descriptor *desc,
1121
- const struct nvsp_message *nvsp)
1171
+ struct netvsc_channel *nvchan,
1172
+ const struct vmpacket_descriptor *desc)
11221173 {
11231174 struct net_device_context *net_device_ctx = netdev_priv(ndev);
1175
+ struct vmbus_channel *channel = nvchan->channel;
11241176 const struct vmtransfer_page_packet_header *vmxferpage_packet
11251177 = container_of(desc, const struct vmtransfer_page_packet_header, d);
1178
+ const struct nvsp_message *nvsp = hv_pkt_data(desc);
1179
+ u32 msglen = hv_pkt_datalen(desc);
11261180 u16 q_idx = channel->offermsg.offer.sub_channel_index;
11271181 char *recv_buf = net_device->recv_buf;
11281182 u32 status = NVSP_STAT_SUCCESS;
11291183 int i;
11301184 int count = 0;
11311185
1186
+ /* Ensure packet is big enough to read header fields */
1187
+ if (msglen < sizeof(struct nvsp_message_header)) {
1188
+ netif_err(net_device_ctx, rx_err, ndev,
1189
+ "invalid nvsp header, length too small: %u\n",
1190
+ msglen);
1191
+ return 0;
1192
+ }
1193
+
11321194 /* Make sure this is a valid nvsp packet */
11331195 if (unlikely(nvsp->hdr.msg_type != NVSP_MSG1_TYPE_SEND_RNDIS_PKT)) {
11341196 netif_err(net_device_ctx, rx_err, ndev,
11351197 "Unknown nvsp packet type received %u\n",
11361198 nvsp->hdr.msg_type);
1199
+ return 0;
1200
+ }
1201
+
1202
+ /* Validate xfer page pkt header */
1203
+ if ((desc->offset8 << 3) < sizeof(struct vmtransfer_page_packet_header)) {
1204
+ netif_err(net_device_ctx, rx_err, ndev,
1205
+ "Invalid xfer page pkt, offset too small: %u\n",
1206
+ desc->offset8 << 3);
11371207 return 0;
11381208 }
11391209
....@@ -1147,6 +1217,14 @@
11471217
11481218 count = vmxferpage_packet->range_cnt;
11491219
1220
+ /* Check count for a valid value */
1221
+ if (NETVSC_XFER_HEADER_SIZE(count) > desc->offset8 << 3) {
1222
+ netif_err(net_device_ctx, rx_err, ndev,
1223
+ "Range count is not valid: %d\n",
1224
+ count);
1225
+ return 0;
1226
+ }
1227
+
11501228 /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
11511229 for (i = 0; i < count; i++) {
11521230 u32 offset = vmxferpage_packet->ranges[i].byte_offset;
....@@ -1154,7 +1232,9 @@
11541232 void *data;
11551233 int ret;
11561234
1157
- if (unlikely(offset + buflen > net_device->recv_buf_size)) {
1235
+ if (unlikely(offset > net_device->recv_buf_size ||
1236
+ buflen > net_device->recv_buf_size - offset)) {
1237
+ nvchan->rsc.cnt = 0;
11581238 status = NVSP_STAT_FAIL;
11591239 netif_err(net_device_ctx, rx_err, ndev,
11601240 "Packet offset:%u + len:%u too big\n",
....@@ -1165,14 +1245,19 @@
11651245
11661246 data = recv_buf + offset;
11671247
1248
+ nvchan->rsc.is_last = (i == count - 1);
1249
+
11681250 trace_rndis_recv(ndev, q_idx, data);
11691251
11701252 /* Pass it to the upper layer */
11711253 ret = rndis_filter_receive(ndev, net_device,
1172
- channel, data, buflen);
1254
+ nvchan, data, buflen);
11731255
1174
- if (unlikely(ret != NVSP_STAT_SUCCESS))
1256
+ if (unlikely(ret != NVSP_STAT_SUCCESS)) {
1257
+ /* Drop incomplete packet */
1258
+ nvchan->rsc.cnt = 0;
11751259 status = NVSP_STAT_FAIL;
1260
+ }
11761261 }
11771262
11781263 enq_receive_complete(ndev, net_device, q_idx,
....@@ -1189,6 +1274,13 @@
11891274 struct net_device_context *net_device_ctx = netdev_priv(ndev);
11901275 u32 count, offset, *tab;
11911276 int i;
1277
+
1278
+ /* Ensure packet is big enough to read send_table fields */
1279
+ if (msglen < sizeof(struct nvsp_message_header) +
1280
+ sizeof(struct nvsp_5_send_indirect_table)) {
1281
+ netdev_err(ndev, "nvsp_v5_msg length too small: %u\n", msglen);
1282
+ return;
1283
+ }
11921284
11931285 count = nvmsg->msg.v5_msg.send_table.count;
11941286 offset = nvmsg->msg.v5_msg.send_table.offset;
....@@ -1221,12 +1313,24 @@
12211313 }
12221314
12231315 static void netvsc_send_vf(struct net_device *ndev,
1224
- const struct nvsp_message *nvmsg)
1316
+ const struct nvsp_message *nvmsg,
1317
+ u32 msglen)
12251318 {
12261319 struct net_device_context *net_device_ctx = netdev_priv(ndev);
12271320
1321
+ /* Ensure packet is big enough to read its fields */
1322
+ if (msglen < sizeof(struct nvsp_message_header) +
1323
+ sizeof(struct nvsp_4_send_vf_association)) {
1324
+ netdev_err(ndev, "nvsp_v4_msg length too small: %u\n", msglen);
1325
+ return;
1326
+ }
1327
+
12281328 net_device_ctx->vf_alloc = nvmsg->msg.v4_msg.vf_assoc.allocated;
12291329 net_device_ctx->vf_serial = nvmsg->msg.v4_msg.vf_assoc.serial;
1330
+
1331
+ if (net_device_ctx->vf_alloc)
1332
+ complete(&net_device_ctx->vf_add);
1333
+
12301334 netdev_info(ndev, "VF slot %u %s\n",
12311335 net_device_ctx->vf_serial,
12321336 net_device_ctx->vf_alloc ? "added" : "removed");
....@@ -1234,45 +1338,51 @@
12341338
12351339 static void netvsc_receive_inband(struct net_device *ndev,
12361340 struct netvsc_device *nvscdev,
1237
- const struct nvsp_message *nvmsg,
1238
- u32 msglen)
1341
+ const struct vmpacket_descriptor *desc)
12391342 {
1343
+ const struct nvsp_message *nvmsg = hv_pkt_data(desc);
1344
+ u32 msglen = hv_pkt_datalen(desc);
1345
+
1346
+ /* Ensure packet is big enough to read header fields */
1347
+ if (msglen < sizeof(struct nvsp_message_header)) {
1348
+ netdev_err(ndev, "inband nvsp_message length too small: %u\n", msglen);
1349
+ return;
1350
+ }
1351
+
12401352 switch (nvmsg->hdr.msg_type) {
12411353 case NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE:
12421354 netvsc_send_table(ndev, nvscdev, nvmsg, msglen);
12431355 break;
12441356
12451357 case NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION:
1246
- netvsc_send_vf(ndev, nvmsg);
1358
+ netvsc_send_vf(ndev, nvmsg, msglen);
12471359 break;
12481360 }
12491361 }
12501362
12511363 static int netvsc_process_raw_pkt(struct hv_device *device,
1252
- struct vmbus_channel *channel,
1364
+ struct netvsc_channel *nvchan,
12531365 struct netvsc_device *net_device,
12541366 struct net_device *ndev,
12551367 const struct vmpacket_descriptor *desc,
12561368 int budget)
12571369 {
1370
+ struct vmbus_channel *channel = nvchan->channel;
12581371 const struct nvsp_message *nvmsg = hv_pkt_data(desc);
1259
- u32 msglen = hv_pkt_datalen(desc);
12601372
12611373 trace_nvsp_recv(ndev, channel, nvmsg);
12621374
12631375 switch (desc->type) {
12641376 case VM_PKT_COMP:
1265
- netvsc_send_completion(ndev, net_device, channel,
1266
- desc, budget);
1377
+ netvsc_send_completion(ndev, net_device, channel, desc, budget);
12671378 break;
12681379
12691380 case VM_PKT_DATA_USING_XFER_PAGES:
1270
- return netvsc_receive(ndev, net_device, channel,
1271
- desc, nvmsg);
1381
+ return netvsc_receive(ndev, net_device, nvchan, desc);
12721382 break;
12731383
12741384 case VM_PKT_DATA_INBAND:
1275
- netvsc_receive_inband(ndev, net_device, nvmsg, msglen);
1385
+ netvsc_receive_inband(ndev, net_device, desc);
12761386 break;
12771387
12781388 default:
....@@ -1311,7 +1421,7 @@
13111421 nvchan->desc = hv_pkt_iter_first(channel);
13121422
13131423 while (nvchan->desc && work_done < budget) {
1314
- work_done += netvsc_process_raw_pkt(device, channel, net_device,
1424
+ work_done += netvsc_process_raw_pkt(device, nvchan, net_device,
13151425 ndev, nvchan->desc, budget);
13161426 nvchan->desc = hv_pkt_iter_next(channel, nvchan->desc);
13171427 }
....@@ -1350,7 +1460,7 @@
13501460 prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index);
13511461
13521462 if (napi_schedule_prep(&nvchan->napi)) {
1353
- /* disable interupts from host */
1463
+ /* disable interrupts from host */
13541464 hv_begin_read(rbi);
13551465
13561466 __napi_schedule_irqoff(&nvchan->napi);
....@@ -1395,6 +1505,21 @@
13951505 nvchan->net_device = net_device;
13961506 u64_stats_init(&nvchan->tx_stats.syncp);
13971507 u64_stats_init(&nvchan->rx_stats.syncp);
1508
+
1509
+ ret = xdp_rxq_info_reg(&nvchan->xdp_rxq, ndev, i);
1510
+
1511
+ if (ret) {
1512
+ netdev_err(ndev, "xdp_rxq_info_reg fail: %d\n", ret);
1513
+ goto cleanup2;
1514
+ }
1515
+
1516
+ ret = xdp_rxq_info_reg_mem_model(&nvchan->xdp_rxq,
1517
+ MEM_TYPE_PAGE_SHARED, NULL);
1518
+
1519
+ if (ret) {
1520
+ netdev_err(ndev, "xdp reg_mem_model fail: %d\n", ret);
1521
+ goto cleanup2;
1522
+ }
13981523 }
13991524
14001525 /* Enable NAPI handler before init callbacks */
....@@ -1440,6 +1565,8 @@
14401565
14411566 cleanup:
14421567 netif_napi_del(&net_device->chan_table[0].napi);
1568
+
1569
+cleanup2:
14431570 free_netvsc_device(&net_device->rcu);
14441571
14451572 return ERR_PTR(ret);