git: 95a7c6f18a6a - stable/14 - LinuxKPI: Queue skbuffs at tail in __skb_queue_tail

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Fri, 22 Mar 2024 13:38:06 UTC
The branch stable/14 has been updated by emaste:

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

commit 95a7c6f18a6a28cf866384ff60b587ec30be1cd1
Author:     Tom Coldrick <tom@coldrick.cc>
AuthorDate: 2024-03-02 19:22:55 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2024-03-22 13:30:33 +0000

    LinuxKPI: Queue skbuffs at tail in __skb_queue_tail
    
    Correct skb_queue_tail to queue the buffer at the tail of the skbuff.
    The skbuff is a circular doubly-linked list, and we call with a pointer
    to the head of the list.  Thus queueing before the head gives us a
    queueing at the tail.
    
    As a motivating factor, the current behaviour (queueing at the head) was
    causing frequent kernel panics from my RTL8822BE wireless card, which
    uses the rtw88 driver.  Interrupts can cause buffers to be added to the
    rtwdev c2h_queue while the queue is being drained in rtw_c2h_work.
    Queueing at the head would leave the nascent entry in the linked list
    pointing to the old, now freed, memory for the buffer being processed.
    When rtw_c2h_work is next called, we try reading this and so panic.
    
    Reviewed by:    emaste, bz
    MFC after:      1 week
    Differential Revision: https://reviews.freebsd.org/D44192
    
    (cherry picked from commit d3befb534b9c8cd80f1b8d75ce6451e3f62b8ba9)
---
 sys/compat/linuxkpi/common/include/linux/skbuff.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h
index f8ce212e7853..02190a29e241 100644
--- a/sys/compat/linuxkpi/common/include/linux/skbuff.h
+++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h
@@ -567,7 +567,7 @@ __skb_queue_tail(struct sk_buff_head *q, struct sk_buff *new)
 {
 
 	SKB_TRACE2(q, new);
-	__skb_queue_after(q, (struct sk_buff *)q, new);
+	__skb_queue_before(q, (struct sk_buff *)q, new);
 }
 
 static inline void