Skip to content

fix(libkernel): fail a short or long socket address like FreeBSD - #4920

Closed
xXPBSXx wants to merge 2 commits into
boykopovar:mainfrom
xXPBSXx:fix/socket-address-length
Closed

xXPBSXx wants to merge 2 commits into
boykopovar:mainfrom
xXPBSXx:fix/socket-address-length

Conversation

@xXPBSXx

@xXPBSXx xXPBSXx commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What

bind, connect and sendto on a libkernel socket checked the guest sockaddr length in Address() (Udp.cpp) with rules of their own: a length below 2 failed with EFAULT (14), and an AF_INET address below 16 or an AF_INET6 address below 28 bytes with EAFNOSUPPORT (47). FreeBSD 11.4 answers these differently:

  • getsockaddr fails a length above SOCK_MAXADDRLEN (255) with ENAMETOOLONG (63) and a length below offsetof(struct sockaddr, sa_data) (2) with EINVAL (22).
  • The protocols compare the length (sa_len) with sizeof(struct sockaddr_in) / sockaddr_in6 and fail a mismatch with EINVAL (tcp_usr_connect, in_pcbconnect_setup). A null address with a length of 2 to 255 is EFAULT (copyin), as before; a null address with a length below 2 now fails with EINVAL and one above 255 with ENAMETOOLONG, because getsockaddr checks the length before it copies (read in release/11.4.0).

Address() now returns these three errors. A full-size address is unchanged. Not changed, because the console's answer is not known: an address longer than sockaddr_in / sockaddr_in6 is still accepted (FreeBSD says EINVAL), and a different family still fails with EAFNOSUPPORT. Both are in the TechnicalDebt entry.

No title evidence: found by writing failure-path tests from the FreeBSD source (see Tested), no title I ran passes a short address. This is FreeBSD conformance.

Overlap: the overlap bot lists no pull request for this one, and git merge-tree of the head 9fc03d33a against main bf8dc610e is clean (checked, not rebuilt). The test registration sits before guest_socket_read_write in core/libs/prx/libkernel/CMakeLists.txt and the TechnicalDebt entry after the send, sendto entry in libkernel.md, away from the places the other socket PRs use. #5565 (Dripl1x, TCP_NODELAY, SO_NOSIGPIPE and SO_NBIO) conflicts with this PR in docs/dev/debt/libkernel.md (git merge-tree of the two heads, re-checked against main ce5c83953; both heads are clean against main); whichever lands second rebases the debt entry.

Tested

Windows 10 (19045), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release, on main c2565f014; moved since to a newer main (git merge-tree against main bf8dc610e is clean; not rebuilt there) with its test registration and debt entry at their own places:

  • guest_socket_address_length (new) passes: lengths 0, 1, 3, 8, 15 (AF_INET), 20 (AF_INET6) fail with EINVAL, 256 with ENAMETOOLONG, a null address with EFAULT, a full sockaddr_in still binds.
  • It fails without the change to Udp.cpp (connect with a length below the size of sa_family must fail with EINVAL (22) (errno 14)).
  • The existing socket tests (guest_udp, guest_tcp, guest_sce_net, guest_poll, guest_dup, guest_select, guest_socket*): pass together with the new one.
  • python tools/check_conventions.py --base upstream/main passes.
  • Measured on a combined build of the twelve open branches of this series (this PR and the others) merged onto main 0f2683cb7: guest_socket_address_length takes 0.21 s (ctest, serial, Windows). The full guest_* / libc / libkernel group passes (391 of 391, 0 failed; the build also contains the other branches of this series).
  • Second commit 2e553b97c (test only): guest_socket_address_length now checks the result of socket(AF_INET6, ...) and closes that socket (before, a host without IPv6 would have answered EBADF instead of EINVAL, and the descriptor stayed open). Rebuilt and run on the new head (base 1e7f4967e, Windows 10, MinGW GCC 15.2.0, Release, -j4): guest_socket_address_length passes; with Udp.cpp taken back to the base it fails (connect with a length below the size of sa_family must fail with EINVAL (22) (errno 14)); python tools/check_conventions.py --base upstream/main passes.
  • Not tested: Linux (one source for both hosts, only Windows was built), a console, a title run.

Checklist

  • Based on current main; no other open PR implements the same functions (overlaps described above)
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt (docs/dev/debt/libkernel.md)
  • No notes, investigation .md files or images added to the repository
  • New third-party code is a submodule built from source (none added)
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • AI-assisted: yes

AI-assisted (Claude Code).

🤖 Generated with Claude Code

This was referenced Oct 13, 2026
@xXPBSXx
xXPBSXx force-pushed the fix/socket-address-length branch from d06efc5 to 004eb28 Compare October 13, 2026 07:03
bind, connect and sendto answered EFAULT for an address length below 2 and EAFNOSUPPORT for an AF_INET address below 16 or an AF_INET6 address below 28 bytes. FreeBSD 11.4's getsockaddr fails a length below 2 with EINVAL and above SOCK_MAXADDRLEN (255) with ENAMETOOLONG, and the protocols compare the length with sizeof(struct sockaddr_in) or sockaddr_in6 and fail with EINVAL.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ess_length

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Closing: no title is known to reach this. With the queue at 700+ open PRs, please hold off on new PRs that don't name a title needing the change until it's down. If a title stops on this on current main, reopen with the title ID and the log line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants