From 3bcb89ec409dc04c55465bdb79ffc7828f003e3c Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Sun, 4 Nov 2012 10:58:13 +0800 Subject: [PATCH] User/Kernel - ARMv7 fixes (relocation of .text) --- KernelLand/Kernel/arch/armv7/lib.c | 2 +- KernelLand/Kernel/arch/armv7/mm_virt.c | 49 +++++- KernelLand/Kernel/arch/armv7/start.S | 38 +++-- KernelLand/Kernel/bin/elf.c | 13 +- KernelLand/Kernel/binary.c | 2 +- KernelLand/Kernel/logging.c | 6 +- KernelLand/Kernel/syscalls.c | 24 +++ KernelLand/Kernel/vfs/mmap.c | 3 +- .../Modules/Filesystems/InitRD/files.lst | 1 - Makefile | 2 +- .../Libraries/ld-acess.so_src/arch/armv7.S.h | 29 ++-- .../ld-acess.so_src/arch/syscalls.s.h | 1 + Usermode/Libraries/ld-acess.so_src/common.h | 2 +- Usermode/Libraries/ld-acess.so_src/elf.c | 147 ++++++++++++------ .../ld-acess.so_src/include_exp/acess/sys.h | 1 + Usermode/Libraries/ld-acess.so_src/loadlib.c | 21 ++- Usermode/Libraries/libc.so_src/Makefile | 2 +- 17 files changed, 243 insertions(+), 100 deletions(-) diff --git a/KernelLand/Kernel/arch/armv7/lib.c b/KernelLand/Kernel/arch/armv7/lib.c index 65c457c1..f33f3394 100644 --- a/KernelLand/Kernel/arch/armv7/lib.c +++ b/KernelLand/Kernel/arch/armv7/lib.c @@ -103,7 +103,7 @@ void *memset(void *_dest, int _value, size_t _length) val32 |= val32 << 16; // Force alignment - while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value; + while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value, _length --; dst = (void *)dst8; // DWORD copies diff --git a/KernelLand/Kernel/arch/armv7/mm_virt.c b/KernelLand/Kernel/arch/armv7/mm_virt.c index 00d6c681..146caea8 100644 --- a/KernelLand/Kernel/arch/armv7/mm_virt.c +++ b/KernelLand/Kernel/arch/armv7/mm_virt.c @@ -10,6 +10,7 @@ #include #define TRACE_MAPS 0 +#define TRACE_COW 1 #define AP_KRW_ONLY 1 // Kernel page #define AP_KRO_ONLY 5 // Kernel RO page @@ -18,6 +19,13 @@ #define AP_RO_USER 2 // User RO Page #define PADDR_MASK_LVL1 0xFFFFFC00 +const char * const caAPValueNames[] = { + "AP_NOACCESS", "AP_KRW_ONLY", + "AP_RO_USER", "AP_RW_BOTH", + "AP_???_4", "AP_KRO_ONLY", + "AP_???_6", "AP_RO_BOTH" +}; + // === IMPORTS === extern Uint32 kernel_table0[]; @@ -53,7 +61,7 @@ tPAddr MM_Clone(void); tVAddr MM_NewKStack(int bGlobal); void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info); //void MM_DumpTables(tVAddr Start, tVAddr End); -void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch); +void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR); // === GLOBALS === tPAddr giMM_ZeroPage; @@ -938,18 +946,20 @@ void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info) { if( giMM_ZeroPage && Info->PhysAddr == giMM_ZeroPage ) { - Debug("%p => %8s - 0x%7x %i %x %s", + Debug("%p => %8s - 0x%7x D%i %x %s %s", Start, "ZERO", Len, Info->Domain, Info->AP, - Info->bGlobal ? "G" : "nG" + Info->bExecutable ? " X" : "nX", + Info->bGlobal ? " G" : "nG" ); } else { - Debug("%p => %8x - 0x%7x %i %x %s", + Debug("%p => %8x - 0x%7x D%i %x %s %s", Start, Info->PhysAddr-Len, Len, Info->Domain, Info->AP, - Info->bGlobal ? "G" : "nG" + Info->bExecutable ? " X" : "nX", + Info->bGlobal ? " G" : "nG" ); } } @@ -996,7 +1006,7 @@ void MM_DumpTables(tVAddr Start, tVAddr End) } // NOTE: Runs in abort context, not much difference, just a smaller stack -void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch) +void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR) { int rv; tMM_PageInfo pi; @@ -1070,6 +1080,33 @@ void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch) Log_Error("MMVirt", "Code at %p accessed %p (DFSR = 0x%x)%s", PC, Addr, DFSR, (bPrefetch ? " - Prefetch" : "") ); + Log_Error("MMVirt", "- User LR = 0x%x", UserLR); + const char * const dfsr_errors[] = { + /* 00000 */ "-", "Alignment Fault", + /* 00010 */ "Debug event", "Access Flag (Section)", + /* 00100 */ "Instr Cache Maint", "Translation (Section)", + /* 00110 */ "Access Flag (Page)", "Translation (Page)", + /* 01000 */ "Sync. External abort", "Domain (Section)", + /* 01010 */ "-", "Domain (Page)", + /* 01100 */ "Table Walk sync ext (lvl 1)", "Permission (Section)", + /* 01110 */ "Table Walk sync ext (lvl 2)", "Permission (Page)", + // 0b10000 + /* 10000 */ "-", "-", + /* 10010 */ "-", "-", + /* 10100 */ "IMPL (Lockdown)", "-", + /* 10110 */ "Async. Extern. Abort", "-", + /* 11000 */ "Mem. access async pairity error", "Mem. access async pairity error", + /* 11010 */ "IMPL (Coprocessor abort)", "-", + /* 11100 */ "Table Walk Sync parity (lvl 1)", "-", + /* 11110 */ "Table Walk Sync parity (lvl 2)", "-" + }; + int errcode = (DFSR & 0xF) | (((DFSR >> 10) & 1) << 4); + Log_Error("MMVirt", "- Errcode 0b%05b", errcode); + Log_Error("MMVirt", "- Dom %i %s %s", + (DFSR >> 4) & 0xF, (DFSR & 0x800 ? "Write": "Read"), + dfsr_errors[errcode] + ); + Log_Error("MMVirt", "- AP=%i(%s) %s", pi.AP, caAPValueNames[pi.AP], pi.bExecutable ? " Executable":""); if( Addr < 0x80000000 ) MM_DumpTables(0, 0x80000000); else diff --git a/KernelLand/Kernel/arch/armv7/start.S b/KernelLand/Kernel/arch/armv7/start.S index 113c8a43..71534f57 100644 --- a/KernelLand/Kernel/arch/armv7/start.S +++ b/KernelLand/Kernel/arch/armv7/start.S @@ -194,12 +194,21 @@ DataAbort: @ cpsid ifa, #19 PUSH_GPRS + @ Get the user's LR value (and push to stack) + cps #31 @ Go to system mode + mov r1, lr + cps #19 @ Go to supervisor + mov r0, lr + cps #23 @ back to exception + push {r0,r1} + mov r3, #0 @ not a prefetch abort mrc p15, 0, r2, c5, c0, 0 @ Read DFSR (Data Fault Status Register) to R2 mrc p15, 0, r1, c6, c0, 0 @ Read DFAR (Data Fault Address Register) into R1 mov r0, lr @ PC ldr r4, =MM_PageFault blx r4 + add sp, #8 @ Undo push of the user/system LR POP_GPRS rfeia sp! @ Pop state (actually RFEFD) @@ -211,17 +220,24 @@ PrefetchAbort: @ cpsid ifa, #19 PUSH_GPRS - ldr r0, =csAbort_Tag - ldr r1, =csPrefetchAbort_Fmt -# mov r2, lr - mrc p15, 0, r2, c6, c0, 2 @ Read IFAR (Instruction Fault Address Register) into R3 - mrc p15, 0, r3, c5, c0, 1 @ Read IFSR (Instruction Fault Status Register) into R3 - ldr r5, =Log_Error - blx r5 -.loop: - wfi - b .loop + @ Get the user's LR value (and push to stack) + cps #31 @ Go to system mode + mov r0, lr + cps #23 @ back to supervisor + push {r0} + + mrc p15, 0, r2, c5, c0, 1 @ Read IFSR (Instruction Fault Status Register) into R3 + mrc p15, 0, r1, c6, c0, 2 @ Read IFAR (Instruction Fault Address Register) into R3 + mov r0, r1 + mov r3, #1 @ IS a prefetch abort + ldr r4, =MM_PageFault + blx r4 + add sp, #4 @ Undo push of the user LR + + POP_GPRS + rfeia sp! @ Pop state (actually RFEFD) + .globl Undef_Handler Undef_Handler: wfi @@ -238,7 +254,7 @@ csIRQ_Fmt: csDataAbort_Fmt: .asciz "Data Abort - %p accessed %p, DFSR=%x Unk:%x Unk:%x" csPrefetchAbort_Fmt: - .asciz "Prefetch Abort at %p, IFSR=%x" + .asciz "Prefetch Abort at %p, IFSR=%x, UserLR:0x%x" csSyscallPrintRetAddr: .asciz "Syscall ret to %p" diff --git a/KernelLand/Kernel/bin/elf.c b/KernelLand/Kernel/bin/elf.c index 76724bc2..7e1ef5e9 100644 --- a/KernelLand/Kernel/bin/elf.c +++ b/KernelLand/Kernel/bin/elf.c @@ -11,10 +11,19 @@ #if BITS <= 32 # define DISABLE_ELF64 #endif -void *GetSymbol(const char *Name, size_t *Size); -void *GetSymbol(const char *Name, size_t *Size) { Uint val; Binary_GetSymbol(Name, &val); if(Size)*Size=0; return (void*)val; }; +static int GetSymbol(const char *Name, void **Value, size_t *Size); +static int GetSymbol(const char *Name, void **Value, size_t *Size) { + Uint val; + if(Binary_GetSymbol(Name, &val)) + return 0; + if(Size) + *Size=0; + *Value = (void*)val; + return 1; +} #define AddLoaded(a,b) do{}while(0) #define LoadLibrary(a,b,c) (Log_Debug("ELF", "Module requested lib '%s'",a),0) +#define SysSetMemFlags(ad,f,m) do{}while(0) #include "../../../Usermode/Libraries/ld-acess.so_src/elf.c" #define DEBUG_WARN 1 diff --git a/KernelLand/Kernel/binary.c b/KernelLand/Kernel/binary.c index 92baa737..ec5db13f 100644 --- a/KernelLand/Kernel/binary.c +++ b/KernelLand/Kernel/binary.c @@ -2,7 +2,7 @@ * Acess2 * Common Binary Loader */ -#define DEBUG 0 +#define DEBUG 1 #include #include #include diff --git a/KernelLand/Kernel/logging.c b/KernelLand/Kernel/logging.c index 9617b834..323e84b3 100644 --- a/KernelLand/Kernel/logging.c +++ b/KernelLand/Kernel/logging.c @@ -161,9 +161,11 @@ void Log_Int_PrintMessage(tLogEntry *Entry) if( CPU_HAS_LOCK(&glLogOutput) ) return ; // TODO: Error? SHORTLOCK( &glLogOutput ); - LogF("%s%014lli%s [%-8s] %i - %s", + LogF("%s%014lli", csaLevelColours[Entry->Level], - Entry->Time, + Entry->Time + ); + LogF("%s [%-8s] %i - %s", csaLevelCodes[Entry->Level], Entry->Ident, Threads_GetTID(), diff --git a/KernelLand/Kernel/syscalls.c b/KernelLand/Kernel/syscalls.c index bfd68bf1..3dc19555 100644 --- a/KernelLand/Kernel/syscalls.c +++ b/KernelLand/Kernel/syscalls.c @@ -38,6 +38,7 @@ extern Uint Binary_Load(const char *file, Uint *entryPoint); void SyscallHandler(tSyscallRegs *Regs); int Syscall_ValidString(const char *Addr); int Syscall_Valid(int Size, const void *Addr); + int Syscall_MM_SetFlags(const void *Addr, Uint Flags, Uint Mask); // === CODE === // TODO: Do sanity checking on arguments, ATM the user can really fuck with the kernel @@ -114,6 +115,11 @@ void SyscallHandler(tSyscallRegs *Regs) // -- Unmap an address case SYS_UNMAP: MM_Deallocate(Regs->Arg1); break; + // -- Change the protection on an address + case SYS_SETFLAGS: + ret = Syscall_MM_SetFlags((void*)Regs->Arg1, Regs->Arg2, Regs->Arg3); + break; + // -- Get Thread/Process IDs case SYS_GETTID: ret = Threads_GetTID(); break; case SYS_GETPID: ret = Threads_GetPID(); break; @@ -398,3 +404,21 @@ int Syscall_Valid(int Size, const void *Addr) return CheckMem( Addr, Size ); } + +int Syscall_MM_SetFlags(const void *Addr, Uint Flags, Uint Mask) +{ + tPAddr paddr = MM_GetPhysAddr(Addr); + Flags &= MM_PFLAG_RO|MM_PFLAG_EXEC; + Mask &= MM_PFLAG_RO|MM_PFLAG_EXEC; + // Enable write? + if( (Mask & MM_PFLAG_RO) && !(Flags & MM_PFLAG_RO) ) { + void *node; + // HACK - Assume that RO mmap'd files are immutable + if( MM_GetPageNode(paddr, &node) == 0 && node ) { + Flags |= MM_PFLAG_COW; + Mask |= MM_PFLAG_COW; + } + } + MM_SetFlags((tVAddr)Addr, Flags, Mask); + return 0; +} diff --git a/KernelLand/Kernel/vfs/mmap.c b/KernelLand/Kernel/vfs/mmap.c index c5015e67..15dacf20 100644 --- a/KernelLand/Kernel/vfs/mmap.c +++ b/KernelLand/Kernel/vfs/mmap.c @@ -5,7 +5,7 @@ * mmap.c * - VFS_MMap support */ -#define DEBUG 0 +#define DEBUG 1 #include #include #include @@ -57,6 +57,7 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, PAGE_SIZE - (mapping_base & (PAGE_SIZE-1)) ); memset( (void*)(mapping_base + ofs), 0, PAGE_SIZE - (mapping_base & (PAGE_SIZE-1))); + LOG("dune"); } else { LOG("New empty page"); diff --git a/KernelLand/Modules/Filesystems/InitRD/files.lst b/KernelLand/Modules/Filesystems/InitRD/files.lst index fe2fc4da..77426dac 100644 --- a/KernelLand/Modules/Filesystems/InitRD/files.lst +++ b/KernelLand/Modules/Filesystems/InitRD/files.lst @@ -19,7 +19,6 @@ Dir "Libs" { File "ld-acess.so" "__BIN__/Libs/ld-acess.so" File "libld-acess.so" "__BIN__/Libs/libld-acess.so" File "libc.so" "__BIN__/Libs/libc.so" - File "libgcc.so" "__BIN__/Libs/libgcc.so" File "libreadline.so" "__BIN__/Libs/libreadline.so" File "libnet.so" "__BIN__/Libs/libnet.so" File "liburi.so" "__BIN__/Libs/liburi.so" diff --git a/Makefile b/Makefile index 1d05b1a4..abf19e59 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ SUBMAKE = $(MAKE) --no-print-directory -USRLIBS := crt0.o acess.ld ld-acess.so libgcc.so libc.so +USRLIBS := crt0.o acess.ld ld-acess.so libc.so USRLIBS += libreadline.so libnet.so liburi.so libpsocket.so USRLIBS += libimage_sif.so diff --git a/Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h b/Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h index 9132c026..46128b21 100644 --- a/Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h +++ b/Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h @@ -39,29 +39,19 @@ __clear_cache: svc #0x1001 mov pc, lr -@ DEST -@ SRC -@_memcpy: -@ push rbp -@ mov rbp, rsp -@ -@ ; RDI - First Param -@ ; RSI - Second Param -@ mov rcx, rdx ; RDX - Third -@ rep movsb -@ -@ pop rbp -@ ret -@ +.section .data .globl _errno _errno: .long 0 @ Placed in .text, to allow use of relative addressing +.section .text .macro syscall0 _name, _num .globl \_name \_name: push {lr} svc #\_num - str r2, _errno + @mrc p15, 0, r3, c13, c0, 2 + ldr r3, =_errno + str r2, [r3] pop {pc} .endm @@ -71,7 +61,8 @@ _errno: .long 0 @ Placed in .text, to allow use of relative addressing push {r4, lr} ldr r4, [sp,#8] svc #\_num - str r2, _errno + ldr r3, =_errno + str r2, [r3] pop {r4, pc} .endm @@ -82,7 +73,8 @@ _errno: .long 0 @ Placed in .text, to allow use of relative addressing ldr r4, [sp,#12] ldr r5, [sp,#16] svc #\_num - str r2, _errno + ldr r3, =_errno + str r2, [r3] pop {r4,r5,pc} .endm @@ -107,7 +99,8 @@ _clone: push {r4} mov r4, r1 svc #SYS_CLONE - str r2, _errno + ldr r3, =_errno + str r2, [r3] tst r4, r4 beq _clone_ret @ If in child, set SP diff --git a/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h b/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h index a978a35c..a59e8571 100644 --- a/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h +++ b/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h @@ -37,6 +37,7 @@ SYSCALL1(_SysSetFaultHandler, SYS_SETFAULTHANDLER) SYSCALL6(_SysDebug, 0x100) SYSCALL1(_SysGetPhys, SYS_GETPHYS) // uint64_t _SysGetPhys(uint addr) SYSCALL1(_SysAllocate, SYS_ALLOCATE) // uint64_t _SysAllocate(uint addr) +SYSCALL3(SysSetMemFlags, SYS_SETFLAGS) // uint32_t SysSetMemFlags(uint addr, uint flags, uint mask) // VFS System calls SYSCALL2(open, SYS_OPEN) // char*, int SYSCALL3(reopen, SYS_REOPEN) // int, char*, int diff --git a/Usermode/Libraries/ld-acess.so_src/common.h b/Usermode/Libraries/ld-acess.so_src/common.h index 6f67811a..eb9b83b9 100644 --- a/Usermode/Libraries/ld-acess.so_src/common.h +++ b/Usermode/Libraries/ld-acess.so_src/common.h @@ -39,7 +39,7 @@ extern void *DoRelocate(void *Base, char **envp, const char *Filename); // === Library/Symbol Manipulation == extern void *LoadLibrary(const char *Filename, const char *SearchDir, char **envp); extern void AddLoaded(const char *File, void *base); -extern void *GetSymbol(const char *name, size_t *size); +extern int GetSymbol(const char *Name, void **Value, size_t *size); extern int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size); // === Library Functions === diff --git a/Usermode/Libraries/ld-acess.so_src/elf.c b/Usermode/Libraries/ld-acess.so_src/elf.c index dc9dca36..9a2668a7 100644 --- a/Usermode/Libraries/ld-acess.so_src/elf.c +++ b/Usermode/Libraries/ld-acess.so_src/elf.c @@ -9,6 +9,10 @@ # define DEBUG 0 #endif +#ifndef PAGE_SIZE +# define PAGE_SIZE 4096 +#endif + #include "common.h" #include #include "elf32.h" @@ -35,8 +39,8 @@ void *ElfRelocate(void *Base, char **envp, const char *Filename); int ElfGetSymbol(void *Base, const char *Name, void **Ret, size_t *Size); void *Elf32Relocate(void *Base, char **envp, const char *Filename); int Elf32GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size); -void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff); -void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff); + int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff); + int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff); #ifdef SUPPORT_ELF64 void *Elf64Relocate(void *Base, char **envp, const char *Filename); int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size); @@ -87,26 +91,28 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret, size_t *Size) } } -void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff) +int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, + int bRela, const char *Sym, intptr_t iBaseDiff) { - intptr_t val; + void *symval; switch( type ) { // Standard 32 Bit Relocation (S+A) case R_386_32: - val = (intptr_t) GetSymbol(Sym, NULL); - DEBUGS(" elf_doRelocate: R_386_32 *0x%x += 0x%x('%s')", - ptr, val, Sym); - *ptr = val + addend; + if( !GetSymbol(Sym, &symval, NULL) ) + return 1; + DEBUGS(" elf_doRelocate: R_386_32 *0x%x += %p('%s')", + ptr, symval, Sym); + *ptr = (intptr_t)symval + addend; break; // 32 Bit Relocation wrt. Offset (S+A-P) case R_386_PC32: DEBUGS(" elf_doRelocate: '%s'", Sym); - val = (intptr_t) GetSymbol(Sym, NULL); - DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%x - 0x%x", - ptr, *ptr, val, (intptr_t)ptr ); - *ptr = val + addend - (intptr_t)ptr; + if( !GetSymbol(Sym, &symval, NULL) ) return 1; + DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%p - 0x%x", + ptr, *ptr, symval, (intptr_t)ptr ); + *ptr = (intptr_t)symval + addend - (intptr_t)ptr; //*ptr = val + addend - ((Uint)ptr - iBaseDiff); break; @@ -114,9 +120,9 @@ void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int t case R_386_GLOB_DAT: case R_386_JMP_SLOT: DEBUGS(" elf_doRelocate: '%s'", Sym); - val = (intptr_t) GetSymbol( Sym, NULL ); - DEBUGS(" elf_doRelocate: %s *0x%x = 0x%x", csaR_NAMES[type], ptr, val); - *ptr = val; + if( !GetSymbol(Sym, &symval, NULL) ) return 1; + DEBUGS(" elf_doRelocate: %s *0x%x = %p", csaR_NAMES[type], ptr, symval); + *ptr = (intptr_t)symval; break; // Base Address (B+A) @@ -127,18 +133,19 @@ void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int t case R_386_COPY: { size_t size; - void *src = GetSymbol(Sym, &size); - DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, src, size); - memcpy(ptr, src, size); + if( !GetSymbol(Sym, &symval, &size) ) return 1; + DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, symval, size); + memcpy(ptr, symval, size); break; } default: SysDebug("elf_doRelocate_386: Unknown relocation %i", type); - break; + return 2; } + return 0; } -void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff) +int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff) { uint32_t val; switch(type) @@ -146,32 +153,35 @@ void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int t // (S + A) | T case R_ARM_ABS32: DEBUGS(" elf_doRelocate_arm: R_ARM_ABS32 %p (%s + %x)", ptr, Sym, addend); - val = (intptr_t)GetSymbol(Sym, NULL); + if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1; *ptr = val + addend; break; case R_ARM_GLOB_DAT: DEBUGS(" elf_doRelocate_arm: R_ARM_GLOB_DAT %p (%s + %x)", ptr, Sym, addend); - val = (intptr_t)GetSymbol(Sym, NULL); + if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1; *ptr = val + addend; break; case R_ARM_JUMP_SLOT: if(!bRela) addend = 0; DEBUGS(" elf_doRelocate_arm: R_ARM_JUMP_SLOT %p (%s + %x)", ptr, Sym, addend); - val = (intptr_t)GetSymbol(Sym, NULL); + if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1; *ptr = val + addend; break; // Copy case R_ARM_COPY: { size_t size; - void *src = GetSymbol(Sym, &size); + void *src; + if( !GetSymbol(Sym, &src, &size) ) return 1; DEBUGS(" elf_doRelocate_arm: R_ARM_COPY (%p, %p, %i)", ptr, src, size); memcpy(ptr, src, size); break; } // Delta between link and runtime locations + A case R_ARM_RELATIVE: + DEBUGS(" elf_doRelocate_arm: R_ARM_RELATIVE %p (0x%x + 0x%x)", ptr, iBaseDiff, addend); if(Sym[0] != '\0') { // TODO: Get delta for a symbol SysDebug("elf_doRelocate_arm: TODO - Implment R_ARM_RELATIVE for symbols"); + return 2; } else { *ptr = iBaseDiff + addend; @@ -179,8 +189,9 @@ void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int t break; default: SysDebug("elf_doRelocate_arm: Unknown Relocation, %i", type); - break; + return 2; } + return 0; } void *Elf32Relocate(void *Base, char **envp, const char *Filename) @@ -202,8 +213,8 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer char *dynstrtab = NULL; // .dynamic String Table Elf32_Sym *dynsymtab; - void (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff); - auto void _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend); + int (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff); + auto int _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend); DEBUGS("ElfRelocate: (Base=0x%x)", Base); @@ -236,7 +247,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) // Adjust "Real" Base iBaseDiff = (intptr_t)Base - iRealBase; - + // hdr->entrypoint += iBaseDiff; // Adjust Entrypoint // Check if a PT_DYNAMIC segement was found @@ -244,7 +255,19 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base); return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff); } - + + // Allow writing to read-only segments, just in case they need to be relocated + // - Will be reversed at the end of the function + for( i = 0; i < iSegmentCount; i ++ ) + { + if(phtab[i].Type == PT_LOAD && phtab[i].Flags & PF_R ) { + uintptr_t addr = phtab[i].VAddr + iBaseDiff; + uintptr_t end = addr + phtab[i].MemSize; + for( ; addr < end; addr += PAGE_SIZE ) + SysSetMemFlags(addr, 0, 1); // Unset RO + } + } + // Adjust Dynamic Table dynamicTab = (void *)( (intptr_t)dynamicTab + iBaseDiff ); @@ -340,12 +363,12 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) DEBUGS(" elf_relocate: Beginning Relocation"); - void _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend) + int _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend) { int type = ELF32_R_TYPE(r_info); int sym = ELF32_R_SYM(r_info); const char *symname = dynstrtab + dynsymtab[sym].nameOfs; - do_relocate(r_info, ptr, addend, type, bRela, symname, iBaseDiff); + return do_relocate(r_info, ptr, addend, type, bRela, symname, iBaseDiff); } switch(hdr->machine) @@ -358,11 +381,14 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) break; default: SysDebug("Elf32Relocate: Unknown machine type %i", hdr->machine); + // TODO: Chuck sad break; } DEBUGS("do_relocate = %p (%p or %p)", do_relocate, &elf_doRelocate_386, &elf_doRelocate_arm); + int fail = 0; + // Parse Relocation Entries if(rel && relSz) { @@ -373,7 +399,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) { //DEBUGS(" Rel %i: 0x%x+0x%x", i, iBaseDiff, rel[i].r_offset); ptr = (void*)(iBaseDiff + rel[i].r_offset); - _doRelocate(rel[i].r_info, ptr, 0, *ptr); + fail |= _doRelocate(rel[i].r_info, ptr, 0, *ptr); } } // Parse Relocation Entries @@ -385,7 +411,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) for( i = 0; i < j; i++ ) { ptr = (void*)(iBaseDiff + rela[i].r_offset); - _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend); + fail |= _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend); } } @@ -402,7 +428,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename) for(i=0;ientrypoint + iBaseDiff, __builtin_return_address(0)); return (void*)(intptr_t)( hdr->entrypoint + iBaseDiff ); } @@ -663,45 +705,51 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) } // Relocation function - void _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend) + int _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend) { int sym = ELF64_R_SYM(r_info); int type = ELF64_R_TYPE(r_info); const char *symname = strtab + symtab[sym].st_name; + void *symval; switch( type ) { case R_X86_64_NONE: break; case R_X86_64_64: - *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL) + addend; + if( !GetSymbol(symname, &symval, NULL) ) return 1; + *(uint64_t*)ptr = (uintptr_t)symval + addend; break; case R_X86_64_COPY: { size_t size; - void *symptr = GetSymbol(symname, &size); - memcpy(ptr, symptr, size); + if( !GetSymbol(symname, &symval, &size) ) return 1; + memcpy(ptr, symval, size); } break; case R_X86_64_GLOB_DAT: - *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL); + if( !GetSymbol(symname, &symval, NULL) ) return 1; + *(uint64_t*)ptr = (uintptr_t)symval; break; case R_X86_64_JUMP_SLOT: - *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL); + if( !GetSymbol(symname, &symval, NULL) ) return 1; + *(uint64_t*)ptr = (uintptr_t)symval; break; case R_X86_64_RELATIVE: *(uint64_t*)ptr = (uintptr_t)Base + addend; break; default: SysDebug("ld-acess - _Elf64DoReloc: Unknown relocation type %i", type); - break; + return 2; } + return 0; } + int fail = 0; if( rel ) { DEBUGS("rel_count = %i", rel_count); for( i = 0; i < rel_count; i ++ ) { uint64_t *ptr = (void *)(uintptr_t)( rel[i].r_offset + baseDiff ); - _Elf64DoReloc( rel[i].r_info, ptr, *ptr); + fail |= _Elf64DoReloc( rel[i].r_info, ptr, *ptr); } } @@ -711,7 +759,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) for( i = 0; i < rela_count; i ++ ) { uint64_t *ptr = (void *)(uintptr_t)( rela[i].r_offset + baseDiff ); - _Elf64DoReloc( rela[i].r_info, ptr, rela[i].r_addend ); + fail |= _Elf64DoReloc( rela[i].r_info, ptr, rela[i].r_addend ); } } @@ -724,7 +772,7 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) for( i = 0; i < count; i ++ ) { uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff ); - _Elf64DoReloc( plt[i].r_info, ptr, *ptr); + fail |= _Elf64DoReloc( plt[i].r_info, ptr, *ptr); } } else { @@ -734,11 +782,16 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) for( i = 0; i < count; i ++ ) { uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff ); - _Elf64DoReloc( plt[i].r_info, ptr, plt[i].r_addend); + fail |= _Elf64DoReloc( plt[i].r_info, ptr, plt[i].r_addend); } } } + if( fail ) { + DEBUGS("Elf64Relocate: Failure"); + return NULL; + } + { void *ret = (void *)(uintptr_t)(hdr->e_entry + baseDiff); DEBUGS("Elf64Relocate: Relocations done, return %p", ret); diff --git a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h index 5505479d..88502b04 100644 --- a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h +++ b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h @@ -90,5 +90,6 @@ extern int SysGetMessage(pid_t *src, uint buflen, void *Data); // --- MEMORY --- uint64_t _SysGetPhys(uint vaddr); uint64_t _SysAllocate(uint vaddr); +uint32_t SysSetMemFlags(uint vaddr, uint32_t flags, uint32_t mask); #endif diff --git a/Usermode/Libraries/ld-acess.so_src/loadlib.c b/Usermode/Libraries/ld-acess.so_src/loadlib.c index 3f8e6742..f59caf2e 100644 --- a/Usermode/Libraries/ld-acess.so_src/loadlib.c +++ b/Usermode/Libraries/ld-acess.so_src/loadlib.c @@ -15,7 +15,6 @@ // === PROTOTYPES === void *IsFileLoaded(const char *file); - int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size); // === IMPORTS === extern const struct { @@ -88,6 +87,9 @@ void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp) // Load Symbols fEntry = DoRelocate( base, envp, filename ); + if( !fEntry ) { + return 0; + } // Call Entrypoint DEBUGS(" LoadLibrary: '%s' Entry %p", SoName, fEntry); @@ -198,26 +200,31 @@ void Unload(void *Base) \fn Uint GetSymbol(const char *name) \brief Gets a symbol value from a loaded library */ -void *GetSymbol(const char *name, size_t *Size) +int GetSymbol(const char *name, void **Value, size_t *Size) { int i; - void *ret; //SysDebug("ciNumLocalExports = %i", ciNumLocalExports); for(i=0;i