iOS: Use sandbox-safe shared memory for GS

GSAllocateWrappedMemory's POSIX branch called shm_open("/GS.mem",
O_RDWR | O_CREAT | O_EXCL, 0600) directly. The iOS application
sandbox rejects named POSIX shared memory in the system-wide
namespace, so shm_open returned -1, the function returned nullptr,
and GSLocalMemory::GSLocalMemory() aborted via
pxFailRel("Failed to allocate GS memory storage."). On hosts that
re-enter the CPU thread across launches, this surfaced as a game-
launch abort on the GS thread.

The rest of the codebase already routes shared-memory creation
through HostSys::CreateSharedMemory (pcsx2/Memory.cpp uses it for
EE/IOP RAM), whose Linux/Apple branch selects memfd_create on
Android, shm_open on desktop POSIX, and a file-backed TMPDIR
fallback on iOS so the same call works under the sandbox.
GSAllocateWrappedMemory was the only production caller bypassing
the helper.

Delegate fd creation to HostSys::CreateSharedMemory, drop the
Android-only memfd_create special-case and the redundant ftruncate
(both are handled inside the helper), and use
HostSys::GetFileMappingName so the name is PID-qualified instead of
the fixed "/GS.mem". The MAP_SHARED repeat-mirroring mmap loop is
preserved unchanged so the 4 MB GS VRAM still appears `repeat` times
at contiguous virtual addresses for the PS2 GS address-wrap
behaviour. GSFreeWrappedMemory is updated symmetrically to call
HostSys::DestroySharedMemory.

The Windows branch is untouched, and the caller contract (return
nullptr on failure; the caller's pxFailRel handles the abort) is
preserved.

Verified with the iOS build and repeated game launch/exit/relaunch
cycles: GSLocalMemory construction no longer aborts and the wrapped
memory layout is unchanged.
This commit is contained in:
J1coding
2026-07-18 17:45:36 +02:00
committed by Jeen
parent 3080080226
commit 445d7aee1b
+15 -25
View File
@@ -44,6 +44,7 @@
#include "common/Console.h"
#include "common/FileSystem.h"
#include "common/HostSys.h"
#include "common/Path.h"
#include "common/SmallString.h"
#include "common/StringUtil.h"
@@ -1079,10 +1080,6 @@ void GSFreeWrappedMemory(void* ptr, size_t size, size_t repeat)
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#if defined(__ANDROID__)
#include <sys/syscall.h>
#include <android/sharedmem.h>
#endif
static int s_shm_fd = -1;
@@ -1090,29 +1087,22 @@ void* GSAllocateWrappedMemory(size_t size, size_t repeat)
{
pxAssert(s_shm_fd == -1);
const char* file_name = "/GS.mem";
#if defined(__ANDROID__)
s_shm_fd = static_cast<int>(syscall(__NR_memfd_create, "GS.mem", 0));
if (s_shm_fd == -1)
// Route fd creation through HostSys::CreateSharedMemory so iOS gets the
// file-backed fallback the helper already provides for the rest of the
// codebase. The bare shm_open("/GS.mem", ...) the prior implementation
// used is rejected by the iOS sandbox, which returned -1 and propagated
// nullptr up to GSLocalMemory.
const std::string file_name = HostSys::GetFileMappingName("GS.mem");
void* const handle = HostSys::CreateSharedMemory(file_name.c_str(), repeat * size);
if (!handle)
{
fprintf(stderr, "Failed to create memfd due to %s\n", strerror(errno));
std::fprintf(stderr,
"GSAllocateWrappedMemory: HostSys::CreateSharedMemory failed "
"(size=%zu repeat=%zu total=%zu)\n",
size, repeat, repeat * size);
return nullptr;
}
#else
s_shm_fd = shm_open(file_name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (s_shm_fd != -1)
{
shm_unlink(file_name); // file is deleted but descriptor is still open
}
else
{
fprintf(stderr, "Failed to open %s due to %s\n", file_name, strerror(errno));
return nullptr;
}
#endif
if (ftruncate(s_shm_fd, repeat * size) < 0)
fprintf(stderr, "Failed to reserve memory due to %s\n", strerror(errno));
s_shm_fd = static_cast<int>(reinterpret_cast<intptr_t>(handle));
void* fifo = mmap(nullptr, size * repeat, PROT_READ | PROT_WRITE, MAP_SHARED, s_shm_fd, 0);
@@ -1136,7 +1126,7 @@ void GSFreeWrappedMemory(void* ptr, size_t size, size_t repeat)
munmap(ptr, size * repeat);
close(s_shm_fd);
HostSys::DestroySharedMemory(reinterpret_cast<void*>(static_cast<intptr_t>(s_shm_fd)));
s_shm_fd = -1;
}