Commit Graph
7727 Commits
Author SHA1 Message Date
Yunus Shaikh 9a48a9605c fix(libkernel): map a protected main stack up to its top on Linux
A protect below the main thread's stack mapping mapped only the
protected pages. Linux keeps a growing stack one guard gap (1 MiB by
default) above a readable mapping, so after a read-only protect, or a
protect later restored to read/write, at the bottom of the reported
stack the stack could no longer grow into the megabyte above it and a
deep enough call faulted where the console has stack pages. The pages
between the protect and the top of the stack are now mapped as well,
so the stack never has to grow past them.
2026-10-16 07:28:23 +00:00
Yunus Shaikh 8d2053a21e fix(libkernel): keep a host thread's stack range once queried on Linux
glibc reports the main thread's stack as reaching down to the end of
the mapping below it. The pages a protect maps under the main stack
become that mapping, so after the first protect sceKernelIsStack
reported a stack starting above them, and a second protect of the same
pages, such as restoring them to read/write, failed as outside any
stack. Each thread now queries its host stack once, which also stops
every protect on the main thread from reading /proc/self/maps.
2026-10-16 07:27:37 +00:00
Yunus Shaikh d5c12169fc fix(libkernel): map a host stack's unmapped pages in runs on Linux
MapUnmappedPages probed every 4 KiB page of the protected range with
msync before mapping it. Under an unlimited stack limit the main
thread's reported stack reaches down to the heap, tens of TiB, so a
guest protect over the whole stack ran for hours. Mapped and unmapped
runs are now found by halving the remaining range, and the unmapped
ones are mapped without reserving swap, as the stack itself grows.
2026-10-16 07:24:41 +00:00
Yunus Shaikh f29ee47366 refactor(libkernel): record a host stack protect's guarded part on its own line
The stack branch now records the reserve and guard below a protected
range with a separate RecordProtection call, and keeps the call that
records the protected range itself as main has it. The ranges recorded
are the same: RecordProtection replaces what it covers, so the two calls
together record the whole requested range, as before. #6184 adds a line
next to that call, and the two no longer touch.
2026-10-15 08:52:21 -07:00
Yunus Shaikh 5796ddfcfd fix(libkernel): commit a protect at the bottom of a host stack's reserve
HotSpot makes its stack guard zones with an RW protect of the lowest
pages of the thread's stack, then PROT_NONE, as it commits them on
native Windows (os::pd_create_stack_guard_pages, then os::guard_memory).
Below a host stack's guard page such a protect was only recorded, so the
pages stayed reserved: they could not be written after the RW protect,
and the zones never held.

A protect of reserved pages that starts at the bottom of the reserve and
stops short of the guard page now commits and protects them. The guard
page and the reserve above the range stay as they are, so the stack still
grows through the guard down to it, and the stack limit in the TEB still
follows the committed stack.

Windows moves the guard down by committing the pages below it as
read/write guard pages, committed or not. The zones therefore hold until
the stack is within one guard region of them (three pages on GitHub's
runners), and the pages the guard reaches then come in read/write. The
test checks both, and the debt entry says so.
2026-10-15 08:10:42 -07:00
Yunus Shaikh 56ed31b334 test(libkernel): protect the bottom of a reserved host stack, then make it inaccessible
HotSpot makes its stack guard zones this way: an RW protect of the
lowest 48 KiB of the thread's stack, then PROT_NONE. Both calls succeed,
the guard page stays above them, and the stack still grows through it.
Every case now also checks that the stack limit in the TEB follows the
committed stack.
2026-10-15 08:10:42 -07:00
Yunus Shaikh 3724c577d8 fix(libkernel): keep a host stack's guard page and reserve when protecting it on Windows
Committing the reserved pages of a host thread's stack before protecting
it, as the stack branch did for a range the arena doesn't own, also
cleared the guard page's PAGE_GUARD. The thread was left with no guard
and no reserve: an overflow ran into whatever lay below the stack instead
of raising a stack overflow, and the stack limit in the thread's TEB,
which Windows moves only when the guard page is hit, stopped following
the stack. A range that began inside the reserve also left the reserved
pages below it with no guard above them, so the stack could no longer
grow into them.

The stack branch now leaves the guard page and the reserved pages below
it as they are, and commits and protects only what lies above them;
reserved pages above the guard are still committed first. The protection
is recorded for the whole range, and a range of only reserved and guard
pages changes nothing on the host. The test protects the main thread's
whole stack and a reserved thread's whole stack and upper part, then
checks that the guard page is still there and that the stack grows
through it, also after a PROT_NONE protect of its lowest page. The debt
file records that those pages come in read/write as the stack grows.
2026-10-15 08:10:42 -07:00
Yunus Shaikh 877320a5cd test(libkernel): protect the whole main-thread stack on Linux too
ProtectWholeStack also runs on the Linux main thread, whose reported
stack is mostly not mapped yet.
2026-10-15 08:10:42 -07:00
Yunus Shaikh b5909a5ee0 fix(libkernel): map the unmapped pages of a host stack before protecting it on Linux
On Linux the guest's main runs on the host main thread's stack, which
the kernel maps only as it grows. sceKernelIsStack reports the whole
range that pthread_getattr_np gives, which is sized by RLIMIT_STACK and
is mostly not mapped yet. A protection of that range failed with ENOMEM,
so mprotect returned EINVAL and sceKernelMprotect stopped the title.

When the stack branch's mprotect fails with ENOMEM, the range's unmapped
pages are now mapped read-write at their own addresses
(MAP_FIXED_NOREPLACE) and the protection is applied again. This matches
how the reserved pages of a host stack are committed on Windows.
2026-10-15 08:10:42 -07:00
Adrià d67b79a7e4 Merge pull request #5709 from fogydes/fix/libc-formatting-allocation-and-bounds
fix(libc): check allocation result in vasprintf and guard null pointer in strndup
2026-10-15 17:04:33 +02:00
Adrià 37e0f1688e Merge pull request #5708 from MarcZX100/codex/test-untracked-storage-repeat-5693
test(agc): cover repeated untracked storage writes after sampling
2026-10-15 17:04:27 +02:00
Adrià 0b5d774545 Merge pull request #5704 from fogydes/fix/libkernel-app-metadata-concurrency
fix(libkernel): protect app metadata state across threads and validate icon stream read
2026-10-15 17:04:22 +02:00
Adrià d8862a63ba Merge pull request #5703 from EagleBearerYS/fix/libkernel-protect-reserved-host-stack
fix(libkernel): commit a reserved host stack before protecting it
2026-10-15 17:04:17 +02:00
Adrià 3751c55111 Merge pull request #5700 from specbug/fix/default-scope-guest-symbols
fix(libkernel): resolve renamed guest exports in the default scope
2026-10-15 17:04:10 +02:00
Adrià 0e6a5e7a5c Merge pull request #5690 from SandstromPL/fix/savedata-mount3-invalid-dir-name
fix(savedata): return a parameter error from sceSaveDataMount3 for an invalid directory name
2026-10-15 17:04:04 +02:00
Adrià 162adb9da8 Merge pull request #5669 from MarcZX100/codex/signal-mask-128
fix(libkernel): honor all guest signal mask words
2026-10-15 17:03:59 +02:00
Adrià 8a253707e6 Merge pull request #5663 from al3w0f205/feat/libkernel-munlockall
feat(libkernel): add munlockall export
2026-10-15 17:03:54 +02:00
Adrià f5a55a11d0 Merge pull request #5662 from Roojool/contrib/g15-libc-pending
feat(libc): implement collate<wchar_t>::_Getcat
2026-10-15 17:03:49 +02:00
Adrià 21ca964f3f Merge pull request #5632 from babyhuey/fix/libc-closed-stream-writes
fix(libc): fail stream calls on a stream that a failed freopen closed
2026-10-15 17:03:43 +02:00
Adrià 9490a6da68 Merge pull request #5617 from Dripl1x/feat/socket-timeouts
feat(libkernel): apply SO_RCVTIMEO and SO_SNDTIMEO on a guest socket
2026-10-15 17:03:37 +02:00
Adrià 63b377b51b Merge pull request #5612 from JJenkx/feat/private-mutex-sharing
fix(libkernel): store mutex process-sharing attributes
2026-10-15 17:03:30 +02:00
Adrià 51b1d4a3a0 Merge pull request #5611 from JJenkx/fix/kernel-virtual-query-layout
fix(libkernel): stabilize virtual-query layout across hosts
2026-10-15 17:03:24 +02:00
Adrià 08290338aa Merge pull request #5599 from JJenkx/feat/libc-isfinitel
feat(libc): implement x87 long-double finite classification
2026-10-15 17:03:18 +02:00
Adrià b4a4fcac0e Merge pull request #5254 from 0xRickx/fix/libsceaudiodec-heaac
fix(libSceAudiodec): decode HE-AAC as the console does
2026-10-15 16:59:46 +02:00
Adrià 120615bc73 Merge pull request #4927 from QRMOE/fix-libc-getcwd-allocated-size
fix(libc): ignore getcwd size when allocating a buffer
2026-10-15 16:59:41 +02:00
Adrià ff23657f34 Merge pull request #2852 from alfalfa-star/feat/np-user-id-by-account-id
feat(npmanager): implement sceNpGetUserIdByAccountId
2026-10-15 16:34:37 +02:00
Adrià f7bc3732e0 Merge pull request #5712 from ErenYeager1836/fix/msgdialog-native-error-codes
fix(libSceMsgDialog.native): return error codes instead of throwing in initialize and terminate
2026-10-15 16:34:28 +02:00
Adrià 0dab493f5b Merge pull request #5816 from Nawasfadili/feat/libc-wide-and-unlocked-stream-io
feat(libc): implement wide and unlocked stream I/O
2026-10-15 15:58:44 +02:00
Adrià 636b1b93cf Merge pull request #5759 from YossiYad/fix/sparse-import-test-backings
test(agc): drop a shared range's backing when the range goes away
2026-10-15 15:58:31 +02:00
Adrià 56f5a6eef7 Merge pull request #5757 from hypermoist/perf/vector-window-unindexed-slots
perf(recompiler): keep the vector window's unindexed slots out of the array
2026-10-15 15:58:23 +02:00
Adrià 5c0cc1bba4 Merge pull request #5755 from AlexOfTheForest/fix/decoder-rip-far-indirect
fix(relinker): report RIP-relative operands of far indirect CALL and JMP
2026-10-15 15:58:16 +02:00
Adrià 281336041a Merge pull request #5754 from fogydes/fix/libkernel-eventflag-clear-pattern-and-attr-validation
fix(libkernel): reject unknown event flag creation attributes
2026-10-15 15:58:10 +02:00
Adrià 6359e3466a Merge pull request #5751 from NaitikJoshiPro/pr/agc-raw-graphics-beside-registered
fix(agc): read unregistered graphics programs beside registered shaders
2026-10-15 15:08:26 +02:00
Adrià 73e924acd4 Merge pull request #5750 from NaitikJoshiPro/pr/agc-queue0-idle-wait
fix(agc): queue 0 waits instead of spinning when every queue is idle
2026-10-15 15:08:03 +02:00
Adrià 0c32e8dd02 Merge pull request #5741 from IshmamDC217/fix/relinker-load-file-ranges
fix(relinker): check PT_LOAD and uncovered PT_SCE_RELRO file ranges
2026-10-15 15:07:43 +02:00
Adrià 73d6424d6b Merge pull request #5735 from mugurc/fix/libscefiber-host-stack-macos
fix(libSceFiber): map fiber host stacks on hosts without MAP_STACK
2026-10-15 15:05:24 +02:00
Adrià 489466d3f9 Merge pull request #5734 from YossiYad/fix/strip-last-provoking
fix(agc): refuse last-vertex strips only for reads of a vertex slot
2026-10-15 15:03:44 +02:00
Adrià e534fd98b6 Merge pull request #5715 from ErenYeager1836/fix/web-browser-dialog-error-codes
fix(libSceWebBrowserDialog): return error codes instead of throwing in initialize and terminate
2026-10-15 15:00:27 +02:00
Adrià f0a1e3443b Merge pull request #5691 from xXPBSXx/fix/video-out-flip-rate-error-v2
fix(libSceVideoOut): return VIDEO_OUT_ERROR_INVALID_VALUE for a flip rate outside 0..2
2026-10-15 14:59:01 +02:00
Nithishvelan M cb5b3e22a2 fix(libSceMsgDialog.native): return error codes instead of throwing in initialize and terminate 2026-10-15 18:28:04 +05:30
Adrià 2b8a685dfe Merge pull request #5683 from MarcZX100/codex/rosetta-scalar-compare-5642
fix(relinker): isolate Rosetta scalar compare hazards
2026-10-15 14:57:14 +02:00
Adrià 54ee3c0945 Merge pull request #5675 from fogydes/fix/test-windows-fixed-base-error-mode
test(relinker): suppress Windows error dialog in occupied base collision check
2026-10-15 14:56:20 +02:00
Adrià f3c00ad28e Merge pull request #5670 from fogydes/fix/relinker-cfg-address-overflow-guards
fix(relinker): prevent address overflow and signed UB in CFG, GOT access, and entry point analysis
2026-10-15 14:55:50 +02:00
Adrià e890b4a385 Merge pull request #5660 from milescoviello/fix/ngs2-empty-waveform-blocks
fix(ngs2): accept empty waveform blocks and matrix levels on a voice without a format
2026-10-15 14:54:20 +02:00
Adrià 3ee5371915 Merge pull request #5627 from AlxcBTW/fix/agc-htile-written-by-any-kernel
fix(agc): take depth fast clears from HTILE written by any kernel
2026-10-15 14:52:34 +02:00
Adrià a61c8a37e0 Merge pull request #5554 from Amoenus/codex/native-depth-htile-clears
fix(agc): apply completion-proven native depth clears
2026-10-15 14:51:07 +02:00
Adrià FranchandClaude 57ce03944d fix(agc): keep the draw key trace map out of module teardown on Windows
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-15 14:48:04 +02:00
fogydes 2210200232 fix(libkernel): reject unknown event flag creation attributes 2026-10-15 18:14:45 +05:30
Adrià FranchandClaude bc3f81c198 test(libc): pin vasprintf allocation failure; move debt line off the section end
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-15 14:44:16 +02:00
fogydes ceb963c6dd fix(libc): check allocation result in vasprintf and guard null pointer in strndup 2026-10-15 14:43:04 +02:00