From 2726d705f8dde6d8fcbcfcd55e065a0598e10969 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 20 Nov 2021 20:23:59 -0500 Subject: [PATCH] kernel: svc: Implement SetProcessMemoryPermission - Used by Skyline modding framework --- src/core/hle/kernel/svc.cpp | 42 ++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index f9d99bc514..23dc44780e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1183,6 +1183,18 @@ constexpr bool IsValidRemoteSharedMemoryPermission(Svc::MemoryPermission perm) { return IsValidSharedMemoryPermission(perm) || perm == Svc::MemoryPermission::DontCare; } +constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) { + switch (perm) { + case Svc::MemoryPermission::None: + case Svc::MemoryPermission::Read: + case Svc::MemoryPermission::ReadWrite: + case Svc::MemoryPermission::ReadExecute: + return true; + default: + return false; + } +} + static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size, Svc::MemoryPermission map_perm) { LOG_TRACE(Kernel_SVC, @@ -1262,6 +1274,34 @@ static ResultCode UnmapSharedMemory32(Core::System& system, Handle shmem_handle, return UnmapSharedMemory(system, shmem_handle, address, size); } +static ResultCode SetProcessMemoryPermission(Core::System& system, Handle process_handle, + VAddr address, u64 size, Svc::MemoryPermission perm) { + LOG_TRACE(Kernel_SVC, + "called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", + process_handle, address, size, perm); + + // Validate the address/size. + R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); + R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); + R_UNLESS(size > 0, ResultInvalidSize); + R_UNLESS((address < address + size), ResultInvalidCurrentMemory); + + // Validate the memory permission. + R_UNLESS(IsValidProcessMemoryPermission(perm), ResultInvalidNewMemoryPermission); + + // Get the process from its handle. + KScopedAutoObject process = + system.CurrentProcess()->GetHandleTable().GetObject(process_handle); + R_UNLESS(process.IsNotNull(), ResultInvalidHandle); + + // Validate that the address is in range. + auto& page_table = process->PageTable(); + R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); + + // Set the memory permission. + return page_table.SetProcessMemoryPermission(address, size, ConvertToKMemoryPermission(perm)); +} + static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address, Handle process_handle, VAddr address) { @@ -2588,7 +2628,7 @@ static const FunctionDef SVC_Table_64[] = { {0x70, nullptr, "CreatePort"}, {0x71, nullptr, "ManageNamedPort"}, {0x72, nullptr, "ConnectToPort"}, - {0x73, nullptr, "SetProcessMemoryPermission"}, + {0x73, SvcWrap64, "SetProcessMemoryPermission"}, {0x74, nullptr, "MapProcessMemory"}, {0x75, nullptr, "UnmapProcessMemory"}, {0x76, SvcWrap64, "QueryProcessMemory"},