::unpack(): another check on b_info; uncompressed ElfXX_Ehdr must match input
This commit is contained in:
+24
-5
@@ -2629,7 +2629,7 @@ int PackLinuxElf32::ARM_is_QNX(void)
|
|||||||
unsigned const sz_interp = get_te32(&phdr->p_filesz);
|
unsigned const sz_interp = get_te32(&phdr->p_filesz);
|
||||||
unsigned const pos_interp = get_te32(&phdr->p_offset);
|
unsigned const pos_interp = get_te32(&phdr->p_offset);
|
||||||
if (sz_interp <= sizeof(interp)
|
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->seek(pos_interp, SEEK_SET);
|
||||||
fi->readx(interp, sz_interp);
|
fi->readx(interp, sz_interp);
|
||||||
for (int k = sz_interp - 5; k>=0; --k) {
|
for (int k = sz_interp - 5; k>=0; --k) {
|
||||||
@@ -3024,7 +3024,8 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
|||||||
fi->readx(&bhdr, szb_info);
|
fi->readx(&bhdr, szb_info);
|
||||||
ph.u_len = get_te32(&bhdr.sz_unc);
|
ph.u_len = get_te32(&bhdr.sz_unc);
|
||||||
ph.c_len = get_te32(&bhdr.sz_cpr);
|
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");
|
throwCantUnpack("b_info corrupted");
|
||||||
|
|
||||||
ph.filter_cto = bhdr.b_cto8;
|
ph.filter_cto = bhdr.b_cto8;
|
||||||
@@ -3032,6 +3033,14 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
|||||||
// Uncompress Ehdr and Phdrs.
|
// Uncompress Ehdr and Phdrs.
|
||||||
fi->readx(ibuf, ph.c_len);
|
fi->readx(ibuf, ph.c_len);
|
||||||
decompress(ibuf, (upx_byte *)ehdr, false);
|
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_in = 0;
|
||||||
unsigned total_out = 0;
|
unsigned total_out = 0;
|
||||||
@@ -3063,7 +3072,7 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
|||||||
if (is_shlib
|
if (is_shlib
|
||||||
|| ((unsigned)(get_te64(&ehdri.e_entry) - load_va) + up4(lsize) +
|
|| ((unsigned)(get_te64(&ehdri.e_entry) - load_va) + up4(lsize) +
|
||||||
ph.getPackHeaderSize() + sizeof(overlay_offset))
|
ph.getPackHeaderSize() + sizeof(overlay_offset))
|
||||||
< up4(fi->st_size())) {
|
< up4(file_size)) {
|
||||||
// Loader is not at end; skip past it.
|
// Loader is not at end; skip past it.
|
||||||
funpad4(fi); // MATCH01
|
funpad4(fi); // MATCH01
|
||||||
unsigned d_info[4]; fi->readx(d_info, sizeof(d_info));
|
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);
|
fi->readx(&bhdr, szb_info);
|
||||||
ph.u_len = get_te32(&bhdr.sz_unc);
|
ph.u_len = get_te32(&bhdr.sz_unc);
|
||||||
ph.c_len = get_te32(&bhdr.sz_cpr);
|
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");
|
throwCantUnpack("b_info corrupted");
|
||||||
ph.filter_cto = bhdr.b_cto8;
|
ph.filter_cto = bhdr.b_cto8;
|
||||||
bool const is_shlib = (ehdr->e_entry==0) || (ehdr->e_shoff!=0);
|
bool const is_shlib = (ehdr->e_entry==0) || (ehdr->e_shoff!=0);
|
||||||
@@ -3555,6 +3565,15 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
|||||||
throwCompressedDataViolation();
|
throwCompressedDataViolation();
|
||||||
fi->readx(ibuf, ph.c_len);
|
fi->readx(ibuf, ph.c_len);
|
||||||
decompress(ibuf, (upx_byte *)ehdr, false);
|
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);
|
fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR);
|
||||||
|
|
||||||
unsigned const u_phnum = get_te16(&ehdr->e_phnum);
|
unsigned const u_phnum = get_te16(&ehdr->e_phnum);
|
||||||
@@ -3627,7 +3646,7 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
|||||||
if (is_shlib
|
if (is_shlib
|
||||||
|| ((unsigned)(get_te32(&ehdri.e_entry) - load_va) + up4(lsize) +
|
|| ((unsigned)(get_te32(&ehdri.e_entry) - load_va) + up4(lsize) +
|
||||||
ph.getPackHeaderSize() + sizeof(overlay_offset))
|
ph.getPackHeaderSize() + sizeof(overlay_offset))
|
||||||
< up4(fi->st_size())) {
|
< up4(file_size)) {
|
||||||
// Loader is not at end; skip past it.
|
// Loader is not at end; skip past it.
|
||||||
funpad4(fi); // MATCH01
|
funpad4(fi); // MATCH01
|
||||||
unsigned d_info[4]; fi->readx(d_info, sizeof(d_info));
|
unsigned d_info[4]; fi->readx(d_info, sizeof(d_info));
|
||||||
|
|||||||
Reference in New Issue
Block a user