Unpacking detects and defends against malicious ELF

This commit is contained in:
John Reiser 2024-03-28 07:48:55 -07:00 committed by Markus F.X.J. Oberhumer
parent d1f62e3ab4
commit 3949af6d3c
2 changed files with 18 additions and 8 deletions

View File

@ -6484,13 +6484,17 @@ void PackLinuxElf64::un_shlib_1(
struct {
struct l_info l;
struct p_info p;
struct b_info b;
} hdr;
fi->readx(&hdr, sizeof(hdr));
if (hdr.l.l_magic != UPX_MAGIC_LE32
|| hdr.l.l_lsize != (unsigned)lsize
|| hdr.p.p_filesize != ph.u_file_size) {
throwCantUnpack("corrupt l_info/p_info");
|| get_te16(&hdr.l.l_lsize) != (unsigned)lsize
|| get_te32(&hdr.p.p_filesize) != ph.u_file_size
|| get_te32(&hdr.b.sz_unc) < sz_elf_hdrs // peek: 1st b_info covers Elf headers
) {
throwCantUnpack("corrupt l_info/p_info/b_info");
}
fi->seek(-(off_t)sizeof(struct b_info), SEEK_CUR); // hdr.b_info was a peek
// The default layout for a shared library created by binutils-2.29
// (Fedora 28; 2018) has two PT_LOAD: permissions r-x and rw-.
@ -6680,13 +6684,17 @@ void PackLinuxElf32::un_shlib_1(
struct {
struct l_info l;
struct p_info p;
struct b_info b;
} hdr;
fi->readx(&hdr, sizeof(hdr));
if (hdr.l.l_magic != UPX_MAGIC_LE32
|| hdr.l.l_lsize != (unsigned)lsize
|| hdr.p.p_filesize != ph.u_file_size) {
throwCantUnpack("corrupt l_info/p_info");
|| get_te16(&hdr.l.l_lsize) != (unsigned)lsize
|| get_te32(&hdr.p.p_filesize) != ph.u_file_size
|| get_te32(&hdr.b.sz_unc) < sz_elf_hdrs // peek: 1st b_info covers Elf headers
) {
throwCantUnpack("corrupt l_info/p_info/b_info");
}
fi->seek(-(off_t)sizeof(struct b_info), SEEK_CUR); // hdr.b_info was a peek
// The default layout for a shared library created by binutils-2.29
// (Fedora 28; 2018) has two PT_LOAD: permissions r-x and rw-.

View File

@ -491,8 +491,10 @@ unsigned PackUnix::unpackExtent(unsigned wanted, OutputFile *fo,
throwCantUnpack("corrupt b_info");
// place the input for overlapping de-compression
// FIXME: inlen cheats OVERHEAD; assumes small wanted peek length
int j = inlen + blocksize + OVERHEAD - sz_cpr;
int j = inlen + sz_unc + OVERHEAD - sz_cpr;
if (ibuf.getSize() < (unsigned)(j + sz_cpr)) {
throwCantUnpack("corrupt b_info");
}
fi->readx(ibuf+j, sz_cpr);
total_in += sz_cpr;
// update checksum of compressed data