{"id":41067,"date":"2026-10-19T00:32:00","date_gmt":"2026-10-18T16:32:00","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-98595"},"modified":"2026-10-19T00:32:00","modified_gmt":"2026-10-18T16:32:00","slug":"cve-2026-98595","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-98595","title":{"rendered":"CVE-2026-98595 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nudp: remove a disconn"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>udp: remove a disconnected socket from the 4-tuple hash table<\/p>\n<p>A UDP socket bound to a specific address and port keeps its entry in the<br \/>\n4-tuple hash table after it is disconnected:<\/p>\n<p>    sk binds to 127.0.0.1:21001<br \/>\n    sk connects to 127.0.0.2:20001\t\/\/ filed in the 4-tuple table<br \/>\n    sk disconnects, connect(AF_UNSPEC)\t\/\/ still filed, peer now 0.0.0.0:0<\/p>\n<p>__udp_disconnect() takes a socket out of that table only as a side effect<br \/>\nof -&gt;rehash() or -&gt;unhash(), and it skips -&gt;rehash() when<br \/>\nSOCK_BINDADDR_LOCK is set and -&gt;unhash() when SOCK_BINDPORT_LOCK is set.<br \/>\ncommit 6996a2d2d0a6 (&#8220;udp: Unhash auto-bound connected sk from 4-tuple hash<br \/>\ntable when disconnected.&#8221;) fixed the same end state for a wildcard-bound<br \/>\nsocket, by a path this one does not take.<\/p>\n<p>The entry is counted whether or not anything hits it. hash4_cnt on the<br \/>\nhash2 slot stays raised for as long as the socket lives, so udp_has_hash4()<br \/>\nkeeps sending every packet for that address and port through the 4-tuple<br \/>\nlookup first.<\/p>\n<p>On IPv6 it can also be hit. __udp_disconnect() does not clear sk_v6_daddr,<br \/>\nso udp_v6_rehash() files the entry under the peer the socket was connected<br \/>\nto with a zero dport, and inet6_match() compares that same<br \/>\nfield: a datagram from the former peer with a zero source port matches,<br \/>\nand source port zero is accepted on receive. On IPv4 the peer is cleared,<br \/>\nso a match would need a zero source address as well, which the routing<br \/>\nlayer rejects as martian. The stale sk_v6_daddr is a separate defect, not<br \/>\naddressed here; removing the entry closes this path either way.<\/p>\n<p>The entry can also be relocated. __udp_disconnect() clears sk_bound_dev_if,<br \/>\nso a subsequent SO_BINDTODEVICE calls -&gt;rehash(), and because the receive<br \/>\naddress is still specific udp_lib_rehash() moves the entry instead of<br \/>\nremoving it, into the bucket that (rcv_saddr, num, 0, 0) hashes to &#8212; a<br \/>\npure function of the address and port, so every socket reaching this state<br \/>\non one address and port collects in one bucket. The bucket cannot be chosen<br \/>\nfrom outside, as udp_ehashfn() is seeded with a per-boot secret. This last<br \/>\none became reachable only with commit 644f9108f3a5 (&#8220;udp: Make rehash4<br \/>\nindependent in udp_lib_rehash()&#8221;), which moved the hash4 handling out of a<br \/>\nbranch a disconnected socket does not take; the stale entry itself dates<br \/>\nfrom the commit in Fixes.<\/p>\n<p>Take the socket out of the table before __udp_disconnect() runs, while it<br \/>\nstill matches how it was filed. This also reaches the wildcard case ahead<br \/>\nof udp_lib_rehash()&#8217;s udp_unhash4() branch, leaving that branch unreachable<br \/>\nfrom udp_disconnect(); removing it belongs in net-next. udp_disconnect()<br \/>\nand udp_abort() are the only UDP entries into __udp_disconnect(), which is<br \/>\nshared with raw, ping and l2tp sockets that are not struct udp_sock:<br \/>\nping_prot.obj_size is sizeof(struct inet_sock), so udp_hashed4() on one<br \/>\nwould read past the allocation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>udp: remove a disconnected socket from the 4-tuple hash table<\/p>\n<p>A UDP socket bound to a specific address and port keeps its entry in<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-41067","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/41067","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln"}],"about":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/types\/vuln"}],"wp:attachment":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=41067"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=41067"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=41067"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}