When an sk_msg scatterlist ring wraps (sg.end < sg.start), tls_push_record() chains the tail portion of the ring to the head using sg_chain(). The entry count passed to sg_chain() determines where the chain pointer is written: at prv[prv_nents - 1]. The current code uses MAX_SKB_FRAGS (17) as the ring size: sg_chain(&msg_pl->sg.data[msg_pl->sg.start], MAX_SKB_FRAGS - msg_pl->sg.start + 1, msg_pl->sg.data); This places the chain pointer at data[start + (MAX_SKB_FRAGS - start + 1) - 1] = data[MAX_SKB_FRAGS] = data[17]. However, since commit 031097d9e079 ("bpf: sk_msg, zap ingress queue on psock down") expanded the ring from MAX_MSG_FRAGS to NR_MSG_FRAG_IDS (18) positions, data[17] is a valid ring slot that can hold live scatterlist entries. The chain pointer must land at data[NR_MSG_FRAG_IDS] (index 18), the reserved chaining slot. Every other wrapped-ring arithmetic operation in the sk_msg subsystem (sk_msg_iter_dist, sk_msg_iter_var_next, sk_msg_iter_var_prev, bpf_msg_pull_data) correctly uses NR_MSG_FRAG_IDS as the ring modulus. This sg_chain call is the sole remaining use of MAX_SKB_FRAGS for ring-modulus arithmetic and was introduced after the ring expansion. Reported-by: 钱一铭 Fixes: 9aaaa56845a0 ("bpf: Sockmap/tls, skmsg can have wrapped skmsg that needs extra chaining") Signed-off-by: Jakub Kicinski --- CC: john.fastabend@gmail.com CC: sd@queasysnail.net CC: daniel@iogearbox.net CC: jonathan.lemon@gmail.com CC: bpf@vger.kernel.org --- net/tls/tls_sw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 906a1998c630..600e13effaab 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -802,7 +802,7 @@ static int tls_push_record(struct sock *sk, int flags, if (msg_pl->sg.end < msg_pl->sg.start) { sg_chain(&msg_pl->sg.data[msg_pl->sg.start], - MAX_SKB_FRAGS - msg_pl->sg.start + 1, + NR_MSG_FRAG_IDS - msg_pl->sg.start + 1, msg_pl->sg.data); } -- 2.54.0