diff options
| author | Alan Somers <asomers@FreeBSD.org> | 2019-06-27 23:50:54 +0000 |
|---|---|---|
| committer | Alan Somers <asomers@FreeBSD.org> | 2019-06-27 23:50:54 +0000 |
| commit | 7f49ce7a0b5f0d501d233308d73ccb1bf191a68b (patch) | |
| tree | e83ad4ddd396607f9b0ea1a3a8262ce92aa3fcf9 /libexec | |
| parent | c1afff113ceec2c78b96b2e52379cb5a9275d5fb (diff) | |
| parent | e3680954376d380b897066a542ba7cf0b7ba9124 (diff) | |
Notes
Diffstat (limited to 'libexec')
| -rwxr-xr-x | libexec/rc/rc.d/motd | 12 | ||||
| -rw-r--r-- | libexec/rtld-elf/debug.h | 4 | ||||
| -rw-r--r-- | libexec/rtld-elf/powerpc/reloc.c | 27 | ||||
| -rw-r--r-- | libexec/rtld-elf/powerpc/rtld_start.S | 63 | ||||
| -rw-r--r-- | libexec/rtld-elf/rtld.c | 6 | ||||
| -rw-r--r-- | libexec/rtld-elf/rtld.h | 4 | ||||
| -rw-r--r-- | libexec/rtld-elf/rtld_printf.h | 1 |
7 files changed, 84 insertions, 33 deletions
diff --git a/libexec/rc/rc.d/motd b/libexec/rc/rc.d/motd index acb376723e804..2c06187c1d2a2 100755 --- a/libexec/rc/rc.d/motd +++ b/libexec/rc/rc.d/motd @@ -37,11 +37,15 @@ motd_start() uname -v | sed -e 's,^\([^#]*\) #\(.* [1-2][0-9][0-9][0-9]\).*/\([^\]*\) $,\1 (\3) #\2,' > ${T} awk '{if (NR == 1) {if ($1 == "FreeBSD") {next} else {print "\n"$0}} else {print}}' < /etc/motd >> ${T} - cmp -s $T /etc/motd || { - cp $T /etc/motd + if ! cmp -s $T /etc/motd; then + mv -f $T /etc/.motd.tmp + fsync /etc/.motd.tmp + mv -f /etc/.motd.tmp /etc/motd chmod ${PERMS} /etc/motd - } - rm -f $T + fsync /etc + else + rm -f $T + fi check_startmsgs && echo '.' } diff --git a/libexec/rtld-elf/debug.h b/libexec/rtld-elf/debug.h index 1ad0323b42f99..4dcefbabdb45f 100644 --- a/libexec/rtld-elf/debug.h +++ b/libexec/rtld-elf/debug.h @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #include <string.h> -#include <unistd.h> +#include "rtld_printf.h" void debug_printf(const char *, ...) __printflike(1, 2); extern int debug; @@ -57,7 +57,7 @@ extern int debug; #define assert(cond) ((cond) ? (void) 0 : \ (msg(_MYNAME ": assert failed: " __FILE__ ":" \ __XSTRING(__LINE__) "\n"), abort())) -#define msg(s) write(STDOUT_FILENO, s, strlen(s)) +#define msg(s) rtld_putstr(s) #define trace() msg(_MYNAME ": " __XSTRING(__LINE__) "\n") diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c index 382417ca34903..c923c73260796 100644 --- a/libexec/rtld-elf/powerpc/reloc.c +++ b/libexec/rtld-elf/powerpc/reloc.c @@ -57,6 +57,8 @@ #define JMPTAB_BASE(N) (18 + N*2 + ((N > PLT_EXTENDED_BEGIN) ? \ (N - PLT_EXTENDED_BEGIN)*2 : 0)) +void _rtld_bind_secureplt_start(void); + /* * Process the R_PPC_COPY relocations */ @@ -361,6 +363,11 @@ reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela) if (reloff < 0) return (-1); + if (obj->gotptr != NULL) { + *where += (Elf_Addr)obj->relocbase; + return (0); + } + pltlongresolve = obj->pltgot + 5; pltresolve = pltlongresolve + 5; @@ -425,7 +432,7 @@ reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused) * Sync the icache for the byte range represented by the * trampoline routines and call slots. */ - if (obj->pltgot != NULL) + if (obj->pltgot != NULL && obj->gotptr == NULL) __syncicache(obj->pltgot, JMPTAB_BASE(N)*4); return (0); @@ -501,6 +508,14 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, */ offset = target - (Elf_Addr)wherep; + if (obj->gotptr != NULL) { + assert(wherep >= (Elf_Word *)obj->pltgot); + assert(wherep < + (Elf_Word *)obj->pltgot + obj->pltrelasize); + *wherep = target; + goto out; + } + if (abs((int)offset) < 32*1024*1024) { /* inside 32MB? */ /* b value # branch directly */ *wherep = 0x48000000 | (offset & 0x03fffffc); @@ -579,6 +594,16 @@ init_pltgot(Obj_Entry *obj) return; } + /* Handle Secure-PLT first, if applicable. */ + if (obj->gotptr != NULL) { + obj->gotptr[1] = (Elf_Addr)_rtld_bind_secureplt_start; + obj->gotptr[2] = (Elf_Addr)obj; + dbg("obj %s secure-plt gotptr=%p start=%p obj=%p", + obj->path, obj->gotptr, + (void *)obj->gotptr[1], (void *)obj->gotptr[2]); + return; + } + /* * From the SVR4 PPC ABI: * diff --git a/libexec/rtld-elf/powerpc/rtld_start.S b/libexec/rtld-elf/powerpc/rtld_start.S index 28ec19bad110e..5a2cd7bd2652f 100644 --- a/libexec/rtld-elf/powerpc/rtld_start.S +++ b/libexec/rtld-elf/powerpc/rtld_start.S @@ -52,35 +52,22 @@ _ENTRY(.rtld_start) * - use link-time constants to determine offset to the * _DYNAMIC section and the GOT. Add these to the PC to * convert to absolute addresses. - * - sync icache to allow execution of the SVR4 ABI-specified - * blrl instruction preceding the GOT - * - Use this instruction to determine the GOT absolute address * - read GOT[0], which is the SVR4 ABI-specified link-time * value of _DYNAMIC. Subtract this value from the absolute * value to determine the load address * - call reloc_non_plt_self() to fix up ld-elf.so's relocations */ - bl 1f - .long _DYNAMIC-. - .long _GLOBAL_OFFSET_TABLE_-. /* branch lr + 4 */ -1: - mflr %r3 /* PC value at .long */ - lwz %r4,4(%r3) - add %r4,%r4,%r3 /* &_GLOBAL_OFFSET_TABLE-4, blrl insn. */ - dcbst %r0,%r4 /* sync i-cache with d-cache */ - sync - icbi %r0,%r4 - isync - - lwz %r4,0(%r3) /* offset to _DYNAMIC */ - add %r3,%r4,%r3 /* r3 = &_DYNAMIC, absolute value */ - - bl _GLOBAL_OFFSET_TABLE_@local-4 - mflr %r4 /* &_GLOBAL_OFFSET_TABLE_, absolute value */ - lwz %r4,0(%r4) /* linker &_DYNAMIC, from got[0] */ - subf %r4,%r4,%r3 /* subtract to calculate relocbase */ - - bl reloc_non_plt_self@plt /* reloc_non_plt_self(&_DYNAMIC,base) */ + bcl 20,31,1f +1: mflr %r30 + mr %r3,%r30 # save for _DYNAMIC + addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha + addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l + addis %r3,%r3,_DYNAMIC-1b@ha # get _DYNAMIC actual address + addi %r3,%r3,_DYNAMIC-1b@l + lwz %r28,0(%r30) # get base-relative &_DYNAMIC + sub %r28,%r3,%r28 # r28 = relocbase + mr %r4,%r28 # r4 = relocbase + bl reloc_non_plt_self /* reloc_non_plt_self(&_DYNAMIC,base) */ /* * The _rtld() function likes to see a stack layout containing @@ -95,7 +82,7 @@ _ENTRY(.rtld_start) addi %r4,%r1,8 /* &exit_proc on stack */ addi %r5,%r1,12 /* &obj_main on stack */ - bl _rtld@plt /* &_start = _rtld(sp, &exit_proc, &obj_main)*/ + bl _rtld /* &_start = _rtld(sp, &exit_proc, &obj_main)*/ mtlr %r3 /* @@ -115,6 +102,29 @@ _ENTRY(.rtld_start) sc /* + * _rtld_bind_secureplt_start() + * + * Call into the MI binder (Secure-PLT stub). + * secure-plt expects %r11 to be the offset to the rela entry. + * bss-plt expects %r11 to be index of the rela entry. + * So for bss-plt, we multiply the index by 12 to get the offset. + */ +_ENTRY(_rtld_bind_secureplt_start) + stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr + stw %r0,20(%r1) # save r0 + + /* + * Instead of division which is costly we will use multiplicative + * inverse. a / n = ((a * inv(n)) >> 32) + * where inv(n) = (0x100000000 + n - 1) / n + */ + mr %r0,%r11 + lis %r11,0x15555556@h # load multiplicative inverse of 12 + ori %r11,%r11,0x15555556@l + mulhwu %r11,%r11,%r0 # get high half of multiplication + b 1f + +/* * _rtld_bind_start() * * Call into the MI binder. This routine is reached via the PLT call cell, @@ -129,6 +139,7 @@ _ENTRY(.rtld_start) _ENTRY(_rtld_bind_start) stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr stw %r0,20(%r1) # save r0 +1: mflr %r0 stw %r0,16(%r1) # save lr mfcr %r0 @@ -137,7 +148,7 @@ _ENTRY(_rtld_bind_start) mr %r3,%r12 # obj mulli %r4,%r11,12 # rela index * sizeof(Elf_Rela) - bl _rtld_bind@PLT # target addr = _rtld_bind(obj, reloff) + bl _rtld_bind # target addr = _rtld_bind(obj, reloff) mtctr %r3 # move absolute target addr into ctr lmw %r3,24(%r1) # restore r3-r31 diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 7cdd5c58c5dc8..ece58e1382358 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -1286,10 +1286,16 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, #endif +#ifdef __powerpc__ #ifdef __powerpc64__ case DT_PPC64_GLINK: obj->glink = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); break; +#else + case DT_PPC_GOT: + obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); + break; +#endif #endif case DT_FLAGS_1: diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index d7ef9d56b8d03..fc9f102558110 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -190,8 +190,12 @@ typedef struct Struct_Obj_Entry { Elf_Word gotsym; /* First dynamic symbol in GOT */ Elf_Addr *mips_pltgot; /* Second PLT GOT */ #endif +#ifdef __powerpc__ #ifdef __powerpc64__ Elf_Addr glink; /* GLINK PLT call stub section */ +#else + Elf_Addr *gotptr; /* GOT pointer (secure-plt only) */ +#endif #endif const Elf_Verneed *verneed; /* Required versions. */ diff --git a/libexec/rtld-elf/rtld_printf.h b/libexec/rtld-elf/rtld_printf.h index 5cfcc6d062f1c..3d3a0480eccea 100644 --- a/libexec/rtld-elf/rtld_printf.h +++ b/libexec/rtld-elf/rtld_printf.h @@ -31,6 +31,7 @@ #define RTLD_PRINTF_H 1 #include <sys/cdefs.h> +#include <stdarg.h> #include <unistd.h> int rtld_snprintf(char *buf, size_t bufsize, const char *fmt, ...) |
