Common: Don't use MAP_FIXED on Linux

MAP_FIXED will clobber any existing memory mapping, and is not safe
to use in a multi-threaded environment. Whether we like it or not,
we are a multi-threaded environment, because Qt initializes before
we get to main(), so it's already too late to safely use MAP_FIXED
by the time we get there.

Use MAP_FIXED_NOREPLACE instead. This is how MAP_FIXED should have
behaved from the beginning.

Obviously this means you'll need Linux 4.17+ and a semi-recent libc
to use PCSX2 now. But if you're running a 6 year old unsupported
kernel, you have bigger problems.

Fixes "random" startup crashes.
This commit is contained in:
Stenzek 2024-05-21 22:38:33 +10:00 committed by Connor McLaughlin
parent fb4aaf5236
commit e24d97bbe4
1 changed files with 3 additions and 2 deletions

View File

@ -316,7 +316,7 @@ void* HostSys::MapSharedMemory(void* handle, size_t offset, void* baseaddr, size
{
const uint lnxmode = LinuxProt(mode);
const int flags = (baseaddr != nullptr) ? (MAP_SHARED | MAP_FIXED) : MAP_SHARED;
const int flags = (baseaddr != nullptr) ? (MAP_SHARED | MAP_FIXED_NOREPLACE) : MAP_SHARED;
void* ptr = mmap(baseaddr, size, lnxmode, flags, static_cast<int>(reinterpret_cast<intptr_t>(handle)), static_cast<off_t>(offset));
if (ptr == MAP_FAILED)
return nullptr;
@ -326,7 +326,7 @@ void* HostSys::MapSharedMemory(void* handle, size_t offset, void* baseaddr, size
void HostSys::UnmapSharedMemory(void* baseaddr, size_t size)
{
if (mmap(baseaddr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) == MAP_FAILED)
if (munmap(baseaddr, size) != 0)
pxFailRel("Failed to unmap shared memory");
}
@ -370,6 +370,7 @@ u8* SharedMemoryMappingArea::Map(void* file_handle, size_t file_offset, void* ma
{
pxAssert(static_cast<u8*>(map_base) >= m_base_ptr && static_cast<u8*>(map_base) < (m_base_ptr + m_size));
// MAP_FIXED is okay here, since we've reserved the entire region, and *want* to overwrite the mapping.
const uint lnxmode = LinuxProt(mode);
void* const ptr = mmap(map_base, map_size, lnxmode, MAP_SHARED | MAP_FIXED,
static_cast<int>(reinterpret_cast<intptr_t>(file_handle)), static_cast<off_t>(file_offset));