Check TMD sizes using the actual constant
0x49e4 is the actual maximum TMD size (which is checked against in ES). IsValidTMDSize is added to ESFormats to avoid duplicating the constant.
This commit is contained in:
parent
f4190ab1c4
commit
b5a2f34a37
|
@ -57,6 +57,11 @@ bool Content::IsShared() const
|
||||||
return (type & 0x8000) != 0;
|
return (type & 0x8000) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsValidTMDSize(size_t size)
|
||||||
|
{
|
||||||
|
return size <= 0x49e4;
|
||||||
|
}
|
||||||
|
|
||||||
TMDReader::TMDReader(const std::vector<u8>& bytes) : m_bytes(bytes)
|
TMDReader::TMDReader(const std::vector<u8>& bytes) : m_bytes(bytes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,8 @@ struct Ticket
|
||||||
static_assert(sizeof(Ticket) == 0x2A4, "Ticket has the wrong size");
|
static_assert(sizeof(Ticket) == 0x2A4, "Ticket has the wrong size");
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
bool IsValidTMDSize(size_t size);
|
||||||
|
|
||||||
class TMDReader final
|
class TMDReader final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -91,6 +91,9 @@ IPCCommandResult ES::ImportTmd(Context& context, const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(1, 0))
|
if (!request.HasNumberOfValidVectors(1, 0))
|
||||||
return GetDefaultReply(ES_EINVAL);
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
|
if (!IOS::ES::IsValidTMDSize(request.in_vectors[0].size))
|
||||||
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
std::vector<u8> tmd(request.in_vectors[0].size);
|
std::vector<u8> tmd(request.in_vectors[0].size);
|
||||||
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
return GetDefaultReply(ImportTmd(context, tmd));
|
return GetDefaultReply(ImportTmd(context, tmd));
|
||||||
|
@ -131,6 +134,9 @@ IPCCommandResult ES::ImportTitleInit(Context& context, const IOCtlVRequest& requ
|
||||||
if (!request.HasNumberOfValidVectors(4, 0))
|
if (!request.HasNumberOfValidVectors(4, 0))
|
||||||
return GetDefaultReply(ES_EINVAL);
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
|
if (!IOS::ES::IsValidTMDSize(request.in_vectors[0].size))
|
||||||
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
std::vector<u8> tmd(request.in_vectors[0].size);
|
std::vector<u8> tmd(request.in_vectors[0].size);
|
||||||
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||||
return GetDefaultReply(ImportTitleInit(context, tmd));
|
return GetDefaultReply(ImportTitleInit(context, tmd));
|
||||||
|
|
|
@ -41,7 +41,7 @@ CVolumeWAD::CVolumeWAD(std::unique_ptr<IBlobReader> reader) : m_reader(std::move
|
||||||
m_opening_bnr_offset =
|
m_opening_bnr_offset =
|
||||||
m_tmd_offset + Common::AlignUp(m_tmd_size, 0x40) + Common::AlignUp(m_data_size, 0x40);
|
m_tmd_offset + Common::AlignUp(m_tmd_size, 0x40) + Common::AlignUp(m_data_size, 0x40);
|
||||||
|
|
||||||
if (m_tmd_size > 1024 * 1024 * 4)
|
if (!IOS::ES::IsValidTMDSize(m_tmd_size))
|
||||||
{
|
{
|
||||||
ERROR_LOG(DISCIO, "TMD is too large: %u bytes", m_tmd_size);
|
ERROR_LOG(DISCIO, "TMD is too large: %u bytes", m_tmd_size);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -81,13 +81,11 @@ CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader)
|
||||||
if (!m_pReader->ReadSwapped(partition_offset + 0x2a8, &tmd_address))
|
if (!m_pReader->ReadSwapped(partition_offset + 0x2a8, &tmd_address))
|
||||||
continue;
|
continue;
|
||||||
tmd_address <<= 2;
|
tmd_address <<= 2;
|
||||||
if (tmd_size > 1024 * 1024 * 4)
|
if (!IOS::ES::IsValidTMDSize(tmd_size))
|
||||||
{
|
{
|
||||||
// The size is checked so that a malicious or corrupt ISO
|
// This check is normally done by ES in ES_DiVerify, but that would happen too late
|
||||||
// can't force Dolphin to allocate up to 4 GiB of memory.
|
// (after allocating the buffer), so we do the check here.
|
||||||
// 4 MiB should be much bigger than the size of TMDs and much smaller
|
PanicAlert("Invalid TMD size");
|
||||||
// than the amount of RAM in a computer that can run Dolphin.
|
|
||||||
PanicAlert("TMD > 4 MiB");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::vector<u8> tmd_buffer(tmd_size);
|
std::vector<u8> tmd_buffer(tmd_size);
|
||||||
|
|
Loading…
Reference in New Issue