)]}'
{
  "commit": "aa40afa831ebfe45e40a23721711059f2ac584d4",
  "tree": "00ab54887463de83b9b137e3a596a5fcdcb8ae30",
  "parents": [
    "29dfa436bc488056a84ee423ba82336db453e2a6"
  ],
  "author": {
    "name": "Hyunwoo Kim",
    "email": "imv4bel@gmail.com",
    "time": "Tue Nov 10 23:04:44 2026 +0900"
  },
  "committer": {
    "name": "Jakub Kicinski",
    "email": "kuba@kernel.org",
    "time": "Fri Nov 13 16:46:31 2026 -0800"
  },
  "message": "tcp: fix NULL pointer dereference when restarting a Fast Open listener\n\nWhen a valid RST is received for a Fast Open child accepted before the\nthree-way handshake completes, reqsk_fastopen_remove() adds the\nrequest_sock to the listener\u0027s RST list if the listener is in TCP_LISTEN.\n\nAn application can call shutdown(SHUT_RD) on a listener socket.\ninet_csk_listen_stop() checks rskq_rst_head without holding\nfastopenq.lock. If rskq_rst_head is NULL, it does not acquire the lock\nand therefore does not synchronize with an insertion by\nreqsk_fastopen_remove() after that function has passed the TCP_LISTEN\ncheck.\n\nThe more likely outcome of this race, even without a subsequent\nlisten(), is a leak. If reqsk_fastopen_remove() inserts a request_sock\nafter inet_csk_listen_stop() observes an empty list and returns, the\nrequest_sock is stranded in rskq_rst_head and keeps a reference on the\nlistener. The socket is already in TCP_CLOSE, so a subsequent close()\ndoes not call inet_csk_listen_stop() again.\n\nIf listen() is called again on the same socket before the delayed list\ninsertion, the insertion can overlap the queue initialization in\nreqsk_queue_alloc(). If it occurs after rskq_rst_head is set to NULL but\nbefore rskq_rst_tail is set to NULL, rskq_rst_head points to the\nrequest_sock while rskq_rst_tail is NULL.\n\nWhen a valid RST is later received for another accepted Fast Open child,\nrskq_rst_head is not NULL, so reqsk_fastopen_remove() attempts to write\nthe request_sock pointer to rskq_rst_tail-\u003edl_next while rskq_rst_tail is\nNULL. KASAN reports:\n\n  BUG: KASAN: null-ptr-deref in reqsk_fastopen_remove+0x147/0x210\n  Write of size 8 at addr 0000000000000088 by task swapper/3/0\n  ...\n  Call Trace:\n   \u003cIRQ\u003e\n   ...\n   reqsk_fastopen_remove+0x147/0x210\n   tcp_check_req+0xa70/0x1060\n   ...\n   tcp_rcv_state_process+0x1cb/0x2ae0\n   ...\n   tcp_v4_do_rcv+0x1fe/0x740\n   tcp_v4_rcv+0x1744/0x2070\n   ...\n   ip_protocol_deliver_rcu+0x5c/0x280\n   ip_local_deliver_finish+0x171/0x330\n   ip_local_deliver+0x107/0x370\n   ...\n   \u003c/IRQ\u003e\n\nTo widen the race window, the issue was reproduced after adding\nmdelay(3000) immediately after reqsk_fastopen_remove() checks that the\nlistener is in TCP_LISTEN and immediately after reqsk_queue_alloc() sets\nrskq_rst_head to NULL.\n\nMake inet_csk_listen_stop() acquire fastopenq.lock regardless of the\nvalue of rskq_rst_head and detach the list while holding the lock. With\nthis synchronization, reqsk_fastopen_remove() either inserts the\nrequest_sock before inet_csk_listen_stop() acquires the lock, in which\ncase inet_csk_listen_stop() reclaims it, or sees that the listener is\nnot in TCP_LISTEN and does not insert anything.\n\nFixes: 0536fcc039a8 (\"tcp: prepare fastopen code for upcoming listener changes\")\nCc: stable@vger.kernel.org\nSigned-off-by: Hyunwoo Kim \u003cimv4bel@gmail.com\u003e\nReviewed-by: Kuniyuki Iwashima \u003ckuniyu@google.com\u003e\nReviewed-by: Eric Dumazet \u003cedumazet@kernel.org\u003e\nLink: https://patch.msgid.link/avMkfJrXhCFXn8M_@v4bel\nSigned-off-by: Jakub Kicinski \u003ckuba@kernel.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "6c079929e06f69d0708b90a2d01485d504940aa7",
      "old_mode": 33188,
      "old_path": "net/ipv4/inet_connection_sock.c",
      "new_id": "ca3057192e6daefa88b4b25f6c1b894dab8ba003",
      "new_mode": 33188,
      "new_path": "net/ipv4/inet_connection_sock.c"
    }
  ]
}
