1
0
mirror of https://github.com/upx/upx.git synced 2025-08-11 22:52:30 +08:00

SELinux for i386 shlib stub

modified:   stub/src/i386-linux.elf-so_entry.S
	modified:   stub/src/i386-linux.elf-so_fold.S
	modified:   stub/src/i386-linux.elf-so_main.c
	modified:   stub/src/include/linux.h
This commit is contained in:
John Reiser
2023-04-27 18:49:35 -07:00
parent db5a39572c
commit 937d4462ca
4 changed files with 234 additions and 137 deletions

View File

@ -48,12 +48,14 @@ MAP_PRIVATE= 2
MAP_FIXED= 0x10
MAP_ANONYMOUS= 0x20
__NR_memfd_create= 0x164 // 356
__NR_mmap= 90
__NR_mprotect=125
__NR_munmap= 91
__NR_write= 4
__NR_close= 6
__NR_exit= 1
__NR_write= 4
PAGE_SHIFT= 12
PAGE_MASK= (~0<<PAGE_SHIFT)
@ -76,7 +78,7 @@ M_NRV2E_LE32=8
// .long offset({l_info; p_info; b_info; compressed data})
section ELFMAINX
_start: // C-called: %esp: ret_addr,argc,argv,envp; must save %ebx,%esi,%edi,%ebp
nop // DEBUG i386 so_entry.S
nop // int3 // DEBUG i386 so_entry.S
pusha // MATCH_03
call L70 // MATCH_08 push $&getbit
L70ret:
@ -102,25 +104,20 @@ refill:
adc bits,bits // LSB= 1 (CarryIn); CarryOut= next bit
ret // infrequent (1/32)
#define foldi %esi
#define old_sp %ebp
L20:
pop %ebx // MATCH_09 &fold_info
cmpw $M_NRV2B_LE32|(0<<8),b_method(%ebx); je 0f; hlt; 0: // check method and filter bytes
pop foldi // MATCH_09 &fold_info
cmpw $M_NRV2B_LE32|(0<<8),b_method(foldi); je 0f; hlt; 0: // check method and filter bytes
lea _start - 4*NBPW - L70ret(%edx),%ecx // &so_info
push %ecx // MATCH_14 &so_info
push %ebx // MATCH_15 old_mmap destroys
mov /*sz_unc*/(foldi),%eax; push %eax // MATCH_15 F_LENU
mov %esp,old_sp
#define F_LENU 0*NBPW
// Get pages for unfolded code
push $0 // arg6 offset
push $-1 // arg5 fd
push $MAP_PRIVATE|MAP_ANONYMOUS // arg4 modes
push $PROT_READ|PROT_WRITE // arg3 prot
push /*sz_unc*/(%ebx) // arg2 dstlen
push $0 // arg1 addr (kernel chooses)
call old_mmap
pop %ebx // MATCH_15 &fold_info
push /*sz_unc*/(%ebx) // MATCH_10 len unfolded cold
push %eax // MATCH_04 ptr unfolded_code
sub %eax,%esp // alloca
and $-2*NBPW,%esp // align stack
// This is nrv2b_d32, inlined and optimized for small space (about 160 bytes).
// The task is to de-compress the folded pieces for shared library init:
@ -132,15 +129,19 @@ L20:
// and compressability of C-coded de-compressors for Lzma and Zstd
// in contrast to the simple and small assembly-coded NRV.
mov %eax,dst // &unfolded_code
mov sz_cpr(%ebx),lsrc
lea sz_b_info(%ebx),src
mov %esp,dst // &unfolded_code
push old_sp // MATCH_16
mov sz_cpr(foldi),lsrc
lea sz_b_info(foldi),src // foldi dead
decompress: // inlined: (uchar const *src, uint len, uchar *dst /*, u32 &ldst, uint method */)
add src,lsrc; push lsrc // MATCH_05 &input_eof
//%esp:
// MATCH_05 &input_eof
// MATCH_04 ptr unfolded_code
// MATCH_16 old_sp
// space for de-compressed code
//old_sp:
// MATCH_10 len unfolded_code
// MATCH_14 &so_info
// MATCH_03 pusha regs {%edi,%esi,%ebp,%esp,%ebx,%edx,%ecx,%eax}
@ -188,14 +189,35 @@ gotlen_n2b:
eof_n2b:
pop %ecx // MATCH_05 &input_eof
cmp %ecx,%esi; je 0f; hlt; 0: // test for ending in correct place
pop old_sp // MATCH_16
pop %ebx // MATCH_04 arg1 ptr unfolded_code
pop %ecx // MATCH_10 arg2 len unfoded_code
push %ecx // MATCH_12 len unfolded code
push %ebx // MATCH_13 ptr unfolded code
push $PROT_EXEC|PROT_READ; pop %edx // arg3
push $__NR_mprotect; pop %eax; int $0x80
xor %ecx,%ecx // zero
call 0f; .asciz "upx"; 0: pop %ebx
push $__NR_memfd_create; pop %eax; int $0x80
#define mfd %edi
mov %eax,mfd
mov F_LENU(old_sp),%edx
mov %esp,%ecx
mov %edi,%ebx
push $__NR_write; pop %eax; int $0x80
mov old_sp,%esp // de-alloca
push $0 // arg6
push mfd // arg5
push $MAP_PRIVATE // arg4
push $PROT_READ|PROT_EXEC // arg3
push 4*NBPW(%esp) // arg2 F_LENU
push $0 // arg1
mov %esp,%ebx
push $__NR_mmap; pop %eax; int $0x80; add $6*NBPW,%esp
push %eax // MATCH_13 ptr unfolded_code
mov mfd,%ebx
push $__NR_close; pop %eax; int $0x80
pop %eax; push %eax
jmp *%eax
// %esp:
// MATCH_13 ptr unfolded_code; for escape hatch
// MATCH_12 len unfolded code; for escape hatch
@ -206,8 +228,6 @@ eof_n2b:
// MATCH_01 argv
// MATCH_07 envp
pop %eax; push %eax // MATCH_13 ptr unfolded code
jmp *%eax // enter C code
old_mmap: // oldmmap: ebx -> 6 arguments; remove arguments on return
lea 4(%esp),%ebx

View File

@ -1,3 +1,5 @@
#include "MAX_ELF_HDR.S"
#define section .section
NBPW= 4
@ -23,10 +25,11 @@ NBPW= 4
fold:
mov %esp,%eax
mov 2*NBPW(%eax),%ecx // &so_info
sub $MAX_ELF_HDR_32,%esp; push %esp // &elf_tmp
add $(3+8+1)*NBPW,%eax; push %eax // &{argc,argv,envp}
push %ecx // &so_info
call upx_so_main // (&so_info, &{argc, argv, envp}); returns &escape_hatch
add $2*NBPW,%esp // remove args
call upx_so_main // (&so_info, &{argc, argv, envp}, &elf_tmp); returns &escape_hatch
add $MAX_ELF_HDR_32 + 3*NBPW,%esp // remove args
mov %eax,%ebp // save &escape_hatch
pop %ebx // MATCH_13 ptr unfolded code
@ -106,6 +109,7 @@ __NR_write= 4
__NR_open= 5
__NR_close= 6
__NR_memfd_create= 0x164 // 356
__NR_mmap= 90
__NR_mprotect=125
__NR_munmap= 91
@ -164,6 +168,9 @@ Pprotect: .globl Pprotect
mov 1*NBPW(%esp),%ebx // restore reg
ret
memfd_create: .globl memfd_create
int3
push $__NR_memfd_create; 5: jmp 5f
mprotect: .globl mprotect
mov %ebx,%eax; and $-1+ (1<<12),%eax
sub %eax,%ebx
@ -171,6 +178,8 @@ mprotect: .globl mprotect
push $ __NR_mprotect; 5: jmp 5f
exit: .globl exit
push $ __NR_exit; 5: jmp 5f
close: .globl close
push $__NR_close; 5: jmp 5f
munmap: .globl munmap
push $ __NR_munmap; 5: jmp 5f
write: .globl write

View File

@ -107,9 +107,9 @@ ssize_t write(int, void const *, size_t);
static int dprintf(char const *fmt, ...); // forward
#endif //}
#ifdef __arm__ /*{*/
#ifdef __arm__ //{
extern unsigned div10(unsigned);
#endif /*}*/
#endif //}
#if DEBUG //{
void dprint8(
@ -241,99 +241,100 @@ ERR_LAB
}
}
#if defined(__i386__) /*{*/
#if defined(__i386__) //}{
#define addr_string(string) ({ \
char const *str; \
asm("call 0f; .asciz \"" string "\"; 0: pop %0" \
/*out*/ : "=r"(str) ); \
str; \
})
#elif defined(__arm__) //}{
#define addr_string(string) ({ \
char const *str; \
asm("bl 0f; .string \"" string "\"; .balign 4; 0: mov %0,lr" \
/*out*/ : "=r"(str) \
/* in*/ : \
/*und*/ : "lr"); \
str; \
})
#else //}{
error;
#endif //}
#if defined(__i386__) //
// 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
static void *
make_hatch_i386(Elf32_Phdr const *const phdr, ptrdiff_t reloc)
static char *
make_hatch_i386(
Elf32_Phdr const *const phdr,
char *base,
char *next_unc,
char *mfd_addr,
unsigned frag_mask
)
{
unsigned xprot = 0;
unsigned *hatch = 0;
DPRINTF("make_hatch %%p %%x %%x\\n",phdr,reloc,0);
char *hatch = 0;
DPRINTF("make_hatch %%p %%p %%p %%p %%x\\n", phdr, base, next_unc, mfd_addr, frag_mask);
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
// The format of the 'if' is
// if ( ( (hatch = loc1), test_loc1 )
// || ( (hatch = loc2), test_loc2 ) ) {
// action
// }
// which uses the comma to save bytes when test_locj involves locj
// and the action is the same when either test succeeds.
if (
// Try page fragmentation just beyond .text .
( (hatch = (void *)(phdr->p_memsz + phdr->p_vaddr + reloc)),
( phdr->p_memsz==phdr->p_filesz // don't pollute potential .bss
&& 4<=(~PAGE_MASK & -(int)hatch) ) ) // space left on page
// Try Elf32_Ehdr.e_ident[12..15] . warning: 'const' cast away
|| ( (hatch = (void *)(&((Elf32_Ehdr *)phdr->p_vaddr + reloc)->e_ident[12])),
(phdr->p_offset==0) )
// Allocate and use a new page.
|| ( xprot = 1, hatch = mmap(0, PAGE_SIZE, PROT_WRITE|PROT_READ,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) )
) {
// Omitting 'const' saves repeated literal in gcc.
unsigned /*const*/ escape = 0xc36180cd; // "int $0x80; popa; ret"
// Don't store into read-only page if value is already there.
if (* (volatile unsigned*) hatch != escape) {
* hatch = escape;
}
if (xprot) {
Pprotect(hatch, 1*sizeof(unsigned), PROT_EXEC|PROT_READ);
}
DPRINTF(" hatch at %%p\\n", hatch);
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
frag_mask &= -(long)next_unc; // bytes left on pge
unsigned /*const*/ escape = 0xc36180cd; // "int $0x80; popa; ret"
if (4 <= frag_mask) {
hatch = next_unc;
*(long *)&hatch[0] = escape;
hatch += phdr->p_vaddr + (base - mfd_addr); // relocate to eventual address
}
else {
hatch = 0;
else { // Does not fit at hi end of .text, so must use a new page "permanently"
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
write(mfd, &escape, 4);
mfd_addr = mmap(0, 4, PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
close(mfd);
hatch = mfd_addr;
}
}
DPRINTF("hatch=%%p\\n", hatch);
return hatch;
}
#elif defined(__arm__) /*}{*/
extern unsigned get_sys_munmap(void);
static void *
make_hatch_arm(
make_hatch_arm32(
Elf32_Phdr const *const phdr,
ptrdiff_t reloc
char *base,
char *next_unc,
char *mfd_addr,
unsigned frag_mask
)
{
unsigned const sys_munmap = get_sys_munmap();
unsigned xprot = 0;
unsigned code[2] = {
sys_munmap, // syscall __NR_unmap
0xe8bd80ff, // ldmia sp!,{r0,r1,r2,r3,r4,r5,r6,r7,pc}
};
unsigned *hatch = 0;
DPRINTF("make_hatch %%p %%x %%x\\n",phdr,reloc,sys_munmap);
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
// The format of the 'if' is
// if ( ( (hatch = loc1), test_loc1 )
// || ( (hatch = loc2), test_loc2 ) ) {
// action
// }
// which uses the comma to save bytes when test_locj involves locj
// and the action is the same when either test succeeds.
DPRINTF("make_hatch %%p %%p %%p %%p %%x\\n", phdr, base, next_unc, mfd_addr, frag_mask);
if (
// Try page fragmentation just beyond .text .
( (hatch = (void *)(~3u & (3+ phdr->p_memsz + phdr->p_vaddr + reloc))),
( phdr->p_memsz==phdr->p_filesz // don't pollute potential .bss
&& (2*4)<=(~PAGE_MASK & -(int)hatch) ) ) // space left on page
// Try Elf32_Ehdr.e_ident[8..15] . warning: 'const' cast away
|| ( (hatch = (void *)(&((Elf32_Ehdr *)phdr->p_vaddr + reloc)->e_ident[8])),
(phdr->p_offset==0) )
// Allocate and use a new page.
// Linux on ARM wants PROT_EXEC or else __clear_cache does not work?
|| ( xprot = 1, hatch = mmap(0, PAGE_SIZE, PROT_EXEC|PROT_WRITE|PROT_READ,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) )
) {
hatch[0] = sys_munmap; // syscall __NR_unmap
hatch[1] = 0xe8bd80ff; // ldmia sp!,{r0,r1,r2,r3,r4,r5,r6,r7,pc}
__clear_cache(&hatch[0], &hatch[2]); // ? needed before Pprotect()
if (xprot) {
Pprotect(hatch, 2*sizeof(unsigned), PROT_EXEC|PROT_READ);
}
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
next_unc += phdr->p_memsz - phdr->p_filesz; // Skip over local .bss
frag_mask &= -(long)next_unc; // bytes left on pge
if (2*4 <= frag_mask) {
hatch = (unsigned *)(void *)next_unc;
hatch[0]= code[0];
hatch[1]= code[1];
char *t = (phdr->p_vaddr + base) + ((char *)hatch - mfd_addr);
__clear_cache(&hatch[0], &hatch[2]);
hatch = (unsigned *)(void *)t;
}
else {
hatch = 0;
else { // Does not fit at hi end of .text, so must use a new page "permanently"
int mfd = memfd_create(addr_string("upx"), 0); // the directory entry
write(mfd, &code, 2*4);
mfd_addr = mmap(0, 2*4, PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
close(mfd);
hatch = (unsigned *)(void *)mfd_addr;
}
}
DPRINTF("hatch=%%p\\n", hatch);
return hatch;
}
#elif defined(__mips__) /*}{*/
@ -424,8 +425,14 @@ make_hatch_ppc32(
#define nullptr (void *)0
#if 0 //{
unsigned long
#if defined(__i386__) //{
unsigned
get_PAGE_MASK(void)
{
return ~0xFFF;
}
#else //}{
unsigned
get_PAGE_MASK(void) // the mask which KEEPS the page address
{
int fd = open("/proc/self/auxv", O_RDONLY, 0);
@ -461,8 +468,18 @@ extern void
underlay(unsigned size, char *ptr, unsigned len, unsigned p_flags);
#endif //}
extern int ftruncate(int fd, size_t length);
// Exchange the bits with values 4 (PF_R, PROT_EXEC) and 1 (PF_X, PROT_READ)
// Use table lookup into a PIC-string that pre-computes the result.
unsigned PF_to_PROT(Elf32_Phdr const *phdr)
{
return 7& addr_string("@\x04\x02\x06\x01\x05\x03\x07")
[phdr->p_flags & (PF_R|PF_W|PF_X)];
}
typedef struct {
int argc;
long argc;
char **argv;
char **envp;
} So_args;
@ -481,22 +498,23 @@ typedef struct {
void *
upx_so_main( // returns &escape_hatch
So_info *so_info,
So_args *so_args
So_args *so_args,
Elf32_Ehdr *elf_tmp // scratch for Elf32_Ehdr and Elf32_Phdrs
)
{
unsigned long const page_mask = get_PAGE_MASK();
char *const va_load = (char *)&so_info->off_reloc - so_info->off_reloc;
Elf32_Phdr const *phdr = (Elf32_Phdr *)(1+ (Elf32_Ehdr *)(void *)va_load);
Elf32_Addr const base = (Elf32_Addr)va_load - phdr->p_vaddr;
while (phdr->p_type != PT_LOAD) ++phdr; // skip PT_PHDR if any
So_info so_infc; // So_info Copy
memcpy(&so_infc, so_info, sizeof(so_infc)); // before de-compression overwrites
unsigned const xct_off = so_infc.off_xct_off;
(void)xct_off; // use even if not DEBUG
unsigned const xct_off = so_infc.off_xct_off; (void)xct_off;
char *const cpr_ptr = so_infc.off_info + va_load;
char *const cpr_ptr = so_info->off_info + va_load;
unsigned const cpr_len = (char *)so_info - cpr_ptr;
DPRINTF("upx_so_main@%%p va_load=%%p base=%%p cpr_ptr=%%p cpr_len=%%x xct_off=%%x\\n",
upx_so_main, va_load, base, cpr_ptr, cpr_len, xct_off);
typedef void (*Dt_init)(int argc, char *argv[], char *envp[]);
Dt_init const dt_init = (Dt_init)(void *)(so_info->off_user_DT_INIT + va_load);
DPRINTF("upx_so_main va_load=%%p so_infc=%%p cpr_ptr=%%p cpr_len=%%x xct_off=%%x\\n",
va_load, &so_infc, cpr_ptr, cpr_len, xct_off);
// DO NOT USE *so_info AFTER THIS!! It gets overwritten.
// Copy compressed data before de-compression overwrites it.
char *const sideaddr = mmap(nullptr, cpr_len, PROT_WRITE|PROT_READ,
@ -524,11 +542,28 @@ upx_so_main( // returns &escape_hatch
// Pprotect(,, PF_TO_PROT(.p_flags));
// Get the uncompressed Elf32_Ehdr and Elf32_Phdr
// The first b_info is aligned, so direct access of fields is OK.
Extent x1 = {binfo->sz_unc, va_load}; // destination
Pprotect(va_load, binfo->sz_unc, PROT_WRITE|PROT_READ);
// The first b_info is aligned, so direct access to fields is OK.
Extent x1 = {binfo->sz_unc, (char *)elf_tmp}; // destination
Extent x0 = {binfo->sz_cpr + sizeof(*binfo), (char *)binfo}; // source
unpackExtent(&x0, &x1); // de-compress Elf headers; x0.buf is updated
unpackExtent(&x0, &x1); // de-compress _Ehdr and _Phdrs; x0.buf is updated
Elf32_Phdr const *phdr = (Elf32_Phdr *)(1+ elf_tmp);
Elf32_Phdr const *const phdrN = &phdr[elf_tmp->e_phnum];
while (phdr->p_type != PT_LOAD) ++phdr; // skip PT_PHDR if any
Elf32_Addr const base = (Elf32_Addr)va_load - phdr->p_vaddr;
DPRINTF("base=%%p\\n", base);
if (phdr->p_flags & PF_X) {
int mfd = memfd_create(addr_string("upx"), 0);
unsigned mfd_len = 0ul - page_mask;
write(mfd, elf_tmp, binfo->sz_unc); // de-compressed Elf_Ehdr and Elf_Phdrs
write(mfd, binfo->sz_unc + va_load, mfd_len - binfo->sz_unc); // rest of 1st page
munmap(va_load, mfd_len); // make SELinux forget any previous protection
Elf32_Addr va_mfd = (Elf32_Addr)mmap(va_load, mfd_len, PF_to_PROT(phdr),
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, mfd, 0); (void)va_mfd;
close(mfd);
}
// Process each read-only PT_LOAD.
// A read+write PT_LOAD might be relocated by rtld before de-compression,
@ -536,8 +571,7 @@ upx_so_main( // returns &escape_hatch
struct b_info al_bi; // for aligned data from binfo
void *hatch = nullptr;
unsigned n_phdr = ((Elf32_Ehdr *)(void *)va_load)->e_phnum;
for (; n_phdr > 0; --n_phdr, ++phdr)
for (; phdr < phdrN; ++phdr)
if ( phdr->p_type == PT_LOAD && !(phdr->p_flags & PF_W)) {
DPRINTF("phdr@%%p p_offset=%%p p_vaddr=%%p p_filesz=%%p p_memsz=%%p binfo=%%p\\n",
phdr, phdr->p_offset, phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz, x0.buf);
@ -556,38 +590,69 @@ upx_so_main( // returns &escape_hatch
al_bi.sz_unc, al_bi.sz_cpr, *(unsigned *)(void *)&al_bi.b_method);
// Using .p_memsz implicitly handles .bss via MAP_ANONYMOUS.
// Omit any not-compressed prefix (below xct_off)
// Omit any non-tcompressed prefix (below xct_off)
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
pfx = (phdr->p_vaddr + pfx) & ~page_mask; // lo fragment on page
x1.buf -= pfx;
x1.size += pfx;
DPRINTF("mmap(%%p %%p) xct_off=%%x pfx=%%x\\n", x1.buf, x1.size, xct_off, pfx);
underlay(x1.size, x1.buf, pfx, phdr->p_flags);
DPRINTF("phdr(%%p %%p) xct_off=%%x pfx=%%x\\n", x1.buf, x1.size, xct_off, pfx);
int mfd = 0;
char *mfd_addr = 0;
if (phdr->p_flags & PF_X) { // SELinux
// 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"
// 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.
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
// file (MAP_SHARED) so that they can be mmap() according to *phdr.
// 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
}
else {
underlay(x1.size, x1.buf, pfx, phdr->p_flags); // also makes PROT_WRITE
}
x1.buf += pfx;
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);
unpackExtent(&x0, &x1); // updates x0 and x1
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) {
//#define PAGE_MASK ~0xFFFull
#if defined(__arm__) //{
hatch = make_hatch_arm(phdr, base);
#elif defined(__powerpc__) //}{
hatch = make_hatch_ppc(phdr, base, ~PAGE_MASK);
#elif defined(__i386__) //}{
hatch = make_hatch_i386(phdr, base);
#if defined(__i386__) //{
hatch = make_hatch_i386(phdr, (char *)base, x1.buf, mfd_addr, ~page_mask);
#elif defined(__arm__) //}{
hatch = make_hatch_arm32(phdr, (char *)base, x1.buf, mfd_addr, ~page_mask);
#elif defined(__powerpc32__) //}{
hatch = make_hatch_ppc32(phdr, (char *)base, x1.buf, mfd_addr, ~page_mask);
#endif //}
}
DPRINTF("mprotect %%p (%%p %%p %%x)\\n",
phdr, (char *)(phdr->p_vaddr + base), phdr->p_memsz, PF_TO_PROT(phdr->p_flags));
Pprotect( (char *)(phdr->p_vaddr + base), phdr->p_memsz, PF_TO_PROT(phdr->p_flags));
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),
MAP_FIXED|MAP_PRIVATE, mfd, 0);
close(mfd);
}
else { // easy
Pprotect( (char *)(phdr->p_vaddr + base), phdr->p_memsz, PF_to_PROT(phdr));
}
}
typedef void (*Dt_init)(int argc, char *argv[], char *envp[]);
Dt_init dt_init = (Dt_init)(void *)(so_infc.off_user_DT_INIT + va_load);
munmap(sideaddr, cpr_len);
DPRINTF("calling user DT_INIT %%p\\n", dt_init);
dt_init(so_args->argc, so_args->argv, so_args->envp);

View File

@ -184,6 +184,7 @@ struct timespec {
#define __NR_adjtimex 124
#define __NR_mprotect 125
#define __NR_nanosleep 162
#define __NR_memfd_create 356 /*0x164*/
#undef _syscall0
#undef _syscall1
@ -353,6 +354,7 @@ static inline _syscall2(int,ftruncate,int,fd,size_t,len)
static inline _syscall0(pid_t,getpid)
static inline _syscall2(int,gettimeofday,struct timeval *,tv,void *,tz)
static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,whence)
static inline _syscall2(int,memfd_create,char const *,name,unsigned,flags);
static inline _syscall3(int,mprotect,void *,addr,size_t,len,int,prot)
static inline _syscall2(int,munmap,void *,start,size_t,length)
static inline _syscall2(int,nanosleep,const struct timespec *,rqtp,struct timespec *,rmtp)
@ -542,6 +544,7 @@ static ssize_t write(int fd, void const *buf, size_t len)
void *brk(void *);
int close(int);
void exit(int) __attribute__((__noreturn__,__nothrow__));
int memfd_create(char const *, unsigned);
void *mmap(void *, size_t, int, int, int, off_t);
int munmap(void *, size_t);
int mprotect(void const *, size_t, int);