Fix dst_off being reset per-descriptor instead of per-packet in the RX
slow path. When processing chained descriptors (MEMIF_DESC_FLAG_NEXT),
goto next_slot2 reset dst_off to 0, overwriting the beginning of the
current mbuf with data from subsequent descriptors. Move dst_off
initialization before the next_slot2 label so it is only reset once
per packet.

Add boundary check in both RX paths before processing next segment.
If MEMIF_DESC_FLAG_NEXT is set but n_slots is 0, free the incomplete
mbuf chain and exit gracefully to prevent reading beyond available
descriptors.

Bugzilla ID: 1609
Fixes: aa17df860891 ("net/memif: add a Rx fast path")
Cc: [email protected]

Reported-by: Mike Bly <[email protected]>
Signed-off-by: Sriram Yagnaraman <[email protected]>
---
 drivers/net/memif/rte_eth_memif.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/net/memif/rte_eth_memif.c 
b/drivers/net/memif/rte_eth_memif.c
index 0002e24..cef1b0d 100644
--- a/drivers/net/memif/rte_eth_memif.c
+++ b/drivers/net/memif/rte_eth_memif.c
@@ -376,6 +376,13 @@ eth_memif_rx(void *queue, struct rte_mbuf **bufs, uint16_t 
nb_pkts)
                        n_slots--;
 
                        if (d0->flags & MEMIF_DESC_FLAG_NEXT) {
+                               if (unlikely(n_slots == 0)) {
+                                       MIF_LOG(ERR, "Truncated packet: NEXT 
flag set but no more slots");
+                                       rte_pktmbuf_free(mbuf_head);
+                                       rte_pktmbuf_free_bulk(mbufs + rx_pkts,
+                                                       MAX_PKT_BURST - 
rx_pkts);
+                                       goto no_free_bufs;
+                               }
                                mbuf_tail = mbuf;
                                mbuf = rte_pktmbuf_alloc(mq->mempool);
                                if (unlikely(mbuf == NULL)) {
@@ -414,13 +421,13 @@ eth_memif_rx(void *queue, struct rte_mbuf **bufs, 
uint16_t nb_pkts)
                                goto no_free_bufs;
                        mbuf = mbuf_head;
                        mbuf->port = mq->in_port;
+                       dst_off = 0;
 
 next_slot2:
                        s0 = cur_slot & mask;
                        d0 = &ring->desc[s0];
 
                        src_len = d0->length;
-                       dst_off = 0;
                        src_off = 0;
 
                        do {
@@ -462,8 +469,14 @@ eth_memif_rx(void *queue, struct rte_mbuf **bufs, uint16_t 
nb_pkts)
                        cur_slot++;
                        n_slots--;
 
-                       if (d0->flags & MEMIF_DESC_FLAG_NEXT)
+                       if (d0->flags & MEMIF_DESC_FLAG_NEXT) {
+                               if (unlikely(n_slots == 0)) {
+                                       MIF_LOG(ERR, "Truncated packet: NEXT 
flag set but no more slots");
+                                       rte_pktmbuf_free(mbuf_head);
+                                       goto no_free_bufs;
+                               }
                                goto next_slot2;
+                       }
 
                        mq->n_bytes += rte_pktmbuf_pkt_len(mbuf_head);
                        *bufs++ = mbuf_head;
-- 
2.43.7

Reply via email to