diff options
author | 2014-02-16 01:16:38 +0000 | |
---|---|---|
committer | 2014-02-16 01:16:38 +0000 | |
commit | f876f11b4113c557dcbcd7c1f590a96857e01c91 (patch) | |
tree | dce9986f528cd7a6978d21bd5580d70579f94ba8 | |
parent | Update ld.so-cookie test which is currently broken and gets in the (diff) | |
download | wireguard-openbsd-f876f11b4113c557dcbcd7c1f590a96857e01c91.tar.xz wireguard-openbsd-f876f11b4113c557dcbcd7c1f590a96857e01c91.zip |
Unbreak ld.so with ssp-strong/all on sparc64 and powerpc. With the
new SSP logic it additionally protects functions which have their
local addresses taken of, and _dl_boot_bind() gets selected.
We have to go through GOT to reach __guard_local, however it hasn't
been relocated yet. So add boot.c and don't protect everything up
to the point until it has been relocated and no longer needs the
loff adjustment.
OK matthew@. Full build done & tested by florian@.
-rw-r--r-- | libexec/ld.so/Makefile | 9 | ||||
-rw-r--r-- | libexec/ld.so/boot.c | 244 | ||||
-rw-r--r-- | libexec/ld.so/loader.c | 189 |
3 files changed, 251 insertions, 191 deletions
diff --git a/libexec/ld.so/Makefile b/libexec/ld.so/Makefile index e25cefc7616..d2456c68bdf 100644 --- a/libexec/ld.so/Makefile +++ b/libexec/ld.so/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.46 2013/12/31 04:07:34 guenther Exp $ +# $OpenBSD: Makefile,v 1.47 2014/02/16 01:16:38 martynas Exp $ SUBDIR=ldconfig ldd MAN= ld.so.1 @@ -12,8 +12,8 @@ PROG= ld.so VPATH=${.CURDIR}/../../lib/libc/string -SRCS= ldasm.S loader.c resolve.c dlfcn.c dl_printf.c rtld_machine.c path.c -SRCS+= util.c sod.c strsep.c strtol.c dir.c library_subr.c dl_prebind.c +SRCS= ldasm.S boot.c loader.c resolve.c dlfcn.c dl_printf.c rtld_machine.c +SRCS+= path.c util.c sod.c strsep.c strtol.c dir.c library_subr.c dl_prebind.c SRCS+= dl_realpath.c dl_uname.c dl_dirname.c strlcat.c strlen.c trace.c .if (${MACHINE_ARCH} == "i386") SRCS+= library_mquery.c @@ -48,3 +48,6 @@ $(PROG): $(test_prog) .endif .include <bsd.prog.mk> + +boot.o: boot.c + ${COMPILE.c} -fno-stack-protector ${.IMPSRC} diff --git a/libexec/ld.so/boot.c b/libexec/ld.so/boot.c new file mode 100644 index 00000000000..eecc574d14d --- /dev/null +++ b/libexec/ld.so/boot.c @@ -0,0 +1,244 @@ +/* $OpenBSD: boot.c,v 1.1 2014/02/16 01:16:38 martynas Exp $ */ + +/* + * Copyright (c) 1998 Per Fogelstrom, Opsycon AB + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * IMPORTANT: any functions below are NOT protected by SSP. Please + * do not add anything except what is required to reach GOT with + * an adjustment. + */ + +#define _DYN_LOADER + +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/exec.h> +#include <sys/param.h> +#include <sys/sysctl.h> +#include <nlist.h> +#include <string.h> +#include <link.h> +#include <dlfcn.h> + +#include "syscall.h" +#include "archdep.h" +#include "path.h" +#include "resolve.h" +#include "sod.h" +#include "stdlib.h" +#include "dl_prebind.h" + +#include "../../lib/csu/common_elf/os-note-elf.h" + +/* + * Local decls. + */ +void _dl_boot_bind(const long, long *, Elf_Dyn *); + +void +_dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp) +{ + struct elf_object dynld; /* Resolver data for the loader */ + AuxInfo *auxstack; + long *stack; + Elf_Dyn *dynp; + int n, argc; + char **argv, **envp; + long loff; + + /* + * Scan argument and environment vectors. Find dynamic + * data vector put after them. + */ + stack = (long *)sp; + argc = *stack++; + argv = (char **)stack; + envp = &argv[argc + 1]; + stack = (long *)envp; + while (*stack++ != 0L) + ; + + /* + * Zero out dl_data. + */ + for (n = 0; n <= AUX_entry; n++) + dl_data[n] = 0; + + /* + * Dig out auxiliary data set up by exec call. Move all known + * tags to an indexed local table for easy access. + */ + for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null; + auxstack++) { + if (auxstack->au_id > AUX_entry) + continue; + dl_data[auxstack->au_id] = auxstack->au_v; + } + loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */ + + /* + * We need to do 'selfreloc' in case the code weren't + * loaded at the address it was linked to. + * + * Scan the DYNAMIC section for the loader. + * Cache the data for easier access. + */ + +#if defined(__alpha__) + dynp = (Elf_Dyn *)((long)_DYNAMIC); +#elif defined(__sparc__) || defined(__sparc64__) || defined(__powerpc__) || \ + defined(__hppa__) || defined(__sh__) + dynp = dynamicp; +#else + dynp = (Elf_Dyn *)((long)_DYNAMIC + loff); +#endif + while (dynp != NULL && dynp->d_tag != DT_NULL) { + if (dynp->d_tag < DT_NUM) + dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val; + else if (dynp->d_tag >= DT_LOPROC && + dynp->d_tag < DT_LOPROC + DT_PROCNUM) + dynld.Dyn.info[dynp->d_tag - DT_LOPROC + DT_NUM] = + dynp->d_un.d_val; + if (dynp->d_tag == DT_TEXTREL) + dynld.dyn.textrel = 1; + dynp++; + } + + /* + * Do the 'bootstrap relocation'. This is really only needed if + * the code was loaded at another location than it was linked to. + * We don't do undefined symbols resolving (to difficult..) + */ + + /* "relocate" dyn.X values if they represent addresses */ + { + int i, val; + /* must be code, not pic data */ + int table[20]; + + i = 0; + table[i++] = DT_PLTGOT; + table[i++] = DT_HASH; + table[i++] = DT_STRTAB; + table[i++] = DT_SYMTAB; + table[i++] = DT_RELA; + table[i++] = DT_INIT; + table[i++] = DT_FINI; + table[i++] = DT_REL; + table[i++] = DT_JMPREL; + /* other processors insert their extras here */ + table[i++] = DT_NULL; + for (i = 0; table[i] != DT_NULL; i++) { + val = table[i]; + if (val >= DT_LOPROC && val < DT_LOPROC + DT_PROCNUM) + val = val - DT_LOPROC + DT_NUM; + else if (val >= DT_NUM) + continue; + if (dynld.Dyn.info[val] != 0) + dynld.Dyn.info[val] += loff; + } + } + + { + u_int32_t rs; + Elf_Rel *rp; + int i; + + rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]); + rs = dynld.dyn.relsz; + + for (i = 0; i < rs; i += sizeof (Elf_Rel)) { + Elf_Addr *ra; + const Elf_Sym *sp; + + sp = dynld.dyn.symtab; + sp += ELF_R_SYM(rp->r_info); + + if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { +#if 0 +/* cannot printf in this function */ + _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); + _dl_wrstderr("Undefined symbol: "); + _dl_wrstderr((char *)dynld.dyn.strtab + + sp->st_name); +#endif + _dl_exit(5); + } + + ra = (Elf_Addr *)(rp->r_offset + loff); + RELOC_REL(rp, sp, ra, loff); + rp++; + } + } + + for (n = 0; n < 2; n++) { + unsigned long rs; + Elf_RelA *rp; + int i; + + switch (n) { + case 0: + rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]); + rs = dynld.dyn.pltrelsz; + break; + case 1: + rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]); + rs = dynld.dyn.relasz; + break; + default: + rp = NULL; + rs = 0; + } + for (i = 0; i < rs; i += sizeof (Elf_RelA)) { + Elf_Addr *ra; + const Elf_Sym *sp; + + sp = dynld.dyn.symtab; + sp += ELF_R_SYM(rp->r_info); + if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { +#if 0 + _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); + _dl_wrstderr("Undefined symbol: "); + _dl_wrstderr((char *)dynld.dyn.strtab + + sp->st_name); +#endif + _dl_exit(6); + } + + ra = (Elf_Addr *)(rp->r_offset + loff); + RELOC_RELA(rp, sp, ra, loff, dynld.dyn.pltgot); + rp++; + } + } + + RELOC_GOT(&dynld, loff); + + /* + * we have been fully relocated here, so most things no longer + * need the loff adjustment + */ +} diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index 3463099065f..3e688382a57 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.146 2014/01/23 00:31:34 deraadt Exp $ */ +/* $OpenBSD: loader.c,v 1.147 2014/02/16 01:16:38 martynas Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -46,8 +46,6 @@ #include "stdlib.h" #include "dl_prebind.h" -#include "../../lib/csu/common_elf/os-note-elf.h" - /* * Local decls. */ @@ -55,7 +53,6 @@ unsigned long _dl_boot(const char **, char **, const long, long *); void _dl_debug_state(void); void _dl_setup_env(char **); void _dl_dtors(void); -void _dl_boot_bind(const long, long *, Elf_Dyn *); void _dl_fixup_user_env(void); void _dl_call_init_recurse(elf_object_t *object, int initfirst); @@ -605,190 +602,6 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data) return(dl_data[AUX_entry]); } -void -_dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp) -{ - struct elf_object dynld; /* Resolver data for the loader */ - AuxInfo *auxstack; - long *stack; - Elf_Dyn *dynp; - int n, argc; - char **argv, **envp; - long loff; - - /* - * Scan argument and environment vectors. Find dynamic - * data vector put after them. - */ - stack = (long *)sp; - argc = *stack++; - argv = (char **)stack; - envp = &argv[argc + 1]; - stack = (long *)envp; - while (*stack++ != 0L) - ; - - /* - * Zero out dl_data. - */ - for (n = 0; n <= AUX_entry; n++) - dl_data[n] = 0; - - /* - * Dig out auxiliary data set up by exec call. Move all known - * tags to an indexed local table for easy access. - */ - for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null; - auxstack++) { - if (auxstack->au_id > AUX_entry) - continue; - dl_data[auxstack->au_id] = auxstack->au_v; - } - loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */ - - /* - * We need to do 'selfreloc' in case the code weren't - * loaded at the address it was linked to. - * - * Scan the DYNAMIC section for the loader. - * Cache the data for easier access. - */ - -#if defined(__alpha__) - dynp = (Elf_Dyn *)((long)_DYNAMIC); -#elif defined(__sparc__) || defined(__sparc64__) || defined(__powerpc__) || \ - defined(__hppa__) || defined(__sh__) - dynp = dynamicp; -#else - dynp = (Elf_Dyn *)((long)_DYNAMIC + loff); -#endif - while (dynp != NULL && dynp->d_tag != DT_NULL) { - if (dynp->d_tag < DT_NUM) - dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val; - else if (dynp->d_tag >= DT_LOPROC && - dynp->d_tag < DT_LOPROC + DT_PROCNUM) - dynld.Dyn.info[dynp->d_tag - DT_LOPROC + DT_NUM] = - dynp->d_un.d_val; - if (dynp->d_tag == DT_TEXTREL) - dynld.dyn.textrel = 1; - dynp++; - } - - /* - * Do the 'bootstrap relocation'. This is really only needed if - * the code was loaded at another location than it was linked to. - * We don't do undefined symbols resolving (to difficult..) - */ - - /* "relocate" dyn.X values if they represent addresses */ - { - int i, val; - /* must be code, not pic data */ - int table[20]; - - i = 0; - table[i++] = DT_PLTGOT; - table[i++] = DT_HASH; - table[i++] = DT_STRTAB; - table[i++] = DT_SYMTAB; - table[i++] = DT_RELA; - table[i++] = DT_INIT; - table[i++] = DT_FINI; - table[i++] = DT_REL; - table[i++] = DT_JMPREL; - /* other processors insert their extras here */ - table[i++] = DT_NULL; - for (i = 0; table[i] != DT_NULL; i++) { - val = table[i]; - if (val >= DT_LOPROC && val < DT_LOPROC + DT_PROCNUM) - val = val - DT_LOPROC + DT_NUM; - else if (val >= DT_NUM) - continue; - if (dynld.Dyn.info[val] != 0) - dynld.Dyn.info[val] += loff; - } - } - - { - u_int32_t rs; - Elf_Rel *rp; - int i; - - rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]); - rs = dynld.dyn.relsz; - - for (i = 0; i < rs; i += sizeof (Elf_Rel)) { - Elf_Addr *ra; - const Elf_Sym *sp; - - sp = dynld.dyn.symtab; - sp += ELF_R_SYM(rp->r_info); - - if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { -#if 0 -/* cannot printf in this function */ - _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); - _dl_wrstderr("Undefined symbol: "); - _dl_wrstderr((char *)dynld.dyn.strtab + - sp->st_name); -#endif - _dl_exit(5); - } - - ra = (Elf_Addr *)(rp->r_offset + loff); - RELOC_REL(rp, sp, ra, loff); - rp++; - } - } - - for (n = 0; n < 2; n++) { - unsigned long rs; - Elf_RelA *rp; - int i; - - switch (n) { - case 0: - rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]); - rs = dynld.dyn.pltrelsz; - break; - case 1: - rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]); - rs = dynld.dyn.relasz; - break; - default: - rp = NULL; - rs = 0; - } - for (i = 0; i < rs; i += sizeof (Elf_RelA)) { - Elf_Addr *ra; - const Elf_Sym *sp; - - sp = dynld.dyn.symtab; - sp += ELF_R_SYM(rp->r_info); - if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { -#if 0 - _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); - _dl_wrstderr("Undefined symbol: "); - _dl_wrstderr((char *)dynld.dyn.strtab + - sp->st_name); -#endif - _dl_exit(6); - } - - ra = (Elf_Addr *)(rp->r_offset + loff); - RELOC_RELA(rp, sp, ra, loff, dynld.dyn.pltgot); - rp++; - } - } - - RELOC_GOT(&dynld, loff); - - /* - * we have been fully relocated here, so most things no longer - * need the loff adjustment - */ -} - #define DL_SM_SYMBUF_CNT 512 sym_cache _dl_sm_symcache_buffer[DL_SM_SYMBUF_CNT]; |