git: beab4a237a45 - main - igmp: Avoid leaving dangling pointers in the state-change queue

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 12 May 2026 20:06:10 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=beab4a237a45aea809e81802b9e1e9ff30f3d929

commit beab4a237a45aea809e81802b9e1e9ff30f3d929
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-05-12 17:53:49 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-05-12 20:05:19 +0000

    igmp: Avoid leaving dangling pointers in the state-change queue
    
    When igmp_v3_merge_state_changes() is iterating over state-change
    packets, there is a case where it'll free a queued packet but will fail
    to remove it from the queue.  Fix that.
    
    Reported by:    Yuxiang Yang, Yizhou Zhao, Xuewei Feng, Qi Li, and Ke Xu from Tsinghua University using GLM5.1 from Z.ai
    Reviewed by:    pouria, glebius
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D56947
---
 sys/netinet/igmp.c | 8 +++++---
 sys/sys/mbuf.h     | 8 ++++++++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index 00288356cb1f..226f38a035fb 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -3326,10 +3326,12 @@ igmp_v3_merge_state_changes(struct in_multi *inm, struct mbufq *scq)
 			CTR2(KTR_IGMPV3,
 			    "%s: outbound queue full, skipping whole packet %p",
 			    __func__, m);
-			mt = m->m_nextpkt;
-			if (!docopy)
+			m0 = m->m_nextpkt;
+			if (!docopy) {
+				mbufq_remove(gq, m);
 				m_freem(m);
-			m = mt;
+			}
+			m = m0;
 			continue;
 		}
 
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index c5072cec904b..fb1a0a5b81d0 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1656,6 +1656,14 @@ mbufq_enqueue(struct mbufq *mq, struct mbuf *m)
 	return (0);
 }
 
+static inline void
+mbufq_remove(struct mbufq *mq, struct mbuf *m)
+{
+
+	STAILQ_REMOVE(&mq->mq_head, m, mbuf, m_stailqpkt);
+	mq->mq_len--;
+}
+
 static inline struct mbuf *
 mbufq_dequeue(struct mbufq *mq)
 {