From 4f8756edd06d76af33208047a5ed9b776132d97a Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Thu, 13 Sep 2018 21:04:43 -0400
Subject: [PATCH] kernel/svc: Sanitize creation of shared memory via
 svcCreateSharedMemory()

The kernel caps the size limit of shared memory to 8589930496 bytes (or
(1GB - 512 bytes) * 8), so approximately 8GB, where every GB has a 512
byte sector taken off of it.

It also ensures the shared memory is created with either read or
read/write permissions for both permission types passed in, allowing the
remote permissions to also be set as "don't care".
---
 src/core/hle/kernel/svc.cpp | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index d19182639..4529002ba 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -935,12 +935,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;