Repository navigation
fix(libkernel): answer sysarch I386_GET_FSBASE, I386_GET_GSBASE and undefined operations as measured on a PS5 - #7654
Conversation
…ndefined operations as measured on a PS5 In a payload process on a PS5 (firmware 12.70), I386_GET_FSBASE (7) and I386_GET_GSBASE (9) wrote 4 bytes, the low 32 bits of the FS and GS bases, and failed with EFAULT for a null argument; both threw here. On Linux x86-64 hosts they now do the same. The nine operation numbers tried that FreeBSD 11's amd64 sysarch has no case for (2, 5, 6, 12, 127, 133, 134, 1000 and -1), each with a null argument, failed with EINVAL there, as its default case does, and threw here. Every such number now returns EINVAL on every host. Threads made with pthread_create and scePthreadCreate started with their creator's GS base there; the test now checks that a guest thread does so on Linux. The sysarch debt entry records these measurements and what AMD64_GET_XFPUSTATE and I386_GET_XFPUSTATE returned there; both still throw here.
|
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.
|
|
Linux run of the part listed as not run: WSL Ubuntu 24.04, GCC 13.3, base
With The copyout matches FreeBSD 11.4 as well as 11.0: Note: #7658, opened after this PR, rewrites the same AI-assisted: yes (Claude Code); results above were run on this machine. |
…n over the database exports - sysarch: boykopovar#7654's PS5-measured behaviour (I386_GET_FSBASE/GSBASE writing the low 32 bits, EINVAL for undefined operations, GS-base inheritance) replaces this branch's documented error paths; the messages the branch's GuestSysarch expected are gone, so Process.cpp and GuestSysarch.cpp come from upstream. - Hmd2: al3w0f205's database exports join the guest test (their three throw expectations run after the reprojection session walk) and the debt file (their aerolib bullet follows the session bullet, which now links the export table to satisfy the new debt-file rule from boykopovar#6723). - Http: sceHttpAuthCacheFlush/sceHttpAuthCookieFlush merged around the cookie hunk without overlap.
What
sysarchthrew forI386_GET_FSBASE(7),I386_GET_GSBASE(9) and for every operation number that FreeBSD 11's amd64sysarchhas no case for. In a payload process on a PS5 (firmware 12.70), 7 and 9 wrote the low 32 bits of the base, and nine undefined numbers, called with a null argument, failed withEINVAL. Here 7 and 9 now do the same on Linux x86-64 hosts, and every undefined number fails withEINVALon every host: the nine tried, and the rest by FreeBSD 11's default case.mainbefore this PRsysarch(7, buf)sysarch(9, buf)sysarch(7, NULL),sysarch(9, NULL)EFAULTEINVALEINVALfor every number FreeBSD 11's amd64sysarchhas no case for, on every hostOn other hosts 7 and 9 still throw, like the other segment-base operations. FreeBSD 11's amd64
sysarchends withdefault: error = EINVAL; numbers other than the nine tried follow that default case here and were not measured. Operation 6 (I386_VM86) is named in its header but has no case on amd64, so it getsEINVALhere, as it did in the payload process.GS base of a new thread. The debt entry ended with an unfinished sentence saying that a new thread's GS base is not modelled. In the payload process, a GS base that one thread set left the main thread's unchanged, and threads that thread made with
pthread_createandscePthreadCreatestarted with its GS base. Here the host thread of a guest thread is created on the creating thread (scePthreadCreateinThread.cpp), and Linux'scopy_threadgives a new thread its creator's GS base (CLONE_SETTLSsets only the FS base).guest_sysarchnow checks this on Linux for a thread made withscePthreadCreate.Not changed:
AMD64_GET_XFPUSTATE(132) returned 0 there for lengths 0, 64, 128, 256 and 512 (512 was also the largest length a search accepted) and failed withEINVALfor 1024, 2048, 4096 and 8192 and withEFAULTfor a null argument or address, andI386_GET_XFPUSTATE(11) failed withEFAULTfor a null argument. Both still throw here; the debt entry records these answers.I386_SET_FSBASE,I386_SET_GSBASE, the LDT and I/O permission operations were not called.Debt: the
sysarchentry indocs/dev/debt/libkernel.mdrecords the measurements above, and its unfinished last sentence is replaced.Overlaps: #7658, opened after this PR, rewrites the same parts of
sysarch: it replaces theNotImplemented_nid_no_patchcall for unhandled operations, 7 and 9 included, with astd::runtime_errorsaying the operation "is not supported", turns the fallback for other hosts intostd::runtime_error("sysarch: segment bases on this host"), and changes the matching lines ofGuestSysarch.cpp: thesysarch(7, nullptr)check and the other-host message that this PR's newsysarch(7, &base)check expects. This PR answers 7 and 9 and returnsEINVALfor undefined operations instead, so the two conflict inProcess.cppandGuestSysarch.cpp, and whichever lands second has to reconcile those lines. No other open PR changessysarchorGuestSysarch.cpp. Seven other open PRs (#5021, #6879, #7039, #7201, #7332, #7543 and #7804) change other functions inProcess.cpp, and more than 50 others changedocs/dev/debt/libkernel.md.tools/pr_overlap.py --branchdid not finish within 25 minutes here, so each of them was merged withgit merge-tree, once withmainand once with this branch: with this branch, none of them conflicts in a file where it does not already conflict withmain.How the console was measured
resolvelines show thatsysarchandscePthreadCreatewere taken fromlibkernel_sys.sprxand that thepthread_createthe probe calls is the onelibkernel_sys.sprxexports.0xaaand compares its first 4 bytes with the low 32 bits of the base thatAMD64_GET_FSBASE(128) orAMD64_GET_GSBASE(130) returned, or, on the helper thread below, of the GS base it set (which 130 read back).AMD64_SET_GSBASE(131) to the address of a buffer in the probe. While it is set, the main thread reads its own GS base, and the helper makes one thread withpthread_createand one withscePthreadCreate, each of which reads its own. The helper then sets its GS base back to 0. The FS base was not changed.AMD64_GET_XFPUSTATEwas called with lengths 0, 64, 128 and so on up to 8192, and a search found the largest length it accepted.Console output (excerpt, lines copied unchanged)
The
p74:prefix names the probe; the rest of each line is copied unchanged.Tested
Build: Windows 11 x86-64, full build with WinLibs MinGW-w64 GCC 15.2.0 (posix-seh, ucrt, r7) and
-DBUILD_TESTING=ON.Tests: with this branch on top of
main8d17389, built in one tree together withfix/libkernel-kevent-timer-readd(which changes onlykevent),guest_sysarchand the otherguest_*tests pass: 470 of 471, andguest_video_out_wqhd_detection_no_vulkanis skipped on this machine. Of two full runs the second passed; the first, right after the build, timed out inguest_requested_exit, which this PR does not touch. On Windowsguest_sysarchchecks the undefined operations and that 7, 129, 130 and 132 still throw.Not run here: the Linux x86-64 part of
guest_sysarch(7 and 9 against the FS and GS bases,EFAULTfor a null argument, and the GS base of a thread made withscePthreadCreate). There is no Linux machine here, so they were only syntax-checked withg++ -fsyntax-only -Wall -Wextraand__linux__defined, without warnings: the changedsysarchfunction copied out with stub declarations forsyscalland theARCH_*constants, and the whole test file. Full builds do not run automatically for pull requests; a collaborator's manual Build run would run them on Linux. A reviewer reported a Linux run ofguest_sysarchin the comments.Old code, new test: with
Process.cppreverted tomainand the new test kept,guest_sysarchaborts withsysarch: operation 2 not implemented.Console: behaviour measured on a PS5 (firmware 12.70), as described above.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)