[ Upstream commit 990348e5bb457697c2f1f7f7b65154a3334d9d2b ]
A child socket inherits the listener's bpf_sock_ops_cb_flags via
sk_clone_lock(). If its setup fails in tcp_v4_syn_recv_sock() /
tcp_v6_syn_recv_sock(), the child is freed through put_and_exit, where
inet_csk_prepare_forced_close() drops the socket lock and tcp_done()
runs without it.
6.12.y still ships DCCP. Its put_and_exit path (dccp_v4_request_recv_sock() ->
inet_csk_prepare_forced_close() -> inet_csk_prepare_for_destroy_sock()) reaches
the same function you relocated, which now unconditionally casts sk to struct
tcp_sock and writes through it. On a DCCP child that's a write past the end of
the smaller struct dccp_sock. Upstream is only safe here because DCCP was
retired by 2a63dd0edf38 ("net: Retire DCCP socket."), about a year before this
fix landed.
Could you send a v2 that guards the call, e.g. only when sk->sk_protocol ==
IPPROTO_TCP, or keep tcp_clear_sock_ops_cb_flags() out of the generic inet_csk
teardown path?
--
Thanks,
Sasha