mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 15:41:52 +02:00
bpf, skmsg: fix verdict sk_data_ready racing with ktls rx
sk_psock_strp_data_ready() already checks tls_sw_has_ctx_rx() and defers to psock->saved_data_ready when a TLS RX context is present, avoiding a conflict with the TLS strparser's ownership of the receive queue (commite91de6afa8, "bpf: Fix running sk_skb program types with ktls"). sk_psock_verdict_data_ready() has no equivalent guard. When a socket is inserted into a sockmap (BPF_SK_SKB_VERDICT) before TLS RX is configured, tls_sw_strparser_arm() saves sk_psock_verdict_data_ready as rx_ctx->saved_data_ready. On data arrival: tls_data_ready -> tls_strp_data_ready -> tls_rx_msg_ready -> saved_data_ready() = sk_psock_verdict_data_ready() -> tcp_read_skb() drains sk_receive_queue via __skb_unlink() without calling tcp_eat_skb(), so copied_seq is not advanced. tls_strp_msg_load() then finds tcp_inq() >= full_len (stale), calls tcp_recv_skb() on the now-empty queue, hits WARN_ON_ONCE(!first), and returns with rx_ctx->strp.anchor.frag_list pointing at a psock-owned (potentially freed) skb. tls_decrypt_sg() subsequently walks that frag_list: use-after-free. Apply the same fix as sk_psock_strp_data_ready(): if a TLS RX context is present, call psock->saved_data_ready (sock_def_readable) to wake recv() waiters and return immediately, leaving the receive queue untouched. TLS retains sole ownership of the queue and decrypts the record normally through tls_sw_recvmsg(). Fixes:ef5659280e("bpf, sockmap: Allow skipping sk_skb parser program") Signed-off-by: Xingwang Xiang <v3rdant.xiang@gmail.com> Link: https://patch.msgid.link/20260517145630.20521-2-v3rdant.xiang@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
e7c70bf97e
commit
ddf8029623
|
|
@ -1268,12 +1268,19 @@ static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)
|
|||
static void sk_psock_verdict_data_ready(struct sock *sk)
|
||||
{
|
||||
const struct proto_ops *ops = NULL;
|
||||
struct sk_psock *psock;
|
||||
struct socket *sock;
|
||||
int copied;
|
||||
|
||||
trace_sk_data_ready(sk);
|
||||
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (psock && tls_sw_has_ctx_rx(sk)) {
|
||||
psock->saved_data_ready(sk);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
sock = READ_ONCE(sk->sk_socket);
|
||||
if (likely(sock))
|
||||
ops = READ_ONCE(sock->ops);
|
||||
|
|
@ -1283,8 +1290,6 @@ static void sk_psock_verdict_data_ready(struct sock *sk)
|
|||
|
||||
copied = ops->read_skb(sk, sk_psock_verdict_recv);
|
||||
if (copied >= 0) {
|
||||
struct sk_psock *psock;
|
||||
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (psock)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user