diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2015-08-26 02:04:42 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2015-08-26 02:04:42 +0000 |
commit | 650a82e7f091b349b4184eea9af663a0c82f014a (patch) | |
tree | 812198ac0f3f6ebdbd31dc627fd65ad51d1aa2ba | |
parent | f03d89be46ee4a5bb94cd7d45ebb115408e59fcb (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.c | 46 | ||||
-rw-r--r-- | libexec/ld.so/mips64/rtld_machine.c | 45 |
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); } |