Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tls: handle data disappearing from under the TLS ULP

TLS expects that it owns the receive queue of the TCP socket.
This cannot be guaranteed in case the reader of the TCP socket
entered before the TLS ULP was installed, or uses some non-standard
read API (eg. zerocopy ones). Replace the WARN_ON() and a buggy
early exit (which leaves anchor pointing to a freed skb) with real
error handling. Wipe the parsing state and tell the reader to retry.

We already reload the anchor every time we (re)acquire the socket lock,
so the only condition we need to avoid is an out of bounds read
(not having enough bytes in the socket for previously parsed record len).

If some data was read from under TLS but there's enough in the queue
we'll reload and decrypt what is most likely not a valid TLS record.
Leading to some undefined behavior from TLS perspective (corrupting
a stream? missing an alert? missing an attack?) but no kernel crash
should take place.

Reported-by: William Liu <will@willsroot.io>
Reported-by: Savino Dicanosa <savy@syst3mfailure.io>
Link: https://lore.kernel.org/tFjq_kf7sWIG3A7CrCg_egb8CVsT_gsmHAK0_wxDPJXfIzxFAMxqmLwp3MlU5EHiet0AwwJldaaFdgyHpeIUCS-3m3llsmRzp9xIOBR4lAI=@syst3mfailure.io
Fixes: 84c61fe1a75b ("tls: rx: do not use the standard strparser")
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250807232907.600366-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+11 -5
+1 -1
net/tls/tls.h
··· 196 196 int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb); 197 197 void tls_rx_msg_ready(struct tls_strparser *strp); 198 198 199 - void tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh); 199 + bool tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh); 200 200 int tls_strp_msg_cow(struct tls_sw_context_rx *ctx); 201 201 struct sk_buff *tls_strp_msg_detach(struct tls_sw_context_rx *ctx); 202 202 int tls_strp_msg_hold(struct tls_strparser *strp, struct sk_buff_head *dst);
+8 -3
net/tls/tls_strp.c
··· 475 475 strp->stm.offset = offset; 476 476 } 477 477 478 - void tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh) 478 + bool tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh) 479 479 { 480 480 struct strp_msg *rxm; 481 481 struct tls_msg *tlm; ··· 484 484 DEBUG_NET_WARN_ON_ONCE(!strp->stm.full_len); 485 485 486 486 if (!strp->copy_mode && force_refresh) { 487 - if (WARN_ON(tcp_inq(strp->sk) < strp->stm.full_len)) 488 - return; 487 + if (unlikely(tcp_inq(strp->sk) < strp->stm.full_len)) { 488 + WRITE_ONCE(strp->msg_ready, 0); 489 + memset(&strp->stm, 0, sizeof(strp->stm)); 490 + return false; 491 + } 489 492 490 493 tls_strp_load_anchor_with_queue(strp, strp->stm.full_len); 491 494 } ··· 498 495 rxm->offset = strp->stm.offset; 499 496 tlm = tls_msg(strp->anchor); 500 497 tlm->control = strp->mark; 498 + 499 + return true; 501 500 } 502 501 503 502 /* Called with lock held on lower socket */
+2 -1
net/tls/tls_sw.c
··· 1384 1384 return sock_intr_errno(timeo); 1385 1385 } 1386 1386 1387 - tls_strp_msg_load(&ctx->strp, released); 1387 + if (unlikely(!tls_strp_msg_load(&ctx->strp, released))) 1388 + return tls_rx_rec_wait(sk, psock, nonblock, false); 1388 1389 1389 1390 return 1; 1390 1391 }