Elf i386 stub: get enough space when unfolded code requires another page

modified:   src/i386-linux.elf-entry.S
This commit is contained in:
John Reiser 2017-10-03 11:48:27 -07:00
parent ca7217e717
commit 08d3376740
3 changed files with 1979 additions and 1967 deletions

File diff suppressed because it is too large Load Diff

View File

@ -151,6 +151,9 @@ __NR_mprotect= 125
szElf32_Ehdr= 0x34
p_memsz= 5*4
sz_unc= 0
sz_cpr= 4
EINVAL= 22
#define pushsbli .byte 0x6a, /* push sign-extended byte to long immediate*/
@ -172,32 +175,43 @@ die:
// Decompress the rest of this loader, and jump to it
unfold: // IN: ebp= f_exp; esp/ &O_BINFO
pop esi; lodsd // skip O_BINFO; esi= &compressed fold_elf86
lea edi,[sz_pack2 - f_exp + ebp]
sub edi,[edi] // edi= &Elf32_Ehdr of this program
// Open /proc/self/exe
call 0f; .asciz "/proc/self/exe"; 0: pop ebx // path
sub ecx,ecx // O_RDONLY
push __NR_open; pop eax; int 0x80; push eax // P_31 fd
// Duplicate the input data using another mmap.
lea edi,[sz_pack2 - f_exp + ebp]
mov edx,esi
sub edi,[edi] // edi= &Elf32_Ehdr of this program
sub edx,edi // offset(dst) of unfold
add edx,[esi] // + sz_unc
push 0 // offset
push eax // fd
PUSH MAP_PRIVATE
push PROT_READ
// Reserve space for input file and unfolded stub
push 0 // offset
mov edx,esi
push -1 // fd
sub edx,edi // offset(dst) of unfold
push MAP_PRIVATE|MAP_ANONYMOUS
add edx,[esi] // + sz_unc
push PROT_READ|PROT_WRITE
push edx // len
push 0 // addr
call mmap // another copy of this program
add esp,6*4
push 0 // kernel chooses addr
call mmap
pop ecx; push ecx // P_31 fd
push edx // P_23 LENU
push eax // P_24 ADRU
mov edx,eax // copy ADRU
// Decompress folded code onto end of duplicated data.
// PROT_WRITE the destination pages.
// Duplicate the input data.
mov edx,esi
push 0 // offset
sub edx,edi // offset(dst) of unfold
push ecx // fd
add edx,[esi + sz_cpr] // edx <= .st_size
PUSH MAP_PRIVATE|MAP_FIXED // at reserved addr eax by previous mmap
push PROT_READ|PROT_WRITE
push edx // len
push eax // addr
call mmap // another copy of this program
// Remember new f_exp region for PROT_EXEC.
mov edx,eax // copy ADRU
sub eax,edi // relocation amount
add eax,esi // dst for unfolding
mov ecx,eax
@ -208,11 +222,8 @@ unfold: // IN: ebp= f_exp; esp/ &O_BINFO
add eax,edx // new f_exp
and eax,PAGE_MASK // base to protect
sub ecx,eax // length to protect
xchg ebx,eax // ebx= page address
push PROT_WRITE|PROT_READ; pop edx
push __NR_mprotect; pop eax; int 0x80
pop edx; push edx // P_20 dst
push ecx; push ebx // P_21 save for PROT_EXEC
push ecx; push eax // P_21 save for PROT_EXEC
// Unfold
lodsd; push eax; mov ebx,esp // sz_unc
lodsd; xchg ecx,eax // sz_cpr
@ -238,11 +249,11 @@ unfold: // IN: ebp= f_exp; esp/ &O_BINFO
// ebp:f_exp; esi:&old_b_info(fold); edi:dynbase
jmp edx // esp/ ADRU,LENU,fd,entry,argc,argv,0,...
mmap: // oldmmap: ebx -> 6 arguments
mmap: // oldmmap: ebx -> 6 arguments; remove arguments on return
lea ebx,[4+esp]
push __NR_mmap; pop eax; int 0x80
cmp eax,PAGE_MASK; jl 0f; hlt; 0:
ret
ret 6*4
main:
pop ebp // &decompress

View File

@ -169,7 +169,7 @@ Idx Name Size VMA LMA File off Algn Flags
164 ctok32.30 0000000a 00000000 00000000 00001aa8 2**0 CONTENTS, RELOC, READONLY
165 ctok32.40 00000005 00000000 00000000 00001ab2 2**0 CONTENTS, RELOC, READONLY
166 LEXEC017 00000002 00000000 00000000 00001ab7 2**0 CONTENTS, READONLY
167 LEXEC020 000000d4 00000000 00000000 00001ab9 2**0 CONTENTS, RELOC, READONLY
167 LEXEC020 000000e2 00000000 00000000 00001ab9 2**0 CONTENTS, RELOC, READONLY
SYMBOL TABLE:
00000000 l d N2BSMA10 00000000 N2BSMA10
00000000 l d N2BFAS11 00000000 N2BFAS11
@ -657,4 +657,4 @@ OFFSET TYPE VALUE
RELOCATION RECORDS FOR [LEXEC020]:
OFFSET TYPE VALUE
000000d0 R_386_32 O_BINFO
000000de R_386_32 O_BINFO