src/stub: fix ET_DYN with non-zero PT_LOAD[0].p_vaddr

This commit is contained in:
Markus F.X.J. Oberhumer 2025-05-01 20:37:36 +02:00
parent e29e73a4e4
commit 23c70ec447
3 changed files with 21 additions and 22 deletions

View File

@ -502,18 +502,14 @@ do_xmap(
ElfW(Addr) reloc = 0;
if (xi) { // compressed main program:
// C_BASE space reservation, C_TEXT compressed data and stub
ElfW(Addr) ehdr0 = *p_reloc; // the 'hi' copy!
ElfW(Addr) ehdr0 = *p_reloc;
ElfW(Phdr) *phdr0 = (ElfW(Phdr) *)(1+ (ElfW(Ehdr) *)ehdr0); // cheats .e_phoff
// Clear the 'lo' space reservation for use by PT_LOADs
ehdr0 -= phdr0[1].p_vaddr; // the 'lo' copy
if (ET_EXEC == ehdr->e_type) {
ehdr0 = phdr0[0].p_vaddr;
v_brk = ehdr0 + phdr0->p_vaddr + phdr0->p_memsz;
if (ET_DYN == ehdr->e_type) {
reloc = ehdr0 - phdr0[1].p_vaddr;
}
else {
reloc = ehdr0;
}
v_brk = phdr0->p_memsz + ehdr0;
munmap((void *)ehdr0, phdr0->p_memsz);
// paranoia: prevent "hangover" from VMA for C_BASE
munmap((void *)(reloc + phdr0->p_vaddr), phdr0->p_memsz);
}
else { // PT_INTERP
DPRINTF("INTERP\\n", 0);

View File

@ -237,6 +237,13 @@ mfd .req old_sp
call f_expand
add sp,sp,#2*NBPW @ P_02, P_01 remove 5th param
// faster than clearcache + msync; also avoids msync() bug
ldr arg3,[sp,#F_LENU]
ldr arg2,[sp,#F_ADRU]
mov arg1,mfd
do_sys __NR_write
mov r5,#0
mov r4,mfd
mov r3,#MAP_PRIVATE|MAP_FIXED

View File

@ -603,18 +603,14 @@ do_xmap(
ElfW(Addr) reloc = 0;
if (xi) { // compressed main program:
// C_BASE space reservation, C_TEXT compressed data and stub
ElfW(Addr) ehdr0 = *p_reloc; // the 'hi' copy!
ElfW(Addr) ehdr0 = *p_reloc;
ElfW(Phdr) *phdr0 = (ElfW(Phdr) *)(1+ (ElfW(Ehdr) *)ehdr0); // cheats .e_phoff
// Clear the 'lo' space reservation for use by PT_LOADs
ehdr0 -= phdr0[1].p_vaddr; // the 'lo' copy
if (ET_EXEC == ehdr->e_type) {
ehdr0 = phdr0[0].p_vaddr;
v_brk = ehdr0 + phdr0->p_vaddr + phdr0->p_memsz;
if (ET_DYN == ehdr->e_type) {
reloc = ehdr0 - phdr0[1].p_vaddr;
}
else {
reloc = ehdr0;
}
v_brk = phdr0->p_memsz + ehdr0;
munmap((void *)ehdr0, phdr0->p_memsz);
// paranoia: prevent "hangover" from VMA for C_BASE
munmap((void *)(reloc + phdr0->p_vaddr), phdr0->p_memsz);
}
else { // PT_INTERP
DPRINTF("INTERP ehdr=%%p av=%%p\\n", ehdr, av);
@ -662,8 +658,8 @@ do_xmap(
DPRINTF(" mlen=%%p\\n", mlen);
#endif
DPRINTF("mmap addr=%%p mlen=%%p offset=%%p frag=%%p prot=%%x\\n",
addr, mlen, phdr->p_offset - frag, frag, prot);
DPRINTF("mmap addr=%%p mlen=%%p phdr=%%p offset=%%p frag=%%p prot=%%x\\n",
addr, mlen, phdr, phdr->p_offset - frag, frag, prot);
int mfd = 0;
if (xi && phdr->p_flags & PF_X) { // SELinux
// Cannot set PROT_EXEC except via mmap() into a region (Linux "vma")