Stronger test and better message for PT_LOAD[0].p_offset != 0

https://github.com/upx/upx/issues/80
	modified:   p_lx_elf.cpp
This commit is contained in:
John Reiser
2017-03-31 12:20:02 -07:00
parent 0e511c3e07
commit 12e5703541
+67 -66
View File
@@ -1515,18 +1515,17 @@ bool PackLinuxElf32::canPack()
} }
unsigned const p_type = get_te32(&phdr->p_type); unsigned const p_type = get_te32(&phdr->p_type);
unsigned const p_offset = get_te32(&phdr->p_offset); unsigned const p_offset = get_te32(&phdr->p_offset);
if (1!=exetype && phdr->PT_LOAD32 == p_type) { if (1!=exetype && phdr->PT_LOAD32 == p_type) { // 1st PT_LOAD
exetype = 1; exetype = 1;
load_va = get_te32(&phdr->p_vaddr); load_va = get_te32(&phdr->p_vaddr); // class data member
unsigned file_offset = get_te32(&phdr->p_offset); unsigned const off = ~page_mask & load_va;
if (~(upx_uint64_t)page_mask & file_offset) { if (off && off == p_offset) { // specific hint
if ((~page_mask & (unsigned)load_va) == file_offset) { throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'");
throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'"); // Fixing it inside upx fails because packExtent() reads original file.
// Fixing it inside upx fails because packExtent() reads original file. return false;
} }
else { if (0 != p_offset) { // 1st PT_LOAD must cover Ehdr and Phdr
throwCantPack("invalid Phdr p_offset; try '--force-execve'"); throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
}
return false; return false;
} }
} }
@@ -1537,25 +1536,24 @@ bool PackLinuxElf32::canPack()
throwCantPack("PT_NOTEs too big; try '--force-execve'"); throwCantPack("PT_NOTEs too big; try '--force-execve'");
return false; return false;
} }
} if (osabi_note && Elf32_Ehdr::ELFOSABI_NONE==osabi0) { // Still seems to be generic.
if (Elf32_Ehdr::ELFOSABI_NONE==osabi0 // Still seems to be generic. struct {
&& NULL!=osabi_note && phdr->PT_NOTE == p_type) { struct Elf32_Nhdr nhdr;
struct { char name[8];
struct Elf32_Nhdr nhdr; unsigned body;
char name[8]; } note;
unsigned body; memset(&note, 0, sizeof(note));
} note; fi->seek(p_offset, SEEK_SET);
memset(&note, 0, sizeof(note)); fi->readx(&note, sizeof(note));
fi->seek(p_offset, SEEK_SET); fi->seek(0, SEEK_SET);
fi->readx(&note, sizeof(note)); if (4==get_te32(&note.nhdr.descsz)
fi->seek(0, SEEK_SET); && 1==get_te32(&note.nhdr.type)
if (4==get_te32(&note.nhdr.descsz) // && 0==note.end
&& 1==get_te32(&note.nhdr.type) && (1+ strlen(osabi_note))==get_te32(&note.nhdr.namesz)
// && 0==note.end && 0==strcmp(osabi_note, (char const *)&note.name[0])
&& (1+ strlen(osabi_note))==get_te32(&note.nhdr.namesz) ) {
&& 0==strcmp(osabi_note, (char const *)&note.name[0]) osabi0 = ei_osabi; // Specified by PT_NOTE.
) { }
osabi0 = ei_osabi; // Specified by PT_NOTE.
} }
} }
} }
@@ -1723,20 +1721,21 @@ PackLinuxElf64ppcle::canPack()
for (unsigned j=0; j < e_phnum; ++phdr, ++j) { for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
if (j >= 14) if (j >= 14)
return false; return false;
if (phdr->PT_LOAD64 == get_te32(&phdr->p_type)) { unsigned const p_type = get_te32(&phdr->p_type);
load_va = get_te64(&phdr->p_vaddr); if (1!=exetype && phdr->PT_LOAD64 == p_type) { // 1st PT_LOAD
upx_uint64_t file_offset = get_te64(&phdr->p_offset); exetype = 1;
if (~page_mask & file_offset) { load_va = get_te64(&phdr->p_vaddr); // class data member
if ((~page_mask & load_va) == file_offset) { upx_uint64_t const p_offset = get_te64(&phdr->p_offset);
throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'"); upx_uint64_t const off = ~page_mask & load_va;
// Fixing it inside upx fails because packExtent() reads original file. if (off && off == p_offset) { // specific hint
} throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'");
else { // Fixing it inside upx fails because packExtent() reads original file.
throwCantPack("invalid Phdr p_offset; try '--force-execve'"); return false;
} }
if (0 != p_offset) { // 1st PT_LOAD must cover Ehdr and Phdr
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
return false; return false;
} }
exetype = 1;
break; break;
} }
} }
@@ -1916,20 +1915,21 @@ PackLinuxElf64amd::canPack()
for (unsigned j=0; j < e_phnum; ++phdr, ++j) { for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
if (j >= 14) if (j >= 14)
return false; return false;
if (phdr->PT_LOAD64 == get_te32(&phdr->p_type)) { unsigned const p_type = get_te32(&phdr->p_type);
load_va = get_te64(&phdr->p_vaddr); if (1!=exetype && phdr->PT_LOAD64 == p_type) { // 1st PT_LOAD
upx_uint64_t file_offset = get_te64(&phdr->p_offset); exetype = 1;
if (~page_mask & file_offset) { load_va = get_te64(&phdr->p_vaddr); // class data member
if ((~page_mask & load_va) == file_offset) { upx_uint64_t const p_offset = get_te64(&phdr->p_offset);
throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'"); upx_uint64_t const off = ~page_mask & load_va;
// Fixing it inside upx fails because packExtent() reads original file. if (off && off == p_offset) { // specific hint
} throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'");
else { // Fixing it inside upx fails because packExtent() reads original file.
throwCantPack("invalid Phdr p_offset; try '--force-execve'"); return false;
} }
if (0 != p_offset) { // 1st PT_LOAD must cover Ehdr and Phdr
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
return false; return false;
} }
exetype = 1;
break; break;
} }
} }
@@ -2110,20 +2110,21 @@ PackLinuxElf64arm::canPack()
for (unsigned j=0; j < e_phnum; ++phdr, ++j) { for (unsigned j=0; j < e_phnum; ++phdr, ++j) {
if (j >= 14) if (j >= 14)
return false; return false;
if (phdr->PT_LOAD64 == get_te32(&phdr->p_type)) { unsigned const p_type = get_te32(&phdr->p_type);
load_va = get_te64(&phdr->p_vaddr); if (1!=exetype && phdr->PT_LOAD64 == p_type) { // 1st PT_LOAD
upx_uint64_t file_offset = get_te64(&phdr->p_offset); exetype = 1;
if (~page_mask & file_offset) { load_va = get_te64(&phdr->p_vaddr); // class data member
if ((~page_mask & load_va) == file_offset) { upx_uint64_t const p_offset = get_te64(&phdr->p_offset);
throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'"); upx_uint64_t const off = ~page_mask & load_va;
// Fixing it inside upx fails because packExtent() reads original file. if (off && off == p_offset) { // specific hint
} throwCantPack("Go-language PT_LOAD: try hemfix.c, or try '--force-execve'");
else { // Fixing it inside upx fails because packExtent() reads original file.
throwCantPack("invalid Phdr p_offset; try '--force-execve'"); return false;
} }
if (0 != p_offset) { // 1st PT_LOAD must cover Ehdr and Phdr
throwCantPack("first PT_LOAD.p_offset != 0; try '--force-execve'");
return false; return false;
} }
exetype = 1;
break; break;
} }
} }