The commit is pushed to "branch-rh10-6.12.0-211.16.1.12.x.vz10-ovz" and will 
appear at [email protected]:openvz/vzkernel.git
after rh10-6.12.0-211.16.1.12.2.vz10
------>
commit 0b8e90d9924e341ec0bc878e3a09aa84e50ae83a
Author: David Howells <[email protected]>
Date:   Wed Apr 22 17:14:32 2026 +0100

    ms/rxrpc: Fix potential UAF after skb_unshare() failure
    
    If skb_unshare() fails to unshare a packet due to allocation failure in
    rxrpc_input_packet(), the skb pointer in the parent (rxrpc_io_thread())
    will be NULL'd out.  This will likely cause the call to
    trace_rxrpc_rx_done() to oops.
    
    Fix this by moving the unsharing down to where rxrpc_input_call_event()
    calls rxrpc_input_call_packet().  There are a number of places prior to
    that where we ignore DATA packets for a variety of reasons (such as the
    call already being complete) for which an unshare is then avoided.
    
    And with that, rxrpc_input_packet() doesn't need to take a pointer to the
    pointer to the packet, so change that to just a pointer.
    
    Fixes: 2d1faf7a0ca3 ("rxrpc: Simplify skbuff accounting in receive path")
    Closes: 
https://sashiko.dev/#/patchset/20260408121252.2249051-1-dhowells%40redhat.com
    Signed-off-by: David Howells <[email protected]>
    cc: Marc Dionne <[email protected]>
    cc: Jeffrey Altman <[email protected]>
    cc: Simon Horman <[email protected]>
    cc: [email protected]
    cc: [email protected]
    Link: https://patch.msgid.link/[email protected]
    Signed-off-by: Jakub Kicinski <[email protected]>
    (cherry picked from commit 1f2740150f904bfa60e4bad74d65add3ccb5e7f8)
    
    Backport prerequisite for the CVE-2026-43500 rxrpc fixes. It adds the
    rxrpc_skb_put_response_copy / rxrpc_skb_see_unshare_nomem trace enums and
    moves the in-place-decryption unshare into rxrpc_input_call_event(), which
    the follow-up commits 24481a7f5733 ("rxrpc: Fix conn-level packet handling
    to unshare RESPONSE packets"), 55b2984c96c3 ("rxrpc: Fix
    rxrpc_input_call_event() to only unshare DATA packets") and aa54b1d27fe0
    ("rxrpc: Also unshare DATA/RESPONSE packets when paged frags are present")
    build on. Cherry-pick applied cleanly, no conflicts.
    
    https://virtuozzo.atlassian.net/browse/VSTOR-131094
    Feature: fix ms/rxrpc
    Signed-off-by: Konstantin Khorenko <[email protected]>
---
 include/trace/events/rxrpc.h |  4 ++--
 net/rxrpc/ar-internal.h      |  1 -
 net/rxrpc/call_event.c       | 19 ++++++++++++++++++-
 net/rxrpc/io_thread.c        | 24 ++----------------------
 net/rxrpc/skbuff.c           |  9 ---------
 5 files changed, 22 insertions(+), 35 deletions(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index de6f6d25767c6..863956a7f5f4e 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -161,8 +161,6 @@
        E_(rxrpc_call_poke_timer_now,           "Timer-now")
 
 #define rxrpc_skb_traces \
-       EM(rxrpc_skb_eaten_by_unshare,          "ETN unshare  ") \
-       EM(rxrpc_skb_eaten_by_unshare_nomem,    "ETN unshar-nm") \
        EM(rxrpc_skb_get_call_rx,               "GET call-rx  ") \
        EM(rxrpc_skb_get_conn_secured,          "GET conn-secd") \
        EM(rxrpc_skb_get_conn_work,             "GET conn-work") \
@@ -188,6 +186,7 @@
        EM(rxrpc_skb_put_purge,                 "PUT purge    ") \
        EM(rxrpc_skb_put_purge_oob,             "PUT purge-oob") \
        EM(rxrpc_skb_put_response,              "PUT response ") \
+       EM(rxrpc_skb_put_response_copy,         "PUT resp-cpy ") \
        EM(rxrpc_skb_put_rotate,                "PUT rotate   ") \
        EM(rxrpc_skb_put_unknown,               "PUT unknown  ") \
        EM(rxrpc_skb_see_conn_work,             "SEE conn-work") \
@@ -196,6 +195,7 @@
        EM(rxrpc_skb_see_recvmsg_oob,           "SEE recvm-oob") \
        EM(rxrpc_skb_see_reject,                "SEE reject   ") \
        EM(rxrpc_skb_see_rotate,                "SEE rotate   ") \
+       EM(rxrpc_skb_see_unshare_nomem,         "SEE unshar-nm") \
        E_(rxrpc_skb_see_version,               "SEE version  ")
 
 #define rxrpc_local_traces \
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 5b7342d434869..2baa99b76f756 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1479,7 +1479,6 @@ int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, 
int);
 void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *);
 void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
-void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
 void rxrpc_purge_queue(struct sk_buff_head *);
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index fec59d9338b9f..cc8f9dfa44e8a 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -332,7 +332,24 @@ bool rxrpc_input_call_event(struct rxrpc_call *call)
 
                        saw_ack |= sp->hdr.type == RXRPC_PACKET_TYPE_ACK;
 
-                       rxrpc_input_call_packet(call, skb);
+                       if (sp->hdr.securityIndex != 0 &&
+                           skb_cloned(skb)) {
+                               /* Unshare the packet so that it can be
+                                * modified by in-place decryption.
+                                */
+                               struct sk_buff *nskb = skb_copy(skb, 
GFP_ATOMIC);
+
+                               if (nskb) {
+                                       rxrpc_new_skb(nskb, 
rxrpc_skb_new_unshared);
+                                       rxrpc_input_call_packet(call, nskb);
+                                       rxrpc_free_skb(nskb, 
rxrpc_skb_put_call_rx);
+                               } else {
+                                       /* OOM - Drop the packet. */
+                                       rxrpc_see_skb(skb, 
rxrpc_skb_see_unshare_nomem);
+                               }
+                       } else {
+                               rxrpc_input_call_packet(call, skb);
+                       }
                        rxrpc_free_skb(skb, rxrpc_skb_put_call_rx);
                        did_receive = true;
                }
diff --git a/net/rxrpc/io_thread.c b/net/rxrpc/io_thread.c
index e939ecf417c4b..6ff30afbc0854 100644
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -192,13 +192,12 @@ static bool rxrpc_extract_abort(struct sk_buff *skb)
 /*
  * Process packets received on the local endpoint
  */
-static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff 
**_skb)
+static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff *skb)
 {
        struct rxrpc_connection *conn;
        struct sockaddr_rxrpc peer_srx;
        struct rxrpc_skb_priv *sp;
        struct rxrpc_peer *peer = NULL;
-       struct sk_buff *skb = *_skb;
        bool ret = false;
 
        skb_pull(skb, sizeof(struct udphdr));
@@ -244,25 +243,6 @@ static bool rxrpc_input_packet(struct rxrpc_local *local, 
struct sk_buff **_skb)
                        return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call);
                if (sp->hdr.seq == 0)
                        return rxrpc_bad_message(skb, rxrpc_badmsg_zero_seq);
-
-               /* Unshare the packet so that it can be modified for in-place
-                * decryption.
-                */
-               if (sp->hdr.securityIndex != 0) {
-                       skb = skb_unshare(skb, GFP_ATOMIC);
-                       if (!skb) {
-                               rxrpc_eaten_skb(*_skb, 
rxrpc_skb_eaten_by_unshare_nomem);
-                               *_skb = NULL;
-                               return just_discard;
-                       }
-
-                       if (skb != *_skb) {
-                               rxrpc_eaten_skb(*_skb, 
rxrpc_skb_eaten_by_unshare);
-                               *_skb = skb;
-                               rxrpc_new_skb(skb, rxrpc_skb_new_unshared);
-                               sp = rxrpc_skb(skb);
-                       }
-               }
                break;
 
        case RXRPC_PACKET_TYPE_CHALLENGE:
@@ -493,7 +473,7 @@ int rxrpc_io_thread(void *data)
                        switch (skb->mark) {
                        case RXRPC_SKB_MARK_PACKET:
                                skb->priority = 0;
-                               if (!rxrpc_input_packet(local, &skb))
+                               if (!rxrpc_input_packet(local, skb))
                                        rxrpc_reject_packet(local, skb);
                                trace_rxrpc_rx_done(skb->mark, skb->priority);
                                rxrpc_free_skb(skb, rxrpc_skb_put_input);
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index 3bcd6ee803960..e2169d1a14b5f 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -46,15 +46,6 @@ void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace 
why)
        skb_get(skb);
 }
 
-/*
- * Note the dropping of a ref on a socket buffer by the core.
- */
-void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace why)
-{
-       int n = atomic_inc_return(&rxrpc_n_rx_skbs);
-       trace_rxrpc_skb(skb, 0, n, why);
-}
-
 /*
  * Note the destruction of a socket buffer.
  */
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to