aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp25
-rw-r--r--src/core/hle/kernel/hle_ipc.h13
-rw-r--r--src/core/hle/kernel/kernel.cpp10
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/process.h14
-rw-r--r--src/core/hle/kernel/server_session.cpp3
-rw-r--r--src/core/hle/kernel/svc.cpp189
-rw-r--r--src/core/hle/kernel/svc.h4
-rw-r--r--src/core/hle/kernel/thread.cpp2
-rw-r--r--src/core/hle/kernel/vm_manager.cpp55
-rw-r--r--src/core/hle/kernel/vm_manager.h15
11 files changed, 201 insertions, 135 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index edad5f1b1..68d5376cb 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -77,7 +77,8 @@ HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_ses
HLERequestContext::~HLERequestContext() = default;
-void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
+void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf,
+ bool incoming) {
IPC::RequestParser rp(src_cmdbuf);
command_header = std::make_shared<IPC::CommandHeader>(rp.PopRaw<IPC::CommandHeader>());
@@ -94,8 +95,6 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
rp.Skip(2, false);
}
if (incoming) {
- auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
-
// Populate the object lists with the data in the IPC request.
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
@@ -189,10 +188,9 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
}
-ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf,
- Process& src_process,
- HandleTable& src_table) {
- ParseCommandBuffer(src_cmdbuf, true);
+ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const HandleTable& handle_table,
+ u32_le* src_cmdbuf) {
+ ParseCommandBuffer(handle_table, src_cmdbuf, true);
if (command_header->type == IPC::CommandType::Close) {
// Close does not populate the rest of the IPC header
return RESULT_SUCCESS;
@@ -207,14 +205,17 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdb
return RESULT_SUCCESS;
}
-ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread) {
+ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
+ auto& owner_process = *thread.GetOwnerProcess();
+ auto& handle_table = owner_process.GetHandleTable();
+
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf;
- Memory::ReadBlock(*thread.GetOwnerProcess(), thread.GetTLSAddress(), dst_cmdbuf.data(),
+ Memory::ReadBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(),
dst_cmdbuf.size() * sizeof(u32));
// The header was already built in the internal command buffer. Attempt to parse it to verify
// the integrity and then copy it over to the target command buffer.
- ParseCommandBuffer(cmd_buf.data(), false);
+ ParseCommandBuffer(handle_table, cmd_buf.data(), false);
// The data_size already includes the payload header, the padding and the domain header.
std::size_t size = data_payload_offset + command_header->data_size -
@@ -236,8 +237,6 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread)
ASSERT(copy_objects.size() == handle_descriptor_header->num_handles_to_copy);
ASSERT(move_objects.size() == handle_descriptor_header->num_handles_to_move);
- auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
-
// We don't make a distinction between copy and move handles when translating since HLE
// services don't deal with handles directly. However, the guest applications might check
// for specific values in each of these descriptors.
@@ -268,7 +267,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread)
}
// Copy the translated command buffer back into the thread's command buffer area.
- Memory::WriteBlock(*thread.GetOwnerProcess(), thread.GetTLSAddress(), dst_cmdbuf.data(),
+ Memory::WriteBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(),
dst_cmdbuf.size() * sizeof(u32));
return RESULT_SUCCESS;
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 894479ee0..f01491daa 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -24,10 +24,10 @@ class ServiceFrameworkBase;
namespace Kernel {
class Domain;
+class Event;
class HandleTable;
class HLERequestContext;
class Process;
-class Event;
/**
* Interface implemented by HLE Session handlers.
@@ -126,13 +126,12 @@ public:
u64 timeout, WakeupCallback&& callback,
Kernel::SharedPtr<Kernel::Event> event = nullptr);
- void ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming);
-
/// Populates this context with data from the requesting process/thread.
- ResultCode PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf, Process& src_process,
- HandleTable& src_table);
+ ResultCode PopulateFromIncomingCommandBuffer(const HandleTable& handle_table,
+ u32_le* src_cmdbuf);
+
/// Writes data from this context back to the requesting process/thread.
- ResultCode WriteToOutgoingCommandBuffer(const Thread& thread);
+ ResultCode WriteToOutgoingCommandBuffer(Thread& thread);
u32_le GetCommand() const {
return command;
@@ -255,6 +254,8 @@ public:
std::string Description() const;
private:
+ void ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming);
+
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
SharedPtr<Kernel::ServerSession> server_session;
// TODO(yuriks): Check common usage of this and optimize size accordingly
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index bd680adfe..4b6b32dd5 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -118,7 +118,6 @@ struct KernelCore::Impl {
process_list.clear();
current_process = nullptr;
- handle_table.Clear();
resource_limits.fill(nullptr);
thread_wakeup_callback_handle_table.Clear();
@@ -209,7 +208,6 @@ struct KernelCore::Impl {
std::vector<SharedPtr<Process>> process_list;
Process* current_process = nullptr;
- Kernel::HandleTable handle_table;
std::array<SharedPtr<ResourceLimit>, 4> resource_limits;
/// The event type of the generic timer callback event
@@ -241,14 +239,6 @@ void KernelCore::Shutdown() {
impl->Shutdown();
}
-Kernel::HandleTable& KernelCore::HandleTable() {
- return impl->handle_table;
-}
-
-const Kernel::HandleTable& KernelCore::HandleTable() const {
- return impl->handle_table;
-}
-
SharedPtr<ResourceLimit> KernelCore::ResourceLimitForCategory(
ResourceLimitCategory category) const {
return impl->resource_limits.at(static_cast<std::size_t>(category));
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 41554821f..7f822d524 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -47,12 +47,6 @@ public:
/// Clears all resources in use by the kernel instance.
void Shutdown();
- /// Provides a reference to the handle table.
- Kernel::HandleTable& HandleTable();
-
- /// Provides a const reference to the handle table.
- const Kernel::HandleTable& HandleTable() const;
-
/// Retrieves a shared pointer to a ResourceLimit identified by the given category.
SharedPtr<ResourceLimit> ResourceLimitForCategory(ResourceLimitCategory category) const;
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index f2816943a..148478488 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -13,6 +13,7 @@
#include <boost/container/static_vector.hpp>
#include "common/bit_field.h"
#include "common/common_types.h"
+#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/vm_manager.h"
@@ -142,6 +143,16 @@ public:
return vm_manager;
}
+ /// Gets a reference to the process' handle table.
+ HandleTable& GetHandleTable() {
+ return handle_table;
+ }
+
+ /// Gets a const reference to the process' handle table.
+ const HandleTable& GetHandleTable() const {
+ return handle_table;
+ }
+
/// Gets the current status of the process
ProcessStatus GetStatus() const {
return status;
@@ -294,6 +305,9 @@ private:
/// specified by metadata provided to the process during loading.
bool is_64bit_process = true;
+ /// Per-process handle table for storing created object handles in.
+ HandleTable handle_table;
+
std::string name;
};
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 1ece691c7..5fc320403 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -107,8 +107,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
// similar.
Kernel::HLERequestContext context(this);
u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress());
- context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(),
- kernel.HandleTable());
+ context.PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
ResultCode result = RESULT_SUCCESS;
// If the session has been converted to a domain, handle the domain request
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 3e5f11f2b..67ea67666 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;
}
@@ -191,14 +189,15 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
CASCADE_RESULT(client_session, client_port->Connect());
// Return the client session
- CASCADE_RESULT(*out_handle, kernel.HandleTable().Create(client_session));
+ auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ CASCADE_RESULT(*out_handle, handle_table.Create(client_session));
return RESULT_SUCCESS;
}
/// Makes a blocking IPC call to an OS service.
static ResultCode SendSyncRequest(Handle handle) {
- auto& kernel = Core::System::GetInstance().Kernel();
- SharedPtr<ClientSession> session = kernel.HandleTable().Get<ClientSession>(handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ SharedPtr<ClientSession> session = handle_table.Get<ClientSession>(handle);
if (!session) {
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
return ERR_INVALID_HANDLE;
@@ -217,8 +216,8 @@ static ResultCode SendSyncRequest(Handle handle) {
static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -231,8 +230,8 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- const SharedPtr<Process> process = kernel.HandleTable().Get<Process>(process_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const SharedPtr<Process> process = handle_table.Get<Process>(process_handle);
if (!process) {
return ERR_INVALID_HANDLE;
}
@@ -275,11 +274,11 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
using ObjectPtr = Thread::ThreadWaitObjects::value_type;
Thread::ThreadWaitObjects objects(handle_count);
- auto& kernel = Core::System::GetInstance().Kernel();
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
for (u64 i = 0; i < handle_count; ++i) {
const Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
- const auto object = kernel.HandleTable().Get<WaitObject>(handle);
+ const auto object = handle_table.Get<WaitObject>(handle);
if (object == nullptr) {
return ERR_INVALID_HANDLE;
@@ -327,8 +326,8 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
static ResultCode CancelSynchronization(Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -352,7 +351,11 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
return ERR_INVALID_ADDRESS_STATE;
}
- auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
+ if (!Common::IsWordAligned(mutex_addr)) {
+ return ERR_INVALID_ADDRESS;
+ }
+
+ auto& handle_table = Core::CurrentProcess()->GetHandleTable();
return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle,
requesting_thread_handle);
}
@@ -365,6 +368,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);
}
@@ -448,25 +455,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;
@@ -506,13 +500,12 @@ static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called, context=0x{:08X}, thread=0x{:X}", thread_context, handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
+ const auto* current_process = Core::CurrentProcess();
+ const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
- const auto* current_process = Core::CurrentProcess();
if (thread->GetOwnerProcess() != current_process) {
return ERR_INVALID_HANDLE;
}
@@ -538,10 +531,11 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
/// Gets the priority for the specified thread
static ResultCode GetThreadPriority(u32* priority, Handle handle) {
- auto& kernel = Core::System::GetInstance().Kernel();
- const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
- if (!thread)
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const SharedPtr<Thread> thread = handle_table.Get<Thread>(handle);
+ if (!thread) {
return ERR_INVALID_HANDLE;
+ }
*priority = thread->GetPriority();
return RESULT_SUCCESS;
@@ -553,14 +547,15 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
return ERR_INVALID_THREAD_PRIORITY;
}
- auto& kernel = Core::System::GetInstance().Kernel();
- SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
- if (!thread)
+ const auto* const current_process = Core::CurrentProcess();
+ SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
+ if (!thread) {
return ERR_INVALID_HANDLE;
+ }
// Note: The kernel uses the current process's resource limit instead of
// the one from the thread owner's resource limit.
- const ResourceLimit& resource_limit = Core::CurrentProcess()->GetResourceLimit();
+ const ResourceLimit& resource_limit = current_process->GetResourceLimit();
if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
return ERR_NOT_AUTHORIZED;
}
@@ -583,14 +578,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,46 +597,61 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return ERR_INVALID_MEMORY_PERMISSIONS;
}
- auto& kernel = Core::System::GetInstance().Kernel();
- auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
+ auto* const current_process = Core::CurrentProcess();
+ auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
if (!shared_memory) {
return ERR_INVALID_HANDLE;
}
- return shared_memory->Map(Core::CurrentProcess(), addr, permissions_type,
- MemoryPermission::DontCare);
+ 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;
}
- auto& kernel = Core::System::GetInstance().Kernel();
- auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
+ if (!IsValidAddressRange(addr, size)) {
+ return ERR_INVALID_ADDRESS_STATE;
+ }
+
+ auto* const current_process = Core::CurrentProcess();
+ auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
+ if (!shared_memory) {
+ return ERR_INVALID_HANDLE;
+ }
+
+ const auto& vm_manager = current_process->VMManager();
+ if (!vm_manager.IsWithinASLRRegion(addr, size)) {
+ return ERR_INVALID_MEMORY_RANGE;
+ }
- return shared_memory->Unmap(Core::CurrentProcess(), addr);
+ return shared_memory->Unmap(current_process, addr);
}
/// Query process memory
static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_info*/,
Handle process_handle, u64 addr) {
-
- auto& kernel = Core::System::GetInstance().Kernel();
- SharedPtr<Process> process = kernel.HandleTable().Get<Process>(process_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ SharedPtr<Process> process = handle_table.Get<Process>(process_handle);
if (!process) {
return ERR_INVALID_HANDLE;
}
auto vma = process->VMManager().FindVMA(addr);
memory_info->attributes = 0;
- if (vma == Core::CurrentProcess()->VMManager().vma_map.end()) {
+ if (vma == process->VMManager().vma_map.end()) {
memory_info->base_address = 0;
memory_info->permission = static_cast<u32>(VMAPermission::None);
memory_info->size = 0;
@@ -678,20 +692,19 @@ static void ExitProcess() {
/// Creates a new thread
static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top,
u32 priority, s32 processor_id) {
- std::string name = fmt::format("thread-{:X}", entry_point);
-
if (priority > THREADPRIO_LOWEST) {
return ERR_INVALID_THREAD_PRIORITY;
}
- const ResourceLimit& resource_limit = Core::CurrentProcess()->GetResourceLimit();
+ auto* const current_process = Core::CurrentProcess();
+ const ResourceLimit& resource_limit = current_process->GetResourceLimit();
if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
return ERR_NOT_AUTHORIZED;
}
if (processor_id == THREADPROCESSORID_DEFAULT) {
// Set the target CPU to the one specified in the process' exheader.
- processor_id = Core::CurrentProcess()->GetDefaultProcessorID();
+ processor_id = current_process->GetDefaultProcessorID();
ASSERT(processor_id != THREADPROCESSORID_DEFAULT);
}
@@ -706,11 +719,13 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
return ERR_INVALID_PROCESSOR_ID;
}
+ const std::string name = fmt::format("thread-{:X}", entry_point);
auto& kernel = Core::System::GetInstance().Kernel();
CASCADE_RESULT(SharedPtr<Thread> thread,
Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top,
- *Core::CurrentProcess()));
- const auto new_guest_handle = kernel.HandleTable().Create(thread);
+ *current_process));
+
+ const auto new_guest_handle = current_process->GetHandleTable().Create(thread);
if (new_guest_handle.Failed()) {
return new_guest_handle.Code();
}
@@ -731,8 +746,8 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
static ResultCode StartThread(Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -779,8 +794,8 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
"called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
- auto& kernel = Core::System::GetInstance().Kernel();
- SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
ASSERT(thread);
CASCADE_CODE(Mutex::Release(mutex_addr));
@@ -891,9 +906,9 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
mutex_val | Mutex::MutexHasWaitersFlag));
// The mutex is already owned by some other thread, make this thread wait on it.
- auto& kernel = Core::System::GetInstance().Kernel();
- Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
- auto owner = kernel.HandleTable().Get<Thread>(owner_handle);
+ const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ auto owner = handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex);
thread->InvalidateWakeupCallback();
@@ -972,16 +987,16 @@ static u64 GetSystemTick() {
static ResultCode CloseHandle(Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- return kernel.HandleTable().Close(handle);
+ auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ return handle_table.Close(handle);
}
/// Reset an event
static ResultCode ResetSignal(Handle handle) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x{:08X}", handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- auto event = kernel.HandleTable().Get<Event>(handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ auto event = handle_table.Get<Event>(handle);
ASSERT(event != nullptr);
@@ -1000,8 +1015,8 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -1016,8 +1031,8 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:16X}, core=0x{:X}", thread_handle,
mask, core);
- auto& kernel = Core::System::GetInstance().Kernel();
- const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -1078,7 +1093,7 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
}
auto& kernel = Core::System::GetInstance().Kernel();
- auto& handle_table = kernel.HandleTable();
+ auto& handle_table = Core::CurrentProcess()->GetHandleTable();
auto shared_mem_handle =
SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
local_perms, remote_perms);
@@ -1090,10 +1105,12 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
static ResultCode ClearEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
- auto& kernel = Core::System::GetInstance().Kernel();
- SharedPtr<Event> evt = kernel.HandleTable().Get<Event>(handle);
- if (evt == nullptr)
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ SharedPtr<Event> evt = handle_table.Get<Event>(handle);
+ if (evt == nullptr) {
return ERR_INVALID_HANDLE;
+ }
+
evt->Clear();
return RESULT_SUCCESS;
}
@@ -1106,8 +1123,8 @@ static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
Status,
};
- const auto& kernel = Core::System::GetInstance().Kernel();
- const auto process = kernel.HandleTable().Get<Process>(process_handle);
+ const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
+ const auto process = handle_table.Get<Process>(process_handle);
if (!process) {
return ERR_INVALID_HANDLE;
}
diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h
index 70148c4fe..554a5e328 100644
--- a/src/core/hle/kernel/svc.h
+++ b/src/core/hle/kernel/svc.h
@@ -41,8 +41,8 @@ enum class GetInfoType : u64 {
RandomEntropy = 11,
PerformanceCounter = 0xF0000002,
// 2.0.0+
- AddressSpaceBaseAddr = 12,
- AddressSpaceSize = 13,
+ ASLRRegionBaseAddr = 12,
+ ASLRRegionSize = 13,
NewMapRegionBaseAddr = 14,
NewMapRegionSize = 15,
// 3.0.0+
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 35ec98c1a..59bc9e0af 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -266,7 +266,7 @@ SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 pri
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
// Register 1 must be a handle to the main thread
- const Handle guest_handle = kernel.HandleTable().Create(thread).Unwrap();
+ const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
thread->SetGuestHandle(guest_handle);
thread->GetContext().cpu_registers[1] = guest_handle;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index e412309fd..e1a34eef1 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -393,30 +393,35 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty
switch (type) {
case FileSys::ProgramAddressSpaceType::Is32Bit:
+ case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
address_space_width = 32;
code_region_base = 0x200000;
code_region_end = code_region_base + 0x3FE00000;
- map_region_size = 0x40000000;
- heap_region_size = 0x40000000;
+ aslr_region_base = 0x200000;
+ aslr_region_end = aslr_region_base + 0xFFE00000;
+ if (type == FileSys::ProgramAddressSpaceType::Is32Bit) {
+ map_region_size = 0x40000000;
+ heap_region_size = 0x40000000;
+ } else {
+ map_region_size = 0;
+ heap_region_size = 0x80000000;
+ }
break;
case FileSys::ProgramAddressSpaceType::Is36Bit:
address_space_width = 36;
code_region_base = 0x8000000;
code_region_end = code_region_base + 0x78000000;
+ aslr_region_base = 0x8000000;
+ aslr_region_end = aslr_region_base + 0xFF8000000;
map_region_size = 0x180000000;
heap_region_size = 0x180000000;
break;
- case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
- address_space_width = 32;
- code_region_base = 0x200000;
- code_region_end = code_region_base + 0x3FE00000;
- map_region_size = 0;
- heap_region_size = 0x80000000;
- break;
case FileSys::ProgramAddressSpaceType::Is39Bit:
address_space_width = 39;
code_region_base = 0x8000000;
code_region_end = code_region_base + 0x80000000;
+ aslr_region_base = 0x8000000;
+ aslr_region_end = aslr_region_base + 0x7FF8000000;
map_region_size = 0x1000000000;
heap_region_size = 0x180000000;
new_map_region_size = 0x80000000;
@@ -490,6 +495,38 @@ u64 VMManager::GetAddressSpaceWidth() const {
return address_space_width;
}
+VAddr VMManager::GetASLRRegionBaseAddress() const {
+ return aslr_region_base;
+}
+
+VAddr VMManager::GetASLRRegionEndAddress() const {
+ return aslr_region_end;
+}
+
+u64 VMManager::GetASLRRegionSize() const {
+ return aslr_region_end - aslr_region_base;
+}
+
+bool VMManager::IsWithinASLRRegion(VAddr begin, u64 size) const {
+ const VAddr range_end = begin + size;
+ const VAddr aslr_start = GetASLRRegionBaseAddress();
+ const VAddr aslr_end = GetASLRRegionEndAddress();
+
+ if (aslr_start > begin || begin > range_end || range_end - 1 > aslr_end - 1) {
+ return false;
+ }
+
+ if (range_end > heap_region_base && heap_region_end > begin) {
+ return false;
+ }
+
+ if (range_end > map_region_base && map_region_end > begin) {
+ return false;
+ }
+
+ return true;
+}
+
VAddr VMManager::GetCodeRegionBaseAddress() const {
return code_region_base;
}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 015559a64..84c890224 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -205,6 +205,18 @@ public:
/// Gets the address space width in bits.
u64 GetAddressSpaceWidth() const;
+ /// Gets the base address of the ASLR region.
+ VAddr GetASLRRegionBaseAddress() const;
+
+ /// Gets the end address of the ASLR region.
+ VAddr GetASLRRegionEndAddress() const;
+
+ /// Determines whether or not the specified address range is within the ASLR region.
+ bool IsWithinASLRRegion(VAddr address, u64 size) const;
+
+ /// Gets the size of the ASLR region
+ u64 GetASLRRegionSize() const;
+
/// Gets the base address of the code region.
VAddr GetCodeRegionBaseAddress() const;
@@ -306,6 +318,9 @@ private:
VAddr address_space_base = 0;
VAddr address_space_end = 0;
+ VAddr aslr_region_base = 0;
+ VAddr aslr_region_end = 0;
+
VAddr code_region_base = 0;
VAddr code_region_end = 0;