mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-30 15:39:02 -05:00 
			
		
		
		
	Merge pull request #1315 from lioncash/size
kernel/svc: Handle a few error cases within memory-related functions
This commit is contained in:
		| @@ -17,6 +17,7 @@ enum { | ||||
|  | ||||
|     // Confirmed Switch OS error codes | ||||
|     MaxConnectionsReached = 7, | ||||
|     InvalidSize = 101, | ||||
|     InvalidAddress = 102, | ||||
|     HandleTableFull = 105, | ||||
|     InvalidMemoryState = 106, | ||||
| @@ -55,6 +56,7 @@ constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS(ErrorModule::Kernel, | ||||
|                                                     ErrCodes::InvalidMemoryPermissions); | ||||
| constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); | ||||
| constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId); | ||||
| constexpr ResultCode ERR_INVALID_SIZE(ErrorModule::Kernel, ErrCodes::InvalidSize); | ||||
| constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState); | ||||
| constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel, | ||||
|                                                  ErrCodes::InvalidThreadPriority); | ||||
|   | ||||
| @@ -35,10 +35,21 @@ | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Kernel { | ||||
| namespace { | ||||
| constexpr bool Is4KBAligned(VAddr address) { | ||||
|     return (address & 0xFFF) == 0; | ||||
| } | ||||
| } // Anonymous namespace | ||||
|  | ||||
| /// Set the process heap to a given Size. It can both extend and shrink the heap. | ||||
| static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { | ||||
|     LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); | ||||
|  | ||||
|     // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 4GB. | ||||
|     if ((heap_size & 0xFFFFFFFE001FFFFF) != 0) { | ||||
|         return ERR_INVALID_SIZE; | ||||
|     } | ||||
|  | ||||
|     auto& process = *Core::CurrentProcess(); | ||||
|     CASCADE_RESULT(*heap_addr, | ||||
|                    process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); | ||||
| @@ -56,6 +67,15 @@ static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state | ||||
| static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { | ||||
|     LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, | ||||
|               src_addr, size); | ||||
|  | ||||
|     if (!Is4KBAligned(dst_addr) || !Is4KBAligned(src_addr)) { | ||||
|         return ERR_INVALID_ADDRESS; | ||||
|     } | ||||
|  | ||||
|     if (size == 0 || !Is4KBAligned(size)) { | ||||
|         return ERR_INVALID_SIZE; | ||||
|     } | ||||
|  | ||||
|     return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size); | ||||
| } | ||||
|  | ||||
| @@ -63,6 +83,15 @@ static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { | ||||
| static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { | ||||
|     LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, | ||||
|               src_addr, size); | ||||
|  | ||||
|     if (!Is4KBAligned(dst_addr) || !Is4KBAligned(src_addr)) { | ||||
|         return ERR_INVALID_ADDRESS; | ||||
|     } | ||||
|  | ||||
|     if (size == 0 || !Is4KBAligned(size)) { | ||||
|         return ERR_INVALID_SIZE; | ||||
|     } | ||||
|  | ||||
|     return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size); | ||||
| } | ||||
|  | ||||
| @@ -415,35 +444,43 @@ 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)) { | ||||
|         return ERR_INVALID_ADDRESS; | ||||
|     } | ||||
|  | ||||
|     if (size == 0 || !Is4KBAligned(size)) { | ||||
|         return ERR_INVALID_SIZE; | ||||
|     } | ||||
|  | ||||
|     const auto permissions_type = static_cast<MemoryPermission>(permissions); | ||||
|     if (permissions_type != MemoryPermission::Read && | ||||
|         permissions_type != MemoryPermission::ReadWrite) { | ||||
|         LOG_ERROR(Kernel_SVC, "Invalid permissions=0x{:08X}", permissions); | ||||
|         return ERR_INVALID_MEMORY_PERMISSIONS; | ||||
|     } | ||||
|  | ||||
|     auto& kernel = Core::System::GetInstance().Kernel(); | ||||
|     auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); | ||||
|     if (!shared_memory) { | ||||
|         return ERR_INVALID_HANDLE; | ||||
|     } | ||||
|  | ||||
|     MemoryPermission permissions_type = static_cast<MemoryPermission>(permissions); | ||||
|     switch (permissions_type) { | ||||
|     case MemoryPermission::Read: | ||||
|     case MemoryPermission::Write: | ||||
|     case MemoryPermission::ReadWrite: | ||||
|     case MemoryPermission::Execute: | ||||
|     case MemoryPermission::ReadExecute: | ||||
|     case MemoryPermission::WriteExecute: | ||||
|     case MemoryPermission::ReadWriteExecute: | ||||
|     case MemoryPermission::DontCare: | ||||
|         return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type, | ||||
|                                   MemoryPermission::DontCare); | ||||
|     default: | ||||
|         LOG_ERROR(Kernel_SVC, "unknown permissions=0x{:08X}", permissions); | ||||
|     } | ||||
|  | ||||
|     return RESULT_SUCCESS; | ||||
|     return shared_memory->Map(Core::CurrentProcess().get(), 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)) { | ||||
|         return ERR_INVALID_ADDRESS; | ||||
|     } | ||||
|  | ||||
|     if (size == 0 || !Is4KBAligned(size)) { | ||||
|         return ERR_INVALID_SIZE; | ||||
|     } | ||||
|  | ||||
|     auto& kernel = Core::System::GetInstance().Kernel(); | ||||
|     auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); | ||||
|  | ||||
| @@ -899,12 +936,28 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss | ||||
|     LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size, | ||||
|               local_permissions, remote_permissions); | ||||
|  | ||||
|     // Size must be a multiple of 4KB and be less than or equal to | ||||
|     // approx. 8 GB (actually (1GB - 512B) * 8) | ||||
|     if (size == 0 || (size & 0xFFFFFFFE00000FFF) != 0) { | ||||
|         return ERR_INVALID_SIZE; | ||||
|     } | ||||
|  | ||||
|     const auto local_perms = static_cast<MemoryPermission>(local_permissions); | ||||
|     if (local_perms != MemoryPermission::Read && local_perms != MemoryPermission::ReadWrite) { | ||||
|         return ERR_INVALID_MEMORY_PERMISSIONS; | ||||
|     } | ||||
|  | ||||
|     const auto remote_perms = static_cast<MemoryPermission>(remote_permissions); | ||||
|     if (remote_perms != MemoryPermission::Read && remote_perms != MemoryPermission::ReadWrite && | ||||
|         remote_perms != MemoryPermission::DontCare) { | ||||
|         return ERR_INVALID_MEMORY_PERMISSIONS; | ||||
|     } | ||||
|  | ||||
|     auto& kernel = Core::System::GetInstance().Kernel(); | ||||
|     auto& handle_table = kernel.HandleTable(); | ||||
|     auto shared_mem_handle = | ||||
|         SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size, | ||||
|                              static_cast<MemoryPermission>(local_permissions), | ||||
|                              static_cast<MemoryPermission>(remote_permissions)); | ||||
|                              local_perms, remote_perms); | ||||
|  | ||||
|     CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle)); | ||||
|     return RESULT_SUCCESS; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei