arm32 shlib works with SELinux

modified:   stub/src/arch/arm/v4a/macros.S
	modified:   stub/src/arm.v4a-linux.elf-so_entry.S
	modified:   stub/src/arm.v4a-linux.elf-so_fold.S
	modified:   stub/src/arm64-linux.elf-so_entry.S
	modified:   stub/src/i386-linux.elf-so_main.c
This commit is contained in:
John Reiser 2023-04-28 13:52:26 -07:00
parent 937d4462ca
commit 0cffeca102
5 changed files with 69 additions and 40 deletions

View File

@ -72,9 +72,11 @@ __NR_SYSCALL_BASE = 0
mov r7,r12 // restore r7 from ip
.endm
.macro do_sys7t2 N // "7t2": two-byte N; clobbers r7 as a temporary
mov r12,r7 // save r7 in ip
mov r7, #(\N) & 0xff // syscall number
orr r7,r7,#(\N) &~0xff // high bits
swi 0
mov r7,r12 // restore r7 from ip
.endm
.macro do_sys2 N // two-byte N; clobbers 'ip' (r12), saves r7
mov r12,r7 // save r7 in ip

View File

@ -67,11 +67,13 @@ PAGE_SHIFT= 12
PAGE_MASK= (~0<<PAGE_SHIFT)
PAGE_SIZE= -PAGE_MASK
__NR_close= 6 + __NR_SYSCALL_BASE
__NR_exit = 1 + __NR_SYSCALL_BASE
__NR_write = 4 + __NR_SYSCALL_BASE
__NR_memfd_create= 0x181 + __NR_SYSCALL_BASE // 385
__NR_mmap64 = 0xc0 + __NR_SYSCALL_BASE
__NR_mprotect =125 + __NR_SYSCALL_BASE
__NR_munmap = 91 + __NR_SYSCALL_BASE
__NR_write = 4 + __NR_SYSCALL_BASE
__ARM_NR_BASE = 0xf0000 + __NR_SYSCALL_BASE
__ARM_NR_cacheflush = 2 + __ARM_NR_BASE
@ -142,7 +144,7 @@ _start: .globl _start // in Thumb mode (via PackLinuxElf32::pack3)
bkpt // DEBUG
#endif //}
// argc,argv,envp, r3 convenience, r4-r7 callee-saved, lr ret_addr
stmfd sp!,{r0,r1,r2, r3, r4,r5,r6,r7, lr}
stmfd sp!,{r0,r1,r2, r3, r4,r5,r6,r7, lr} // MATCH_99
sub sp,sp,#2*NBPW // space for ADRU, LENU
F_ADRU= 0 * NBPW
@ -151,34 +153,51 @@ F_ARGC= 2 * NBPW
call4 L70
L70_ret:
foldi .req lr // &fold_info
mov arg6,#0 // cleanliness
mvn arg5,#~-1 // fd= -1
mov arg4,#MAP_PRIVATE|MAP_ANONYMOUS // modes
mov arg3,#PROT_READ|PROT_WRITE // prot
ldr arg2,[foldi, #sz_unc] // dstlen
str arg2,[sp, #F_LENU]
mov arg1,#0 // addr (kernel chooses)
PUSH {foldi} // defend against lr clobbered by syscall
do_sys7t __NR_mmap64; cmn r0,#4096; bcc 0f; bkpt; 0:
POP {foldi}
str r0,[sp, #F_ADRU]
foldi .req lr // &fold_info
old_sp .req r5 // busy: lr,r5
mov old_sp,sp
ldr r0,[foldi,#sz_unc]
str r0,[old_sp,#F_LENU]
sub r0,sp,r0 // alloca
and sp,r0,#-2*NBPW // align stack
add arg4,sp,#F_LENU // &dstlen
mov arg3,r0 // dst
ldr arg2,[foldi, #sz_cpr] // srclen
add arg4,old_sp,#F_LENU // &dstlen
mov arg3,sp // dst for decompress
ldr arg2,[foldi,#sz_cpr] // srclen
add arg1,foldi,#sz_b_info // src
call4 f_decompress // includes cache flush
.unreq foldi // busy: r5
bl f_decompress
ldr arg1,[sp, #F_ADRU]
ldr arg2,[sp, #F_LENU]
mov arg3,#PROT_EXEC|PROT_READ
do_sys7t __NR_mprotect
mov arg2,#0
adr arg1,str_upx
mfd .req r6 // busy: r6,r5
do_sys7t2 __NR_memfd_create; mov mfd,r0
mov arg2,sp
ldr arg3,[old_sp,#F_LENU]
do_sys __NR_write
mov sp,old_sp // de-alloca
.unreq old_sp // busy: r6
mov arg6,#0 // beginning of file
mov arg5,mfd
mov arg4,#MAP_PRIVATE // modes
mov arg3,#PROT_READ|PROT_EXEC // prot
ldr arg2,[sp,#F_LENU]
mov arg1,#0 // addr (kernel chooses)
do_sys __NR_mmap64; str r0,[sp,#F_ADRU]
mov arg1,mfd
.unreq mfd // busy: empty
do_sys __NR_close
adr r0,_start -4 *NBPW // &SO_INFO
add r1,sp,#F_ARGC
ldr pc,[sp, #F_ADRU] // invoke folded code
str_upx:
.asciz "upx"
f_decompress:
#define LINUX_ARM_CACHEFLUSH 1
#include "arch/arm/v4a/nrv2b_d8.S"

View File

@ -29,6 +29,7 @@
#define ARM_OLDABI 1
#include "arch/arm/v4a/macros.S"
#include "MAX_ELF_HDR.S"
#define bkpt .long 0xe7f001f0 /* reserved instr "udf #0x10"; Linux GNU eabi breakpoint */
NBPW= 4
@ -73,15 +74,9 @@ PATH_MAX= 4096
mflg_data: .int MAP_PRIVATE|MAP_ANONYMOUS @ overwritten for QNX vs Linux
// %esp:
// &Elf32_Ehdr
// &{l_info; p_info; b_info; compressed data}
// &escape_hatch
// MATCH_13 ptr unfolded_code; for escape hatch
// MATCH_12 len unfolded code; for escape hatch
// &entry ??
// MATCH_00 argc
// MATCH_01 argv
// MATCH_07 envp
// MATCH_99 9 saved registers {r0= argc, r1= argv, r2= envp, r3-r7, lr)
F_ADRU= 0 * NBPW
F_LENU= 2 * NBPW
@ -90,7 +85,9 @@ F_LENU= 2 * NBPW
section SO_HEAD
fold: .globl fold
sub sp,sp,#MAX_ELF_HDR_32; mov r2,sp // &elf_tmp
call upx_so_main // (&so_info, &argc); returns &escape_hatch
add sp,sp,#MAX_ELF_HDR_32
mov lr,r0 // save &escape_hatch
ldmia sp!,{r0,r1} // F_ADRU, F_LENU (unfolded region)
mov r7,#0xff & __NR_munmap // FIXME depends on HW and ABI of OS
@ -132,12 +129,14 @@ __NR_close = 6 + __NR_SYSCALL_BASE
__NR_unlink= 10 + __NR_SYSCALL_BASE
__NR_getpid= 20 + __NR_SYSCALL_BASE
__NR_brk = 45 + __NR_SYSCALL_BASE
__NR_readlink=85+ __NR_SYSCALL_BASE
__NR_readlink= 85 + __NR_SYSCALL_BASE // 0x55
__NR_ftruncate= 93 + __NR_SYSCALL_BASE // 0x5d
__NR_mmap2 = 192 + __NR_SYSCALL_BASE
__NR_mprotect = 125 + __NR_SYSCALL_BASE
__NR_munmap = 91 + __NR_SYSCALL_BASE
__NR_memfd_create= 0x181 + __NR_SYSCALL_BASE // 385
__NR_mmap2 = 192 + __NR_SYSCALL_BASE // 0xc0
__NR_mprotect = 125 + __NR_SYSCALL_BASE // 0x7d
__NR_munmap = 91 + __NR_SYSCALL_BASE // 0x5b
__ARM_NR_BASE = 0x0f0000 + __NR_SYSCALL_BASE
__ARM_NR_cacheflush = 2 + __ARM_NR_BASE
@ -187,6 +186,12 @@ readlink:
munmap:
do_sys __NR_munmap; ret
ftruncate: .globl ftruncate
do_sys __NR_ftruncate; ret
memfd_create: .globl memfd_create
do_sys7t2 __NR_memfd_create; ret
// Sometimes Linux enforces page-aligned address
Pprotect: .globl Pprotect
mprotect: .globl mprotect

View File

@ -101,14 +101,10 @@ F_ADRU= 0 * NBPW
F_LENU= 1 * NBPW
F_ARGC= 2 * NBPW
old_sp .req x15
foldi .req x14
u_ptr .req x12
mfd .req w11
bl L70
L70_ret:
mov foldi,lr
foldi .req lr
old_sp .req x14 // busy: lr,x14
mov old_sp,sp
ldr w0,[foldi,#sz_unc]
str x0,[old_sp,#F_LENU]
@ -119,16 +115,19 @@ L70_ret:
mov arg3,sp // dst for decompress
ldr arg2w,[foldi,#sz_cpr] // srclen
add arg1,foldi,#sz_b_info // src
.unreq foldi // busy: x14
bl f_decompress
mov arg2w,#0
adr arg1,str_upx
mfd .req w15 // busy: x15,x14
do_sys __NR_memfd_create; mov mfd, w0
mov arg2,sp
ldr arg3,[old_sp,#F_LENU]
do_sys __NR_write
mov sp,old_sp // de-alloca
.unreq old_sp // busy: x15
mov arg6,#0 // beginning of file
mov arg5w,mfd
@ -137,14 +136,17 @@ L70_ret:
ldr arg2,[sp,#F_LENU]
mov arg1,#0 // addr (kernel chooses)
do_sys __NR_mmap; str x0,[sp,#F_ADRU]
u_ptr .req x14 // busy: x15,x14
mov u_ptr,x0
mov arg1w,mfd
.unreq mfd // busy: x14
do_sys __NR_close
adr arg1,_start - 4*4 // &SO_INFO
add arg2,sp,#F_ARGC // &{argc, argv, envp}
br u_ptr
.unreq u_ptr
str_upx:
.asciz "upx"

View File

@ -435,7 +435,7 @@ get_PAGE_MASK(void)
unsigned
get_PAGE_MASK(void) // the mask which KEEPS the page address
{
int fd = open("/proc/self/auxv", O_RDONLY, 0);
int fd = open(addr_string("/proc/self/auxv"), O_RDONLY, 0);
Elf32_auxv_t data[40];
Elf32_auxv_t *end = &data[read(fd, data, sizeof(data)) / sizeof(data[0])];
close(fd);
@ -617,6 +617,7 @@ 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