On macOS under Rosetta, Aps5StartGuest moves the main thread off the host
stack and releases the old range to the guest arena. dyld keeps its own
pointers into the process start block at the top of that range and offers
no call that redirects them, where argv and environ have one:
_NSGetExecutablePath copies the path string out of the block on every
call, so the first call after the move read unmapped memory and the
process died with KERN_PROTECTION_FAILURE. A title does not have to call
it: libxpc reaches it from xpc_connection_resume, and ShaderCacheDirectory
calls it for the shader disk cache.
Release the old stack only up to the pages that hold the block, and only
while argv still points into the stack. They are the top two pages, 8 KiB
of the 8372224-byte stack here, so a title that fixes a mapping over that
range now fails with a host region overlap; the rest is free as before.
guest_main_stack_move asked for a 64 KiB guest mapping aligned down from
a local of main, which falls inside the kept pages. It now probes the
64 KiB below them, requires the kept pages to be refused, and calls
_NSGetExecutablePath after the move, which segfaults without this change.
Cut the two longest exception handler entries under the 1000 character
limit: the mapping entry keeps the unverified protection fault signal and
what counts as title code, the Linux entry keeps what a later guest signal,
the conversion stubs and older glibc change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
dladdr1 searches the object's symbol table, which made every host fault
chained past an installed handler about 8 us slower on Linux. glibc 2.35
and later answer the same question with _dl_find_object, which is also
async-signal-safe; older glibc keeps dladdr1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A handler that returns the context unchanged runs again on the same fault,
a handler that fixes the page with mprotect and returns lets the store
complete, and a handler that removes itself and returns ends the process
with the fault (checked in a child process, so a loop fails on a timeout).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A handler installed for SIGILL, SIGFPE, SIGBUS or SIGSEGV now receives
the faults raised in title code instead of the process ending, with
mc_trapno, mc_addr and mc_err filled as FreeBSD 11's amd64 trap() does.
On Windows the crash reporter's vectored handler offers unclaimed faults
to libkernel, which redirects the thread to a stub that runs the handler
outside the exception dispatcher; on Linux chained host signal handlers
classify faults by REG_TRAPNO.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Resolves docs/dev/debt/libkernel.md: main's sigaction entry (SIGPIPE outside Windows) and this branch's signal entry, which points to libSceLibcInternal for siginterrupt.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
cpuset_getaffinity and cpuset_setaffinity return ERANGE from 24 bytes, as a PS5 payload process did (rooklz sweep, #7135 comment 6391606624: 8 to 16 accepted, below 8 and from 24 up ERANGE), and throw for the unmeasured 17 to 23, as pthread_getaffinity_np does. The tests that used 32 bytes use 16 and pin 7, 24, 32 and 64 to ERANGE. The setter entry records that the console answers EPERM for a CPU outside the process's set where this clips and returns 0.
cpuset_getaffinity at CPU_LEVEL_ROOT returns 0xffff, as a PS5 payload process read it (rooklz, #7135 comment 6390891591), instead of throwing; the target is checked as at the other levels. The level 2 base-set test now passes 8 and 16 bytes, which the console accepts (it returns ERANGE from 24 bytes), instead of depending on the 32 bytes it rejects. The debt entry records the root measurement and that the title root set is unmeasured.
Unbacked PRT pages were private read-only commits, so every page that was
read took its own host page. They are now views of one pagefile-backed
section created read-only, so the range costs one page however large and
no view of it can be made writable. Host imports treat such views as
read-only memory instead of asking for a read-write alias.