::unpack(): another check on b_info; uncompressed ElfXX_Ehdr must match input

This commit is contained in:
John Reiser 2015-05-16 15:23:01 -07:00
parent 1d13d8c4a0
commit 298ea1f0d3

View File

@ -2629,7 +2629,7 @@ int PackLinuxElf32::ARM_is_QNX(void)
unsigned const sz_interp = get_te32(&phdr->p_filesz);
unsigned const pos_interp = get_te32(&phdr->p_offset);
if (sz_interp <= sizeof(interp)
&& (sz_interp + pos_interp) <= (unsigned) fi->st_size()) {
&& (sz_interp + pos_interp) <= file_size) {
fi->seek(pos_interp, SEEK_SET);
fi->readx(interp, sz_interp);
for (int k = sz_interp - 5; k>=0; --k) {
@ -3024,7 +3024,8 @@ void PackLinuxElf64::unpack(OutputFile *fo)
fi->readx(&bhdr, szb_info);
ph.u_len = get_te32(&bhdr.sz_unc);
ph.c_len = get_te32(&bhdr.sz_cpr);
if (ph.c_len > fi->st_size() || ph.c_len == 0 || ph.u_len == 0)
if (ph.c_len > file_size || ph.c_len == 0 || ph.u_len == 0
|| ph.u_len > sizeof(u))
throwCantUnpack("b_info corrupted");
ph.filter_cto = bhdr.b_cto8;
@ -3032,6 +3033,14 @@ void PackLinuxElf64::unpack(OutputFile *fo)
// Uncompress Ehdr and Phdrs.
fi->readx(ibuf, ph.c_len);
decompress(ibuf, (upx_byte *)ehdr, false);
if (ehdr->e_type !=ehdri.e_type
|| ehdr->e_machine!=ehdri.e_machine
|| ehdr->e_version!=ehdri.e_version
|| ehdr->e_flags !=ehdri.e_flags
|| ehdr->e_ehsize !=ehdri.e_ehsize
// check EI_MAG[0-3], EI_CLASS, EI_DATA, EI_VERSION
|| memcmp(ehdr->e_ident, ehdri.e_ident, Elf32_Ehdr::EI_OSABI))
throwCantUnpack("ElfXX_Ehdr corrupted");
unsigned total_in = 0;
unsigned total_out = 0;
@ -3063,7 +3072,7 @@ void PackLinuxElf64::unpack(OutputFile *fo)
if (is_shlib
|| ((unsigned)(get_te64(&ehdri.e_entry) - load_va) + up4(lsize) +
ph.getPackHeaderSize() + sizeof(overlay_offset))
< up4(fi->st_size())) {
< up4(file_size)) {
// Loader is not at end; skip past it.
funpad4(fi); // MATCH01
unsigned d_info[4]; fi->readx(d_info, sizeof(d_info));
@ -3544,7 +3553,8 @@ void PackLinuxElf32::unpack(OutputFile *fo)
fi->readx(&bhdr, szb_info);
ph.u_len = get_te32(&bhdr.sz_unc);
ph.c_len = get_te32(&bhdr.sz_cpr);
if (ph.c_len > fi->st_size() || ph.c_len == 0 || ph.u_len == 0)
if (ph.c_len > file_size || ph.c_len == 0 || ph.u_len == 0
|| ph.u_len > sizeof(u))
throwCantUnpack("b_info corrupted");
ph.filter_cto = bhdr.b_cto8;
bool const is_shlib = (ehdr->e_entry==0) || (ehdr->e_shoff!=0);
@ -3555,6 +3565,15 @@ void PackLinuxElf32::unpack(OutputFile *fo)
throwCompressedDataViolation();
fi->readx(ibuf, ph.c_len);
decompress(ibuf, (upx_byte *)ehdr, false);
if (ehdr->e_type !=ehdri.e_type
|| ehdr->e_machine!=ehdri.e_machine
|| ehdr->e_version!=ehdri.e_version
|| ehdr->e_flags !=ehdri.e_flags
|| ehdr->e_ehsize !=ehdri.e_ehsize
// check EI_MAG[0-3], EI_CLASS, EI_DATA, EI_VERSION
|| memcmp(ehdr->e_ident, ehdri.e_ident, Elf32_Ehdr::EI_OSABI))
throwCantUnpack("ElfXX_Ehdr corrupted");
fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR);
unsigned const u_phnum = get_te16(&ehdr->e_phnum);
@ -3627,7 +3646,7 @@ void PackLinuxElf32::unpack(OutputFile *fo)
if (is_shlib
|| ((unsigned)(get_te32(&ehdri.e_entry) - load_va) + up4(lsize) +
ph.getPackHeaderSize() + sizeof(overlay_offset))
< up4(fi->st_size())) {
< up4(file_size)) {
// Loader is not at end; skip past it.
funpad4(fi); // MATCH01
unsigned d_info[4]; fi->readx(d_info, sizeof(d_info));