diff options
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 108 |
1 files changed, 77 insertions, 31 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index e406df829..3b8a2e230 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -8,6 +8,7 @@ #include <mutex> #include <vector> +#include "common/alignment.h" #include "common/assert.h" #include "common/logging/log.h" #include "common/microprofile.h" @@ -36,9 +37,6 @@ namespace Kernel { namespace { -constexpr bool Is4KBAligned(VAddr address) { - return (address & 0xFFF) == 0; -} // Checks if address + size is greater than the given address // This can return false if the size causes an overflow of a 64-bit type @@ -69,11 +67,11 @@ bool IsInsideNewMapRegion(const VMManager& vm, VAddr address, u64 size) { // in the same order. ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_addr, VAddr src_addr, u64 size) { - if (!Is4KBAligned(dst_addr) || !Is4KBAligned(src_addr)) { + if (!Common::Is4KBAligned(dst_addr) || !Common::Is4KBAligned(src_addr)) { return ERR_INVALID_ADDRESS; } - if (size == 0 || !Is4KBAligned(size)) { + if (size == 0 || !Common::Is4KBAligned(size)) { return ERR_INVALID_SIZE; } @@ -352,6 +350,10 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr, return ERR_INVALID_ADDRESS_STATE; } + if (!Common::IsWordAligned(mutex_addr)) { + return ERR_INVALID_ADDRESS; + } + auto& handle_table = Core::System::GetInstance().Kernel().HandleTable(); return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle, requesting_thread_handle); @@ -365,6 +367,10 @@ static ResultCode ArbitrateUnlock(VAddr mutex_addr) { return ERR_INVALID_ADDRESS_STATE; } + if (!Common::IsWordAligned(mutex_addr)) { + return ERR_INVALID_ADDRESS; + } + return Mutex::Release(mutex_addr); } @@ -389,6 +395,12 @@ static void Break(u32 reason, u64 info1, u64 info2) { "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", reason, info1, info2); ASSERT(false); + + Core::CurrentProcess()->PrepareForTermination(); + + // Kill the current thread + GetCurrentThread()->Stop(); + Core::System::GetInstance().PrepareReschedule(); } } @@ -442,25 +454,12 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) case GetInfoType::RandomEntropy: *result = 0; break; - case GetInfoType::AddressSpaceBaseAddr: - *result = vm_manager.GetCodeRegionBaseAddress(); + case GetInfoType::ASLRRegionBaseAddr: + *result = vm_manager.GetASLRRegionBaseAddress(); break; - case GetInfoType::AddressSpaceSize: { - const u64 width = vm_manager.GetAddressSpaceWidth(); - - switch (width) { - case 32: - *result = 0xFFE00000; - break; - case 36: - *result = 0xFF8000000; - break; - case 39: - *result = 0x7FF8000000; - break; - } + case GetInfoType::ASLRRegionSize: + *result = vm_manager.GetASLRRegionSize(); break; - } case GetInfoType::NewMapRegionBaseAddr: *result = vm_manager.GetNewMapRegionBaseAddress(); break; @@ -577,14 +576,18 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", shared_memory_handle, addr, size, permissions); - if (!Is4KBAligned(addr)) { + if (!Common::Is4KBAligned(addr)) { return ERR_INVALID_ADDRESS; } - if (size == 0 || !Is4KBAligned(size)) { + if (size == 0 || !Common::Is4KBAligned(size)) { return ERR_INVALID_SIZE; } + if (!IsValidAddressRange(addr, size)) { + return ERR_INVALID_ADDRESS_STATE; + } + const auto permissions_type = static_cast<MemoryPermission>(permissions); if (permissions_type != MemoryPermission::Read && permissions_type != MemoryPermission::ReadWrite) { @@ -598,26 +601,46 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s return ERR_INVALID_HANDLE; } - return shared_memory->Map(Core::CurrentProcess(), addr, permissions_type, - MemoryPermission::DontCare); + auto* const current_process = Core::CurrentProcess(); + const auto& vm_manager = current_process->VMManager(); + + if (!vm_manager.IsWithinASLRRegion(addr, size)) { + return ERR_INVALID_MEMORY_RANGE; + } + + return shared_memory->Map(current_process, addr, permissions_type, MemoryPermission::DontCare); } static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}", shared_memory_handle, addr, size); - if (!Is4KBAligned(addr)) { + if (!Common::Is4KBAligned(addr)) { return ERR_INVALID_ADDRESS; } - if (size == 0 || !Is4KBAligned(size)) { + if (size == 0 || !Common::Is4KBAligned(size)) { return ERR_INVALID_SIZE; } + if (!IsValidAddressRange(addr, size)) { + return ERR_INVALID_ADDRESS_STATE; + } + auto& kernel = Core::System::GetInstance().Kernel(); auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); + if (!shared_memory) { + return ERR_INVALID_HANDLE; + } + + auto* const current_process = Core::CurrentProcess(); + const auto& vm_manager = current_process->VMManager(); - return shared_memory->Unmap(Core::CurrentProcess(), addr); + if (!vm_manager.IsWithinASLRRegion(addr, size)) { + return ERR_INVALID_MEMORY_RANGE; + } + + return shared_memory->Unmap(current_process, addr); } /// Query process memory @@ -803,7 +826,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target std::vector<SharedPtr<Thread>>& waiting_threads, VAddr condvar_addr) { const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); - const auto& thread_list = scheduler->GetThreadList(); + const auto& thread_list = scheduler.GetThreadList(); for (const auto& thread : thread_list) { if (thread->GetCondVarWaitAddress() == condvar_addr) @@ -1092,6 +1115,29 @@ static ResultCode ClearEvent(Handle handle) { return RESULT_SUCCESS; } +static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) { + LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); + + // This function currently only allows retrieving a process' status. + enum class InfoType { + Status, + }; + + const auto& kernel = Core::System::GetInstance().Kernel(); + const auto process = kernel.HandleTable().Get<Process>(process_handle); + if (!process) { + return ERR_INVALID_HANDLE; + } + + const auto info_type = static_cast<InfoType>(type); + if (info_type != InfoType::Status) { + return ERR_INVALID_ENUM_VALUE; + } + + *out = static_cast<u64>(process->GetStatus()); + return RESULT_SUCCESS; +} + namespace { struct FunctionDef { using Func = void(); @@ -1227,7 +1273,7 @@ static const FunctionDef SVC_Table[] = { {0x79, nullptr, "CreateProcess"}, {0x7A, nullptr, "StartProcess"}, {0x7B, nullptr, "TerminateProcess"}, - {0x7C, nullptr, "GetProcessInfo"}, + {0x7C, SvcWrap<GetProcessInfo>, "GetProcessInfo"}, {0x7D, nullptr, "CreateResourceLimit"}, {0x7E, nullptr, "SetResourceLimitLimitValue"}, {0x7F, nullptr, "CallSecureMonitor"}, |