feat(libkernel): implement sceKernelGetFsSandboxRandomWord
Returns the name of the directory under which a title's sandbox exposes system files, which homebrew SDKs splice into paths such as /<name>/common/cert/CA_LIST.cer and /<name>/common/lib/libc.sprx. The name is fixed here; recorded in TechnicalDebt together with the fact that nothing is mounted under it. Registers guest_sandbox_random_word. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
b858fdc48e
commit
7785933807
|
|
@ -45,6 +45,7 @@ add_library(libkernel SHARED EXCLUDE_FROM_ALL
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Sanitizer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Rtld.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Process.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Sandbox.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/SystemConfiguration.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Signals.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Notification.cpp
|
||||
|
|
@ -471,4 +472,14 @@ if(BUILD_TESTING)
|
|||
set_tests_properties(guest_file_vector PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
|
||||
endif()
|
||||
add_test_executable(guest_sandbox_random_word_tests ${LIBS_INCLUDE_DIR}/tests/GuestSandboxRandomWord.cpp)
|
||||
target_include_directories(guest_sandbox_random_word_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(guest_sandbox_random_word_tests PRIVATE libkernel libc)
|
||||
configure_windows_unwind(guest_sandbox_random_word_tests)
|
||||
add_test(NAME guest_sandbox_random_word COMMAND guest_sandbox_random_word_tests)
|
||||
set_tests_properties(guest_sandbox_random_word PROPERTIES TIMEOUT 20)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_sandbox_random_word PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
|
||||
extern "C" const char* APS5_VABI sceKernelGetFsSandboxRandomWord() {
|
||||
static constexpr char word[] = "gkbHtXc3Wq";
|
||||
return word;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
extern "C" {
|
||||
const char* APS5_VABI sceKernelGetFsSandboxRandomWord();
|
||||
int APS5_VABI open_nid_postfix(const char*, int, int);
|
||||
int* APS5_VABI __error_nid_postfix();
|
||||
}
|
||||
|
||||
static void Require(bool value) { if (!value) std::abort(); }
|
||||
|
||||
int main() {
|
||||
const char* word = sceKernelGetFsSandboxRandomWord();
|
||||
Require(word != nullptr);
|
||||
const std::size_t length = std::strlen(word);
|
||||
Require(length >= 1);
|
||||
for (std::size_t index = 0; index < length; ++index)
|
||||
Require(std::isalnum(static_cast<unsigned char>(word[index])));
|
||||
|
||||
Require(sceKernelGetFsSandboxRandomWord() == word);
|
||||
const char* fromThread = nullptr;
|
||||
std::thread([&] { fromThread = sceKernelGetFsSandboxRandomWord(); }).join();
|
||||
Require(fromThread == word);
|
||||
|
||||
const std::string path = std::string("/") + word + "/common/lib/libc.sprx";
|
||||
*__error_nid_postfix() = 0;
|
||||
Require(open_nid_postfix(path.c_str(), 0, 0) == -1);
|
||||
Require(*__error_nid_postfix() == 2);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -244,6 +244,7 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [sceNetSendmsg and sceNetRecvmsg](../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) copy the scatter/gather list through one host buffer and accept only the flags `sceNetSend`/`sceNetRecv` accept. Sending control data throws; a receive never returns control data (`msg_controllen` 0), since no socket option that queues it is supported
|
||||
- [Additional content](../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) is not installed or mounted: `sceAppContentAddcontMount` answers `NOT_FOUND` for every entitlement label and `sceAppContentAddcontUnmount` for every mount point, as no add-content mount is ever handed out; `sceAppContentGetAddcontInfo` answers `DRM_NO_ENTITLEMENT` for every label and `sceAppContentGetAddcontInfoList` reports 0 entries
|
||||
- [sceKernelPread, sceKernelPwrite, sceKernelPreadv, sceKernelPwritev](../../core/libs/prx/libkernel/File/src/Stdio.cpp) (libkernel) on Windows transfer at the given offset with an overlapped `ReadFile`/`WriteFile` and restore the descriptor's file pointer afterwards, so a concurrent `read`/`write` on the same descriptor can see the moved pointer in between, unlike on the console. Handles that are not disk files return `ESPIPE`. `readv` on a pipe or console handle stops after the first iovec read, a short read the console is assumed to allow; each iovec is transferred separately, so a failure after the first transfer returns the bytes already done
|
||||
- [sceKernelGetFsSandboxRandomWord](../../core/libs/prx/libkernel/System/src/Sandbox.cpp) (libkernel) returns a fixed directory name, `gkbHtXc3Wq`. On the console the name is the process's randomized path (syscall 602, `randomized_path`), and the sandbox exposes system files under it, such as `common/lib` and `common/cert`. Nothing is mounted under the name here, so `/gkbHtXc3Wq/common/...` resolves under the guest root like any other path and does not exist
|
||||
- [sceKernelSync](../../core/libs/prx/libc/src/General.cpp) (libkernel) on Windows flushes only the host files and directories recorded through `RecordWrittenPath_nid_no_patch` (the libc, libkernel, save data and app content file functions) and their changed parent directories. A host write in a library that does not record its path is not flushed by `sceKernelSync`
|
||||
- [sceKernelSync](../../core/libs/prx/libc/src/General.cpp) (libkernel) on Windows skips a recorded file it cannot open for writing (read-only, or held open by a handle that denies write sharing), since `FlushFileBuffers` needs a writable handle. Such a file's data may not reach the disk before a host crash; the guest reads the same data either way
|
||||
- [sceKernelInstallExceptionHandler](../../core/libs/prx/libkernel/System/src/Exception.cpp) records the handler, but a host fault still ends the process: only signals raised with `sceKernelRaiseException` are delivered. Unity's PS5Util module installs a SIGUSR1 handler that reads `uc_mcontext.mc_rsp` (offset 0xf8 of the context) and raises SIGUSR1 on other threads to stop them for garbage collection
|
||||
|
|
|
|||
Loading…
Reference in New Issue