Fix stubs for shlib with only 2 PT_LOAD

This commit is contained in:
John Reiser 2023-07-22 11:46:44 -07:00 committed by Markus F.X.J. Oberhumer
parent 670aae2e11
commit 05539ad5b6
12 changed files with 6475 additions and 6387 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -115,10 +115,11 @@ __NR_readlink= 89
O_BINFO: .globl O_BINFO # ignored dummy needed by elf-entry.o
Pmap: .globl Pmap
mov %arg1,%rax; and $0xfff,%eax
sub %rax,%arg1 # page align lo end
add %rax,%arg2
mmap: .globl mmap
mov %arg1,%r10; and $0xfff,%r10
sub %r10,%arg1 # page align lo end
add %r10,%arg2
push $ __NR_mmap
sys_4args:
movq %arg4,%sys4
@ -148,6 +149,12 @@ sysgo: # NOTE: kernel demands 4th arg in %sys4, NOT %arg4
syscall; cmp $-4096,%rax; jb 0f; int3; 0:
ret
Punmap: .globl Punmap // page-align the lo end
mov %arg1,%rax; and $0xfff,%eax
sub %rax,%arg1
add %rax,%arg2
munmap: .globl munmap
push $__NR_munmap; 5: jmp sysgo
exit: .globl exit
push $ __NR_exit; 5: jmp 5f
ftruncate: .globl ftruncate
@ -162,15 +169,13 @@ write: .globl write
push $__NR_write; 5: jmp 5f
read: .globl read
push $ __NR_read; 5: jmp 5f
munmap: .globl munmap
push $__NR_munmap; 5: jmp sysgo
// Sometimes Linux enforces page-aligned address for mprotect
Pprotect: .globl Pprotect
mprotect: .globl mprotect
mov %rdi,%rax; and $-1+ (1<<12),%rax
sub %rax,%rdi
add %rax,%rsi
mprotect: .globl mprotect
push $ __NR_mprotect; 5: jmp sysgo
// section SO_MAIN inserted here

View File

@ -34,6 +34,8 @@
// Pprotect is mprotect, but page-aligned on the lo end (Linux requirement)
unsigned Pprotect(void *, size_t, unsigned);
void *Pmap(void *, size_t, unsigned, unsigned, int, size_t);
int Punmap(void *, size_t);
extern void f_int3(int arg);
@ -435,7 +437,7 @@ typedef struct {
typedef struct {
unsigned off_reloc; // distance back to &Elf64_Ehdr
unsigned off_user_DT_INIT;
unsigned off_xct_off; // where un-compressed bytes end [unused?]
unsigned off_xct_off; // where un-compressed bytes end
unsigned off_info; // xct_off: {l_info; p_info; b_info; compressed data)
} So_info;
@ -527,10 +529,9 @@ upx_so_main( // returns &escape_hatch
if ((phdr->p_filesz + phdr->p_offset) <= so_infc.off_xct_off) {
continue; // below compressed region
}
Elf64_Addr pfx = so_infc.off_xct_off - phdr->p_offset;
if ( so_infc.off_xct_off < phdr->p_offset) {
pfx = 0; // no more partially-compressed PT_LOAD
}
Elf64_Addr const pfx = (so_infc.off_xct_off < phdr->p_offset)
? 0 // entire PT_LOAD is compressed
: so_infc.off_xct_off - phdr->p_offset ; // below xct_off is not
x0.size = sizeof(struct b_info);
xread(&x0, (char *)&al_bi, x0.size); // aligned binfo
x0.buf -= sizeof(al_bi); // back up (the xread() was a peek)
@ -539,13 +540,13 @@ upx_so_main( // returns &escape_hatch
// Using .p_memsz implicitly handles .bss via MAP_ANONYMOUS.
// Omit any non-tcompressed prefix (below xct_off)
x1.buf = (char *)(phdr->p_vaddr + pfx + base);
x1.buf = (char *)(pfx + phdr->p_vaddr + base);
x1.size = phdr->p_memsz - pfx;
pfx = (phdr->p_vaddr + pfx) & ~PAGE_MASK; // lo fragment on page
x1.buf -= pfx;
x1.size += pfx;
DPRINTF("phdr(%%p %%p) xct_off=%%x pfx=%%x\\n", x1.buf, x1.size, xct_off, pfx);
unsigned const frag = (phdr->p_vaddr + pfx) & ~PAGE_MASK; // lo fragment on page
x1.buf -= frag;
x1.size += 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;
@ -555,7 +556,7 @@ upx_so_main( // returns &escape_hatch
// to hold the contents.
mfd = memfd_create(addr_string("upx"), 0); // the directory entry
ftruncate(mfd, x1.size); // Allocate the pages in the file.
write(mfd, x1.buf, pfx); // Save lo fragment of contents on first page.
write(mfd, x1.buf, frag); // Save lo fragment of contents on first page.
mfd_addr = mmap(0, x1.size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0);
DPRINTF("mfd_addr= %%p\\n", mfd_addr); // Now "somewhere" in RAM,
// and ready to receive de-compressed bytes, and remember them in the
@ -563,14 +564,14 @@ upx_so_main( // returns &escape_hatch
// Must keep the original compressed data until now, in order to
// prevent the mmap(0, ...) from stealing that address range.
munmap(x1.buf, x1.size); // Discard original page frames in RAM.
x1.buf = mfd_addr; // will add pfx soon
Punmap(x1.buf, x1.size); // Discard original page frames in RAM.
x1.buf = mfd_addr; // will add frag soon
}
else {
underlay(x1.size, x1.buf, pfx); // also makes PROT_WRITE
underlay(x1.size, x1.buf, frag); // also makes PROT_WRITE
}
x1.buf += pfx;
x1.buf += frag;
x1.size = al_bi.sz_unc;
x0.size = al_bi.sz_cpr + sizeof(struct b_info);
DPRINTF("befor unpack x0=(%%p %%p x1=(%%p %%p)\\n", x0.size, x0.buf, x1.size, x1.buf);
@ -590,8 +591,8 @@ upx_so_main( // returns &escape_hatch
if (phdr->p_flags & PF_X) { // SELinux
// Map the contents of mfd as per *phdr.
DPRINTF("mfd mmap addr=%%p len=%%p\\n", (phdr->p_vaddr + base + pfx), al_bi.sz_unc);
munmap(mfd_addr, pfx + al_bi.sz_unc); // Discard RW mapping; mfd has the bytes
mmap((char *)(phdr->p_vaddr + base + pfx), al_bi.sz_unc, PF_to_PROT(phdr),
munmap(mfd_addr, frag + al_bi.sz_unc); // Discard RW mapping; mfd has the bytes
Pmap((char *)(phdr->p_vaddr + base + pfx), al_bi.sz_unc, PF_to_PROT(phdr),
MAP_FIXED|MAP_PRIVATE, mfd, 0);
close(mfd);
}

View File

@ -182,10 +182,6 @@ brk:
readlink:
do_sys __NR_readlink; ret
.globl munmap
munmap:
do_sys __NR_munmap; ret
ftruncate: .globl ftruncate
do_sys __NR_ftruncate; ret
@ -194,15 +190,19 @@ memfd_create: .globl memfd_create
// Sometimes Linux enforces page-aligned address
Pprotect: .globl Pprotect
mprotect: .globl mprotect
ldr r12,m_off4k
and r12,r12,r0
sub r0,r0,r12
add r1,r1,r12
mprotect: .globl mprotect
do_sys __NR_mprotect; ret
.globl mmap
mmap:
Pmap: .globl Pmap
ldr r12,m_off4k
and r12,r12,r0
sub r0,r0,r12
add r1,r1,r12
mmap: .globl mmap
stmdb sp!,{r4,r5,lr}
ldr r5,[sp,#4*4]
ldr r4,[sp,#3*4]
@ -215,6 +215,14 @@ mmap_do:
do_sys __NR_mmap2
ldmia sp!,{r4,r5,pc}
Punmap: .globl Punmap
ldr r12,m_off4k
and r12,r12,r0
sub r0,r0,r12
add r1,r1,r12
munmap: .globl munmap
do_sys __NR_munmap; ret
m_off4k:
.word -1+ (1<<PAGE_SHIFT) // offset mask for 4KiB

View File

@ -146,8 +146,11 @@ brk:
readlink:
do_sys __NR_readlink; ret
.globl munmap
munmap:
Punmap: .globl Punmap
and x8,x0,#-1+ (1<<12) // FIXME: variable PAGE_MASK
sub x0,x0,x8
add x1,x1,x8
munmap: .globl munmap
do_sys __NR_munmap; ret
// Sometimes Linux enforces page-aligned address
@ -170,11 +173,11 @@ mmap_privanon: .globl mmap_privanon
mov x5,#0 // offset= 0
// FALL THROUGH to mmap
.globl mmap
mmap:
Pmap: .globl Pmap
and x8,x0,#-1+ (1<<12) // FIXME: variable PAGE_MASK
sub x0,x0,x8
add x1,x1,x8
mmap: .globl mmap
do_sys __NR_mmap; ret
get_sys_munmap: .globl get_sys_munmap // r0= system call instruction

View File

@ -121,6 +121,7 @@ __NR_exit= 1
__NR_readlink= 85
Pmap: .globl Pmap
mmap: .globl mmap // oldmmap: %ebx -> 6 word parameters
push %ebx // save C-lang register
lea 2*NBPW(%esp),%ebx
@ -156,7 +157,7 @@ mmap: .globl mmap // oldmmap: %ebx -> 6 word parameters
#endif //}
// Sometimes linux enforces page-aligned address
Pprotect: .globl Pprotect
Pprotect: .globl Pprotect // from C
xchg %ebx,1*NBPW(%esp) // save reg, %ebx= address
mov %ebx,%ecx // copy address
and $~0<<12,%ebx // page align
@ -168,6 +169,19 @@ Pprotect: .globl Pprotect
mov 1*NBPW(%esp),%ebx // restore reg
ret
Punmap: .globl Punmap // from C
push %ebp; mov %esp,%ebp
push %ebx
mov (0+2)*NBPW(%ebp),%ebx // addr
mov %ebx,%eax; and $-1+ (1<<12),%eax
sub %eax,%ebx
mov (1+2)*NBPW(%ebp),%ecx // len
add %eax,%ecx
push $__NR_munmap; pop %eax; int $0x80
cmp $-0x1000,%eax; jna 0f; hlt; 0:
pop %ebx; pop %ebp
ret
memfd_create: .globl memfd_create
int3
push $__NR_memfd_create; 5: jmp 5f

View File

@ -39,6 +39,9 @@ extern void my_bkpt(void const *arg1, ...);
// Pprotect is mprotect, but page-aligned on the lo end (Linux requirement)
unsigned Pprotect(void *, size_t, unsigned);
void *mmap(void *, size_t, int, int, int, off_t);
void *Pmap(void *, size_t, int, int, int, off_t);
int Punmap(void *, size_t);
#if defined(__i386__) || defined(__mips__) || defined(__powerpc__) //{
# define mmap_privanon(addr,len,prot,flgs) mmap((addr),(len),(prot), \
MAP_PRIVATE|MAP_ANONYMOUS|(flgs),-1,0)
@ -581,10 +584,9 @@ upx_so_main( // returns &escape_hatch
if ((phdr->p_filesz + phdr->p_offset) <= so_infc.off_xct_off) {
continue; // below compressed region
}
Elf32_Addr pfx = so_infc.off_xct_off - phdr->p_offset;
if ( so_infc.off_xct_off < phdr->p_offset) {
pfx = 0; // no more partially-compressed PT_LOAD
}
Elf32_Addr const pfx = (so_infc.off_xct_off < phdr->p_offset)
? 0 // entire PT_LOAD is compressed
: so_infc.off_xct_off - phdr->p_offset ; // below xct_off is not
x0.size = sizeof(struct b_info);
xread(&x0, (char *)&al_bi, x0.size); // aligned binfo
x0.buf -= sizeof(al_bi); // back up (the xread() was a peek)
@ -596,10 +598,10 @@ upx_so_main( // returns &escape_hatch
x1.buf = (char *)(phdr->p_vaddr + pfx + base);
x1.size = phdr->p_memsz - pfx;
pfx = (phdr->p_vaddr + pfx) & ~page_mask; // lo fragment on page
x1.buf -= pfx;
x1.size += pfx;
DPRINTF("phdr(%%p %%p) xct_off=%%x pfx=%%x\\n", x1.buf, x1.size, xct_off, pfx);
unsigned const frag = (phdr->p_vaddr + pfx) & ~page_mask; // lo fragment on page
x1.buf -= frag;
x1.size += 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;
@ -609,7 +611,7 @@ upx_so_main( // returns &escape_hatch
// to hold the contents.
mfd = memfd_create(addr_string("upx"), 0); // the directory entry
ftruncate(mfd, x1.size); // Allocate the pages in the file.
write(mfd, x1.buf, pfx); // Save lo fragment of contents on first page.
write(mfd, x1.buf, frag); // Save lo fragment of contents on first page.
mfd_addr = mmap(0, x1.size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0);
DPRINTF("mfd_addr= %%p\\n", mfd_addr); // Now "somewhere" in RAM,
// and ready to receive de-compressed bytes, and remember them in the
@ -619,13 +621,12 @@ upx_so_main( // returns &escape_hatch
// prevent the mmap(0, ...) from stealing that address range.
munmap(x1.buf, x1.size); // Discard original page frames in RAM.
x1.buf = mfd_addr; // will add pfx soon
DPRINTF("mfd_addr= %%p\\n", mfd_addr);
}
else {
underlay(x1.size, x1.buf, pfx, phdr->p_flags); // also makes PROT_WRITE
underlay(x1.size, x1.buf, frag, phdr->p_flags); // also makes PROT_WRITE
}
x1.buf += pfx;
x1.buf += frag;
x1.size = al_bi.sz_unc;
x0.size = al_bi.sz_cpr + sizeof(struct b_info);
DPRINTF("befor unpack x0=(%%p %%p x1=(%%p %%p)\\n", x0.size, x0.buf, x1.size, x1.buf);
@ -647,7 +648,7 @@ upx_so_main( // returns &escape_hatch
// Map the contents of mfd as per *phdr.
DPRINTF("mfd mmap addr=%%p len=%%p\\n", (phdr->p_vaddr + base + pfx), al_bi.sz_unc);
munmap(mfd_addr, pfx + al_bi.sz_unc); // Discard RW mapping; mfd has the bytes
mmap((char *)(phdr->p_vaddr + base + pfx), al_bi.sz_unc, PF_to_PROT(phdr),
Pmap((char *)(phdr->p_vaddr + base + pfx), al_bi.sz_unc, PF_to_PROT(phdr),
MAP_FIXED|MAP_PRIVATE, mfd, 0);
close(mfd);
}

View File

@ -2,19 +2,19 @@ file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn Flags
0 SO_MAIN 01229 0 0 040 2**4 CONTENTS
1 EXP_HEAD 0e0 0 0 01269 2**0 CONTENTS
2 NRV2E 0e5 0 0 01349 2**0 CONTENTS
3 NRV2D 0d7 0 0 0142e 2**0 CONTENTS
4 NRV2B 0c1 0 0 01505 2**0 CONTENTS
5 SO_HEAD 02c 0 0 015c6 2**0 CONTENTS
6 ptr_NEXT 0 0 0 015f2 2**0 CONTENTS
7 SO_TAIL 08c 0 0 015f2 2**0 CONTENTS
8 LZMA_ELF00 064 0 0 0167e 2**0 CONTENTS
9 LZMA_DEC10 09f7 0 0 016e2 2**0 CONTENTS
10 LZMA_DEC20 09f7 0 0 020d9 2**0 CONTENTS
11 LZMA_DEC30 018 0 0 02ad0 2**0 CONTENTS
12 EXP_TAIL 0c 0 0 02ae8 2**0 CONTENTS
0 SO_MAIN 01259 0 0 040 2**4 CONTENTS
1 EXP_HEAD 0e0 0 0 01299 2**0 CONTENTS
2 NRV2E 0e5 0 0 01379 2**0 CONTENTS
3 NRV2D 0d7 0 0 0145e 2**0 CONTENTS
4 NRV2B 0c1 0 0 01535 2**0 CONTENTS
5 SO_HEAD 02c 0 0 015f6 2**0 CONTENTS
6 ptr_NEXT 0 0 0 01622 2**0 CONTENTS
7 SO_TAIL 098 0 0 01622 2**0 CONTENTS
8 LZMA_ELF00 064 0 0 016ba 2**0 CONTENTS
9 LZMA_DEC10 09f7 0 0 0171e 2**0 CONTENTS
10 LZMA_DEC20 09f7 0 0 02115 2**0 CONTENTS
11 LZMA_DEC30 018 0 0 02b0c 2**0 CONTENTS
12 EXP_TAIL 0c 0 0 02b24 2**0 CONTENTS
SYMBOL TABLE:
0000000000000000 l d EXP_HEAD 0 EXP_HEAD
0000000000000000 l d LZMA_DEC30 0 LZMA_DEC30
@ -29,26 +29,28 @@ SYMBOL TABLE:
0000000000000000 l d LZMA_ELF00 0 LZMA_ELF00
0000000000000000 l d LZMA_DEC10 0 LZMA_DEC10
0000000000000000 l d LZMA_DEC20 0 LZMA_DEC20
0000000000000031 g SO_TAIL 0 Pmap
0000000000000000 g EXP_HEAD 0 f_expand
0000000000000075 g SO_TAIL 0 munmap
000000000000005f g SO_TAIL 0 munmap
000000000000001c g SO_TAIL 0 memcpy
0000000000000000 g F SO_MAIN 030 dprint8
0000000000000031 g SO_TAIL 0 O_BINFO
0000000000000057 g SO_TAIL 0 ftruncate
0000000000000031 g SO_TAIL 0 mmap
0000000000000067 g SO_TAIL 0 ftruncate
000000000000003f g SO_TAIL 0 mmap
0000000000000000 g F SO_TAIL 0 eof
000000000000006d g SO_TAIL 0 write
000000000000007d g SO_TAIL 0 write
0000000000000680 g F SO_MAIN 01d PF_to_PROT
000000000000005b g SO_TAIL 0 memfd_create
0000000000000071 g SO_TAIL 0 read
000000000000006b g SO_TAIL 0 memfd_create
0000000000000081 g SO_TAIL 0 read
0000000000000013 g SO_TAIL 0 memset
0000000000000011 g SO_TAIL 0 my_bkpt
0000000000000079 g SO_TAIL 0 Pprotect
0000000000000053 g SO_TAIL 0 exit
0000000000000066 g SO_TAIL 0 openat
0000000000000079 g SO_TAIL 0 mprotect
0000000000000062 g SO_TAIL 0 close
000000000000069d g F SO_MAIN 07c8 upx_so_main
0000000000000085 g SO_TAIL 0 Pprotect
0000000000000051 g SO_TAIL 0 Punmap
0000000000000063 g SO_TAIL 0 exit
0000000000000076 g SO_TAIL 0 openat
0000000000000094 g SO_TAIL 0 mprotect
0000000000000072 g SO_TAIL 0 close
000000000000069d g F SO_MAIN 0800 upx_so_main
RELOCATION RECORDS FOR [SO_MAIN]:
OFFSET TYPE VALUE
@ -68,31 +70,31 @@ OFFSET TYPE VALUE
0000000000000654 R_X86_64_PLT32 memcpy+0xfffffffffffffffc
000000000000079c R_X86_64_PLT32 mmap+0xfffffffffffffffc
00000000000007d1 R_X86_64_PLT32 memcpy+0xfffffffffffffffc
00000000000008f3 R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
000000000000090c R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000000920 R_X86_64_PLT32 write+0xfffffffffffffffc
000000000000092f R_X86_64_PLT32 munmap+0xfffffffffffffffc
0000000000000937 R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
0000000000000952 R_X86_64_PLT32 mmap+0xfffffffffffffffc
0000000000000959 R_X86_64_PLT32 close+0xfffffffffffffffc
0000000000000bde R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
0000000000000bf0 R_X86_64_PLT32 ftruncate+0xfffffffffffffffc
0000000000000c03 R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000000c28 R_X86_64_PLT32 mmap+0xfffffffffffffffc
0000000000000c61 R_X86_64_PLT32 munmap+0xfffffffffffffffc
0000000000000d72 R_X86_64_PLT32 munmap+0xfffffffffffffffc
0000000000000d7a R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
0000000000000da0 R_X86_64_PLT32 mmap+0xfffffffffffffffc
0000000000000da8 R_X86_64_PLT32 close+0xfffffffffffffffc
0000000000000db2 R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
0000000000000dc8 R_X86_64_PLT32 Pprotect+0xfffffffffffffffc
0000000000000de3 R_X86_64_PLT32 munmap+0xfffffffffffffffc
0000000000001043 R_X86_64_PLT32 write+0xfffffffffffffffc
00000000000010aa R_X86_64_PLT32 write+0xfffffffffffffffc
00000000000010fc R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000001150 R_X86_64_PLT32 write+0xfffffffffffffffc
00000000000011ac R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000001208 R_X86_64_PLT32 write+0xfffffffffffffffc
00000000000008f9 R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
0000000000000912 R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000000926 R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000000935 R_X86_64_PLT32 munmap+0xfffffffffffffffc
000000000000093d R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
0000000000000958 R_X86_64_PLT32 mmap+0xfffffffffffffffc
000000000000095f R_X86_64_PLT32 close+0xfffffffffffffffc
0000000000000bf6 R_X86_64_PLT32 memfd_create+0xfffffffffffffffc
0000000000000c09 R_X86_64_PLT32 ftruncate+0xfffffffffffffffc
0000000000000c1d R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000000c44 R_X86_64_PLT32 mmap+0xfffffffffffffffc
0000000000000c7f R_X86_64_PLT32 Punmap+0xfffffffffffffffc
0000000000000da4 R_X86_64_PLT32 munmap+0xfffffffffffffffc
0000000000000dac R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
0000000000000dd7 R_X86_64_PLT32 Pmap+0xfffffffffffffffc
0000000000000de0 R_X86_64_PLT32 close+0xfffffffffffffffc
0000000000000dea R_X86_64_PLT32 PF_to_PROT+0xfffffffffffffffc
0000000000000e00 R_X86_64_PLT32 Pprotect+0xfffffffffffffffc
0000000000000e1b R_X86_64_PLT32 munmap+0xfffffffffffffffc
0000000000001078 R_X86_64_PLT32 write+0xfffffffffffffffc
00000000000010da R_X86_64_PLT32 write+0xfffffffffffffffc
000000000000112c R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000001180 R_X86_64_PLT32 write+0xfffffffffffffffc
00000000000011dc R_X86_64_PLT32 write+0xfffffffffffffffc
0000000000001238 R_X86_64_PLT32 write+0xfffffffffffffffc
RELOCATION RECORDS FOR [NRV2E]:
OFFSET TYPE VALUE