git: 6a8973c3324c - main - LinuxKPI: skbuff: fix skb_queue_splice_init()

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Wed, 23 Mar 2022 17:18:31 UTC
The branch main has been updated by bz:

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

commit 6a8973c3324c0c6c270ae4ad371e50c0ec5761da
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2022-03-23 17:05:43 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2022-03-23 17:18:00 +0000

    LinuxKPI: skbuff: fix skb_queue_splice_init()
    
    In skb_queue_splice_init() we set a next value and then used that new
    value to further update the remaining linking rather than the original
    value.  Introduce another temporary variable 'n' to hold the original
    value and use that.
    While here rename q and h to from and to as otherwise it was too
    confusing to read.
    
    Also initialize skb->prev and skb->next to point to skb itself if
    for nothing else at least to aid debugging.
    
    Reported by:    phk (panic in iwl_txq_reclaim)
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
---
 sys/compat/linuxkpi/common/include/linux/skbuff.h | 25 ++++++++++++-----------
 sys/compat/linuxkpi/common/src/linux_skbuff.c     |  2 ++
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h
index be93032c7561..21ea7ee560e2 100644
--- a/sys/compat/linuxkpi/common/include/linux/skbuff.h
+++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h
@@ -762,26 +762,27 @@ skb_mark_not_on_list(struct sk_buff *skb)
 }
 
 static inline void
-skb_queue_splice_init(struct sk_buff_head *q, struct sk_buff_head *h)
+skb_queue_splice_init(struct sk_buff_head *from, struct sk_buff_head *to)
 {
-	struct sk_buff *b, *e;
+	struct sk_buff *b, *e, *n;
 
-	SKB_TRACE2(q, h);
+	SKB_TRACE2(from, to);
 
-	if (skb_queue_empty(q))
+	if (skb_queue_empty(from))
 		return;
 
 	/* XXX do we need a barrier around this? */
-	b = q->next;
-	e = q->prev;
+	b = from->next;
+	e = from->prev;
+	n = to->next;
 
-	b->prev = (struct sk_buff *)h;
-	h->next = b;
-	e->next = h->next;
-	h->next->prev = e;
+	b->prev = (struct sk_buff *)to;
+	to->next = b;
+	e->next = n;
+	n->prev = e;
 
-	h->qlen += q->qlen;
-	__skb_queue_head_init(q);
+	to->qlen += from->qlen;
+	__skb_queue_head_init(from);
 }
 
 static inline void
diff --git a/sys/compat/linuxkpi/common/src/linux_skbuff.c b/sys/compat/linuxkpi/common/src/linux_skbuff.c
index 0a4974d74d9d..efb97fa2f126 100644
--- a/sys/compat/linuxkpi/common/src/linux_skbuff.c
+++ b/sys/compat/linuxkpi/common/src/linux_skbuff.c
@@ -86,6 +86,8 @@ linuxkpi_alloc_skb(size_t size, gfp_t gfp)
 	skb->head = skb->data = skb->tail = (uint8_t *)(skb+1);
 	skb->end = skb->head + size;
 
+	skb->prev = skb->next = skb;
+
 	skb->shinfo = (struct skb_shared_info *)(skb->end);
 
 	SKB_TRACE_FMT(skb, "data %p size %zu", skb->data, size);