Patch "rxrpc: Fix RESPONSE packet verification to extract skb to a linear buffer" has been added to the 6.18-stable tree

gregkh at linuxfoundation.org gregkh at linuxfoundation.org
Fri Jun 5 09:05:57 PDT 2026


This is a note to let you know that I've just added the patch titled

    rxrpc: Fix RESPONSE packet verification to extract skb to a linear buffer

to the 6.18-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch
and it can be found in the queue-6.18 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable at vger.kernel.org> know about it.


>From stable+bounces-256708-greg=kroah.com at vger.kernel.org Fri May 29 20:35:24 2026
From: Sasha Levin <sashal at kernel.org>
Date: Fri, 29 May 2026 14:35:08 -0400
Subject: rxrpc: Fix RESPONSE packet verification to extract skb to a linear buffer
To: stable at vger.kernel.org
Cc: David Howells <dhowells at redhat.com>, Hyunwoo Kim <imv4bel at gmail.com>, Simon Horman <horms at kernel.org>, Jiayuan Chen <jiayuan.chen at linux.dev>, linux-afs at lists.infradead.org, stable at kernel.org, Jeffrey Altman <jaltman at auristor.com>, Marc Dionne <marc.dionne at auristor.com>, Jakub Kicinski <kuba at kernel.org>, Sasha Levin <sashal at kernel.org>
Message-ID: <20260529183508.1594050-3-sashal at kernel.org>

From: David Howells <dhowells at redhat.com>

[ Upstream commit 8bfab4b6ffc2fe92da86300728fc8c3c7ebffb56 ]

This improves the fix for CVE-2026-43500.

Fix the verification of RESPONSE packets to avoid the problem of
overwriting a RESPONSE packet sent via splice to a local address by
extracting the contents of the UDP packet into a kmalloc'd linear buffer
rather than decrypting the data in place in the sk_buff (which may corrupt
the original buffer).

Fixes: 24481a7f5733 ("rxrpc: Fix conn-level packet handling to unshare RESPONSE packets")
Reported-by: Hyunwoo Kim <imv4bel at gmail.com>
Closes: https://lore.kernel.org/r/afKV2zGR6rrelPC7@v4bel/
Signed-off-by: David Howells <dhowells at redhat.com>
cc: Simon Horman <horms at kernel.org>
cc: Jiayuan Chen <jiayuan.chen at linux.dev>
cc: linux-afs at lists.infradead.org
cc: stable at kernel.org
Reviewed-by: Jeffrey Altman <jaltman at auristor.com>
Tested-by: Marc Dionne <marc.dionne at auristor.com>
Link: https://patch.msgid.link/20260515230516.2718212-4-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba at kernel.org>
Signed-off-by: Sasha Levin <sashal at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 net/rxrpc/ar-internal.h |    7 ++-
 net/rxrpc/conn_event.c  |   30 ++++++---------
 net/rxrpc/insecure.c    |    5 +-
 net/rxrpc/rxgk.c        |   96 +++++++++++++++---------------------------------
 net/rxrpc/rxgk_app.c    |   46 +++++++++--------------
 net/rxrpc/rxgk_common.h |   92 +---------------------------------------------
 net/rxrpc/rxkad.c       |   29 +++++---------
 7 files changed, 81 insertions(+), 224 deletions(-)

--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -307,15 +307,16 @@ struct rxrpc_security {
 				    struct sk_buff *challenge);
 
 	/* verify a response */
-	int (*verify_response)(struct rxrpc_connection *,
-			       struct sk_buff *);
+	int (*verify_response)(struct rxrpc_connection *conn,
+			       struct sk_buff *response_skb,
+			       void *response, unsigned int len);
 
 	/* clear connection security */
 	void (*clear)(struct rxrpc_connection *);
 
 	/* Default ticket -> key decoder */
 	int (*default_decode_ticket)(struct rxrpc_connection *conn, struct sk_buff *skb,
-				     unsigned int ticket_offset, unsigned int ticket_len,
+				     void *ticket, unsigned int ticket_len,
 				     struct key **_key);
 };
 
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -243,28 +243,22 @@ static void rxrpc_call_is_secure(struct
 static int rxrpc_verify_response(struct rxrpc_connection *conn,
 				 struct sk_buff *skb)
 {
+	unsigned int len = skb->len - sizeof(struct rxrpc_wire_header);
+	void *buffer;
 	int ret;
 
-	if (skb_cloned(skb) || skb_has_frag_list(skb) ||
-	    skb_has_shared_frag(skb)) {
-		/* Copy the packet if shared so that we can do in-place
-		 * decryption.
-		 */
-		struct sk_buff *nskb = skb_copy(skb, GFP_NOFS);
+	buffer = kmalloc(len, GFP_NOFS);
+	if (!buffer)
+		return -ENOMEM;
 
-		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);
-	}
+	ret = skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), buffer, len);
+	if (ret < 0)
+		goto out;
 
+	ret = conn->security->verify_response(conn, skb, buffer, len);
+
+out:
+	kfree(buffer);
 	return ret;
 }
 
--- a/net/rxrpc/insecure.c
+++ b/net/rxrpc/insecure.c
@@ -54,9 +54,10 @@ static int none_sendmsg_respond_to_chall
 }
 
 static int none_verify_response(struct rxrpc_connection *conn,
-				struct sk_buff *skb)
+				struct sk_buff *response_skb,
+				void *response, unsigned int len)
 {
-	return rxrpc_abort_conn(conn, skb, RX_PROTOCOL_ERROR, -EPROTO,
+	return rxrpc_abort_conn(conn, response_skb, RX_PROTOCOL_ERROR, -EPROTO,
 				rxrpc_eproto_rxnull_response);
 }
 
--- a/net/rxrpc/rxgk.c
+++ b/net/rxrpc/rxgk.c
@@ -1084,11 +1084,12 @@ static int rxgk_sendmsg_respond_to_chall
  *	unsigned int call_numbers<>;
  * };
  */
-static int rxgk_do_verify_authenticator(struct rxrpc_connection *conn,
-					const struct krb5_enctype *krb5,
-					struct sk_buff *skb,
-					__be32 *p, __be32 *end)
+static int rxgk_verify_authenticator(struct rxrpc_connection *conn,
+				     const struct krb5_enctype *krb5,
+				     struct sk_buff *skb,
+				     void *auth, unsigned int auth_len)
 {
+	__be32 *p = auth, *end = auth + auth_len;
 	u32 app_len, call_count, level, epoch, cid, i;
 
 	_enter("");
@@ -1152,37 +1153,6 @@ static int rxgk_do_verify_authenticator(
 }
 
 /*
- * Extract the authenticator and verify it.
- */
-static int rxgk_verify_authenticator(struct rxrpc_connection *conn,
-				     const struct krb5_enctype *krb5,
-				     struct sk_buff *skb,
-				     unsigned int auth_offset, unsigned int auth_len)
-{
-	void *auth;
-	__be32 *p;
-	int ret;
-
-	auth = kmalloc(auth_len, GFP_NOFS);
-	if (!auth)
-		return -ENOMEM;
-
-	ret = skb_copy_bits(skb, auth_offset, auth, auth_len);
-	if (ret < 0) {
-		ret = rxrpc_abort_conn(conn, skb, RXGK_NOTAUTH, -EPROTO,
-				       rxgk_abort_resp_short_auth);
-		goto error;
-	}
-
-	p = auth;
-	ret = rxgk_do_verify_authenticator(conn, krb5, skb, p,
-					   p + auth_len / sizeof(*p));
-error:
-	kfree(auth);
-	return ret;
-}
-
-/*
  * Verify a response.
  *
  * struct RXGK_Response {
@@ -1192,49 +1162,45 @@ error:
  * };
  */
 static int rxgk_verify_response(struct rxrpc_connection *conn,
-				struct sk_buff *skb)
+				struct sk_buff *skb,
+				void *buffer, unsigned int len)
 {
 	const struct krb5_enctype *krb5;
 	struct rxrpc_key_token *token;
 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
-	struct rxgk_response rhdr;
+	struct rxgk_response *rhdr;
 	struct rxgk_context *gk;
 	struct key *key = NULL;
-	unsigned int offset = sizeof(struct rxrpc_wire_header);
-	unsigned int len = skb->len - sizeof(struct rxrpc_wire_header);
-	unsigned int token_offset, token_len;
-	unsigned int auth_offset, auth_len;
+	unsigned int resp_token_len, auth_len;
+	void *resp_token, *auth;
 	__be32 xauth_len;
 	int ret, ec;
 
 	_enter("{%d}", conn->debug_id);
 
 	/* Parse the RXGK_Response object */
-	if (sizeof(rhdr) + sizeof(__be32) > len)
+	if (len < sizeof(*rhdr) + sizeof(__be32))
 		goto short_packet;
-
-	if (skb_copy_bits(skb, offset, &rhdr, sizeof(rhdr)) < 0)
-		goto short_packet;
-	offset	+= sizeof(rhdr);
-	len	-= sizeof(rhdr);
-
-	token_offset	= offset;
-	token_len	= ntohl(rhdr.token_len);
-	if (token_len > len ||
-	    xdr_round_up(token_len) + sizeof(__be32) > len)
+	rhdr = buffer;
+	buffer	+= sizeof(*rhdr);
+	len	-= sizeof(*rhdr);
+
+	resp_token	= buffer;
+	resp_token_len	= ntohl(rhdr->token_len);
+	if (resp_token_len > len ||
+	    xdr_round_up(resp_token_len) + sizeof(__be32) > len)
 		goto short_packet;
 
-	trace_rxrpc_rx_response(conn, sp->hdr.serial, 0, sp->hdr.cksum, token_len);
+	trace_rxrpc_rx_response(conn, sp->hdr.serial, 0, sp->hdr.cksum, resp_token_len);
 
-	offset	+= xdr_round_up(token_len);
-	len	-= xdr_round_up(token_len);
+	buffer	+= xdr_round_up(resp_token_len);
+	len	-= xdr_round_up(resp_token_len);
 
-	if (skb_copy_bits(skb, offset, &xauth_len, sizeof(xauth_len)) < 0)
-		goto short_packet;
-	offset	+= sizeof(xauth_len);
+	xauth_len = *(__be32 *)buffer;
+	buffer	+= sizeof(xauth_len);
 	len	-= sizeof(xauth_len);
 
-	auth_offset	= offset;
+	auth		= buffer;
 	auth_len	= ntohl(xauth_len);
 	if (auth_len > len)
 		goto short_packet;
@@ -1249,7 +1215,7 @@ static int rxgk_verify_response(struct r
 	 * to the app to deal with - which might mean a round trip to
 	 * userspace.
 	 */
-	ret = rxgk_extract_token(conn, skb, token_offset, token_len, &key);
+	ret = rxgk_extract_token(conn, skb, resp_token, resp_token_len, &key);
 	if (ret < 0)
 		goto out;
 
@@ -1263,7 +1229,7 @@ static int rxgk_verify_response(struct r
 	 */
 	token = key->payload.data[0];
 	conn->security_level = token->rxgk->level;
-	conn->rxgk.start_time = __be64_to_cpu(rhdr.start_time);
+	conn->rxgk.start_time = __be64_to_cpu(rhdr->start_time);
 
 	gk = rxgk_generate_transport_key(conn, token->rxgk, sp->hdr.cksum, GFP_NOFS);
 	if (IS_ERR(gk)) {
@@ -1273,18 +1239,18 @@ static int rxgk_verify_response(struct r
 
 	krb5 = gk->krb5;
 
-	trace_rxrpc_rx_response(conn, sp->hdr.serial, krb5->etype, sp->hdr.cksum, token_len);
+	trace_rxrpc_rx_response(conn, sp->hdr.serial, krb5->etype, sp->hdr.cksum,
+				resp_token_len);
 
 	/* Decrypt, parse and verify the authenticator. */
-	ret = rxgk_decrypt_skb(krb5, gk->resp_enc, skb,
-			       &auth_offset, &auth_len, &ec);
+	ret = rxgk_decrypt(krb5, gk->resp_enc, &auth, &auth_len, &ec);
 	if (ret < 0) {
 		rxrpc_abort_conn(conn, skb, RXGK_SEALEDINCON, ret,
 				 rxgk_abort_resp_auth_dec);
 		goto out_gk;
 	}
 
-	ret = rxgk_verify_authenticator(conn, krb5, skb, auth_offset, auth_len);
+	ret = rxgk_verify_authenticator(conn, krb5, skb, auth, auth_len);
 	if (ret < 0)
 		goto out_gk;
 
--- a/net/rxrpc/rxgk_app.c
+++ b/net/rxrpc/rxgk_app.c
@@ -40,7 +40,7 @@
  * };
  */
 int rxgk_yfs_decode_ticket(struct rxrpc_connection *conn, struct sk_buff *skb,
-			   unsigned int ticket_offset, unsigned int ticket_len,
+			   void *buffer, unsigned int ticket_len,
 			   struct key **_key)
 {
 	struct rxrpc_key_token *token;
@@ -49,7 +49,7 @@ int rxgk_yfs_decode_ticket(struct rxrpc_
 	size_t pre_ticket_len, payload_len;
 	unsigned int klen, enctype;
 	void *payload, *ticket;
-	__be32 *t, *p, *q, tmp[2];
+	__be32 *t, *p, *q, *tmp;
 	int ret;
 
 	_enter("");
@@ -59,10 +59,7 @@ int rxgk_yfs_decode_ticket(struct rxrpc_
 					rxgk_abort_resp_short_yfs_tkt);
 
 	/* Get the session key length */
-	ret = skb_copy_bits(skb, ticket_offset, tmp, sizeof(tmp));
-	if (ret < 0)
-		return rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO,
-					rxgk_abort_resp_short_yfs_klen);
+	tmp = buffer;
 	enctype = ntohl(tmp[0]);
 	klen = ntohl(tmp[1]);
 
@@ -84,12 +81,7 @@ int rxgk_yfs_decode_ticket(struct rxrpc_
 	 * it.
 	 */
 	ticket = payload + pre_ticket_len;
-	ret = skb_copy_bits(skb, ticket_offset, ticket, ticket_len);
-	if (ret < 0) {
-		ret = rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO,
-				       rxgk_abort_resp_short_yfs_tkt);
-		goto error;
-	}
+	memcpy(ticket, buffer, ticket_len);
 
 	/* Fill out the form header. */
 	p = payload;
@@ -131,7 +123,7 @@ int rxgk_yfs_decode_ticket(struct rxrpc_
 		goto error;
 	}
 
-	/* Ticket read in with skb_copy_bits above */
+	/* Ticket appended above. */
 	q += xdr_round_up(ticket_len) / 4;
 	if (WARN_ON((unsigned long)q - (unsigned long)payload != payload_len)) {
 		ret = -EIO;
@@ -182,14 +174,15 @@ error:
  * [tools.ietf.org/html/draft-wilkinson-afs3-rxgk-afs-08 sec 6.1]
  */
 int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb,
-		       unsigned int token_offset, unsigned int token_len,
+		       void *token, unsigned int token_len,
 		       struct key **_key)
 {
 	const struct krb5_enctype *krb5;
 	const struct krb5_buffer *server_secret;
 	struct crypto_aead *token_enc = NULL;
 	struct key *server_key;
-	unsigned int ticket_offset, ticket_len;
+	unsigned int ticket_len;
+	void *ticket;
 	u32 kvno, enctype;
 	int ret, ec = 0;
 
@@ -197,24 +190,23 @@ int rxgk_extract_token(struct rxrpc_conn
 		__be32 kvno;
 		__be32 enctype;
 		__be32 token_len;
-	} container;
+	} *container;
 
-	if (token_len < sizeof(container))
+	if (token_len < sizeof(*container))
 		goto short_packet;
 
 	/* Decode the RXGK_TokenContainer object.  This tells us which server
 	 * key we should be using.  We can then fetch the key, get the secret
 	 * and set up the crypto to extract the token.
 	 */
-	if (skb_copy_bits(skb, token_offset, &container, sizeof(container)) < 0)
-		goto short_packet;
+	container = token;
+	token += sizeof(*container);
 
-	kvno		= ntohl(container.kvno);
-	enctype		= ntohl(container.enctype);
-	ticket_len	= ntohl(container.token_len);
-	ticket_offset	= token_offset + sizeof(container);
+	kvno		= ntohl(container->kvno);
+	enctype		= ntohl(container->enctype);
+	ticket_len	= ntohl(container->token_len);
 
-	if (ticket_len > xdr_round_down(token_len - sizeof(container)))
+	if (ticket_len > xdr_round_down(token_len - sizeof(*container)))
 		goto short_packet;
 
 	_debug("KVNO %u", kvno);
@@ -237,8 +229,8 @@ int rxgk_extract_token(struct rxrpc_conn
 	 * gain access to K0, from which we can derive the transport key and
 	 * thence decode the authenticator.
 	 */
-	ret = rxgk_decrypt_skb(krb5, token_enc, skb,
-			       &ticket_offset, &ticket_len, &ec);
+	ticket = token;
+	ret = rxgk_decrypt(krb5, token_enc, &ticket, &ticket_len, &ec);
 	crypto_free_aead(token_enc);
 	token_enc = NULL;
 	if (ret < 0) {
@@ -248,7 +240,7 @@ int rxgk_extract_token(struct rxrpc_conn
 		return ret;
 	}
 
-	ret = conn->security->default_decode_ticket(conn, skb, ticket_offset,
+	ret = conn->security->default_decode_ticket(conn, skb, ticket,
 						    ticket_len, _key);
 	if (ret < 0)
 		goto cant_get_token;
--- a/net/rxrpc/rxgk_common.h
+++ b/net/rxrpc/rxgk_common.h
@@ -41,10 +41,10 @@ struct rxgk_context {
  * rxgk_app.c
  */
 int rxgk_yfs_decode_ticket(struct rxrpc_connection *conn, struct sk_buff *skb,
-			   unsigned int ticket_offset, unsigned int ticket_len,
+			   void *ticket, unsigned int ticket_len,
 			   struct key **_key);
 int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb,
-		       unsigned int token_offset, unsigned int token_len,
+		       void *token, unsigned int token_len,
 		       struct key **_key);
 
 /*
@@ -62,50 +62,6 @@ int rxgk_set_up_token_cipher(const struc
 			     gfp_t gfp);
 
 /*
- * Apply decryption and checksumming functions to part of an skbuff.  The
- * offset and length are updated to reflect the actual content of the encrypted
- * region.
- */
-static inline
-int rxgk_decrypt_skb(const struct krb5_enctype *krb5,
-		     struct crypto_aead *aead,
-		     struct sk_buff *skb,
-		     unsigned int *_offset, unsigned int *_len,
-		     int *_error_code)
-{
-	struct scatterlist sg[16];
-	size_t offset = 0, len = *_len;
-	int nr_sg, ret;
-
-	sg_init_table(sg, ARRAY_SIZE(sg));
-	nr_sg = skb_to_sgvec(skb, sg, *_offset, len);
-	if (unlikely(nr_sg < 0))
-		return nr_sg;
-
-	ret = crypto_krb5_decrypt(krb5, aead, sg, nr_sg,
-				  &offset, &len);
-	switch (ret) {
-	case 0:
-		*_offset += offset;
-		*_len = len;
-		break;
-	case -EBADMSG: /* Checksum mismatch. */
-	case -EPROTO:
-		*_error_code = RXGK_SEALEDINCON;
-		break;
-	case -EMSGSIZE:
-		*_error_code = RXGK_PACKETSHORT;
-		break;
-	case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */
-	default:
-		*_error_code = RXGK_INCONSISTENCY;
-		break;
-	}
-
-	return ret;
-}
-
-/*
  * Apply decryption and checksumming functions a flat data buffer.  The data
  * point and length are updated to reflect the actual content of the encrypted
  * region.
@@ -136,50 +92,6 @@ static inline int rxgk_decrypt(const str
 	case -EPROTO:
 		*_error_code = RXGK_SEALEDINCON;
 		break;
-	case -EMSGSIZE:
-		*_error_code = RXGK_PACKETSHORT;
-		break;
-	case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */
-	default:
-		*_error_code = RXGK_INCONSISTENCY;
-		break;
-	}
-
-	return ret;
-}
-
-/*
- * Check the MIC on a region of an skbuff.  The offset and length are updated
- * to reflect the actual content of the secure region.
- */
-static inline
-int rxgk_verify_mic_skb(const struct krb5_enctype *krb5,
-			struct crypto_shash *shash,
-			const struct krb5_buffer *metadata,
-			struct sk_buff *skb,
-			unsigned int *_offset, unsigned int *_len,
-			u32 *_error_code)
-{
-	struct scatterlist sg[16];
-	size_t offset = 0, len = *_len;
-	int nr_sg, ret;
-
-	sg_init_table(sg, ARRAY_SIZE(sg));
-	nr_sg = skb_to_sgvec(skb, sg, *_offset, len);
-	if (unlikely(nr_sg < 0))
-		return nr_sg;
-
-	ret = crypto_krb5_verify_mic(krb5, shash, metadata, sg, nr_sg,
-				     &offset, &len);
-	switch (ret) {
-	case 0:
-		*_offset += offset;
-		*_len = len;
-		break;
-	case -EBADMSG: /* Checksum mismatch */
-	case -EPROTO:
-		*_error_code = RXGK_SEALEDINCON;
-		break;
 	case -EMSGSIZE:
 		*_error_code = RXGK_PACKETSHORT;
 		break;
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -963,7 +963,6 @@ static int rxkad_decrypt_ticket(struct r
 	*_expiry = 0;
 
 	ASSERT(server_key->payload.data[0] != NULL);
-	ASSERTCMP((unsigned long) ticket & 7UL, ==, 0);
 
 	memcpy(&iv, &server_key->payload.data[2], sizeof(iv));
 
@@ -1112,14 +1111,15 @@ unlock:
  * verify a response
  */
 static int rxkad_verify_response(struct rxrpc_connection *conn,
-				 struct sk_buff *skb)
+				 struct sk_buff *skb,
+				 void *buffer, unsigned int len)
 {
 	struct rxkad_response *response;
 	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
 	struct rxrpc_crypt session_key;
 	struct key *server_key;
 	time64_t expiry;
-	void *ticket = NULL;
+	void *ticket;
 	u32 version, kvno, ticket_len, level;
 	__be32 csum;
 	int ret, i;
@@ -1142,13 +1142,8 @@ static int rxkad_verify_response(struct
 		}
 	}
 
-	ret = -ENOMEM;
-	response = kzalloc(sizeof(struct rxkad_response), GFP_NOFS);
-	if (!response)
-		goto error;
-
-	if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
-			  response, sizeof(*response)) < 0) {
+	response = buffer;
+	if (len < sizeof(*response)) {
 		ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO,
 				       rxkad_abort_resp_short);
 		goto error;
@@ -1160,6 +1155,9 @@ static int rxkad_verify_response(struct
 
 	trace_rxrpc_rx_response(conn, sp->hdr.serial, version, kvno, ticket_len);
 
+	buffer	+= sizeof(*response);
+	len	-= sizeof(*response);
+
 	if (version != RXKAD_VERSION) {
 		ret = rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO,
 				       rxkad_abort_resp_version);
@@ -1179,13 +1177,8 @@ static int rxkad_verify_response(struct
 	}
 
 	/* extract the kerberos ticket and decrypt and decode it */
-	ret = -ENOMEM;
-	ticket = kmalloc(ticket_len, GFP_NOFS);
-	if (!ticket)
-		goto error;
-
-	if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header) + sizeof(*response),
-			  ticket, ticket_len) < 0) {
+	ticket = buffer;
+	if (ticket_len > len) {
 		ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO,
 				       rxkad_abort_resp_short_tkt);
 		goto error;
@@ -1265,8 +1258,6 @@ static int rxkad_verify_response(struct
 	ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno);
 
 error:
-	kfree(ticket);
-	kfree(response);
 	key_put(server_key);
 	_leave(" = %d", ret);
 	return ret;


Patches currently in stable-queue which might be from sashal at kernel.org are

queue-6.18/kunit-fix-use-after-free-in-debugfs-when-using-kunit.patch
queue-6.18/bonding-refuse-to-enslave-can-devices.patch
queue-6.18/asoc-intel-bytcht_es8316-fix-mclk-leak-on-init-error.patch
queue-6.18/asoc-codecs-simple-mux-fix-enum-control-bounds-check.patch
queue-6.18/vsock-keep-poll-shutdown-state-consistent.patch
queue-6.18/net-devmem-reject-dma-buf-bind-with-non-page-aligned-size-or-sg-length.patch
queue-6.18/ethtool-tsconfig-fix-missing-ethnl_ops_complete.patch
queue-6.18/bluetooth-l2cap-fix-possible-crash-on-l2cap_ecred_co.patch
queue-6.18/gpio-adnp-fix-flow-control-regression-caused-by-scop.patch
queue-6.18/ethtool-eeprom-add-more-safeties-to-eeprom-netlink-f.patch
queue-6.18/net-team-fix-null-pointer-dereference-in-team_xmit-d.patch
queue-6.18/ethtool-rss-avoid-modifying-the-rss-context-response.patch
queue-6.18/sctp-fix-race-between-sctp_wait_for_connect-and-peel.patch
queue-6.18/hid-remove-duplicate-hid_warn_ratelimited-definition.patch
queue-6.18/mptcp-do-not-drop-partial-packets.patch
queue-6.18/ksmbd-fix-fsctl-permission-bypass-by-adding-a-permis.patch
queue-6.18/nfc-llcp-fix-use-after-free-race-in-nfc_llcp_recv_cc.patch
queue-6.18/octeontx2-pf-avoid-double-free-of-pool-stack-on-aq-init-failure.patch
queue-6.18/net-netlink-fix-sending-unassigned-nsid-after-assign.patch
queue-6.18/net-avoid-checksumming-unreadable-skb-tail-on-trim.patch
queue-6.18/gpio-rockchip-teardown-bugs-and-resource-leaks.patch
queue-6.18/mptcp-borrow-forward-memory-from-subflow.patch
queue-6.18/drm-i915-psr-read-intel-dpcd-workaround-register.patch
queue-6.18/netfilter-nf_tables-fix-dst-corruption-in-same-regis.patch
queue-6.18/ipv6-rpl-fix-hdrlen-overflow-in-ipv6_rpl_srh_decompr.patch
queue-6.18/ethtool-module-fix-cleanup-if-socket-used-for-flashi.patch
queue-6.18/tun-free-page-on-short-frame-rejection-in-tun_xdp_on.patch
queue-6.18/ethtool-eeprom-add-missing-ethnl_ops_begin-_complete.patch
queue-6.18/ethtool-pse-pd-fix-missing-ethnl_ops_complete.patch
queue-6.18/alsa-pcm-oss-fix-setup-list-uaf-on-proc-write-error.patch
queue-6.18/net-mctp-ensure-our-nlmsg-responses-are-initialised.patch
queue-6.18/net-mlx5-hws-reject-unsupported-remove-header-action.patch
queue-6.18/ethtool-module-check-fw_flash_in_progress-under-rtnl.patch
queue-6.18/nvme-tcp-store-negative-errno-in-queue-tls_err.patch
queue-6.18/ethtool-cmis-fix-u16-to-u8-truncation-of-msleep_pre_.patch
queue-6.18/net-hsr-fix-potential-oob-access-in-supervision-fram.patch
queue-6.18/cxl-test-update-mock-dev-array-before-calling-platfo.patch
queue-6.18/ethtool-coalesce-cap-profile-updates-at-net_dim_para.patch
queue-6.18/ethtool-rss-fix-indir_table-and-hkey-leak-on-get_rxf.patch
queue-6.18/net-sched-revert-net-sched-restrict-conditions-for-a.patch
queue-6.18/xfrm-iptfs-reset-runtime-state-when-cloning-sas.patch
queue-6.18/drm-i915-psr-add-defininitions-for-intel_wa_register.patch
queue-6.18/ethtool-cmis-validate-fw-size-against-start_cmd_payl.patch
queue-6.18/vxlan-do-not-reuse-cached-ip_hdr-value-after-skb_tun.patch
queue-6.18/x86-mm-disable-broadcast-tlb-flush-when-pcid-is-disabled.patch
queue-6.18/bridge-fix-sleep-in-atomic-context-in-sysfs-path.patch
queue-6.18/net-team-remove-unused-team_mode_op-port_enabled.patch
queue-6.18/ethtool-rss-fix-hkey-leak-when-indir_size-is-0.patch
queue-6.18/xfrm-check-for-underflow-in-xfrm_state_mtu.patch
queue-6.18/s390-cio-restore-gfp_dma-for-chsc-allocation.patch
queue-6.18/ethtool-module-call-ethnl_ops_complete-on-module-fla.patch
queue-6.18/net-hibmcge-disable-relaxed-ordering-to-fix-rx-packe.patch
queue-6.18/xfrm-move-policy_bydst-rcu-sync-from-per-netns-.exit.patch
queue-6.18/net-handshake-pass-negative-errno-through-handshake_.patch
queue-6.18/bluetooth-6lowpan-check-skb_clone-return-value-in-se.patch
queue-6.18/accel-rocket-fix-uaf-via-dangling-gem-handle-in-crea.patch
queue-6.18/rxrpc-fix-response-packet-verification-to-extract-skb-to-a-linear-buffer.patch
queue-6.18/arm64-tlb-flush-walk-cache-when-unsharing-pmd-tables.patch
queue-6.18/revert-x86-fpu-refine-and-simplify-the-magic-number-.patch
queue-6.18/ethtool-rss-add-missing-errno-on-rss-context-delete.patch
queue-6.18/gpio-rockchip-convert-bank-clk-to-devm_clk_get_enabl.patch
queue-6.18/vsock-virtio-bind-uarg-before-filling-zerocopy-skb.patch
queue-6.18/smb-client-validate-the-whole-dacl-before-rewriting-.patch
queue-6.18/media-rc-fix-race-between-unregister-and-urb-irq-cal.patch
queue-6.18/cpufreq-intel_pstate-use-correct-scaling-factor-on-raptor-lake-e.patch
queue-6.18/tools-bootconfig-fix-buf-leaks-in-apply_xbc.patch
queue-6.18/serdev-provide-a-bustype-shutdown-function.patch
queue-6.18/net-sched-cls_fw-fix-null-dereference-of-old-filters.patch
queue-6.18/net-netlink-don-t-set-nsid-on-local-notifications.patch
queue-6.18/kernel-fork-validate-exit_signal-in-kernel_clone.patch
queue-6.18/net-smc-do-not-re-initialize-smc-hashtables.patch
queue-6.18/bluetooth-l2cap-clear-chan-ident-on-ecred-reconfigur.patch
queue-6.18/tunnels-do-not-assume-transport-header-in-iptunnel_p.patch
queue-6.18/selftests-mptcp-drop-nanoseconds-width-specifier.patch
queue-6.18/ethtool-tsconfig-fix-reply-error-handling.patch
queue-6.18/ethtool-cmis-validate-start_cmd_payload_size-from-mo.patch
queue-6.18/media-rc-ttusbir-fix-inverted-error-logic.patch
queue-6.18/net-handshake-use-spin_lock_bh-for-hn_lock.patch
queue-6.18/tun-free-page-on-build_skb-failure-in-tun_xdp_one.patch
queue-6.18/bluetooth-hci_sync-set-hci_cmd_drain_workqueue-durin.patch
queue-6.18/platform-x86-intel-vsec-refactor-base_addr-handling.patch
queue-6.18/usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch
queue-6.18/net-team-rename-port_disabled-team-mode-op-to-port_t.patch
queue-6.18/ethtool-module-avoid-racy-updates-to-dev-ethtool-bit.patch
queue-6.18/ipv6-fix-possible-infinite-loop-in-rt6_fill_node.patch
queue-6.18/net-skbuff-fix-pskb_carve-leaking-zcopy-pages.patch
queue-6.18/net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
queue-6.18/ethtool-cmis-require-exact-cdb-reply-length.patch
queue-6.18/ethtool-rss-fix-falsely-ignoring-indir-table-updates.patch
queue-6.18/tunnels-load-network-headers-after-skb_cow-in-iptunn.patch
queue-6.18/netfilter-synproxy-refresh-tcphdr-after-skb_ensure_w.patch
queue-6.18/rxrpc-fix-data-decrypt-vs-splice-by-copying-data-to-buffer-in-recvmsg.patch
queue-6.18/bluetooth-hci_sync-reset-device-counters-in-hci_dev_.patch
queue-6.18/gpio-mxc-fix-irq_high-handling.patch
queue-6.18/bluetooth-hci_qca-migrate-to-serdev-specific-shutdown-function.patch
queue-6.18/net-mana-add-null-guards-in-teardown-path-to-prevent.patch
queue-6.18/bridge-fix-sleep-in-atomic-context-in-netlink-path.patch
queue-6.18/ethtool-tsinfo-fix-uninitialized-stats-on-the-by-phc.patch
queue-6.18/mptcp-cleanup-fallback-dummy-mapping-generation.patch
queue-6.18/mptcp-handle-first-subflow-closing-consistently.patch
queue-6.18/bcache-fix-uninitialized-closure-object.patch
queue-6.18/drm-i915-psr-apply-intel-dpcd-workaround-when-sdp-on.patch
queue-6.18/net-iucv-fix-locking-in-.getsockopt.patch
queue-6.18/ethtool-strset-fix-header-attribute-index-in-ethnl_r.patch
queue-6.18/platform-x86-intel-vsec-make-driver_data-info-const.patch
queue-6.18/platform-x86-intel-vsec-fix-enable_cnt-imbalance-on-pcie-error-recovery.patch
queue-6.18/net-mana-skip-redundant-detach-on-already-detached-p.patch
queue-6.18/netfilter-xt_cpu-prefer-raw_smp_processor_id.patch
queue-6.18/ethtool-linkstate-fix-unbalanced-ethnl_ops_complete-.patch
queue-6.18/bluetooth-hci_qca-convert-timeout-from-jiffies-to-ms.patch
queue-6.18/netfilter-ebtables-fix-oob-read-in-compat_mtw_from_u.patch
queue-6.18/mptcp-reset-rcv-wnd-on-disconnect.patch
queue-6.18/nfc-nxp-nci-i2c-use-rising-edge-irq-on-acpi-systems.patch
queue-6.18/gpio-virtuser-fix-uninitialized-data-bug-in-gpio_vir.patch
queue-6.18/ethtool-rss-avoid-device-context-leak-on-reply-build.patch
queue-6.18/cpufreq-intel_pstate-add-and-use-hybrid_get_cpu_type.patch
queue-6.18/ipv6-fix-possible-infinite-loop-in-fib6_select_path.patch
queue-6.18/scsi-core-run-queues-for-all-non-sdev_del-devices-fr.patch
queue-6.18/nfc-llcp-fix-use-after-free-in-llcp_sock_release.patch
queue-6.18/ethtool-module-avoid-leaking-a-netdev-ref-on-module-.patch
queue-6.18/phy-mscc-use-phy_id_match_exact-for-vsc8584-vsc8582-.patch
queue-6.18/ipv4-free-net-ipv4.sysctl_local_reserved_ports-after.patch
queue-6.18/drm-xe-restore-idledly-regiter-on-engine-reset.patch
queue-6.18/ethtool-tsinfo-don-t-pass-err_ptr-to-genlmsg_cancel-.patch



More information about the linux-afs mailing list