From 7a4f19ed98a86b8370155cf1c2a96e7c00541151 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 26 Nov 2016 18:06:31 +0100 Subject: [PATCH] IOS HLE: Correct handling of paths that don't start with / --- Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp | 10 ++- .../IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp | 8 +- .../Core/IPC_HLE/WII_IPC_HLE_Device_fs.cpp | 82 +++++++++++++++++-- 3 files changed, 85 insertions(+), 15 deletions(-) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp index a47b529b38..83d8397331 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp @@ -441,7 +441,7 @@ void ExecuteCommand(u32 address) result = IWII_IPC_HLE_Device::GetDefaultReply(); } } - else + else if (device_name.find('/') == 0) { device = CreateFileIO(DeviceID, device_name); result = device->Open(address, Mode); @@ -449,9 +449,13 @@ void ExecuteCommand(u32 address) DEBUG_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)", device->GetDeviceName().c_str(), DeviceID, Mode); if (Memory::Read_U32(address + 4) == (u32)DeviceID) - { s_fdmap[DeviceID] = device; - } + } + else + { + WARN_LOG(WII_IPC_HLE, "Invalid device: %s", device_name.c_str()); + Memory::Write_U32(FS_ENOENT, address + 4); + result = IWII_IPC_HLE_Device::GetDefaultReply(); } } else diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index dc659c244f..3616bd39d1 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -7,6 +7,7 @@ #include #include +#include "Common/Assert.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/FileUtil.h" @@ -22,10 +23,11 @@ static std::map> openFiles; std::string HLE_IPC_BuildFilename(const std::string& wii_path) { std::string nand_path = File::GetUserPath(D_SESSION_WIIROOT_IDX); - if (wii_path.empty() || wii_path[0] != '/') - return nand_path; + if (wii_path.compare(0, 1, "/") == 0) + return nand_path + Common::EscapePath(wii_path); - return nand_path + Common::EscapePath(wii_path); + _assert_(false); + return nand_path; } void HLE_IPC_CreateVirtualFATFilesystem() diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_fs.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_fs.cpp index 15533cada5..6d686b2797 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_fs.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_fs.cpp @@ -22,6 +22,11 @@ #include "Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.h" #include "Core/IPC_HLE/WII_IPC_HLE_Device_fs.h" +static bool IsValidWiiPath(const std::string& path) +{ + return path.compare(0, 1, "/") == 0; +} + CWII_IPC_HLE_Device_fs::CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string& _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) { @@ -93,9 +98,18 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress) { case IOCTLV_READ_DIR: { + const std::string relative_path = + Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size); + + if (!IsValidWiiPath(relative_path)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relative_path.c_str()); + ReturnValue = FS_RESULT_FATAL; + break; + } + // the Wii uses this function to define the type (dir or file) - std::string DirName(HLE_IPC_BuildFilename( - Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size))); + std::string DirName(HLE_IPC_BuildFilename(relative_path)); INFO_LOG(WII_IPC_FILEIO, "FS: IOCTL_READ_DIR %s", DirName.c_str()); @@ -177,6 +191,14 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress) // It should be correct, but don't count on it... std::string relativepath = Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size); + + if (!IsValidWiiPath(relativepath)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relativepath.c_str()); + ReturnValue = FS_RESULT_FATAL; + break; + } + std::string path(HLE_IPC_BuildFilename(relativepath)); u32 fsBlocks = 0; u32 iNodes = 0; @@ -291,7 +313,13 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B Addr += 4; u16 GroupID = Memory::Read_U16(Addr); Addr += 2; - std::string DirName(HLE_IPC_BuildFilename(Memory::GetString(Addr, 64))); + const std::string wii_path = Memory::GetString(Addr, 64); + if (!IsValidWiiPath(wii_path)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str()); + return FS_RESULT_FATAL; + } + std::string DirName(HLE_IPC_BuildFilename(wii_path)); Addr += 64; Addr += 9; // owner attribs, permission u8 Attribs = Memory::Read_U8(Addr); @@ -316,7 +344,13 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B Addr += 4; u16 GroupID = Memory::Read_U16(Addr); Addr += 2; - std::string Filename = HLE_IPC_BuildFilename(Memory::GetString(_BufferIn, 64)); + const std::string wii_path = Memory::GetString(_BufferIn, 64); + if (!IsValidWiiPath(wii_path)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str()); + return FS_RESULT_FATAL; + } + std::string Filename = HLE_IPC_BuildFilename(wii_path); Addr += 64; u8 OwnerPerm = Memory::Read_U8(Addr); Addr += 1; @@ -348,7 +382,13 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B u32 OwnerID = 0; u16 GroupID = 0x3031; // this is also known as makercd, 01 (0x3031) for nintendo and 08 // (0x3038) for MH3 etc - std::string Filename = HLE_IPC_BuildFilename(Memory::GetString(_BufferIn, 64)); + const std::string wii_path = Memory::GetString(_BufferIn, 64); + if (!IsValidWiiPath(wii_path)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str()); + return FS_RESULT_FATAL; + } + std::string Filename = HLE_IPC_BuildFilename(wii_path); u8 OwnerPerm = 0x3; // read/write u8 GroupPerm = 0x3; // read/write u8 OtherPerm = 0x3; // read/write @@ -401,7 +441,13 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B _dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0); int Offset = 0; - std::string Filename = HLE_IPC_BuildFilename(Memory::GetString(_BufferIn + Offset, 64)); + const std::string wii_path = Memory::GetString(_BufferIn + Offset, 64); + if (!IsValidWiiPath(wii_path)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str()); + return FS_RESULT_FATAL; + } + std::string Filename = HLE_IPC_BuildFilename(wii_path); Offset += 64; if (File::Delete(Filename)) { @@ -425,10 +471,22 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B _dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0); int Offset = 0; - std::string Filename = HLE_IPC_BuildFilename(Memory::GetString(_BufferIn + Offset, 64)); + const std::string wii_path = Memory::GetString(_BufferIn + Offset, 64); + if (!IsValidWiiPath(wii_path)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str()); + return FS_RESULT_FATAL; + } + std::string Filename = HLE_IPC_BuildFilename(wii_path); Offset += 64; - std::string FilenameRename = HLE_IPC_BuildFilename(Memory::GetString(_BufferIn + Offset, 64)); + const std::string wii_path_rename = Memory::GetString(_BufferIn + Offset, 64); + if (!IsValidWiiPath(wii_path_rename)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path_rename.c_str()); + return FS_RESULT_FATAL; + } + std::string FilenameRename = HLE_IPC_BuildFilename(wii_path_rename); Offset += 64; // try to make the basis directory @@ -465,7 +523,13 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B Addr += 4; u16 GroupID = Memory::Read_U16(Addr); Addr += 2; - std::string Filename(HLE_IPC_BuildFilename(Memory::GetString(Addr, 64))); + const std::string wii_path = Memory::GetString(Addr, 64); + if (!IsValidWiiPath(wii_path)) + { + WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str()); + return FS_RESULT_FATAL; + } + std::string Filename(HLE_IPC_BuildFilename(wii_path)); Addr += 64; u8 OwnerPerm = Memory::Read_U8(Addr); Addr++;