Skip to content

Commit

Permalink
Merge pull request #1596 from Sonicadvance1/fix_old_kernel_bug
Browse files Browse the repository at this point in the history
LinuxAllocator: Fixes bug with old kernels and hint allocation
  • Loading branch information
lioncash authored Mar 2, 2022
2 parents 4a3cbf1 + 23daf4c commit 08938ec
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions Source/Tests/LinuxSyscalls/LinuxAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ void *MemAllocator32Bit::mmap(void *addr, size_t length, int prot, int flags, in
uintptr_t Addr = reinterpret_cast<uintptr_t>(addr);
uintptr_t PageAddr = Addr >> PAGE_SHIFT;

// Define MAP_FIXED_NOREPLACE ourselves to ensure we always parse this flag
constexpr int FEX_MAP_FIXED_NOREPLACE = 0x100000;
bool Fixed = ((flags & MAP_FIXED) ||
(flags & MAP_FIXED_NOREPLACE));
(flags & FEX_MAP_FIXED_NOREPLACE));

// Both Addr and length must be page aligned
if (Addr & ~PAGE_MASK) {
Expand Down Expand Up @@ -168,8 +170,7 @@ void *MemAllocator32Bit::mmap(void *addr, size_t length, int prot, int flags, in

bool Map32Bit = flags & FEX::HLE::X86_64_MAP_32BIT;

// Find a region that fits our address
if (Addr == 0) {
auto AllocateNoHint = [&]() -> void*{
bool Wrapped = false;
uint64_t BottomPage = Map32Bit && (LastScanLocation >= LastKeyLocation32Bit) ? LastKeyLocation32Bit : LastScanLocation;
restart:
Expand All @@ -192,7 +193,7 @@ void *MemAllocator32Bit::mmap(void *addr, size_t length, int prot, int flags, in
reinterpret_cast<void*>(LowerPage<< PAGE_SHIFT),
length,
prot,
flags | MAP_FIXED_NOREPLACE,
flags | FEX_MAP_FIXED_NOREPLACE,
fd,
offset);

Expand Down Expand Up @@ -242,6 +243,11 @@ void *MemAllocator32Bit::mmap(void *addr, size_t length, int prot, int flags, in
}
}
}
};

// Find a region that fits our address
if (Addr == 0) {
return AllocateNoHint();
}
else {
void *MappedPtr = ::mmap(
Expand All @@ -252,7 +258,15 @@ void *MemAllocator32Bit::mmap(void *addr, size_t length, int prot, int flags, in
fd,
offset);

if (MappedPtr != MAP_FAILED) {
if (MappedPtr >= reinterpret_cast<void*>(TOP_KEY << PAGE_SHIFT) &&
(flags & FEX_MAP_FIXED_NOREPLACE)) {
// Handles the case where MAP_FIXED_NOREPLACE isn't handled by the host system's
// kernel and returns the wrong pointer
// Make sure to munmap this so we don't leak memory
::munmap(MappedPtr, length);
return reinterpret_cast<void*>(-EEXIST);
}
else if (MappedPtr != MAP_FAILED) {
SetUsedPages(PageAddr, PagesLength);
return MappedPtr;
}
Expand Down

0 comments on commit 08938ec

Please sign in to comment.