From a79c4494938f6ca1a7fe1899c86037488b6a06cd Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 12 Nov 2016 17:13:16 +0100 Subject: [PATCH] Avoid buffer over-reads in /dev/net/ip/top Also fixes the less serious problem of buffer overflows in emulated memory when BufferOutSize is less than 2. --- .../Core/IPC_HLE/WII_IPC_HLE_Device_net.cpp | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_net.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_net.cpp index 617e764a8d..f87d114dfd 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_net.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_net.cpp @@ -2,7 +2,9 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include #include +#include #include #include #include @@ -14,6 +16,7 @@ #include "Common/CommonPaths.h" #include "Common/FileUtil.h" +#include "Common/Logging/Log.h" #include "Common/NandPaths.h" #include "Common/Network.h" #include "Common/SettingsHandler.h" @@ -848,9 +851,16 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress) sa_len = sizeof(sa); int ret = getsockname(fd, &sa, &sa_len); - Memory::Write_U8(BufferOutSize, BufferOut); - Memory::Write_U8(sa.sa_family & 0xFF, BufferOut + 1); - Memory::CopyToEmu(BufferOut + 2, &sa.sa_data, BufferOutSize - 2); + if (BufferOutSize < 2 + sizeof(sa.sa_data)) + WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETSOCKNAME output buffer is too small. Truncating"); + + if (BufferOutSize > 0) + Memory::Write_U8(BufferOutSize, BufferOut); + if (BufferOutSize > 1) + Memory::Write_U8(sa.sa_family & 0xFF, BufferOut + 1); + if (BufferOutSize > 2) + Memory::CopyToEmu(BufferOut + 2, &sa.sa_data, + std::min(sizeof(sa.sa_data), BufferOutSize - 2)); ReturnValue = ret; break; } @@ -864,9 +874,16 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress) int ret = getpeername(fd, &sa, &sa_len); - Memory::Write_U8(BufferOutSize, BufferOut); - Memory::Write_U8(AF_INET, BufferOut + 1); - Memory::CopyToEmu(BufferOut + 2, &sa.sa_data, BufferOutSize - 2); + if (BufferOutSize < 2 + sizeof(sa.sa_data)) + WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME output buffer is too small. Truncating"); + + if (BufferOutSize > 0) + Memory::Write_U8(BufferOutSize, BufferOut); + if (BufferOutSize > 1) + Memory::Write_U8(AF_INET, BufferOut + 1); + if (BufferOutSize > 2) + Memory::CopyToEmu(BufferOut + 2, &sa.sa_data, + std::min(sizeof(sa.sa_data), BufferOutSize - 2)); INFO_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME(%x)", fd);