Skip to content

fix(libSceNet): receive sceNetRecvmsg through the iovecs it had at entry - #11619

Merged
oneandonlydean merged 2 commits into
boykopovar:mainfrom
MaxLikesCode:fix/net-recvmsg-iovec-snapshot
Oct 27, 2026
Merged

oneandonlydean merged 2 commits into
boykopovar:mainfrom
MaxLikesCode:fix/net-recvmsg-iovec-snapshot

Conversation

@MaxLikesCode

@MaxLikesCode MaxLikesCode commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

What

sceNetRecvmsg now receives through the header and iovec table it had at entry, instead of reading the live table again after the receive.

It opened write guards for the destinations of the iovecs it saw at entry, received into a host buffer, then read msg->iov[i] again to scatter the data. When an earlier destination overlaps a later iovec, as #11610 reports, the received bytes replace that iovec first. The rest of the data then goes to an address that was never guarded, and the process crashes when that address is not writable.

FreeBSD 11.4's sys_recvmsg:

  • copies in the header and the iovec table (copyin, then copyiniov);
  • receives through the kernel's copy of the iovecs (recvit);
  • on success, copies the whole header back to the caller's pointer, with the entry-time msg_iov and the new msg_namelen, msg_controllen and msg_flags (copyout).

sceNetRecvmsg now does the same:

  • it copies the header and the iovecs after the existing checks;
  • it uses those copies for the guards, the scatter and the sender address, whose capacity is the entry-time name_length;
  • it writes the header back from the copy, also in the early return that receives nothing on Windows and macOS.

The checks and their order are unchanged. #11472 (sendmsg) touches the function above it, and the two merge cleanly.

Tested

Windows 11 Pro 26200, WinLibs GCC 15.2.0 r7, full Release build with BUILD_TESTING=ON, main 74acfad.

Checklist

  • Based on current main; no other open PR implements the same functions
  • 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 under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: Fixes libSceNet: sceNetRecvmsg rereads an iovec modified by earlier output and crashes the host #11610
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes. Written with Claude Code (Claude Opus 5.5).

🤖 Generated with Claude Code

sceNetRecvmsg guarded the destinations of the iovec table it saw at
entry, then read the live table again to scatter the received bytes.
When an earlier destination overlapped a later iovec, the received
bytes replaced that iovec and the rest of the data went to an address
that was never guarded, which crashed the host when that address was
not writable. Copy the header and the iovec table once, as FreeBSD
11.4's sys_recvmsg does with copyin and copyiniov, use that copy for
the guards, the scatter and the address, and write the header back
from it as sys_recvmsg's copyout does.

Fixes boykopovar#11610

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

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed head 3d2b723f714d2e7c643b612e490614898d5fbbfe.

[P2] Handle a zero-length iovec list without null pointer arithmetic. message_length() accepts iov_length == 0 with iov == nullptr, and sceNetRecvmsg() supports this zero-capacity receive path. The new std::vector<NetIovec> vectors(header.iov, header.iov + header.iov_length) evaluates nullptr + 0; pointer arithmetic on a null pointer is undefined, and the range constructor may subtract the null iterators. Please default-construct vectors and copy/assign the range only when iov_length > 0 (or otherwise explicitly handle the empty case), then add a zero-iovec receive test.

The overlapping-destination test is a good regression for the issue: it ensures the scatter uses the entry-time iovec descriptors after an earlier destination overwrites the guest table. The report says it fails on baseline and passes on the change on Windows 11; I did not rerun the Windows tests. At review time eligibility and report pass, while conventions/labels are still queued and intake is running; platform build jobs are skipped by path policy.

Copy the iovec table only when there is one, and receive a datagram
with no iovecs in guest_sce_net: it returns 0 with MSG_TRUNC and the
sender's address.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxLikesCode

Copy link
Copy Markdown
Contributor Author

Thanks for the review. vectors now stays empty unless iov_length > 0 and copies the table only then (ff5e67d). guest_sce_net gains CheckEmptyReceiveVectors: a 1-byte datagram received with iov null and iov_length 0 returns 0 with MSG_TRUNC (0x10), name_length 16 and the sender's address, and leaves iov and iov_length as they were. The Windows-only net_empty_stream_recvmsg_nullbuf passes the same arguments on a connected stream socket and passes too.

With this head the full suite passes 2546 of 2548 on Windows, with the same two failures as main on this machine, and guest_sce_net passes 3 of 3. I added this to the Tested section.

AI-assisted: yes (Claude Code)

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed updated head ff5e67de1581fc5d3ec8e0cc2c976e25134c07db. The empty iovec case now leaves the copied vector list empty without forming a range from a null pointer, and the new regression covers a one-byte datagram with {iov=nullptr, iov_length=0} and checks the returned truncation/header fields. The earlier overlapping-iovec test still exercises the entry-time snapshot behavior. I verified that the diff from #11472 merges cleanly with this head; it changes sceNetSendmsg/sendto and adds separate fault tests, while this change is confined to sceNetRecvmsg and its test.

The author reports guest_sce_net passing 3/3 and the full Windows suite passing 2546/2548 with the same two baseline failures. I did not independently rerun those Windows tests. Hosted conventions, labels, eligibility and report pass; platform build jobs are skipped by path policy. The local host lacks required PS5 CPU instructions, so it cannot execute the guest tests here.

@github-actions github-actions Bot added the fix error Closes an issue (Fixes #N) label Oct 26, 2026
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

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.

Pull request Shared files not compared
PR 5836 core/libs/prx/libSceNet/Export.cpp
core/libs/tests/GuestSceNet.cpp
PR 7201 core/libs/prx/libSceNet/Export.cpp
PR 9932 core/libs/prx/libSceNet/Export.cpp
core/libs/tests/GuestSceNet.cpp
PR 9948 core/libs/prx/libSceNet/Export.cpp
core/libs/tests/GuestSceNet.cpp
PR 11341 core/libs/prx/libSceNet/Export.cpp

@jotitadev jotitadev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First run on Linux, since the PR lists Linux as not tested.

Exact head ff5e67de1581fc5d3ec8e0cc2c976e25134c07db, merged on main cb45ae2dd. Linux x86_64 (bare metal, not WSL), i7-8700, Ubuntu 26.04, kernel 7.0, GCC 15.2, glibc 2.43, CMake 4.2.3, Ninja, Release, BUILD_TESTING=ON, full build.

  • guest_sce_net passes, 3 of 3 runs. The 13 guest_net*|guest_sce_net* tests pass.
  • Full non-GPU suite on the same main without the PR: 1361/1361.
  • With only core/libs/prx/libSceNet/Export.cpp reverted to main (new test kept), guest_sce_net crashes with SIGSEGV. So the overlapping-iovec case from #11610 also crashes on Linux, and the test catches it there.

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@MaxLikesCode

Copy link
Copy Markdown
Contributor Author

Thanks @jotitadev for the bare-metal Linux run and the baseline-library control. I added both to the Tested section.

AI-assisted: yes (Claude Code)

@oneandonlydean
oneandonlydean merged commit 09f9a63 into boykopovar:main Oct 27, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix error Closes an issue (Fixes #N)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

libSceNet: sceNetRecvmsg rereads an iovec modified by earlier output and crashes the host

4 participants