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.
This commit is contained in:
JosJuice 2016-11-12 17:13:16 +01:00
parent b47e607105
commit a79c449493
1 changed files with 23 additions and 6 deletions

View File

@ -2,7 +2,9 @@
// Licensed under GPLv2+ // Licensed under GPLv2+
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <algorithm>
#include <cinttypes> #include <cinttypes>
#include <cstddef>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <string> #include <string>
@ -14,6 +16,7 @@
#include "Common/CommonPaths.h" #include "Common/CommonPaths.h"
#include "Common/FileUtil.h" #include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/NandPaths.h" #include "Common/NandPaths.h"
#include "Common/Network.h" #include "Common/Network.h"
#include "Common/SettingsHandler.h" #include "Common/SettingsHandler.h"
@ -848,9 +851,16 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress)
sa_len = sizeof(sa); sa_len = sizeof(sa);
int ret = getsockname(fd, &sa, &sa_len); int ret = getsockname(fd, &sa, &sa_len);
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); Memory::Write_U8(BufferOutSize, BufferOut);
if (BufferOutSize > 1)
Memory::Write_U8(sa.sa_family & 0xFF, BufferOut + 1); Memory::Write_U8(sa.sa_family & 0xFF, BufferOut + 1);
Memory::CopyToEmu(BufferOut + 2, &sa.sa_data, BufferOutSize - 2); if (BufferOutSize > 2)
Memory::CopyToEmu(BufferOut + 2, &sa.sa_data,
std::min<size_t>(sizeof(sa.sa_data), BufferOutSize - 2));
ReturnValue = ret; ReturnValue = ret;
break; break;
} }
@ -864,9 +874,16 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress)
int ret = getpeername(fd, &sa, &sa_len); int ret = getpeername(fd, &sa, &sa_len);
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); Memory::Write_U8(BufferOutSize, BufferOut);
if (BufferOutSize > 1)
Memory::Write_U8(AF_INET, BufferOut + 1); Memory::Write_U8(AF_INET, BufferOut + 1);
Memory::CopyToEmu(BufferOut + 2, &sa.sa_data, BufferOutSize - 2); if (BufferOutSize > 2)
Memory::CopyToEmu(BufferOut + 2, &sa.sa_data,
std::min<size_t>(sizeof(sa.sa_data), BufferOutSize - 2));
INFO_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME(%x)", fd); INFO_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME(%x)", fd);