Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ld.elf_so Add secure-plt support for powerpc to ld.e...
details: https://anonhg.NetBSD.org/src/rev/c0d7464da3ce
branches: trunk
changeset: 760889:c0d7464da3ce
user: matt <matt%NetBSD.org@localhost>
date: Sun Jan 16 01:22:29 2011 +0000
description:
Add secure-plt support for powerpc to ld.elf_so. As part of this, we have to
stop calling into the GOT/_DYNAMIC since they are no longer executable.
diffstat:
libexec/ld.elf_so/arch/powerpc/ppc_reloc.c | 142 +++++++++++++++++----------
libexec/ld.elf_so/arch/powerpc/rtld_start.S | 46 +++++---
libexec/ld.elf_so/headers.c | 9 +-
libexec/ld.elf_so/rtld.h | 5 +-
4 files changed, 127 insertions(+), 75 deletions(-)
diffs (truncated from 376 to 300 lines):
diff -r 0c13cebb361a -r c0d7464da3ce libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
--- a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c Sun Jan 16 01:13:10 2011 +0000
+++ b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c Sun Jan 16 01:22:29 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ppc_reloc.c,v 1.45 2010/08/06 16:33:18 joerg Exp $ */
+/* $NetBSD: ppc_reloc.c,v 1.46 2011/01/16 01:22:29 matt Exp $ */
/*-
* Copyright (C) 1998 Tsubai Masanari
@@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: ppc_reloc.c,v 1.45 2010/08/06 16:33:18 joerg Exp $");
+__RCSID("$NetBSD: ppc_reloc.c,v 1.46 2011/01/16 01:22:29 matt Exp $");
#endif /* not lint */
#include <stdarg.h>
@@ -50,10 +50,11 @@
((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
#define l(x) ((u_int32_t)(x) & 0xffff)
-void _rtld_bind_start(void);
+void _rtld_bind_bssplt_start(void);
+void _rtld_bind_secureplt_start(void);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
-static inline int _rtld_relocate_plt_object(const Obj_Entry *,
+static int _rtld_relocate_plt_object(const Obj_Entry *,
const Elf_Rela *, int, Elf_Addr *);
/*
@@ -67,7 +68,7 @@
*/
/*
- * Setup the plt glue routines.
+ * Setup the plt glue routines (for bss-plt).
*/
#define PLTCALL_SIZE 20
#define PLTRESOLVE_SIZE 24
@@ -75,34 +76,42 @@
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
- Elf_Word *pltcall, *pltresolve;
- Elf_Word *jmptab;
- int N = obj->pltrelalim - obj->pltrela;
+ /*
+ * Secure-PLT is much more sane.
+ */
+ if (obj->gotptr != NULL) {
+ obj->gotptr[1] = (Elf_Addr) _rtld_bind_secureplt_start;
+ obj->gotptr[2] = (Elf_Addr) obj;
+ } else {
+ Elf_Word *pltcall, *pltresolve;
+ Elf_Word *jmptab;
+ int N = obj->pltrelalim - obj->pltrela;
- /* Entries beyond 8192 take twice as much space. */
- if (N > 8192)
- N += N-8192;
+ /* Entries beyond 8192 take twice as much space. */
+ if (N > 8192)
+ N += N-8192;
- pltcall = obj->pltgot;
- jmptab = pltcall + 18 + N * 2;
+ pltcall = obj->pltgot;
+ jmptab = pltcall + 18 + N * 2;
- memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE);
- pltcall[1] |= ha(jmptab);
- pltcall[2] |= l(jmptab);
+ memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE);
+ pltcall[1] |= ha(jmptab);
+ pltcall[2] |= l(jmptab);
- pltresolve = obj->pltgot + 8;
+ pltresolve = obj->pltgot + 8;
- memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE);
- pltresolve[0] |= ha(_rtld_bind_start);
- pltresolve[1] |= l(_rtld_bind_start);
- pltresolve[3] |= ha(obj);
- pltresolve[4] |= l(obj);
+ memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE);
+ pltresolve[0] |= ha(_rtld_bind_bssplt_start);
+ pltresolve[1] |= l(_rtld_bind_bssplt_start);
+ pltresolve[3] |= ha(obj);
+ pltresolve[4] |= l(obj);
- /*
- * Invalidate the icache for only the code part of the PLT
- * (and not the jump table at the end).
- */
- __syncicache(pltcall, (char *)jmptab - (char *)pltcall);
+ /*
+ * Invalidate the icache for only the code part of the PLT
+ * (and not the jump table at the end).
+ */
+ __syncicache(pltcall, (char *)jmptab - (char *)pltcall);
+ }
}
void
@@ -207,44 +216,52 @@
int
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
{
+ Elf_Addr * const pltresolve = obj->pltgot + 8;
const Elf_Rela *rela;
int reloff;
- for (rela = obj->pltrela, reloff = 0; rela < obj->pltrelalim; rela++, reloff++) {
+ for (rela = obj->pltrela, reloff = 0;
+ rela < obj->pltrelalim;
+ rela++, reloff++) {
Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
- int distance;
- Elf_Addr *pltresolve;
assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
- pltresolve = obj->pltgot + 8;
+ if (obj->gotptr != NULL) {
+ /*
+ * For now, simply treat then as relative.
+ */
+ *where += (Elf_Addr)obj->relocbase;
+ } else {
+ int distance;
- if (reloff < 32768) {
- /* li r11,reloff */
- *where++ = 0x39600000 | reloff;
- } else {
- /* lis r11,ha(reloff) */
- /* addi r11,l(reloff) */
- *where++ = 0x3d600000 | ha(reloff);
- *where++ = 0x396b0000 | l(reloff);
+ if (reloff < 32768) {
+ /* li r11,reloff */
+ *where++ = 0x39600000 | reloff;
+ } else {
+ /* lis r11,ha(reloff) */
+ /* addi r11,l(reloff) */
+ *where++ = 0x3d600000 | ha(reloff);
+ *where++ = 0x396b0000 | l(reloff);
+ }
+ /* b pltresolve */
+ distance = (Elf_Addr)pltresolve - (Elf_Addr)where;
+ *where++ = 0x48000000 | (distance & 0x03fffffc);
+
+ /*
+ * Icache invalidation is not done for each entry here
+ * because we sync the entire code part of the PLT once
+ * in _rtld_setup_pltgot() after all the entries have been
+ * initialized.
+ */
+ /* __syncicache(where - 3, 12); */
}
- /* b pltresolve */
- distance = (Elf_Addr)pltresolve - (Elf_Addr)where;
- *where++ = 0x48000000 | (distance & 0x03fffffc);
-
- /*
- * Icache invalidation is not done for each entry here
- * because we sync the entire code part of the PLT once
- * in _rtld_setup_pltgot() after all the entries have been
- * initialized.
- */
- /* __syncicache(where - 3, 12); */
}
return 0;
}
-static inline int
+static int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff, Elf_Addr *tp)
{
Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
@@ -267,7 +284,15 @@
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)value));
- if (abs(distance) < 32*1024*1024) { /* inside 32MB? */
+ if (obj->gotptr != NULL) {
+ /*
+ * For Secure-PLT we simply replace the entry in GOT with the address
+ * of the routine.
+ */
+ assert(where >= (Elf_Word *)obj->pltgot);
+ assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
+ *where = value;
+ } else if (abs(distance) < 32*1024*1024) { /* inside 32MB? */
/* b value # branch directly */
*where = 0x48000000 | (distance & 0x03fffffc);
__syncicache(where, 4);
@@ -288,10 +313,21 @@
/* li r11,reloff */
*where++ = 0x39600000 | reloff;
} else {
+#ifdef notyet
+ /* lis r11,ha(value) */
+ /* addi r11,l(value) */
+ /* mtctr r11 */
+ /* bctr */
+ *where++ = 0x3d600000 | ha(value);
+ *where++ = 0x396b0000 | l(value);
+ *where++ = 0x7d6903a6;
+ *where++ = 0x4e800420;
+#else
/* lis r11,ha(reloff) */
/* addi r11,l(reloff) */
*where++ = 0x3d600000 | ha(reloff);
*where++ = 0x396b0000 | l(reloff);
+#endif
}
/* b pltcall */
distance = (Elf_Addr)pltcall - (Elf_Addr)where;
@@ -307,7 +343,7 @@
caddr_t
_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
{
- const Elf_Rela *rela = obj->pltrela + reloff;
+ const Elf_Rela *rela = (const void *)((const char *)obj->pltrela + reloff);
Elf_Addr new_value;
int err;
diff -r 0c13cebb361a -r c0d7464da3ce libexec/ld.elf_so/arch/powerpc/rtld_start.S
--- a/libexec/ld.elf_so/arch/powerpc/rtld_start.S Sun Jan 16 01:13:10 2011 +0000
+++ b/libexec/ld.elf_so/arch/powerpc/rtld_start.S Sun Jan 16 01:22:29 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld_start.S,v 1.13 2002/12/04 01:19:37 thorpej Exp $ */
+/* $NetBSD: rtld_start.S,v 1.14 2011/01/16 01:22:29 matt Exp $ */
/*-
* Copyright (C) 1998 Tsubai Masanari
@@ -44,24 +44,22 @@
/* stw %r7,28(%r1) # cleanup (always 0) */
stw %r8,32(%r1) # ps_strings
- bl _GLOBAL_OFFSET_TABLE_-4@local
- mflr %r31 # r31 = (real) GOT
- lwz %r28,0(%r31) # base-relative &_DYNAMIC
-
- bl 0f # lr = next instruction
- b _DYNAMIC@local
-0: mflr %r30
- lwz %r29,0(%r30) # load instruction contents
- rlwinm %r29,%r29,0,6,29 # extract PC offset
- add %r3,%r29,%r30 # r3 = &_DYNAMIC
- sub %r28,%r3,%r28
+ 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 _rtld_relocate_nonplt_self@plt
+ bl _rtld_relocate_nonplt_self
lwz %r3,16(%r1)
addi %r3,%r3,-12 # sp = &argv[-3] /* XXX */
mr %r4,%r28 # r4 = relocbase
- bl _rtld@plt # _start = _rtld(sp, relocbase)
+ bl _rtld # _start = _rtld(sp, relocbase)
mtlr %r3
lwz %r3,12(%r1) # argc
@@ -77,11 +75,20 @@
li %r0,1 # _exit()
sc
+END(_rtld_start)
- .globl _rtld_bind_start
.globl _rtld_bind
-_rtld_bind_start:
+/*
+ * 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_NOPROFILE(_rtld_bind_bssplt_start)
+ slwi %r11,%r11,2
+ add %r0,%r11,%r11
+ add %r11,%r11,%r0
+ENTRY_NOPROFILE(_rtld_bind_secureplt_start)
stwu %r1,-160(%r1)
stw %r0,20(%r1)
@@ -93,7 +100,7 @@
Home |
Main Index |
Thread Index |
Old Index