git: 51fcd5ddf016 - stable/14 - igmp: Avoid leaving dangling pointers in the state-change queue

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 19 May 2026 16:46:45 UTC
The branch stable/14 has been updated by markj:

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

commit 51fcd5ddf016835619c94f4dbdc5b29150fc2e48
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-05-12 17:53:49 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-05-19 16:46:29 +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
    
    (cherry picked from commit beab4a237a45aea809e81802b9e1e9ff30f3d929)
---
 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 ae58dc0b8b04..3c4909ba5591 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -3312,10 +3312,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 6966e03cc319..2ba2836f84ac 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1647,6 +1647,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)
 {