From: Alexander Bluhm Subject: ix mbuf double free To: tech@openbsd.org Date: Wed, 6 Mar 2024 15:36:51 +0100 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;