bind, getsockname, sendto and recvfrom validate as for a libkernel socket
before they reach libSceNet, so a forwarded descriptor reports the same
errors. recvfrom keeps its guest address handling and MSG_WAITALL, and a
zero-length datagram receive does not wait.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A title can create a socket with sceNetSocket and then call bind, getsockname, sendto or recvfrom from libkernel, which does not hold that descriptor, so the call failed with EBADF. PPSA06866's RakNet does this, its local server fails to start and the load after difficulty selection never ends. libSceNet now registers these four calls with libkernel, as it does for setsockopt and getsockopt.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Windows, closing a pipe while another thread waited for it in select
terminated the process. The close releases the host handle before the C
runtime descriptor, so in between:
- the readiness query of the pipe failed on the dead handle and threw
'querying pipe descriptor ... failed';
- after that, DescriptorIsOpen still saw the descriptor mapped, select
looked it up again, found no known kind and threw 'is neither a
socket, a pipe, ...'.
QueryPipe now reports a descriptor whose handle is no longer a pipe as
not a pipe instead of throwing, DescriptorIsOpen on Windows also checks
that the mapped handle is still valid, and select answers EBADF for such
a descriptor before throwing for an unknown kind, as FreeBSD 11.4's
kern_select does for a descriptor closed during the wait.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
dup2 from a guest socket notified the event queues only when the
replaced descriptor was itself a guest socket. A kqueue replaced this
way stayed registered, so kevent on the number that now names the
socket still returned the old queue's events, and knotes registered on
a replaced pipe or file stayed attached. FreeBSD 11.4's kern_dup closes
the replaced file through closefp, whose knote_fdclose drops every
knote on the descriptor, as the other dup2 paths here already do.
Fixes#11429
Co-Authored-By: Claude Opus 5.5 <[email protected]>
ioctl(FIONBIO) on a guest socket read its int argument directly, while ioctl(FIONREAD) wrote its int result directly, so passing a non-null pointer into unmapped or read-only memory crashed the host with an access violation. FIONBIO and FIONREAD are _IOW and _IOR requests, which FreeBSD copies in and out using copyin and copyout, returning EFAULT on inaccessible memory. The argument is now safely checked using GuestCopyIn_nid_no_patch and GuestCopyOut_nid_no_patch.
sceKernelJitCreateSharedMemory's size object and maximum protection live
in libkernel's g_jitDescriptors, which the receive side of SCM_RIGHTS
doesn't fill, so a received JIT descriptor failed
sceKernelJitMapSharedMemory with EBADF (XairRrR's review). Passing one
now throws, with the random device and directory cases; IsJitSharedMemory
answers it. The merge of main brought #11296's rename of
IsKqueueDescriptor to IsKqueueDescriptor_nid_no_patch, which the kqueue
check now calls.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A guest kqueue and a guest /dev/urandom are /dev/null placeholders with
their behaviour in libkernel's tables, and a guest directory descriptor
keeps its reading state there too. sendmsg sent the placeholder, and the
receiver got a descriptor that failed kevent or read as empty. FreeBSD's
unp_internalize returns EOPNOTSUPP for a kqueue (no DFLAG_PASSABLE), so a
kqueue now gets that; a random device or a directory throws.
A zero-byte sendmsg carrying descriptors on a stream socket returned 0
and lost them, as Linux sends no record without data. It throws now.
FreeBSD sends the control data alone there.
guest_socket_rights checks the kqueue refusal and that the next send on
the pair arrives without control data.
Co-Authored-By: Claude Opus 5.5 <[email protected]>