{"api_version":"1","generated_at":"2026-07-27T03:09:23+00:00","cve":"CVE-2026-64459","urls":{"html":"https://cve.report/CVE-2026-64459","api":"https://cve.report/api/cve/CVE-2026-64459.json","docs":"https://cve.report/api","cve_org":"https://www.cve.org/CVERecord?id=CVE-2026-64459","nvd":"https://nvd.nist.gov/vuln/detail/CVE-2026-64459"},"summary":{"title":"tcp: restore RCU grace period in tcp_ao_destroy_sock","description":"In the Linux kernel, the following vulnerability has been resolved:\n\ntcp: restore RCU grace period in tcp_ao_destroy_sock\n\nCommit 51e547e8c89c (\"tcp: Free TCP-AO/TCP-MD5 info/keys without RCU\")\nremoved the call_rcu() callback from tcp_ao_destroy_sock(), arguing that\n\"the destruction of info/keys is delayed until the socket destructor\"\nand therefore \"no one can discover it anymore\".\n\nThat argument does not hold for the call site in tcp_connect()\n(net/ipv4/tcp_output.c:4327-4332). At that point the socket is in\nTCP_SYN_SENT, has already been inserted into the inet ehash by\ninet_hash_connect() in tcp_v4_connect(), and is therefore very much\ndiscoverable: any softirq running tcp_v4_rcv() on another CPU can take\nthe socket out of the ehash, walk into tcp_inbound_hash(), and load\ntp->ao_info via implicit RCU before bh_lock_sock_nested() is taken on\nthe destroying CPU.\n\nThe reader path then enters __tcp_ao_do_lookup() (net/ipv4/tcp_ao.c:208)\nwhich re-loads tp->ao_info via rcu_dereference_check(); the re-load can\nstill observe the (about-to-be-freed) pointer because there is no\nsynchronize_rcu() between rcu_assign_pointer(tp->ao_info, NULL) and\ntcp_ao_info_free() in tcp_ao_destroy_sock(). The captured pointer is\nthen walked at line 223:\n\n\thlist_for_each_entry_rcu(key, &ao->head, node, ...)\n\nThe writer's synchronous kfree() is free to complete between the line\n218 re-fetch and the line 223 hlist iteration. The slab is reused\n(or simply LIST_POISON1-stamped if not yet reused) and the iteration\nwalks attacker-controlled or poison memory in softirq context.\n\nReproducer (no debug shim, stock x86_64 v7.1-rc2 SMP+KASAN, QEMU+KVM):\nan unprivileged uid=1000 process inside CLONE_NEWUSER|CLONE_NEWNET\ninstalls TCP_MD5SIG + TCP_AO_ADD_KEY on a TCP socket, sprays forged\nTCP-AO segments toward its eventual 4-tuple via raw sockets, then\ncalls connect(). The md5-wins reconciliation in tcp_connect() fires\ntcp_ao_destroy_sock(); the softirq backlog reader on the loopback\nNAPI path crashes on the freed ao->head.first walk:\n\n  Oops: general protection fault, probably for non-canonical\n    address 0xfbd59c000000002f\n  KASAN: maybe wild-memory-access in range\n    [0xdead000000000178-0xdead00000000017f]\n  CPU: 0 UID: 1000 PID: 100 Comm: repro_userns\n  RIP: 0010:__tcp_ao_do_lookup+0x107/0x1c0\n  Call Trace: <IRQ>\n    __tcp_ao_do_lookup+0x107/0x1c0\n    tcp_ao_inbound_lookup.constprop.0+0x12a/0x200\n    tcp_inbound_ao_hash+0x5ea/0x1520\n    tcp_inbound_hash+0x7ce/0x1240\n    tcp_v4_rcv+0x1e7a/0x3e10\n    ...\n\nRestore the RCU grace period: re-add struct rcu_head to tcp_ao_info\nand replace the synchronous tcp_ao_info_free() with a call_rcu()\ncallback. Readers that captured tp->ao_info before rcu_assign_pointer\nNULLed it now see the object remain valid until rcu_read_unlock().\nWith the patch applied the reproducer runs cleanly for 2000 iterations\non the same kernel build.","state":"PUBLISHED","assigner":"Linux","published_at":"2026-07-25 10:17:31","updated_at":"2026-07-25 10:17:31"},"problem_types":[],"metrics":[],"references":[{"url":"https://git.kernel.org/stable/c/657646c08c94ef7b9dbe468fe7828032216f9841","name":"https://git.kernel.org/stable/c/657646c08c94ef7b9dbe468fe7828032216f9841","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://git.kernel.org/stable/c/8bc4d43bccbd60efe85d0a44d5bf41762f2f0c30","name":"https://git.kernel.org/stable/c/8bc4d43bccbd60efe85d0a44d5bf41762f2f0c30","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://git.kernel.org/stable/c/4caf12c778fed3dc3824cf36263be5e2c491fbd0","name":"https://git.kernel.org/stable/c/4caf12c778fed3dc3824cf36263be5e2c491fbd0","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-64459","name":"CVE Program record","refsource":"CVE.ORG","tags":["canonical"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-64459","name":"NVD vulnerability detail","refsource":"NVD","tags":["canonical","analysis"]}],"affected":[{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 51e547e8c89c661f6fbede4a28b1d33b13625683 657646c08c94ef7b9dbe468fe7828032216f9841 git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 51e547e8c89c661f6fbede4a28b1d33b13625683 4caf12c778fed3dc3824cf36263be5e2c491fbd0 git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 51e547e8c89c661f6fbede4a28b1d33b13625683 8bc4d43bccbd60efe85d0a44d5bf41762f2f0c30 git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 6.18","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 6.18 semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 6.18.39 6.18.* semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 7.1.4 7.1.* semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 7.2-rc2 * original_commit_for_fix","platforms":[]}],"timeline":[],"solutions":[],"workarounds":[],"exploits":[],"credits":[],"nvd_cpes":[],"vendor_comments":[],"enrichments":{"kev":null,"epss":{"cve_year":"2026","cve_id":"64459","cve":"CVE-2026-64459","epss":"0.001730000","percentile":"0.070340000","score_date":"2026-07-26","updated_at":"2026-07-27 00:02:02"},"legacy_qids":[]},"source_records":{"cve_program":{"containers":{"cna":{"affected":[{"defaultStatus":"unaffected","product":"Linux","programFiles":["include/net/tcp_ao.h","net/ipv4/tcp_ao.c"],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","vendor":"Linux","versions":[{"lessThan":"657646c08c94ef7b9dbe468fe7828032216f9841","status":"affected","version":"51e547e8c89c661f6fbede4a28b1d33b13625683","versionType":"git"},{"lessThan":"4caf12c778fed3dc3824cf36263be5e2c491fbd0","status":"affected","version":"51e547e8c89c661f6fbede4a28b1d33b13625683","versionType":"git"},{"lessThan":"8bc4d43bccbd60efe85d0a44d5bf41762f2f0c30","status":"affected","version":"51e547e8c89c661f6fbede4a28b1d33b13625683","versionType":"git"}]},{"defaultStatus":"affected","product":"Linux","programFiles":["include/net/tcp_ao.h","net/ipv4/tcp_ao.c"],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","vendor":"Linux","versions":[{"status":"affected","version":"6.18"},{"lessThan":"6.18","status":"unaffected","version":"0","versionType":"semver"},{"lessThanOrEqual":"6.18.*","status":"unaffected","version":"6.18.39","versionType":"semver"},{"lessThanOrEqual":"7.1.*","status":"unaffected","version":"7.1.4","versionType":"semver"},{"lessThanOrEqual":"*","status":"unaffected","version":"7.2-rc2","versionType":"original_commit_for_fix"}]}],"cpeApplicability":[{"nodes":[{"cpeMatch":[{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"6.18.39","versionStartIncluding":"6.18","vulnerable":true},{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"7.1.4","versionStartIncluding":"6.18","vulnerable":true},{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"7.2-rc2","versionStartIncluding":"6.18","vulnerable":true}],"negate":false,"operator":"OR"}]}],"descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\ntcp: restore RCU grace period in tcp_ao_destroy_sock\n\nCommit 51e547e8c89c (\"tcp: Free TCP-AO/TCP-MD5 info/keys without RCU\")\nremoved the call_rcu() callback from tcp_ao_destroy_sock(), arguing that\n\"the destruction of info/keys is delayed until the socket destructor\"\nand therefore \"no one can discover it anymore\".\n\nThat argument does not hold for the call site in tcp_connect()\n(net/ipv4/tcp_output.c:4327-4332). At that point the socket is in\nTCP_SYN_SENT, has already been inserted into the inet ehash by\ninet_hash_connect() in tcp_v4_connect(), and is therefore very much\ndiscoverable: any softirq running tcp_v4_rcv() on another CPU can take\nthe socket out of the ehash, walk into tcp_inbound_hash(), and load\ntp->ao_info via implicit RCU before bh_lock_sock_nested() is taken on\nthe destroying CPU.\n\nThe reader path then enters __tcp_ao_do_lookup() (net/ipv4/tcp_ao.c:208)\nwhich re-loads tp->ao_info via rcu_dereference_check(); the re-load can\nstill observe the (about-to-be-freed) pointer because there is no\nsynchronize_rcu() between rcu_assign_pointer(tp->ao_info, NULL) and\ntcp_ao_info_free() in tcp_ao_destroy_sock(). The captured pointer is\nthen walked at line 223:\n\n\thlist_for_each_entry_rcu(key, &ao->head, node, ...)\n\nThe writer's synchronous kfree() is free to complete between the line\n218 re-fetch and the line 223 hlist iteration. The slab is reused\n(or simply LIST_POISON1-stamped if not yet reused) and the iteration\nwalks attacker-controlled or poison memory in softirq context.\n\nReproducer (no debug shim, stock x86_64 v7.1-rc2 SMP+KASAN, QEMU+KVM):\nan unprivileged uid=1000 process inside CLONE_NEWUSER|CLONE_NEWNET\ninstalls TCP_MD5SIG + TCP_AO_ADD_KEY on a TCP socket, sprays forged\nTCP-AO segments toward its eventual 4-tuple via raw sockets, then\ncalls connect(). The md5-wins reconciliation in tcp_connect() fires\ntcp_ao_destroy_sock(); the softirq backlog reader on the loopback\nNAPI path crashes on the freed ao->head.first walk:\n\n  Oops: general protection fault, probably for non-canonical\n    address 0xfbd59c000000002f\n  KASAN: maybe wild-memory-access in range\n    [0xdead000000000178-0xdead00000000017f]\n  CPU: 0 UID: 1000 PID: 100 Comm: repro_userns\n  RIP: 0010:__tcp_ao_do_lookup+0x107/0x1c0\n  Call Trace: <IRQ>\n    __tcp_ao_do_lookup+0x107/0x1c0\n    tcp_ao_inbound_lookup.constprop.0+0x12a/0x200\n    tcp_inbound_ao_hash+0x5ea/0x1520\n    tcp_inbound_hash+0x7ce/0x1240\n    tcp_v4_rcv+0x1e7a/0x3e10\n    ...\n\nRestore the RCU grace period: re-add struct rcu_head to tcp_ao_info\nand replace the synchronous tcp_ao_info_free() with a call_rcu()\ncallback. Readers that captured tp->ao_info before rcu_assign_pointer\nNULLed it now see the object remain valid until rcu_read_unlock().\nWith the patch applied the reproducer runs cleanly for 2000 iterations\non the same kernel build."}],"providerMetadata":{"dateUpdated":"2026-07-25T08:51:26.879Z","orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","shortName":"Linux"},"references":[{"url":"https://git.kernel.org/stable/c/657646c08c94ef7b9dbe468fe7828032216f9841"},{"url":"https://git.kernel.org/stable/c/4caf12c778fed3dc3824cf36263be5e2c491fbd0"},{"url":"https://git.kernel.org/stable/c/8bc4d43bccbd60efe85d0a44d5bf41762f2f0c30"}],"title":"tcp: restore RCU grace period in tcp_ao_destroy_sock","x_generator":{"engine":"bippy-1.2.0"}}},"cveMetadata":{"assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","assignerShortName":"Linux","cveId":"CVE-2026-64459","datePublished":"2026-07-25T08:51:26.879Z","dateReserved":"2026-07-19T15:36:31.789Z","dateUpdated":"2026-07-25T08:51:26.879Z","state":"PUBLISHED"},"dataType":"CVE_RECORD","dataVersion":"5.2"},"nvd":{"publishedDate":"2026-07-25 10:17:31","lastModifiedDate":"2026-07-25 10:17:31","problem_types":[],"metrics":[],"configurations":[]},"legacy_mitre":{"record":{"CveYear":"2026","CveId":"64459","Ordinal":"1","Title":"tcp: restore RCU grace period in tcp_ao_destroy_sock","CVE":"CVE-2026-64459","Year":"2026"},"notes":[{"CveYear":"2026","CveId":"64459","Ordinal":"1","NoteData":"In the Linux kernel, the following vulnerability has been resolved:\n\ntcp: restore RCU grace period in tcp_ao_destroy_sock\n\nCommit 51e547e8c89c (\"tcp: Free TCP-AO/TCP-MD5 info/keys without RCU\")\nremoved the call_rcu() callback from tcp_ao_destroy_sock(), arguing that\n\"the destruction of info/keys is delayed until the socket destructor\"\nand therefore \"no one can discover it anymore\".\n\nThat argument does not hold for the call site in tcp_connect()\n(net/ipv4/tcp_output.c:4327-4332). At that point the socket is in\nTCP_SYN_SENT, has already been inserted into the inet ehash by\ninet_hash_connect() in tcp_v4_connect(), and is therefore very much\ndiscoverable: any softirq running tcp_v4_rcv() on another CPU can take\nthe socket out of the ehash, walk into tcp_inbound_hash(), and load\ntp->ao_info via implicit RCU before bh_lock_sock_nested() is taken on\nthe destroying CPU.\n\nThe reader path then enters __tcp_ao_do_lookup() (net/ipv4/tcp_ao.c:208)\nwhich re-loads tp->ao_info via rcu_dereference_check(); the re-load can\nstill observe the (about-to-be-freed) pointer because there is no\nsynchronize_rcu() between rcu_assign_pointer(tp->ao_info, NULL) and\ntcp_ao_info_free() in tcp_ao_destroy_sock(). The captured pointer is\nthen walked at line 223:\n\n\thlist_for_each_entry_rcu(key, &ao->head, node, ...)\n\nThe writer's synchronous kfree() is free to complete between the line\n218 re-fetch and the line 223 hlist iteration. The slab is reused\n(or simply LIST_POISON1-stamped if not yet reused) and the iteration\nwalks attacker-controlled or poison memory in softirq context.\n\nReproducer (no debug shim, stock x86_64 v7.1-rc2 SMP+KASAN, QEMU+KVM):\nan unprivileged uid=1000 process inside CLONE_NEWUSER|CLONE_NEWNET\ninstalls TCP_MD5SIG + TCP_AO_ADD_KEY on a TCP socket, sprays forged\nTCP-AO segments toward its eventual 4-tuple via raw sockets, then\ncalls connect(). The md5-wins reconciliation in tcp_connect() fires\ntcp_ao_destroy_sock(); the softirq backlog reader on the loopback\nNAPI path crashes on the freed ao->head.first walk:\n\n  Oops: general protection fault, probably for non-canonical\n    address 0xfbd59c000000002f\n  KASAN: maybe wild-memory-access in range\n    [0xdead000000000178-0xdead00000000017f]\n  CPU: 0 UID: 1000 PID: 100 Comm: repro_userns\n  RIP: 0010:__tcp_ao_do_lookup+0x107/0x1c0\n  Call Trace: <IRQ>\n    __tcp_ao_do_lookup+0x107/0x1c0\n    tcp_ao_inbound_lookup.constprop.0+0x12a/0x200\n    tcp_inbound_ao_hash+0x5ea/0x1520\n    tcp_inbound_hash+0x7ce/0x1240\n    tcp_v4_rcv+0x1e7a/0x3e10\n    ...\n\nRestore the RCU grace period: re-add struct rcu_head to tcp_ao_info\nand replace the synchronous tcp_ao_info_free() with a call_rcu()\ncallback. Readers that captured tp->ao_info before rcu_assign_pointer\nNULLed it now see the object remain valid until rcu_read_unlock().\nWith the patch applied the reproducer runs cleanly for 2000 iterations\non the same kernel build.","Type":"Description","Title":"tcp: restore RCU grace period in tcp_ao_destroy_sock"}]}}}