Repository navigation
fix(libkernel): disconnect a connected datagram socket on connect to port 0 - #9105
Conversation
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Independent Windows run of this PR (data only). Environment: Windows 10 Pro 10.0.19045, Ryzen 7 5800X3D, WinLibs GCC 15.2.0 r7 (MinGW-w64 UCRT), Release, BUILD_TESTING=ON. Merge-tree of the PR head against PR head tested: Results (3 runs each):
GPU: the run output has no Not run: other platforms, the other tests in the same family, the full repository CTest, and any title or console run. AI-assisted (Claude Code). |
…port 0 FreeBSD 11.4's soconnectat() (sys/kern/uipc_socket.c) disconnects a connected socket of a protocol without PR_CONNREQUIRED before it calls pru_connect. udp_disconnect() and udp6_disconnect() drop the peer and reset the local address, then in_pcbconnect_setup() and in6_pcbladdr() fail port 0 with EADDRNOTAVAIL, so the socket is left unconnected. connect to port 0 on a connected datagram socket now dissolves the association through the AF_UNSPEC disconnect path before failing with 49, where it kept the old peer. Stream sockets keep EISCONN.
144470f to
be4fd86
Compare
|
Linux run of head Setup: CachyOS, kernel 7.3.0-4, GCC 16.2.1, glibc 2.44, CMake 4.4.3, Ninja,
Overlap: #10299 (opened later, broader address-family and length checks) also makes No title or console run. AI-assisted: yes (Claude Code). |
What
connectto port 0 on a datagram socket that was already connected kept the old peer. FreeBSD 11.4'ssoconnectat()(sys/kern/uipc_socket.c) disconnects a connected socket of a protocol withoutPR_CONNREQUIREDbefore it callspru_connect.udp_disconnect()(sys/netinet/udp_usrreq.c) andudp6_disconnect()(sys/netinet6/udp6_usrreq.c) drop the peer, reset the local address to the wildcard address and clearSS_ISCONNECTED. Thenudp_connect()reachesin_pcbconnect_setup()(sys/netinet/in_pcb.c), andudp6_connect()reachesin6_pcbladdr()(sys/netinet6/in6_pcb.c). Both fail port 0 withEADDRNOTAVAIL(49) before anything is bound, so the socket ends up unconnected:getpeernamegivesENOTCONN(57) andsendwithout an address givesEDESTADDRREQ(39) fromsosend_dgram().ZeroPortConnectinUdp.cppnow dissolves the association of a connectedAF_INETorAF_INET6datagram socket throughDisconnect, the helper thatconnecttoAF_UNSPECalready uses, and then fails with 49. A failed host disconnect returns that error. Stream sockets are unchanged: a connected one still gets the host'sEISCONN. The gap is cut from theconnectentry indocs/dev/debt/libkernel.md.Test change:
guest_socket_port_zero(CheckDatagram) now connects a UDP socket to a bound loopback peer, forAF_INETandAF_INET6. It then expectsconnectto port 0 to give -1/49,getpeernameto give -1/57 andsendto give -1/39. If the host has no IPv6 loopback, the IPv6 case is skipped the same wayCheckStreamskips it.Tested
Windows 11, WinLibs MinGW-w64 GCC 15.2.0 r7, CMake + Ninja, Release,
-DBUILD_TESTING=ON, rebased onmain11f976b.guest_socket_port_zerowith the new checks fails withconnect to port 0 on a connected datagram socket must fail with EADDRNOTAVAIL (49) (errno 57). With this PR it passes, and IPv6 loopback is available on this machine, so the IPv6 case ran.guest_inet_address,guest_refused_connect,guest_sce_net,guest_socket_*(13 tests),guest_tcp,guest_udp): 18 of 18 pass.guest_refused_connecttimed out once in the full run and passed twice when run alone.guest_socket_*(12 tests,guest_socket_port_zeroamong them) pass 12 of 12.python tools/check_conventions.py --base origin/mainreports no errors. Its one warning is the length of theconnectdebt entry, 1141 characters onmain, which this PR cuts to 1086.guest_socket_port_zeropasses 3 of 3, and fails 3 of 3 withmain'sUdp.cpp(comment below).Disconnect, whichconnecttoAF_UNSPECalready runs on Linux (hostAF_UNSPECconnect, then a rebind when the port was dropped). Linux CI must confirm that the test passes there.Overlap:
tools/pr_overlap.pylists #8499, #8682, #8728 and #8921, and none of them implements this. #8499 (now merged) added asendtoport-0 check right next toZeroPortConnectand rewrote thesendtohalf of the same debt sentence; this PR is rebased onto it, keepsZeroPortSendwhere it is and keeps itssendtosentence word for word. #8682 changesDisconnectto take a non-constSocket&. If it merges first,ZeroPortConnecthas to drop itsconsttoo, and the textual conflict around the moved function will show this. #8728 and #8921 only touch neighbouring debt lines. The tool could not compare some open PRs. I checked the ones that touchUdp.cpp(#5021, #6977, #7088, #7201, #8344, #8483, #8658, #8670), and none changesconnectto port 0 orDisconnect.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)