From 09a219d5b4a45537502c219542a51a57d6d0c317 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 12 Dec 2018 12:52:31 -0500 Subject: [PATCH] svc: Write out the complete MemoryInfo structure in QueryProcessMemory In the previous change, the memory writing was moved into the service function itself, however it still had a problem, in that the entire MemoryInfo structure wasn't being written out, only the first 32 bytes of it were being written out. We still need to write out the trailing two reference count members and zero out the padding bits. Not doing this can result in wrong behavior in userland code in the following scenario: MemoryInfo info; // Put on the stack, not quaranteed to be zeroed out. svcQueryMemory(&info, ...); if (info.device_refcount == ...) // Whoops, uninitialized read. This can also cause the wrong thing to happen if the user code uses std::memcmp to compare the struct, with another one (questionable, but allowed), as the padding bits are not guaranteed to be a deterministic value. Note that the kernel itself also fully zeroes out the structure before writing it out including the padding bits. --- src/core/hle/kernel/svc.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a1ecc4540..8b51aa2c7 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1086,6 +1086,9 @@ static ResultCode QueryProcessMemory(VAddr memory_info_address, VAddr page_info_ Memory::Write32(memory_info_address + 16, memory_info.state); Memory::Write32(memory_info_address + 20, memory_info.attributes); Memory::Write32(memory_info_address + 24, memory_info.permission); + Memory::Write32(memory_info_address + 32, memory_info.ipc_ref_count); + Memory::Write32(memory_info_address + 28, memory_info.device_ref_count); + Memory::Write32(memory_info_address + 36, 0); // Page info appears to be currently unused by the kernel and is always set to zero. Memory::Write32(page_info_address, 0);