Subject: Re: [PATCH] xfrm: espintcp: fix sg.size corruption on partial send error

From: Steffen Klassert <[email-masked]>
Date: Wed, 20 May 2026 08:09:37 +0200

On Mon, May 18, 2026 at 12:21:09PM +0900, Aaron Esau wrote:
> espintcp_sendskmsg_locked() calls put_page() and sk_mem_uncharge() for
> each scatterlist element it successfully sends, but never decrements
> sg.size. If tcp_sendmsg_locked() then fails partway through, the error
> path advances sg.start past the freed elements while sg.size still
> accounts for them. A subsequent sk_msg_free() in espintcp_close() loops
> until sg.size reaches zero, overshoots sg.end, hits zeroed entries with
> NULL pages, and crashes in put_page().
> 
> Fix this by decrementing sg.size as each element is freed. Also use
> sk_msg_iter_var_next() instead of raw addition for sg.start, so it
> wraps at NR_MSG_FRAG_IDS.
> 
> Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)")
> Cc: [email-masked]
> Signed-off-by: Aaron Esau <[email-masked]>
> ---
>  net/xfrm/espintcp.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/net/xfrm/espintcp.c b/net/xfrm/espintcp.c
> index e1b11ab59..6755f6df6 100644
> --- a/net/xfrm/espintcp.c
> +++ b/net/xfrm/espintcp.c
> @@ -237,7 +237,8 @@ static int espintcp_sendskmsg_locked(struct sock *sk,
>  		ret = tcp_sendmsg_locked(sk, &msghdr, size);
>  		if (ret < 0) {
>  			emsg->offset = offset - sg->offset;
> -			skmsg->sg.start += done;
> +			while (done--)
> +				sk_msg_iter_var_next(skmsg->sg.start);
>  			return ret;
>  		}
>  
> @@ -250,6 +251,7 @@ static int espintcp_sendskmsg_locked(struct sock *sk,
>  		done++;
>  		put_page(p);
>  		sk_mem_uncharge(sk, sg->length);
> +		skmsg->sg.size -= sg->length;
>  		sg = sg_next(sg);
>  	} while (sg);
>  

I'd like to see an Ack from Sabrina (she authored espintcp) before
applying this.