mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #1315 from lioncash/size
kernel/svc: Handle a few error cases within memory-related functions
This commit is contained in:
		
						commit
						e6367ab955
					
				| @ -17,6 +17,7 @@ enum { | |||||||
| 
 | 
 | ||||||
|     // Confirmed Switch OS error codes
 |     // Confirmed Switch OS error codes
 | ||||||
|     MaxConnectionsReached = 7, |     MaxConnectionsReached = 7, | ||||||
|  |     InvalidSize = 101, | ||||||
|     InvalidAddress = 102, |     InvalidAddress = 102, | ||||||
|     HandleTableFull = 105, |     HandleTableFull = 105, | ||||||
|     InvalidMemoryState = 106, |     InvalidMemoryState = 106, | ||||||
| @ -55,6 +56,7 @@ constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS(ErrorModule::Kernel, | |||||||
|                                                     ErrCodes::InvalidMemoryPermissions); |                                                     ErrCodes::InvalidMemoryPermissions); | ||||||
| constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); | constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); | ||||||
| constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId); | 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_STATE(ErrorModule::Kernel, ErrCodes::InvalidState); | ||||||
| constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel, | constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel, | ||||||
|                                                  ErrCodes::InvalidThreadPriority); |                                                  ErrCodes::InvalidThreadPriority); | ||||||
|  | |||||||
| @ -35,10 +35,21 @@ | |||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | 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.
 | /// 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) { | static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { | ||||||
|     LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", 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(); |     auto& process = *Core::CurrentProcess(); | ||||||
|     CASCADE_RESULT(*heap_addr, |     CASCADE_RESULT(*heap_addr, | ||||||
|                    process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); |                    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) { | 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, |     LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, | ||||||
|               src_addr, size); |               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); |     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) { | 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, |     LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, | ||||||
|               src_addr, size); |               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); |     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}", |               "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", | ||||||
|               shared_memory_handle, addr, size, permissions); |               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& kernel = Core::System::GetInstance().Kernel(); | ||||||
|     auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); |     auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); | ||||||
|     if (!shared_memory) { |     if (!shared_memory) { | ||||||
|         return ERR_INVALID_HANDLE; |         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, |     return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type, | ||||||
|                               MemoryPermission::DontCare); |                               MemoryPermission::DontCare); | ||||||
|     default: |  | ||||||
|         LOG_ERROR(Kernel_SVC, "unknown permissions=0x{:08X}", permissions); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return RESULT_SUCCESS; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { | 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}", |     LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}", | ||||||
|                 shared_memory_handle, addr, size); |                 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& kernel = Core::System::GetInstance().Kernel(); | ||||||
|     auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); |     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, |     LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size, | ||||||
|               local_permissions, remote_permissions); |               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& kernel = Core::System::GetInstance().Kernel(); | ||||||
|     auto& handle_table = kernel.HandleTable(); |     auto& handle_table = kernel.HandleTable(); | ||||||
|     auto shared_mem_handle = |     auto shared_mem_handle = | ||||||
|         SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size, |         SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size, | ||||||
|                              static_cast<MemoryPermission>(local_permissions), |                              local_perms, remote_perms); | ||||||
|                              static_cast<MemoryPermission>(remote_permissions)); |  | ||||||
| 
 | 
 | ||||||
|     CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle)); |     CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle)); | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei