The title-module variants of sceKernelGetModuleList and
sceKernelGetModuleInfo, following shadPS4: the list leaves out system
libraries and the info call answers EPERM for one. A system library is
a loaded .prx image that is not a relinked title module.
NHL 27 (PPSA34063) imports both and fails to load without them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Windows GUI build started without standard handles has no descriptor 2.
_dup(2) then reached the invalid-parameter handler, which aborts, before the
"cannot keep the host standard error" error could be thrown. It now goes
through WithoutParameterHandler like the other descriptor calls in this file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Guest descriptors are host descriptors, so a guest that moves standard
error with dup2 also moves the stream sceKernelDebugOutText writes to. A
title that forwards its standard error to the kernel log through a pipe
then reads its own debug output back and logs it again without end. Before
the guest's first dup2 onto descriptor 2, the host's standard error is kept,
and sceKernelDebugOutText writes there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Linux, socket() and sceNetSocket() create AF_INET6 sockets in the
host's default dual-stack mode (net.ipv6.bindv6only is 0), so a wildcard
IPv6 bind also claims the IPv4 port. A title that keeps an IPv4 and an
IPv6 socket on the same port fails: with 0.0.0.0:P bound, binding [::]:P
returns EADDRINUSE (48), and an IPv6 socket bound to [::] also receives
IPv4 traffic from v4-mapped peers.
FreeBSD makes every new IPv6 socket IPv6-only. sys/netinet6/in6_proto.c:
VNET_DEFINE(int, ip6_v6only) = 1;
sys/netinet/in_pcb.c, in_pcballoc():
if (INP_SOCKAF(so) == AF_INET6) {
inp->inp_vflag |= INP_IPV6PROTO;
if (V_ip6_v6only)
inp->inp_flags |= IN6P_IPV6_V6ONLY;
}
and sys/netinet6/in6_pcb.c, in6_pcbbind(), looks for an IPv4 owner of
the port only when the flag is clear:
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
socket() and sceNetSocket() now set IPV6_V6ONLY on every IPv6 socket
they create. Windows already defaults to it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_wstat64, the FindFirstFileExW listing and std::filesystem::file_size
report the size of a file symbolic link itself (0). stat therefore gave
0 for linked files, and APR resolved them as empty, so Unity treated a
linked globalgamemanagers as empty and never read it.
stat takes the size from the handle it already opens, which follows the
link. The APR listing skips reparse points, and names missing from it
are sized through stat.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
recvmsg() reads one byte more than the guest buffers hold to see
whether a record did not fit, but only for SOCK_DGRAM sockets. On a
SOCK_SEQPACKET socketpair a record longer than the buffers was cut
short with msg_flags 0: a 6-byte record received into 2 bytes returned
2 and no MSG_TRUNC, and the rest of the record was gone.
FreeBSD's SOCK_SEQPACKET protocol is atomic, sys/kern/uipc_usrreq.c:
.pr_type = SOCK_SEQPACKET,
...
.pr_flags = PR_ADDR|PR_ATOMIC|PR_CONNREQUIRED|PR_WANTRCVD|
PR_RIGHTS,
and its receive routine, soreceive_generic() in sys/kern/uipc_socket.c,
flags the truncation of an atomic record and drops its rest:
if (m != NULL && pr->pr_flags & PR_ATOMIC) {
flags |= MSG_TRUNC;
if ((flags & MSG_PEEK) == 0)
(void) sbdroprecord_locked(&so->so_rcv);
}
which kern_recvit() hands back in msg_flags. recvmsg() now probes for a
longer record on SOCK_SEQPACKET sockets as it does for SOCK_DGRAM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>