summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-09-17 10:11:26 -0400
committerGravatar GitHub2018-09-17 10:11:26 -0400
commite6367ab955b8ced2acfe1b191f812e1b442fe2ae (patch)
tree65ebdbeae1198e9c22760d64e3982ddd8bf209c8
parentMerge pull request #1320 from lioncash/name (diff)
parentkernel/svc: Sanitize creation of shared memory via svcCreateSharedMemory() (diff)
downloadyuzu-e6367ab955b8ced2acfe1b191f812e1b442fe2ae.tar.gz
yuzu-e6367ab955b8ced2acfe1b191f812e1b442fe2ae.tar.xz
yuzu-e6367ab955b8ced2acfe1b191f812e1b442fe2ae.zip
Merge pull request #1315 from lioncash/size
kernel/svc: Handle a few error cases within memory-related functions
-rw-r--r--src/core/hle/kernel/errors.h2
-rw-r--r--src/core/hle/kernel/svc.cpp91
2 files changed, 74 insertions, 19 deletions
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index ad39c8271..2be2fad82 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -17,6 +17,7 @@ enum {
17 17
18 // Confirmed Switch OS error codes 18 // Confirmed Switch OS error codes
19 MaxConnectionsReached = 7, 19 MaxConnectionsReached = 7,
20 InvalidSize = 101,
20 InvalidAddress = 102, 21 InvalidAddress = 102,
21 HandleTableFull = 105, 22 HandleTableFull = 105,
22 InvalidMemoryState = 106, 23 InvalidMemoryState = 106,
@@ -55,6 +56,7 @@ constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS(ErrorModule::Kernel,
55 ErrCodes::InvalidMemoryPermissions); 56 ErrCodes::InvalidMemoryPermissions);
56constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); 57constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle);
57constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId); 58constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
59constexpr ResultCode ERR_INVALID_SIZE(ErrorModule::Kernel, ErrCodes::InvalidSize);
58constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState); 60constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState);
59constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel, 61constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel,
60 ErrCodes::InvalidThreadPriority); 62 ErrCodes::InvalidThreadPriority);
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 3c526304f..c5c1697ee 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -35,10 +35,21 @@
35#include "core/hle/service/service.h" 35#include "core/hle/service/service.h"
36 36
37namespace Kernel { 37namespace Kernel {
38namespace {
39constexpr bool Is4KBAligned(VAddr address) {
40 return (address & 0xFFF) == 0;
41}
42} // Anonymous namespace
38 43
39/// Set the process heap to a given Size. It can both extend and shrink the heap. 44/// Set the process heap to a given Size. It can both extend and shrink the heap.
40static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { 45static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
41 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); 46 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
47
48 // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 4GB.
49 if ((heap_size & 0xFFFFFFFE001FFFFF) != 0) {
50 return ERR_INVALID_SIZE;
51 }
52
42 auto& process = *Core::CurrentProcess(); 53 auto& process = *Core::CurrentProcess();
43 CASCADE_RESULT(*heap_addr, 54 CASCADE_RESULT(*heap_addr,
44 process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); 55 process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite));
@@ -56,6 +67,15 @@ static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state
56static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 67static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
57 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 68 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
58 src_addr, size); 69 src_addr, size);
70
71 if (!Is4KBAligned(dst_addr) || !Is4KBAligned(src_addr)) {
72 return ERR_INVALID_ADDRESS;
73 }
74
75 if (size == 0 || !Is4KBAligned(size)) {
76 return ERR_INVALID_SIZE;
77 }
78
59 return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size); 79 return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size);
60} 80}
61 81
@@ -63,6 +83,15 @@ static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
63static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 83static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
64 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 84 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
65 src_addr, size); 85 src_addr, size);
86
87 if (!Is4KBAligned(dst_addr) || !Is4KBAligned(src_addr)) {
88 return ERR_INVALID_ADDRESS;
89 }
90
91 if (size == 0 || !Is4KBAligned(size)) {
92 return ERR_INVALID_SIZE;
93 }
94
66 return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size); 95 return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size);
67} 96}
68 97
@@ -415,35 +444,43 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
415 "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", 444 "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
416 shared_memory_handle, addr, size, permissions); 445 shared_memory_handle, addr, size, permissions);
417 446
447 if (!Is4KBAligned(addr)) {
448 return ERR_INVALID_ADDRESS;
449 }
450
451 if (size == 0 || !Is4KBAligned(size)) {
452 return ERR_INVALID_SIZE;
453 }
454
455 const auto permissions_type = static_cast<MemoryPermission>(permissions);
456 if (permissions_type != MemoryPermission::Read &&
457 permissions_type != MemoryPermission::ReadWrite) {
458 LOG_ERROR(Kernel_SVC, "Invalid permissions=0x{:08X}", permissions);
459 return ERR_INVALID_MEMORY_PERMISSIONS;
460 }
461
418 auto& kernel = Core::System::GetInstance().Kernel(); 462 auto& kernel = Core::System::GetInstance().Kernel();
419 auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); 463 auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
420 if (!shared_memory) { 464 if (!shared_memory) {
421 return ERR_INVALID_HANDLE; 465 return ERR_INVALID_HANDLE;
422 } 466 }
423 467
424 MemoryPermission permissions_type = static_cast<MemoryPermission>(permissions); 468 return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
425 switch (permissions_type) { 469 MemoryPermission::DontCare);
426 case MemoryPermission::Read:
427 case MemoryPermission::Write:
428 case MemoryPermission::ReadWrite:
429 case MemoryPermission::Execute:
430 case MemoryPermission::ReadExecute:
431 case MemoryPermission::WriteExecute:
432 case MemoryPermission::ReadWriteExecute:
433 case MemoryPermission::DontCare:
434 return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
435 MemoryPermission::DontCare);
436 default:
437 LOG_ERROR(Kernel_SVC, "unknown permissions=0x{:08X}", permissions);
438 }
439
440 return RESULT_SUCCESS;
441} 470}
442 471
443static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { 472static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
444 LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}", 473 LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}",
445 shared_memory_handle, addr, size); 474 shared_memory_handle, addr, size);
446 475
476 if (!Is4KBAligned(addr)) {
477 return ERR_INVALID_ADDRESS;
478 }
479
480 if (size == 0 || !Is4KBAligned(size)) {
481 return ERR_INVALID_SIZE;
482 }
483
447 auto& kernel = Core::System::GetInstance().Kernel(); 484 auto& kernel = Core::System::GetInstance().Kernel();
448 auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); 485 auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
449 486
@@ -899,12 +936,28 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
899 LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size, 936 LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size,
900 local_permissions, remote_permissions); 937 local_permissions, remote_permissions);
901 938
939 // Size must be a multiple of 4KB and be less than or equal to
940 // approx. 8 GB (actually (1GB - 512B) * 8)
941 if (size == 0 || (size & 0xFFFFFFFE00000FFF) != 0) {
942 return ERR_INVALID_SIZE;
943 }
944
945 const auto local_perms = static_cast<MemoryPermission>(local_permissions);
946 if (local_perms != MemoryPermission::Read && local_perms != MemoryPermission::ReadWrite) {
947 return ERR_INVALID_MEMORY_PERMISSIONS;
948 }
949
950 const auto remote_perms = static_cast<MemoryPermission>(remote_permissions);
951 if (remote_perms != MemoryPermission::Read && remote_perms != MemoryPermission::ReadWrite &&
952 remote_perms != MemoryPermission::DontCare) {
953 return ERR_INVALID_MEMORY_PERMISSIONS;
954 }
955
902 auto& kernel = Core::System::GetInstance().Kernel(); 956 auto& kernel = Core::System::GetInstance().Kernel();
903 auto& handle_table = kernel.HandleTable(); 957 auto& handle_table = kernel.HandleTable();
904 auto shared_mem_handle = 958 auto shared_mem_handle =
905 SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size, 959 SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
906 static_cast<MemoryPermission>(local_permissions), 960 local_perms, remote_perms);
907 static_cast<MemoryPermission>(remote_permissions));
908 961
909 CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle)); 962 CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
910 return RESULT_SUCCESS; 963 return RESULT_SUCCESS;