VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-46000

CVE-2026-46000

Description

In the Linux kernel, the following vulnerability has been resolved:

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

The security operations that verify the RESPONSE packets decrypt bits of it in place - however, the sk_buff may be shared with a packet sniffer, which would lead to the sniffer seeing an apparently corrupt packet (actually decrypted).

Fix this by handing a copy of the packet off to the specific security handler if the packet was cloned.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In the Linux kernel, a concurrency issue in rxrpc where shared sk_buff for RESPONSE packets could leak decrypted data to packet sniffers.

Vulnerability

In the Linux kernel, the rxrpc (RxRPC) network protocol implementation had a vulnerability in its connection-level packet handling. The security operations that verify RESPONSE packets decrypt parts of them in place on the sk_buff. However, the sk_buff may be shared with a packet sniffer (e.g., due to cloning). This means the decryption modifies data that a sniffer might also read, causing the sniffer to see an apparently corrupt (actually decrypted) packet. The affected code path is in the security handlers for RESPONSE packets in rxrpc. The fix was applied to the Linux kernel stable tree [1].

Exploitation

An attacker would need to be able to capture network traffic (e.g., a packet sniffer) that includes these RESPONSE packets. The kernel does not require special privileges to trigger the code path during normal RxRPC protocol handling. The attacker does not need to send malicious packets; rather, the vulnerability affects legitimate traffic processing. The issue occurs when the kernel processes a cloned sk_buff and decrypts data in place, inadvertently exposing decrypted content to the clone (sniffer).

Impact

This vulnerability leads to information disclosure: a packet sniffer that has captured a cloned sk_buff would be able to see parts of the decrypted RESPONSE packet data. This could leak sensitive information that was meant to be encrypted. The attacker does not gain code execution or privilege escalation; the impact is limited to unauthorized access to decrypted packet data.

Mitigation

The fix was committed to the Linux kernel stable tree [1]. The specific commit ID is ca71ac2de389b01eecdc48bfafbdf073ec232044. Users should apply the patch or update their kernel to a version that includes this fix. There is no known workaround; systems running an affected kernel version should upgrade. The vulnerability is not listed on the CISA Known Exploited Vulnerabilities (KEV) catalog.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

10
98a2046d155f

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDavid HowellsMay 11, 2026Fixed in 6.12.88via kernel-cna
4 files changed · +58 4
  • include/trace/events/rxrpc.h+1 0 modified
    diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
    index 9377acad0c5f92..63efc9e4e41026 100644
    --- a/include/trace/events/rxrpc.h
    +++ b/include/trace/events/rxrpc.h
    @@ -146,6 +146,7 @@
     	EM(rxrpc_skb_put_jumbo_subpacket,	"PUT jumbo-sub") \
     	EM(rxrpc_skb_put_last_nack,		"PUT last-nack") \
     	EM(rxrpc_skb_put_purge,			"PUT purge    ") \
    +	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") \
    
  • include/trace/events/rxrpc.h+1 0 modified
    diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
    index 9377acad0c5f92..63efc9e4e41026 100644
    --- a/include/trace/events/rxrpc.h
    +++ b/include/trace/events/rxrpc.h
    @@ -146,6 +146,7 @@
     	EM(rxrpc_skb_put_jumbo_subpacket,	"PUT jumbo-sub") \
     	EM(rxrpc_skb_put_last_nack,		"PUT last-nack") \
     	EM(rxrpc_skb_put_purge,			"PUT purge    ") \
    +	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") \
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 82cc72123c9c9f..6dcfaed1f7485c 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 82cc72123c9c9f..6dcfaed1f7485c 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
24481a7f5733

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDavid HowellsApr 22, 2026Fixed in 7.1-rc1via kernel-cna
2 files changed · +56 4
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
d9b93a0f57ca

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDavid HowellsApr 22, 2026Fixed in 7.0.4via kernel-cna
2 files changed · +56 4
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
ca71ac2de389

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDavid HowellsApr 22, 2026Fixed in 6.18.27via kernel-cna
2 files changed · +56 4
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
c0428a22daf6

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDavid HowellsFixed in 6.6.140via kernel-cna
2 files changed · +56 4
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 82cc72123c9c9f..6dcfaed1f7485c 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 82cc72123c9c9f..6dcfaed1f7485c 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
98a2046d155f

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

4 files changed · +58 4
  • include/trace/events/rxrpc.h+1 0 modified
    diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
    index 9377acad0c5f92..63efc9e4e41026 100644
    --- a/include/trace/events/rxrpc.h
    +++ b/include/trace/events/rxrpc.h
    @@ -146,6 +146,7 @@
     	EM(rxrpc_skb_put_jumbo_subpacket,	"PUT jumbo-sub") \
     	EM(rxrpc_skb_put_last_nack,		"PUT last-nack") \
     	EM(rxrpc_skb_put_purge,			"PUT purge    ") \
    +	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") \
    
  • include/trace/events/rxrpc.h+1 0 modified
    diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
    index 9377acad0c5f92..63efc9e4e41026 100644
    --- a/include/trace/events/rxrpc.h
    +++ b/include/trace/events/rxrpc.h
    @@ -146,6 +146,7 @@
     	EM(rxrpc_skb_put_jumbo_subpacket,	"PUT jumbo-sub") \
     	EM(rxrpc_skb_put_last_nack,		"PUT last-nack") \
     	EM(rxrpc_skb_put_purge,			"PUT purge    ") \
    +	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") \
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 82cc72123c9c9f..6dcfaed1f7485c 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 82cc72123c9c9f..6dcfaed1f7485c 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
d9b93a0f57ca

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

2 files changed · +56 4
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
ca71ac2de389

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

2 files changed · +56 4
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
24481a7f5733

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

2 files changed · +56 4
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 9a41ec708aeb9f..aee977291d90bd 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock_irq(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
c0428a22daf6

rxrpc: Fix conn-level packet handling to unshare RESPONSE packets

2 files changed · +56 4
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 82cc72123c9c9f..6dcfaed1f7485c 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    
  • net/rxrpc/conn_event.c+28 2 modified
    diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
    index 82cc72123c9c9f..6dcfaed1f7485c 100644
    --- a/net/rxrpc/conn_event.c
    +++ b/net/rxrpc/conn_event.c
    @@ -226,6 +226,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
     		rxrpc_notify_socket(call);
     }
     
    +static int rxrpc_verify_response(struct rxrpc_connection *conn,
    +				 struct sk_buff *skb)
    +{
    +	int ret;
    +
    +	if (skb_cloned(skb)) {
    +		/* Copy the packet if shared so that we can do in-place
    +		 * decryption.
    +		 */
    +		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
    +
    +		if (nskb) {
    +			rxrpc_new_skb(nskb, rxrpc_skb_new_unshared);
    +			ret = conn->security->verify_response(conn, nskb);
    +			rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy);
    +		} else {
    +			/* OOM - Drop the packet. */
    +			rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem);
    +			ret = -ENOMEM;
    +		}
    +	} else {
    +		ret = conn->security->verify_response(conn, skb);
    +	}
    +
    +	return ret;
    +}
    +
     /*
      * connection-level Rx packet processor
      */
    @@ -253,7 +280,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
     		}
     		spin_unlock(&conn->state_lock);
     
    -		ret = conn->security->verify_response(conn, skb);
    +		ret = rxrpc_verify_response(conn, skb);
     		if (ret < 0)
     			return ret;
     
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"In-place decryption of RESPONSE packets in a shared (cloned) sk_buff corrupts the data visible to other users of the same buffer, such as a packet sniffer."

Attack vector

An attacker on the network sends a RESPONSE packet to an RxRPC connection. The kernel's security handler calls `conn->security->verify_response()`, which decrypts parts of the packet in place. If the `sk_buff` is cloned (shared with a packet sniffer or another kernel path), the decryption modifies the shared buffer, causing the sniffer to observe an apparently corrupt packet. No special privileges are required beyond the ability to send network traffic to the target RxRPC endpoint.

Affected code

The vulnerable code is in `net/rxrpc/conn_event.c` in the function `rxrpc_process_event()`, which directly called `conn->security->verify_response(conn, skb)` without checking whether the `sk_buff` was cloned. The patch replaces that direct call with the new `rxrpc_verify_response()` wrapper.

What the fix does

The patch introduces a new helper function `rxrpc_verify_response()` in `net/rxrpc/conn_event.c` that checks `skb_cloned(skb)` before calling the security handler. If the packet is cloned, it makes a private copy via `skb_copy()` and passes the copy to `conn->security->verify_response()`, so in-place decryption only affects the copy. The original shared `sk_buff` remains untouched. A new tracepoint enum `rxrpc_skb_put_response_copy` is added in `include/trace/events/rxrpc.h` to track the lifecycle of these copied skbs.

Preconditions

  • configThe target system must be running a kernel with the RxRPC (AF_RXRPC) module enabled and a secure RxRPC connection established.
  • networkThe attacker must be able to send network packets to the target's RxRPC endpoint.
  • inputThe RESPONSE packet's sk_buff must be cloned (shared), which occurs naturally when a packet sniffer (e.g., tcpdump) or another kernel path holds a reference to the same buffer.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.