From: miod Date: Fri, 29 May 2015 19:12:26 +0000 (+0000) Subject: Make ld.so on alpha cope with binaries built with secureplt (where secure here X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=4131953d57aa761e2dcd913e3e4fa177fdf94065;p=openbsd 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). --- 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, diff --git a/sys/arch/alpha/include/exec.h b/sys/arch/alpha/include/exec.h index 9442516af91..cb2750bfd83 100644 --- a/sys/arch/alpha/include/exec.h +++ b/sys/arch/alpha/include/exec.h @@ -1,4 +1,4 @@ -/* $OpenBSD: exec.h,v 1.14 2013/10/17 08:02:14 deraadt Exp $ */ +/* $OpenBSD: exec.h,v 1.15 2015/05/29 19:12:26 miod Exp $ */ /* $NetBSD: exec.h,v 1.1 1995/02/13 23:07:37 cgd Exp $ */ /* @@ -43,4 +43,9 @@ #define _NLIST_DO_ELF #define _KERN_DO_ELF64 +/* Processor specific dynamic tag values. */ +#define DT_ALPHA_PLTRO 0x70000000 + +#define DT_PROCNUM (DT_ALPHA_PLTRO + 1 - DT_LOPROC) + #endif /* !_MACHINE_EXEC_H_ */