Validate fat_head; CERT-FI id:000000,sig:06,src:000000,op:flip1,pos:7

This commit is contained in:
John Reiser 2015-05-08 18:32:42 -07:00
parent f0aef9b28b
commit 35944cbfc1
4 changed files with 44 additions and 9 deletions

View File

@ -243,6 +243,7 @@ void InputFile::sopen(const char *name, int flags, int shflags)
else
throwIOException(_name, errno);
}
_length_orig = _length;
}
@ -294,6 +295,10 @@ off_t InputFile::tell() const
return super::tell();
}
off_t InputFile::st_size_orig() const
{
return _length_orig;
}
/*************************************************************************
//

View File

@ -108,6 +108,9 @@ public:
virtual void seek(off_t off, int whence);
virtual off_t tell() const;
virtual off_t st_size_orig() const;
protected:
off_t _length_orig;
};

View File

@ -1443,6 +1443,34 @@ PackMachFat::~PackMachFat()
{
}
unsigned PackMachFat::check_fat_head()
{
struct Mach_fat_arch const *const arch = &fat_head.arch[0];
unsigned nfat = fat_head.fat.nfat_arch;
if (Mach_fat_header::FAT_MAGIC!=fat_head.fat.magic
|| N_FAT_ARCH < nfat) {
return 0;
}
for (unsigned j=0; j < nfat; ++j) {
unsigned const align = arch[j].align;
unsigned const mask = ~(~0u<<align);
unsigned const size = arch[j].size;
unsigned const offset = arch[j].offset;
if (align < 12 || align > 24) { // heuristic
throwUnknownExecutableFormat("align", 0);
}
if (mask > size) {
throwUnknownExecutableFormat("size", 0);
}
if (mask & offset
|| fi->st_size_orig() < (size + offset)
|| fi->st_size_orig() <= offset) { // redundant unless overflow
throwUnknownExecutableFormat("offset", 0);
}
}
return nfat;
}
const int *PackMachFat::getCompressionMethods(int /*method*/, int /*level*/) const
{
static const int m_nrv2e[] = { M_NRV2E_LE32, M_END };
@ -1549,8 +1577,9 @@ void PackMachFat::unpack(OutputFile *fo)
fo->write(&fat_head, sizeof(fat_head.fat) +
fat_head.fat.nfat_arch * sizeof(fat_head.arch[0]));
}
unsigned const nfat = check_fat_head();
unsigned length;
for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) {
for (unsigned j=0; j < nfat; ++j) {
unsigned base = (fo ? fo->unset_extent() : 0); // actual length
base += ~(~0u<<fat_head.arch[j].align) & (0-base); // align up
if (fo) {
@ -1631,11 +1660,8 @@ bool PackMachFat::canPack()
struct Mach_fat_arch *arch = &fat_head.arch[0];
fi->readx(&fat_head, sizeof(fat_head));
if (Mach_fat_header::FAT_MAGIC!=fat_head.fat.magic
|| N_FAT_ARCH < fat_head.fat.nfat_arch) {
return false;
}
for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) {
unsigned const nfat = check_fat_head();
for (unsigned j=0; j < nfat; ++j) {
fi->set_extent(fat_head.arch[j].offset, fat_head.arch[j].size);
fi->seek(0, SEEK_SET);
switch (arch[j].cputype) {
@ -1684,11 +1710,11 @@ int PackMachFat::canUnpack()
struct Mach_fat_arch *arch = &fat_head.arch[0];
fi->readx(&fat_head, sizeof(fat_head));
if (Mach_fat_header::FAT_MAGIC!=fat_head.fat.magic
|| N_FAT_ARCH < fat_head.fat.nfat_arch) {
unsigned const nfat = check_fat_head();
if (0 == nfat) {
return false;
}
for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) {
for (unsigned j=0; j < nfat; ++j) {
fi->set_extent(fat_head.arch[j].offset, fat_head.arch[j].size);
fi->seek(0, SEEK_SET);
switch (arch[j].cputype) {

View File

@ -855,6 +855,7 @@ public:
protected:
// implementation
virtual unsigned check_fat_head(); // number of architectures
virtual void pack(OutputFile *fo);
virtual void unpack(OutputFile *fo);
virtual void list();