Index | Thread | Search

From:
Alexander Bluhm <alexander.bluhm@gmx.net>
Subject:
ix mbuf double free
To:
tech@openbsd.org
Date:
Wed, 6 Mar 2024 15:36:51 +0100

Download raw body.

Thread
Hi,

When ix(4) rx links an mbuf into a chain, it is also referenced by
nxbuf->buf and may be freed later.  As m_freem(rxbuf->fmp) frees
this mbuf as part of the chain it is a double free.

As claudio@ mentioned that linking an mbuf with M_PKTHDR as chain
member is a bug, we can us this flag as indication whether we need
an individual free of the nxbuf->buf.

Unfortunatelly the error case with these free calls is not triggered,
so I cannot test it.

bluhm

Index: dev/pci/if_ix.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_ix.c,v
diff -u -p -r1.209 if_ix.c
--- dev/pci/if_ix.c	15 Feb 2024 10:56:53 -0000	1.209
+++ dev/pci/if_ix.c	6 Mar 2024 13:04:00 -0000
@@ -3172,13 +3172,13 @@ ixgbe_rxeof(struct rx_ring *rxr)
 		rsccnt >>= IXGBE_RXDADV_RSCCNT_SHIFT;
 
 		if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) {
+			if (ISSET(mp->m_flags, M_PKTHDR))
+				m_freem(mp);
+			rxbuf->buf = NULL;
 			if (rxbuf->fmp) {
 				m_freem(rxbuf->fmp);
 				rxbuf->fmp = NULL;
 			}
-
-			m_freem(mp);
-			rxbuf->buf = NULL;
 			goto next_desc;
 		}
 
@@ -3239,6 +3239,7 @@ ixgbe_rxeof(struct rx_ring *rxr)
 		if (eop == 0) {
 			nxbuf->fmp = sendmp;
 			sendmp = NULL;
+			CLR(nxbuf->buf->m_flags, M_PKTHDR);
 			mp->m_next = nxbuf->buf;
 		} else { /* Sending this frame? */
 			uint16_t pkts;