make_hatch() has uniform calling sequence
... so factor out the calls to make_hatch modified: src/i386-linux.elf-so_main.c
This commit is contained in:
parent
a9dc43f7fb
commit
60bdffee84
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
extern void my_bkpt(void const *arg1, ...);
|
extern void my_bkpt(void const *arg1, ...);
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 1
|
||||||
|
|
||||||
// Pprotect is mprotect, but page-aligned on the lo end (Linux requirement)
|
// Pprotect is mprotect, but page-aligned on the lo end (Linux requirement)
|
||||||
unsigned Pprotect(void *, size_t, unsigned);
|
unsigned Pprotect(void *, size_t, unsigned);
|
||||||
@ -275,7 +275,7 @@ extern unsigned long upx_mmap_and_fd( // x86_64 Android emulator of i386 is not
|
|||||||
// Create (or find) an escape hatch to use when munmapping ourselves the stub.
|
// Create (or find) an escape hatch to use when munmapping ourselves the stub.
|
||||||
// Called by do_xmap to create it; remembered in AT_NULL.d_val
|
// Called by do_xmap to create it; remembered in AT_NULL.d_val
|
||||||
static char *
|
static char *
|
||||||
make_hatch_i386(
|
make_hatch(
|
||||||
Elf32_Phdr const *const phdr,
|
Elf32_Phdr const *const phdr,
|
||||||
char *next_unc,
|
char *next_unc,
|
||||||
unsigned frag_mask
|
unsigned frag_mask
|
||||||
@ -307,7 +307,7 @@ extern int upxfd_create(void); // early 32-bit Android lacks memfd_create
|
|||||||
#define SEEK_SET 0
|
#define SEEK_SET 0
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
make_hatch_arm32(
|
make_hatch(
|
||||||
Elf32_Phdr const *const phdr,
|
Elf32_Phdr const *const phdr,
|
||||||
char *next_unc,
|
char *next_unc,
|
||||||
unsigned frag_mask
|
unsigned frag_mask
|
||||||
@ -343,7 +343,7 @@ make_hatch_arm32(
|
|||||||
}
|
}
|
||||||
#elif defined(__mips__) /*}{*/
|
#elif defined(__mips__) /*}{*/
|
||||||
static void *
|
static void *
|
||||||
make_hatch_mips(
|
make_hatch(
|
||||||
Elf32_Phdr const *const phdr,
|
Elf32_Phdr const *const phdr,
|
||||||
ptrdiff_t reloc,
|
ptrdiff_t reloc,
|
||||||
unsigned const frag_mask)
|
unsigned const frag_mask)
|
||||||
@ -378,7 +378,7 @@ make_hatch_mips(
|
|||||||
}
|
}
|
||||||
#elif defined(__powerpc__) /*}{*/
|
#elif defined(__powerpc__) /*}{*/
|
||||||
static void *
|
static void *
|
||||||
make_hatch_ppc32(
|
make_hatch(
|
||||||
Elf32_Phdr const *const phdr,
|
Elf32_Phdr const *const phdr,
|
||||||
ptrdiff_t reloc,
|
ptrdiff_t reloc,
|
||||||
unsigned const frag_mask)
|
unsigned const frag_mask)
|
||||||
@ -538,6 +538,7 @@ upx_so_main( // returns &escape_hatch
|
|||||||
struct b_info al_bi; // for aligned data from binfo
|
struct b_info al_bi; // for aligned data from binfo
|
||||||
void *hatch = nullptr;
|
void *hatch = nullptr;
|
||||||
Elf32_Addr base = 0;
|
Elf32_Addr base = 0;
|
||||||
|
int n_load = 0;
|
||||||
|
|
||||||
for (; phdr < phdrN; ++phdr)
|
for (; phdr < phdrN; ++phdr)
|
||||||
if ( phdr->p_type == PT_LOAD && !(phdr->p_flags & PF_W)) {
|
if ( phdr->p_type == PT_LOAD && !(phdr->p_flags & PF_W)) {
|
||||||
@ -548,8 +549,29 @@ upx_so_main( // returns &escape_hatch
|
|||||||
DPRINTF("base=%%p\\n", base);
|
DPRINTF("base=%%p\\n", base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mfd = 0;
|
||||||
|
char *mfd_addr = 0;
|
||||||
if ((phdr->p_filesz + phdr->p_offset) <= so_infc.off_xct_off) {
|
if ((phdr->p_filesz + phdr->p_offset) <= so_infc.off_xct_off) {
|
||||||
continue; // below compressed region
|
// Below compressed region, but might be the only PF_X segment
|
||||||
|
my_bkpt((void *)0x1244, phdr);
|
||||||
|
if (!hatch && phdr->p_flags & PF_X) {
|
||||||
|
my_bkpt((void *)0x1245, phdr);
|
||||||
|
char *haddr = base + (char *)(phdr->p_filesz + phdr->p_offset);
|
||||||
|
unsigned frag_mask = ~page_mask;
|
||||||
|
unsigned frag = frag_mask & (unsigned)haddr;
|
||||||
|
unsigned long val = upx_mmap_and_fd(haddr - frag, frag, nullptr);
|
||||||
|
mfd = 0xfff & val;
|
||||||
|
val -= mfd; if ((char *)val != (haddr - frag)) my_bkpt((void *)0x1243, val);
|
||||||
|
--mfd;
|
||||||
|
|
||||||
|
Pwrite(mfd, haddr - frag, frag); // original contents
|
||||||
|
mfd_addr = Pmap(haddr - frag, frag, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, mfd, 0);
|
||||||
|
DPRINTF("mfd_addr= %%p\\n", mfd_addr);
|
||||||
|
hatch = make_hatch(phdr, haddr, frag_mask);
|
||||||
|
Punmap(haddr - frag, -page_mask);
|
||||||
|
Pmap(haddr - frag, -page_mask, PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
|
||||||
|
close(mfd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Elf32_Addr const pfx = (so_infc.off_xct_off < phdr->p_offset)
|
Elf32_Addr const pfx = (so_infc.off_xct_off < phdr->p_offset)
|
||||||
? 0 // entire PT_LOAD is compressed
|
? 0 // entire PT_LOAD is compressed
|
||||||
@ -557,21 +579,28 @@ upx_so_main( // returns &escape_hatch
|
|||||||
x0.size = sizeof(struct b_info);
|
x0.size = sizeof(struct b_info);
|
||||||
xread(&x0, (char *)&al_bi, x0.size); // aligned binfo
|
xread(&x0, (char *)&al_bi, x0.size); // aligned binfo
|
||||||
x0.buf -= sizeof(al_bi); // back up (the xread() was a peek)
|
x0.buf -= sizeof(al_bi); // back up (the xread() was a peek)
|
||||||
|
my_bkpt((void *)0x1248, &x0);
|
||||||
DPRINTF("next1 pfx=%%x binfo@%%p (%%p %%p %%p)\\n", pfx, x0.buf,
|
DPRINTF("next1 pfx=%%x binfo@%%p (%%p %%p %%p)\\n", pfx, x0.buf,
|
||||||
al_bi.sz_unc, al_bi.sz_cpr, *(unsigned *)(void *)&al_bi.b_method);
|
al_bi.sz_unc, al_bi.sz_cpr, *(unsigned *)(void *)&al_bi.b_method);
|
||||||
|
my_bkpt((void *)0x1246, phdr);
|
||||||
|
|
||||||
// Using .p_memsz implicitly handles .bss via MAP_ANONYMOUS.
|
// Using .p_memsz implicitly handles .bss via MAP_ANONYMOUS.
|
||||||
// Omit any non-tcompressed prefix (below xct_off)
|
// Omit any non-tcompressed prefix (below xct_off)
|
||||||
x1.buf = (char *)(pfx + phdr->p_vaddr + base);
|
x1.buf = (char *)(pfx + phdr->p_vaddr + base);
|
||||||
x1.size = phdr->p_memsz - pfx;
|
x1.size = phdr->p_memsz;
|
||||||
|
if (phdr->p_memsz > pfx) {
|
||||||
|
x1.size -= pfx;
|
||||||
|
}
|
||||||
|
else if (!n_load) {
|
||||||
|
++n_load; // 0 --> 1
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned const frag = (phdr->p_vaddr + pfx) & ~page_mask; // lo fragment on page
|
unsigned const frag = (phdr->p_vaddr + pfx) & ~page_mask; // lo fragment on page
|
||||||
x1.buf -= frag;
|
x1.buf -= frag;
|
||||||
x1.size += frag;
|
x1.size += frag;
|
||||||
DPRINTF("phdr(%%p %%p) xct_off=%%x frag=%%x\\n", x1.buf, x1.size, xct_off, frag);
|
DPRINTF("phdr(%%p %%p) xct_off=%%x frag=%%x\\n", x1.buf, x1.size, xct_off, frag);
|
||||||
|
|
||||||
int mfd = 0;
|
|
||||||
char *mfd_addr = 0;
|
|
||||||
if (phdr->p_flags & PF_X) { // SELinux
|
if (phdr->p_flags & PF_X) { // SELinux
|
||||||
// Cannot set PROT_EXEC except via mmap() into a region (Linux "vma")
|
// Cannot set PROT_EXEC except via mmap() into a region (Linux "vma")
|
||||||
// that has never had PROT_WRITE. So use a Linux-only "memory file"
|
// that has never had PROT_WRITE. So use a Linux-only "memory file"
|
||||||
@ -599,14 +628,7 @@ upx_so_main( // returns &escape_hatch
|
|||||||
DPRINTF(" after unpack x0=(%%p %%p x1=(%%p %%p)\\n", x0.size, x0.buf, x1.size, x1.buf);
|
DPRINTF(" after unpack x0=(%%p %%p x1=(%%p %%p)\\n", x0.size, x0.buf, x1.size, x1.buf);
|
||||||
|
|
||||||
if (!hatch && phdr->p_flags & PF_X) {
|
if (!hatch && phdr->p_flags & PF_X) {
|
||||||
#if defined(__i386__) //{
|
hatch = make_hatch(phdr, x1.buf, ~page_mask);
|
||||||
hatch = make_hatch_i386(phdr, x1.buf, ~page_mask);
|
|
||||||
#elif defined(__arm__) //}{
|
|
||||||
hatch = make_hatch_arm32(phdr, x1.buf, ~page_mask);
|
|
||||||
|
|
||||||
#elif defined(__powerpc32__) //}{
|
|
||||||
hatch = make_hatch_ppc32(phdr, x1.buf, ~page_mask);
|
|
||||||
#endif //}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phdr->p_flags & PF_X) { // SELinux
|
if (phdr->p_flags & PF_X) { // SELinux
|
||||||
@ -620,6 +642,7 @@ upx_so_main( // returns &escape_hatch
|
|||||||
else { // easy
|
else { // easy
|
||||||
Pprotect( (char *)(phdr->p_vaddr + base), phdr->p_memsz, PF_to_PROT(phdr));
|
Pprotect( (char *)(phdr->p_vaddr + base), phdr->p_memsz, PF_to_PROT(phdr));
|
||||||
}
|
}
|
||||||
|
++n_load;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF("Punmap sideaddr=%%p cpr_len=%%p\\n", sideaddr, cpr_len);
|
DPRINTF("Punmap sideaddr=%%p cpr_len=%%p\\n", sideaddr, cpr_len);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user