summaryrefslogtreecommitdiff
path: root/libexec/ld.so
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2015-05-29 19:12:27 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2015-05-29 19:12:27 +0000
commit770018de067bcb2c147f79e8fcf593d3360d0e6b (patch)
tree2f341d64e2234deeb8f70e5c8f806b6d92118031 /libexec/ld.so
parent4d1bf4263682881620e31cb1fe5883f4d72eaa57 (diff)
Make ld.so on alpha cope with binaries built with secureplt (where secure here
means read-only, which our ld.so already enforced, but a smaller plt section).
Diffstat (limited to 'libexec/ld.so')
-rw-r--r--libexec/ld.so/alpha/ldasm.S82
-rw-r--r--libexec/ld.so/alpha/rtld_machine.c87
2 files changed, 130 insertions, 39 deletions
diff --git a/libexec/ld.so/alpha/ldasm.S b/libexec/ld.so/alpha/ldasm.S
index 4448cd4a228..42c93dd9a2e 100644
--- a/libexec/ld.so/alpha/ldasm.S
+++ b/libexec/ld.so/alpha/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.28 2014/07/28 04:28:43 guenther Exp $ */
+/* $OpenBSD: ldasm.S,v 1.29 2015/05/29 19:12:26 miod Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -146,8 +146,8 @@ NESTED_NOPROFILE(_dl_bind_start, 0, 168, ra, 0, 0)
* Load our global pointer. Note, can't use pv, since it is
* already used by the PLT code.
*/
- br t0, L100
-L100: LDGP(t0)
+ br t0, 1f
+1: LDGP(t0)
/* Set up the arguments for _dl_bind. */
subq at_reg, t12, a1
@@ -193,6 +193,82 @@ L100: LDGP(t0)
jmp zero, (pv)
END(_dl_bind_start)
+/*
+ * Lazy binding entry point, called via secure (read-only) PLT.
+ */
+NESTED_NOPROFILE(_dl_bind_secureplt, 0, 168, ra, 0, 0)
+ .set noat
+ /* at_reg and t11 already used by PLT code. */
+
+ /*
+ * Allocate stack frame and preserve all registers that the caller
+ * would have normally saved themselves.
+ */
+ lda sp, -160(sp)
+ stq ra, 0(sp)
+ stq v0, 8(sp)
+ stq t0, 16(sp)
+ stq t1, 24(sp)
+ stq t2, 32(sp)
+ stq t3, 40(sp)
+ stq t4, 48(sp)
+ stq t5, 56(sp)
+ stq t6, 64(sp)
+ stq t7, 72(sp)
+ stq a0, 80(sp)
+ stq a1, 88(sp)
+ stq a2, 96(sp)
+ stq a3, 104(sp)
+ stq a4, 112(sp)
+ stq a5, 120(sp)
+ stq t8, 128(sp)
+ stq t9, 136(sp)
+ stq t10, 144(sp)
+ stq gp, 152(sp)
+
+ /*
+ * Load our global pointer. Note, can't use pv, since it is
+ * already used by the PLT code.
+ */
+ br t0, 1f
+1: LDGP(t0)
+
+ /* Set up the arguments for _dl_bind. */
+ mov at_reg, a0 /* object */
+ mov t11, a1 /* reloff as computed by the plt resolver */
+ CALL(_dl_bind)
+
+ /* Move the destination address into position. */
+ mov v0, pv
+
+ /* Restore program registers. */
+ ldq ra, 0(sp)
+ ldq v0, 8(sp)
+ ldq t0, 16(sp)
+ ldq t1, 24(sp)
+ ldq t2, 32(sp)
+ ldq t3, 40(sp)
+ ldq t4, 48(sp)
+ ldq t5, 56(sp)
+ ldq t6, 64(sp)
+ ldq t7, 72(sp)
+ ldq a0, 80(sp)
+ ldq a1, 88(sp)
+ ldq a2, 96(sp)
+ ldq a3, 104(sp)
+ ldq a4, 112(sp)
+ ldq a5, 120(sp)
+ ldq t8, 128(sp)
+ ldq t9, 136(sp)
+ ldq t10, 144(sp)
+ ldq gp, 152(sp)
+ /* XXX LDGP? */
+
+ /* Pop the stack frame and turn control to the destination. */
+ lda sp, 160(sp)
+ jmp zero, (pv)
+END(_dl_bind_secureplt)
+
/*
* In reality these are not leaves, but they are stubs which does not need
diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c
index ce41b65fd1c..9e55b6dfcb0 100644
--- a/libexec/ld.so/alpha/rtld_machine.c
+++ b/libexec/ld.so/alpha/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.52 2014/12/27 13:13:25 kettenis Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.53 2015/05/29 19:12:26 miod Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -42,6 +42,8 @@
#include "archdep.h"
#include "resolve.h"
+#define DT_PROC(n) ((n) - DT_LOPROC + DT_NUM)
+
int
_dl_md_reloc(elf_object_t *object, int rel, int relasz)
{
@@ -212,17 +214,7 @@ _dl_bind(elf_object_t *object, int reloff)
sigset_t savedmask;
rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff);
-
addr = (Elf_Addr *)(object->obj_base + rela->r_offset);
- if (object->plt_size != 0 && !(*addr >= object->plt_start &&
- *addr < (object->plt_start + object->plt_size ))) {
- /* something is broken, relocation has already occurred */
-#if 0
- DL_DEB(("*addr doesn't point into plt %p obj %s\n",
- *addr, object->load_name));
-#endif
- return *addr;
- }
sym = object->dyn.symtab;
sym += ELF64_R_SYM(rela->r_info);
@@ -239,19 +231,17 @@ _dl_bind(elf_object_t *object, int reloff)
if (sobj->traced && _dl_trace_plt(sobj, symn))
return ooff + this->st_value + rela->r_addend;
- /* if PLT is protected, allow the write */
- if (object->plt_size != 0) {
+ /* if GOT is protected, allow the write */
+ if (object->got_size != 0) {
_dl_thread_bind_lock(0, &savedmask);
- _dl_mprotect(addr, sizeof(Elf_Addr),
- PROT_READ|PROT_WRITE);
+ _dl_mprotect(addr, sizeof(Elf_Addr), PROT_READ | PROT_WRITE);
}
*addr = ooff + this->st_value + rela->r_addend;
- /* if PLT is (to be protected, change back to RO/X */
- if (object->plt_size != 0) {
- _dl_mprotect(addr, sizeof(Elf_Addr),
- PROT_READ);
+ /* if GOT is to be protected, change back to RO */
+ if (object->got_size != 0) {
+ _dl_mprotect(addr, sizeof(Elf_Addr), PROT_READ);
_dl_thread_bind_lock(1, &savedmask);
}
@@ -267,19 +257,27 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
int fails = 0;
Elf_Addr *pltgot;
extern void _dl_bind_start(void); /* XXX */
+ extern void _dl_bind_secureplt(void); /* XXX */
Elf_Addr ooff;
Elf_Addr plt_addr;
const Elf_Sym *this;
+ u_long pltro;
+ pltro = object->Dyn.info[DT_PROC(DT_ALPHA_PLTRO)];
pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT];
object->got_addr = 0;
object->got_size = 0;
- this = NULL;
- ooff = _dl_find_symbol("__got_start", &this,
- SYM_SEARCH_OBJ|SYM_NOWARNNOTFOUND|SYM_PLT, NULL, object, NULL);
- if (this != NULL)
- object->got_addr = ooff + this->st_value;
+ if (pltro != 0 && pltgot != NULL)
+ object->got_addr = (Elf_Addr)pltgot;
+ else {
+ this = NULL;
+ ooff = _dl_find_symbol("__got_start", &this,
+ SYM_SEARCH_OBJ | SYM_NOWARNNOTFOUND | SYM_PLT, NULL,
+ object, NULL);
+ if (this != NULL)
+ object->got_addr = ooff + this->st_value;
+ }
this = NULL;
ooff = _dl_find_symbol("__got_end", &this,
@@ -289,17 +287,29 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
plt_addr = 0;
object->plt_size = 0;
- this = NULL;
- ooff = _dl_find_symbol("__plt_start", &this,
- SYM_SEARCH_OBJ|SYM_NOWARNNOTFOUND|SYM_PLT, NULL, object, NULL);
- if (this != NULL)
- plt_addr = ooff + this->st_value;
+ /*
+ * Do not even attempt to locate the .plt section if we will not
+ * have to write into it.
+ */
+ if (pltro == 0) {
+ if (pltgot != NULL)
+ plt_addr = (Elf_Addr)pltgot;
+ else {
+ this = NULL;
+ ooff = _dl_find_symbol("__plt_start", &this,
+ SYM_SEARCH_OBJ | SYM_NOWARNNOTFOUND | SYM_PLT, NULL,
+ object, NULL);
+ if (this != NULL)
+ plt_addr = ooff + this->st_value;
+ }
- this = NULL;
- ooff = _dl_find_symbol("__plt_end", &this,
- SYM_SEARCH_OBJ|SYM_NOWARNNOTFOUND|SYM_PLT, NULL, object, NULL);
- if (this != NULL)
- object->plt_size = ooff + this->st_value - plt_addr;
+ this = NULL;
+ ooff = _dl_find_symbol("__plt_end", &this,
+ SYM_SEARCH_OBJ | SYM_NOWARNNOTFOUND | SYM_PLT, NULL,
+ object, NULL);
+ if (this != NULL)
+ object->plt_size = ooff + this->st_value - plt_addr;
+ }
if (object->got_addr == 0)
object->got_start = 0;
@@ -339,8 +349,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
}
}
if (pltgot != NULL) {
- pltgot[2] = (Elf_Addr)_dl_bind_start;
- pltgot[3] = (Elf_Addr)object;
+ if (pltro == 0) {
+ pltgot[2] = (Elf_Addr)_dl_bind_start;
+ pltgot[3] = (Elf_Addr)object;
+ } else {
+ pltgot[0] = (Elf_Addr)_dl_bind_secureplt;
+ pltgot[1] = (Elf_Addr)object;
+ }
}
if (object->got_size != 0)
_dl_mprotect((void*)object->got_start, object->got_size,