Skip to content

Commit 5177373

Browse files
minhbq-99Paolo Abeni
authored andcommitted
virtio-net: xsk: rx: fix the frame's length check
When calling buf_to_xdp, the len argument is the frame data's length without virtio header's length (vi->hdr_len). We check that len with xsk_pool_get_rx_frame_size() + vi->hdr_len to ensure the provided len does not larger than the allocated chunk size. The additional vi->hdr_len is because in virtnet_add_recvbuf_xsk, we use part of XDP_PACKET_HEADROOM for virtio header and ask the vhost to start placing data from hard_start + XDP_PACKET_HEADROOM - vi->hdr_len not hard_start + XDP_PACKET_HEADROOM But the first buffer has virtio_header, so the maximum frame's length in the first buffer can only be xsk_pool_get_rx_frame_size() not xsk_pool_get_rx_frame_size() + vi->hdr_len like in the current check. This commit adds an additional argument to buf_to_xdp differentiate between the first buffer and other ones to correctly calculate the maximum frame's length. Cc: [email protected] Reviewed-by: Xuan Zhuo <[email protected]> Fixes: a4e7ba7 ("virtio_net: xsk: rx: support recv small mode") Signed-off-by: Bui Quang Minh <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent c9cbbe7 commit 5177373

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

drivers/net/virtio_net.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,15 +1147,29 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
11471147
}
11481148
}
11491149

1150+
/* Note that @len is the length of received data without virtio header */
11501151
static struct xdp_buff *buf_to_xdp(struct virtnet_info *vi,
1151-
struct receive_queue *rq, void *buf, u32 len)
1152+
struct receive_queue *rq, void *buf,
1153+
u32 len, bool first_buf)
11521154
{
11531155
struct xdp_buff *xdp;
11541156
u32 bufsize;
11551157

11561158
xdp = (struct xdp_buff *)buf;
11571159

1158-
bufsize = xsk_pool_get_rx_frame_size(rq->xsk_pool) + vi->hdr_len;
1160+
/* In virtnet_add_recvbuf_xsk, we use part of XDP_PACKET_HEADROOM for
1161+
* virtio header and ask the vhost to fill data from
1162+
* hard_start + XDP_PACKET_HEADROOM - vi->hdr_len
1163+
* The first buffer has virtio header so the remaining region for frame
1164+
* data is
1165+
* xsk_pool_get_rx_frame_size()
1166+
* While other buffers than the first one do not have virtio header, so
1167+
* the maximum frame data's length can be
1168+
* xsk_pool_get_rx_frame_size() + vi->hdr_len
1169+
*/
1170+
bufsize = xsk_pool_get_rx_frame_size(rq->xsk_pool);
1171+
if (!first_buf)
1172+
bufsize += vi->hdr_len;
11591173

11601174
if (unlikely(len > bufsize)) {
11611175
pr_debug("%s: rx error: len %u exceeds truesize %u\n",
@@ -1280,7 +1294,7 @@ static int xsk_append_merge_buffer(struct virtnet_info *vi,
12801294

12811295
u64_stats_add(&stats->bytes, len);
12821296

1283-
xdp = buf_to_xdp(vi, rq, buf, len);
1297+
xdp = buf_to_xdp(vi, rq, buf, len, false);
12841298
if (!xdp)
12851299
goto err;
12861300

@@ -1378,7 +1392,7 @@ static void virtnet_receive_xsk_buf(struct virtnet_info *vi, struct receive_queu
13781392

13791393
u64_stats_add(&stats->bytes, len);
13801394

1381-
xdp = buf_to_xdp(vi, rq, buf, len);
1395+
xdp = buf_to_xdp(vi, rq, buf, len, true);
13821396
if (!xdp)
13831397
return;
13841398

0 commit comments

Comments
 (0)