resync_update_sn() handles CQE_TLS_OFFLOAD_RESYNC by looking up the socket with inet_lookup_established() / __inet6_lookup_established() and then dereferencing tls_get_ctx(sk) on the assumption that the returned socket owns the TLS context that produced the CQE. That assumption is not guaranteed. The established lookup matches only on the 5-tuple and does not filter on TLS ULP state, so it can return a TCP_ESTABLISHED socket with no TLS context attached. In that case tls_get_ctx(sk) is NULL and the RX resync path dereferences it. In the observed crash, the returned socket was TCP_ESTABLISHED with both icsk_ulp_ops and icsk_ulp_data NULL, i.e. a socket without a TLS ULP attached at lookup time. This can happen if a stale resync CQE is matched to a different socket for the same 5-tuple, or otherwise resolves to a socket without a TLS context. Fetch tls_get_ctx(sk) once after the TIME_WAIT check and bail out if it is NULL, then pass the sampled tls_context down to the resync helpers. Fixes: 0419d8c9d8f8 ("net/mlx5e: kTLS, Add kTLS RX resync support") Link: https://lore.kernel.org/netdev/20260705104419.4014-1-nils.juenemann@gmail.com/ Reported-by: Nils Juenemann Signed-off-by: Rishikesh Jethwani --- .../mellanox/mlx5/core/en_accel/ktls_rx.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c index bca45679e201..a1cab11a07dc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c @@ -471,12 +471,12 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi, /* Runs in NAPI. * Function elevates the refcount, unless no work is queued. */ -static bool resync_queue_get_psv(struct sock *sk) +static bool resync_queue_get_psv(struct tls_context *tls_ctx) { struct mlx5e_ktls_offload_context_rx *priv_rx; struct mlx5e_ktls_rx_resync_ctx *resync; - priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_get_ctx(sk)); + priv_rx = mlx5e_get_ktls_rx_priv_ctx(tls_ctx); if (unlikely(!priv_rx)) return false; @@ -500,6 +500,7 @@ static void resync_update_sn(struct mlx5e_rq *rq, struct sk_buff *skb) struct tls_offload_resync_async *resync_async; struct net_device *netdev = rq->netdev; struct net *net = dev_net(netdev); + struct tls_context *tls_ctx; struct sock *sk = NULL; unsigned int datalen; struct iphdr *iph; @@ -538,12 +539,20 @@ static void resync_update_sn(struct mlx5e_rq *rq, struct sk_buff *skb) if (unlikely(sk->sk_state == TCP_TIME_WAIT)) goto unref; - if (unlikely(!resync_queue_get_psv(sk))) + /* Established lookup is tuple-based and may return a socket without + * a TLS ULP attached. Sample the TLS context once and bail out if + * none is present. + */ + tls_ctx = tls_get_ctx(sk); + if (unlikely(!tls_ctx)) + goto unref; + + if (unlikely(!resync_queue_get_psv(tls_ctx))) goto unref; seq = th->seq; datalen = skb->len - depth; - resync_async = tls_offload_ctx_rx(tls_get_ctx(sk))->resync_async; + resync_async = tls_offload_ctx_rx(tls_ctx)->resync_async; tls_offload_rx_resync_async_request_start(resync_async, seq, datalen); rq->stats->tls_resync_req_start++; -- 2.25.1