Skip to content

Commit 534fc31

Browse files
rosslagerwalljgross1
authored andcommitted
xen/netback: Fix buffer overrun triggered by unusual packet
It is possible that a guest can send a packet that contains a head + 18 slots and yet has a len <= XEN_NETBACK_TX_COPY_LEN. This causes nr_slots to underflow in xenvif_get_requests() which then causes the subsequent loop's termination condition to be wrong, causing a buffer overrun of queue->tx_map_ops. Rework the code to account for the extra frag_overflow slots. This is CVE-2023-34319 / XSA-432. Fixes: ad7f402 ("xen/netback: Ensure protocol headers don't fall in the non-linear area") Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com> Reviewed-by: Paul Durrant <paul@xen.org> Reviewed-by: Wei Liu <wei.liu@kernel.org> Signed-off-by: Juergen Gross <jgross@suse.com>
1 parent ec351c8 commit 534fc31

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

drivers/net/xen-netback/netback.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
396396
struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops;
397397
struct xen_netif_tx_request *txp = first;
398398

399-
nr_slots = shinfo->nr_frags + 1;
399+
nr_slots = shinfo->nr_frags + frag_overflow + 1;
400400

401401
copy_count(skb) = 0;
402402
XENVIF_TX_CB(skb)->split_mask = 0;
@@ -462,8 +462,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
462462
}
463463
}
464464

465-
for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
466-
shinfo->nr_frags++, gop++) {
465+
for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
466+
shinfo->nr_frags++, gop++, nr_slots--) {
467467
index = pending_index(queue->pending_cons++);
468468
pending_idx = queue->pending_ring[index];
469469
xenvif_tx_create_map_op(queue, pending_idx, txp,
@@ -476,12 +476,12 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
476476
txp++;
477477
}
478478

479-
if (frag_overflow) {
479+
if (nr_slots > 0) {
480480

481481
shinfo = skb_shinfo(nskb);
482482
frags = shinfo->frags;
483483

484-
for (shinfo->nr_frags = 0; shinfo->nr_frags < frag_overflow;
484+
for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots;
485485
shinfo->nr_frags++, txp++, gop++) {
486486
index = pending_index(queue->pending_cons++);
487487
pending_idx = queue->pending_ring[index];
@@ -492,6 +492,11 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
492492
}
493493

494494
skb_shinfo(skb)->frag_list = nskb;
495+
} else if (nskb) {
496+
/* A frag_list skb was allocated but it is no longer needed
497+
* because enough slots were converted to copy ops above.
498+
*/
499+
kfree_skb(nskb);
495500
}
496501

497502
(*copy_ops) = cop - queue->tx_copy_ops;

0 commit comments

Comments
 (0)