summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2015-08-26 02:04:42 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2015-08-26 02:04:42 +0000
commit650a82e7f091b349b4184eea9af663a0c82f014a (patch)
tree812198ac0f3f6ebdbd31dc627fd65ad51d1aa2ba
parentf03d89be46ee4a5bb94cd7d45ebb115408e59fcb (diff)
Kbind 3: The Legend Continues!
Use kbind for lazy binding GOT/PLT updates on alpha and mips64. While here add some gcc __predict hints. Much discussion with and assistance from miod and deraadt ok deraadt@
-rw-r--r--libexec/ld.so/alpha/rtld_machine.c46
-rw-r--r--libexec/ld.so/mips64/rtld_machine.c45
2 files changed, 55 insertions, 36 deletions
diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c
index 9e55b6dfcb0..7365674a797 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.53 2015/05/29 19:12:26 miod Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.54 2015/08/26 02:04:41 guenther Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -33,10 +33,12 @@
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/exec.h>
+#include <sys/syscall.h>
+#include <sys/unistd.h>
+#include <machine/pal.h>
#include <nlist.h>
#include <link.h>
-#include <signal.h>
#include "syscall.h"
#include "archdep.h"
@@ -44,6 +46,8 @@
#define DT_PROC(n) ((n) - DT_LOPROC + DT_NUM)
+int64_t pcookie __attribute__((section(".openbsd.randomdata"))) __dso_hidden;
+
int
_dl_md_reloc(elf_object_t *object, int rel, int relasz)
{
@@ -207,14 +211,17 @@ Elf_Addr
_dl_bind(elf_object_t *object, int reloff)
{
Elf_RelA *rela;
- Elf_Addr *addr, ooff;
+ Elf_Addr ooff;
const Elf_Sym *sym, *this;
const char *symn;
const elf_object_t *sobj;
- sigset_t savedmask;
+ uint64_t cookie = pcookie;
+ struct {
+ struct __kbind param;
+ Elf_Addr newval;
+ } buf;
rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff);
- addr = (Elf_Addr *)(object->obj_base + rela->r_offset);
sym = object->dyn.symtab;
sym += ELF64_R_SYM(rela->r_info);
@@ -228,24 +235,27 @@ _dl_bind(elf_object_t *object, int reloff)
*(volatile int *)0 = 0; /* XXX */
}
- if (sobj->traced && _dl_trace_plt(sobj, symn))
- return ooff + this->st_value + rela->r_addend;
+ buf.newval = ooff + this->st_value + rela->r_addend;
- /* 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);
- }
+ if (__predict_false(sobj->traced) && _dl_trace_plt(sobj, symn))
+ return (buf.newval);
+
+ buf.param.kb_addr = (Elf_Addr *)(object->obj_base + rela->r_offset);
+ buf.param.kb_size = sizeof(Elf_Addr);
- *addr = ooff + this->st_value + rela->r_addend;
+ /* directly code the syscall, so that it's actually inline here */
+ {
+ register long syscall_num __asm("$0") /* v0 */ = SYS_kbind;
+ register void *arg1 __asm("$16") /* a0 */ = &buf;
+ register long arg2 __asm("$17") /* a1 */ = sizeof(buf);
+ register long arg3 __asm("$18") /* a2 */ = cookie;
- /* 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);
+ __asm volatile( "call_pal %1" : "+r" (syscall_num)
+ : "i" (PAL_OSF1_callsys), "r" (arg1), "r" (arg2),
+ "r" (arg3) : "$19", "$20", "memory");
}
- return *addr;
+ return (buf.newval);
}
/*
diff --git a/libexec/ld.so/mips64/rtld_machine.c b/libexec/ld.so/mips64/rtld_machine.c
index 6ac0dc762ff..c2ca902c8c4 100644
--- a/libexec/ld.so/mips64/rtld_machine.c
+++ b/libexec/ld.so/mips64/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.18 2014/05/02 04:55:48 miod Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.19 2015/08/26 02:04:41 guenther Exp $ */
/*
* Copyright (c) 1998-2004 Opsycon AB, Sweden.
@@ -30,14 +30,18 @@
#include <sys/types.h>
#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/unistd.h>
#include <link.h>
-#include <signal.h>
#include "resolve.h"
#include "syscall.h"
#include "archdep.h"
+int64_t pcookie __attribute__((section(".openbsd.randomdata"))) __dso_hidden;
+
+
int
_dl_md_reloc(elf_object_t *object, int rel, int relsz)
{
@@ -274,11 +278,15 @@ Elf_Addr
_dl_bind(elf_object_t *object, int symidx)
{
Elf_Addr *gotp = object->dyn.pltgot;
- Elf_Addr *addr, ooff;
+ Elf_Addr ooff;
const Elf_Sym *sym, *this;
const char *symn;
const elf_object_t *sobj;
- sigset_t savedmask;
+ int64_t cookie = pcookie;
+ struct {
+ struct __kbind param;
+ Elf_Addr newval;
+ } buf;
int n;
sym = object->dyn.symtab;
@@ -295,24 +303,25 @@ _dl_bind(elf_object_t *object, int symidx)
*(volatile int *)0 = 0; /* XXX */
}
- if (sobj->traced && _dl_trace_plt(sobj, symn))
- return ooff + this->st_value;
+ buf.newval = ooff + this->st_value;
- addr = &gotp[n + symidx];
+ if (__predict_false(sobj->traced) && _dl_trace_plt(sobj, symn))
+ return (buf.newval);
- /* 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);
- }
+ buf.param.kb_addr = &gotp[n + symidx];
+ buf.param.kb_size = sizeof(Elf_Addr);
- *addr = ooff + this->st_value;
+ /* directly code the syscall, so that it's actually inline here */
+ {
+ register long syscall_num __asm("v0") = SYS_kbind;
+ register void *arg1 __asm("a0") = &buf;
+ register long arg2 __asm("a1") = sizeof(buf);
+ register long arg3 __asm("a2") = cookie;
- /* 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);
+ __asm volatile("syscall" : "+r" (syscall_num)
+ : "r" (arg1), "r" (arg2), "r" (arg3)
+ : "v1", "a3", "memory");
}
- return *addr;
+ return (buf.newval);
}