diff --git a/k11_extension/include/svc/MapProcessMemoryPrivate.h b/k11_extension/include/svc/MapProcessMemoryPrivate.h new file mode 100644 index 000000000..b82290c7f --- /dev/null +++ b/k11_extension/include/svc/MapProcessMemoryPrivate.h @@ -0,0 +1,34 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2016-2020 Aurora Wright, TuxSH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#pragma once + +#include "utils.h" +#include "kernel.h" +#include "svc.h" + +Result MapProcessMemoryPrivate(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size); +Result MapProcessMemoryPrivateWrapper(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size); diff --git a/k11_extension/source/svc.c b/k11_extension/source/svc.c index dceb1eeab..f29fda6b9 100644 --- a/k11_extension/source/svc.c +++ b/k11_extension/source/svc.c @@ -43,6 +43,7 @@ #include "svc/CustomBackdoor.h" #include "svc/MapProcessMemoryEx.h" #include "svc/UnmapProcessMemoryEx.h" +#include "svc/MapProcessMemoryPrivate.h" #include "svc/ControlService.h" #include "svc/ControlProcess.h" #include "svc/ExitProcess.h" @@ -98,6 +99,7 @@ void buildAlteredSvcTable(void) alteredSvcTable[0xA1] = UnmapProcessMemoryEx; alteredSvcTable[0xA2] = ControlMemoryEx; alteredSvcTable[0xA3] = ControlMemoryUnsafeWrapper; + alteredSvcTable[0xA4] = MapProcessMemoryPrivateWrapper; alteredSvcTable[0xB0] = ControlService; alteredSvcTable[0xB1] = CopyHandleWrapper; diff --git a/k11_extension/source/svc/MapProcessMemoryPrivate.c b/k11_extension/source/svc/MapProcessMemoryPrivate.c new file mode 100644 index 000000000..c1cf95d67 --- /dev/null +++ b/k11_extension/source/svc/MapProcessMemoryPrivate.c @@ -0,0 +1,86 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2016-2020 Aurora Wright, TuxSH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#include "svc/MapProcessMemoryPrivate.h" + +Result MapProcessMemoryPrivate(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size) +{ + Result res = 0; + u32 sizeInPage = size >> 12; + KLinkedList list; + KProcess *srcProcess; + KProcess *dstProcess; + KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess); + + if (dstProcessHandle == CUR_PROCESS_HANDLE) + { + dstProcess = currentCoreContext->objectContext.currentProcess; + KAutoObject__AddReference((KAutoObject *)dstProcess); + } + else + dstProcess = KProcessHandleTable__ToKProcess(handleTable, dstProcessHandle); + + if (dstProcess == NULL) + return 0xD8E007F7; + + if (srcProcessHandle == CUR_PROCESS_HANDLE) + { + srcProcess = currentCoreContext->objectContext.currentProcess; + KAutoObject__AddReference((KAutoObject *)srcProcess); + } + else + srcProcess = KProcessHandleTable__ToKProcess(handleTable, srcProcessHandle); + + if (srcProcess == NULL) + { + res = 0xD8E007F7; + goto exit1; + } + + KLinkedList__Initialize(&list); + + res = KProcessHwInfo__GetListOfKBlockInfoForVA(hwInfoOfProcess(srcProcess), &list, vaSrc, sizeInPage); + + if (res >= 0) + { + // Check if the destination address is free and large enough + res = KProcessHwInfo__CheckVaState(hwInfoOfProcess(dstProcess), vaDst, size, 0, 0); + if (res == 0) + res = KProcessHwInfo__MapListOfKBlockInfo(hwInfoOfProcess(dstProcess), vaDst, &list, 0xBB05, MEMPERM_RW | 0x18, 0); + } + + KLinkedList_KBlockInfo__Clear(&list); + + ((KAutoObject *)srcProcess)->vtable->DecrementReferenceCount((KAutoObject *)srcProcess); + +exit1: + ((KAutoObject *)dstProcess)->vtable->DecrementReferenceCount((KAutoObject *)dstProcess); + + invalidateEntireInstructionCache(); + flushEntireDataCache(); + + return res; +} diff --git a/k11_extension/source/svc/wrappers.s b/k11_extension/source/svc/wrappers.s index 6d07ccde8..cb0cbda21 100644 --- a/k11_extension/source/svc/wrappers.s +++ b/k11_extension/source/svc/wrappers.s @@ -122,4 +122,13 @@ MapProcessMemoryExWrapper: str r4, [sp, #-4]! bl MapProcessMemoryEx add sp, #4 + pop {pc} + +.global MapProcessMemoryPrivateWrapper +.type MapProcessMemoryPrivateWrapper, %function +MapProcessMemoryPrivateWrapper: + push {lr} + str r4, [sp, #-4]! + bl MapProcessMemoryPrivate + add sp, #4 pop {pc} \ No newline at end of file diff --git a/sysmodules/rosalina/include/csvc.h b/sysmodules/rosalina/include/csvc.h index f6d8ce989..d6dad38bd 100644 --- a/sysmodules/rosalina/include/csvc.h +++ b/sysmodules/rosalina/include/csvc.h @@ -83,6 +83,16 @@ void svcInvalidateEntireInstructionCache(void); */ Result svcMapProcessMemoryEx(Handle dstProcessHandle, u32 destAddress, Handle srcProcessHandle, u32 srcAddress, u32 size); +/** + * @brief Maps a block of process memory, but sets MemState to PRIVATE instead of SHARED. + * @param dstProcessHandle Handle of the process to map the memory in (destination) + * @param destAddress Start address of the memory block in the destination process + * @param srcProcessHandle Handle of the process to map the memory from (source) + * @param srcAddress Start address of the memory block in the source process + * @param size Size of the block of the memory to map (truncated to a multiple of 0x1000 bytes) +*/ +Result svcMapProcessMemoryPrivate(Handle dstProcessHandle, u32 destAddress, Handle srcProcessHandle, u32 srcAddress, u32 size); + /** * @brief Unmaps a block of process memory. * @param process Handle of the process to unmap the memory from diff --git a/sysmodules/rosalina/source/csvc.s b/sysmodules/rosalina/source/csvc.s index da6987533..97ba8bf2e 100644 --- a/sysmodules/rosalina/source/csvc.s +++ b/sysmodules/rosalina/source/csvc.s @@ -95,6 +95,14 @@ SVC_BEGIN svcFreeMemory bx lr SVC_END +SVC_BEGIN svcMapProcessMemoryPrivate + str r4, [sp, #-4]! + ldr r4, [sp, #4] + svc 0xA4 + ldr r4, [sp], #4 + bx lr +SVC_END + SVC_BEGIN svcControlService svc 0xB0 bx lr diff --git a/sysmodules/rosalina/source/plugin/memoryblock.c b/sysmodules/rosalina/source/plugin/memoryblock.c index 8738f1efd..9889d93f8 100644 --- a/sysmodules/rosalina/source/plugin/memoryblock.c +++ b/sysmodules/rosalina/source/plugin/memoryblock.c @@ -217,7 +217,16 @@ Result MemoryBlock__MountInProcess(void) } // Heap (to be used by the plugin) - if (R_FAILED((res = svcMapProcessMemoryEx(target, header->heapVA, CUR_PROCESS_HANDLE, (u32)memblock->memblock + header->exeSize, header->heapSize)))) + if (header->heapSize > 0x500000) + { + res = svcMapProcessMemoryEx(target, header->heapVA, CUR_PROCESS_HANDLE, (u32)memblock->memblock + header->exeSize, header->heapSize); + } + else + { + res = svcMapProcessMemoryPrivate(target, header->heapVA, CUR_PROCESS_HANDLE, (u32)memblock->memblock + header->exeSize, header->heapSize); + } + + if (R_FAILED(res)) { error->message = "Couldn't map heap memory block"; error->code = res; @@ -230,10 +239,13 @@ Result MemoryBlock__UnmountFromProcess(void) { Handle target = PluginLoaderCtx.target; PluginHeader *header = &PluginLoaderCtx.header; + MemoryBlock *memblock = &PluginLoaderCtx.memblock; Result res = 0; - res = svcUnmapProcessMemoryEx(target, 0x07000000, header->exeSize); + res = svcMapProcessMemoryEx(target, header->heapVA, CUR_PROCESS_HANDLE, (u32) memblock->memblock + header->exeSize, header->heapSize); + + res |= svcUnmapProcessMemoryEx(target, 0x07000000, header->exeSize); res |= svcUnmapProcessMemoryEx(target, header->heapVA, header->heapSize); return res;