Jakub Sitnicki wrote: > A listening socket linked to a sockmap has its sk_prot overridden. It > points to one of the struct proto variants in tcp_bpf_prots. The variant > depends on the socket's family and which sockmap programs are attached. > > A child socket cloned from a TCP listener initially inherits their sk_prot. > But before cloning is finished, we restore the child's proto to the > listener's original non-tcp_bpf_prots one. This happens in > tcp_create_openreq_child -> tcp_bpf_clone. > > Today, in tcp_bpf_clone we detect if the child's proto should be restored > by checking only for the TCP_BPF_BASE proto variant. This is not > correct. The sk_prot of listening socket linked to a sockmap can point to > to any variant in tcp_bpf_prots. > > If the listeners sk_prot happens to be not the TCP_BPF_BASE variant, then > the child socket unintentionally is left if the inherited sk_prot by > tcp_bpf_clone. > > This leads to issues like infinite recursion on close [1], because the > child state is otherwise not set up for use with tcp_bpf_prot operations. > > Adjust the check in tcp_bpf_clone to detect all of tcp_bpf_prots variants. > > Note that it wouldn't be sufficient to check the socket state when > overriding the sk_prot in tcp_bpf_update_proto in order to always use the > TCP_BPF_BASE variant for listening sockets. Since commit > b8b8315e39ff ("bpf, sockmap: Remove unhash handler for BPF sockmap usage") > it is possible for a socket to transition to TCP_LISTEN state while already > linked to a sockmap, e.g. connect() -> insert into map -> > connect(AF_UNSPEC) -> listen(). > > [1]: https://lore.kernel.org/all/00000000000073b14905ef2e7401@xxxxxxxxxx/ > > Fixes: e80251555f0b ("tcp_bpf: Don't let child socket inherit parent protocol ops on copy") > Reported-by: syzbot+04c21ed96d861dccc5cd@xxxxxxxxxxxxxxxxxxxxxxxxx > Signed-off-by: Jakub Sitnicki <jakub@xxxxxxxxxxxxxx> > --- Acked-by: John Fastabend <john.fastabend@xxxxxxxxx>