From: Wyatt Feng espintcp keeps a single in-flight transmit in ctx->partial. Before building a new sk_msg, espintcp_sendmsg() first tries to flush that state through espintcp_push_msgs(). For blocking callers, espintcp_push_msgs() may return success while the previous partial send is still pending. espintcp_sendmsg() then reinitializes emsg->skmsg and reuses the same ctx->partial slot even though the old send has not completed yet. Wait for the pending partial send to drain before reusing ctx->partial. Nonblocking callers keep the existing error handling, while blocking callers sleep until the partial send can make progress. This preserves the one-message-at-a-time design already used by the espintcp transmit path and avoids overwriting an in-flight partial send. Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)") Cc: stable@kernel.org Reported-by: Yuan Tan Reported-by: Yifan Wu Reported-by: Juefei Pu Reported-by: Zhengchuan Liang Reported-by: Xin Liu Assisted-by: Codex:GPT-5.4 Signed-off-by: Wyatt Feng Signed-off-by: Ren Wei --- net/xfrm/espintcp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/net/xfrm/espintcp.c b/net/xfrm/espintcp.c index a2756186e13a..f8513a19a3c8 100644 --- a/net/xfrm/espintcp.c +++ b/net/xfrm/espintcp.c @@ -340,11 +340,20 @@ static int espintcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) lock_sock(sk); - err = espintcp_push_msgs(sk, msg->msg_flags & MSG_DONTWAIT); - if (err < 0) { - if (err != -EAGAIN || !(msg->msg_flags & MSG_DONTWAIT)) - err = -ENOBUFS; - goto unlock; + while (emsg->len) { + err = espintcp_push_msgs(sk, msg->msg_flags & MSG_DONTWAIT); + if (err < 0) { + if (err != -EAGAIN || !(msg->msg_flags & MSG_DONTWAIT)) + err = -ENOBUFS; + goto unlock; + } + + if (!emsg->len) + break; + + err = sk_stream_wait_memory(sk, &timeo); + if (err) + goto unlock; } sk_msg_init(&emsg->skmsg); -- 2.47.3