Linux TCP fixes race UAFs when sockets flip listen and disconnect
connect(AF_UNSPEC), listen(), and IPV6_ADDRFORM left request sockets and parent state that concurrent paths could free while still in use.
Hyunwoo Kim has posted a second-round set of fixes for multiple use-after-free and related memory-safety bugs in the Linux TCP stack that surface when a socket moves between listening and active roles.
The trigger pattern is legal but awkward: connect(AF_UNSPEC) disconnects a socket, listen() can make it a listener again, and IPV6_ADDRFORM can shrink an IPv6 TCP socket into an IPv4 one. Embryonic request sockets can remain hashed after the parent stops listening, children can inherit out-of-order queues, retransmit counters, and pacing flags from a parent that is mid-transition, and lockless receive paths can re-read socket state after it has already changed. Kim's write-ups show slab use-after-free and out-of-bounds writes under KASAN when those leftover objects are completed, closed, or cloned.
One fix also corrects an accept-queue accounting imbalance after reuseport migration, so a request counted on one listener is not dropped against another. Several of the defects are marked for stable kernels.
David Laight asked whether connect after listen is even valid; Kim replied that the relevant call is the AF_UNSPEC disconnect, which is. Networking maintainer Jakub Kicinski, noting sparse review traffic, asked whether more cleanup on the disconnect path could simplify the series: "Are people getting tired of the disconnect bugs?" Kim pointed at an alternate approach that would close several of the race windows from that path instead.
The bugs matter because any local process that can open sockets and flip these states can hit freed kernel memory on the receive and accept paths, not only exotic IPv6 conversion cases.