Date: Tue, 25 Jun 2019 00:40:44 +0000 (UTC) From: Justin Hibbits <jhibbits@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r349350 - in head: contrib/gcc/config/rs6000 lib/libc/powerpc lib/libc/powerpc/gen lib/libc/powerpc/sys libexec/rtld-elf libexec/rtld-elf/powerpc sys/powerpc/powerpc Message-ID: <201906250040.x5P0ejJP086572@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhibbits Date: Tue Jun 25 00:40:44 2019 New Revision: 349350 URL: https://svnweb.freebsd.org/changeset/base/349350 Log: powerpc: Transition to Secure-PLT, like most other OSs Summary: PowerPC has two PLT models: BSS-PLT and Secure-PLT. BSS-PLT uses runtime code generation to generate the PLT stubs. Secure-PLT was introduced with GCC 4.1 and Binutils 2.17 (base has GCC 4.2.1 and Binutils 2.17), and is a more secure PLT format, using a read-only linkage table, with the dynamic linker populating a non-executable index table. This is the libc, rtld, and kernel support only. The toolchain and build parts will be updated separately. Reviewed By: nwhitehorn, bdragon, pfg Differential Revision: https://reviews.freebsd.org/D20598 MFC after: 1 month Modified: head/contrib/gcc/config/rs6000/tramp.asm head/lib/libc/powerpc/SYS.h head/lib/libc/powerpc/gen/_ctx_start.S head/lib/libc/powerpc/sys/cerror.S head/libexec/rtld-elf/powerpc/reloc.c head/libexec/rtld-elf/powerpc/rtld_start.S head/libexec/rtld-elf/rtld.c head/libexec/rtld-elf/rtld.h head/sys/powerpc/powerpc/machdep.c Modified: head/contrib/gcc/config/rs6000/tramp.asm ============================================================================== --- head/contrib/gcc/config/rs6000/tramp.asm Mon Jun 24 23:18:42 2019 (r349349) +++ head/contrib/gcc/config/rs6000/tramp.asm Tue Jun 25 00:40:44 2019 (r349350) @@ -38,6 +38,7 @@ .file "tramp.asm" .section ".text" #include "ppc-asm.h" + #include "auto-host.h" #ifndef __powerpc64__ .type trampoline_initial,@object @@ -105,7 +106,7 @@ FUNC_START(__trampoline_setup) blr .Labort: -#if defined SHARED && defined HAVE_AS_REL16 +#if (defined(__PIC__) || defined(__pic__)) && defined HAVE_AS_REL16 bcl 20,31,1f 1: mflr r30 addis r30,r30,_GLOBAL_OFFSET_TABLE_-1b@ha Modified: head/lib/libc/powerpc/SYS.h ============================================================================== --- head/lib/libc/powerpc/SYS.h Mon Jun 24 23:18:42 2019 (r349349) +++ head/lib/libc/powerpc/SYS.h Tue Jun 25 00:40:44 2019 (r349350) @@ -44,7 +44,7 @@ #define SYSCALL(name) \ .text; \ .align 2; \ -2: b PIC_PLT(CNAME(HIDENAME(cerror))); \ +2: b CNAME(HIDENAME(cerror)); \ ENTRY(__sys_##name); \ WEAK_REFERENCE(__sys_##name, name); \ WEAK_REFERENCE(__sys_##name, _##name); \ @@ -58,15 +58,14 @@ ENTRY(__sys_##name); \ WEAK_REFERENCE(__sys_##name, _##name); \ _SYSCALL(name); \ bnslr; \ - b PIC_PLT(CNAME(HIDENAME(cerror))) + b CNAME(HIDENAME(cerror)) #define RSYSCALL(name) \ .text; \ .align 2; \ -2: b PIC_PLT(CNAME(HIDENAME(cerror))); \ ENTRY(__sys_##name); \ WEAK_REFERENCE(__sys_##name, name); \ WEAK_REFERENCE(__sys_##name, _##name); \ _SYSCALL(name); \ bnslr; \ - b PIC_PLT(CNAME(HIDENAME(cerror))) + b CNAME(HIDENAME(cerror)) Modified: head/lib/libc/powerpc/gen/_ctx_start.S ============================================================================== --- head/lib/libc/powerpc/gen/_ctx_start.S Mon Jun 24 23:18:42 2019 (r349349) +++ head/lib/libc/powerpc/gen/_ctx_start.S Tue Jun 25 00:40:44 2019 (r349350) @@ -35,11 +35,18 @@ mtlr %r14 blrl /* branch to start function */ mr %r3,%r15 /* pass pointer to ucontext as argument */ - bl PIC_PLT(CNAME(_ctx_done)) /* branch to ctxt completion func */ + bl CNAME(_ctx_done) /* branch to ctxt completion func */ + /* * we should never return from the * above branch. */ + /* Don't bother saving off %r30, we're already in a bad state. */ + 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 bl PIC_PLT(CNAME(abort)) /* abort */ END(_cts_start) Modified: head/lib/libc/powerpc/sys/cerror.S ============================================================================== --- head/lib/libc/powerpc/sys/cerror.S Mon Jun 24 23:18:42 2019 (r349349) +++ head/lib/libc/powerpc/sys/cerror.S Tue Jun 25 00:40:44 2019 (r349350) @@ -40,16 +40,27 @@ __FBSDID("$FreeBSD$"); */ HIDENAME(cerror): mflr %r0 - stwu %r1,-16(%r1) /* allocate new stack frame */ - stw %r0,20(%r1) /* and save lr, r31 */ - stw %r31,8(%r1) + stwu %r1,-20(%r1) /* allocate new stack frame */ + stw %r0,24(%r1) /* and save lr, r31 */ + stw %r31,12(%r1) +#ifdef __PIC__ + stw %r30,8(%r1) + bcl 20,31,1f +1: + mflr %r30 + addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha + addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l +#endif mr %r31,%r3 /* stash errval in callee-saved register */ bl PIC_PLT(CNAME(__error)) stw %r31,0(%r3) /* store errval into &errno */ - lwz %r0,20(%r1) - lwz %r31,8(%r1) + lwz %r0,24(%r1) + lwz %r31,12(%r1) +#ifdef __PIC__ + lwz %r30,8(%r1) +#endif mtlr %r0 - la %r1,16(%r1) + la %r1,20(%r1) li %r3,-1 li %r4,-1 blr /* return to callers caller */ Modified: head/libexec/rtld-elf/powerpc/reloc.c ============================================================================== --- head/libexec/rtld-elf/powerpc/reloc.c Mon Jun 24 23:18:42 2019 (r349349) +++ head/libexec/rtld-elf/powerpc/reloc.c Tue Jun 25 00:40:44 2019 (r349350) @@ -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, RtldLock * 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); @@ -576,6 +591,16 @@ init_pltgot(Obj_Entry *obj) pltcall = obj->pltgot; if (pltcall == NULL) { + 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; } Modified: head/libexec/rtld-elf/powerpc/rtld_start.S ============================================================================== --- head/libexec/rtld-elf/powerpc/rtld_start.S Mon Jun 24 23:18:42 2019 (r349349) +++ head/libexec/rtld-elf/powerpc/rtld_start.S Tue Jun 25 00:40:44 2019 (r349350) @@ -52,36 +52,23 @@ _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 + 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) */ - 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) */ - /* * The _rtld() function likes to see a stack layout containing * { argc, argv[0], argv[1] ... argv[N], 0, env[0], ... , env[N] } @@ -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 Modified: head/libexec/rtld-elf/rtld.c ============================================================================== --- head/libexec/rtld-elf/rtld.c Mon Jun 24 23:18:42 2019 (r349349) +++ head/libexec/rtld-elf/rtld.c Tue Jun 25 00:40:44 2019 (r349350) @@ -1286,10 +1286,16 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_D #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: Modified: head/libexec/rtld-elf/rtld.h ============================================================================== --- head/libexec/rtld-elf/rtld.h Mon Jun 24 23:18:42 2019 (r349349) +++ head/libexec/rtld-elf/rtld.h Tue Jun 25 00:40:44 2019 (r349350) @@ -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. */ Modified: head/sys/powerpc/powerpc/machdep.c ============================================================================== --- head/sys/powerpc/powerpc/machdep.c Mon Jun 24 23:18:42 2019 (r349349) +++ head/sys/powerpc/powerpc/machdep.c Tue Jun 25 00:40:44 2019 (r349350) @@ -595,3 +595,16 @@ bzero(void *buf, size_t len) len--; } } + +/* __stack_chk_fail_local() is called in secure-plt (32-bit). */ +#if !defined(__powerpc64__) +extern void __stack_chk_fail(void); +void __stack_chk_fail_local(void); + +void +__stack_chk_fail_local(void) +{ + + __stack_chk_fail(); +} +#endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201906250040.x5P0ejJP086572>