Index: arch/i386/archdep.h =================================================================== RCS file: arch/i386/archdep.h diff -N arch/i386/archdep.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ arch/i386/archdep.h 8 Oct 2017 15:11:48 -0000 @@ -0,0 +1,53 @@ +/* $OpenBSD: archdep.h,v 1.19 2017/01/24 07:48:37 guenther 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. + * + */ + +#ifndef _I386_ARCHDEP_H_ +#define _I386_ARCHDEP_H_ + +#define RELOC_TAG DT_REL + +#define MACHID EM_386 /* ELF e_machine ID value checked */ + +static inline void +RELOC_DYN(Elf32_Rel *r, const Elf32_Sym *s, Elf32_Addr *p, unsigned long v) +{ + + if (ELF32_R_TYPE(r->r_info) == R_386_RELATIVE) { + *p += v; + } else if (ELF32_R_TYPE(r->r_info) == R_386_GLOB_DAT) { + *p += v + s->st_value; + } else if (ELF32_R_TYPE(r->r_info) == R_386_32) { + *p += v + s->st_value; + } else { + _dl_exit(6); + } +} + +#define RELOC_GOT(obj, offs) + +#endif /* _I386_ARCHDEP_H_ */ Index: arch/x86_64/archdep.h =================================================================== RCS file: arch/x86_64/archdep.h diff -N arch/x86_64/archdep.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ arch/x86_64/archdep.h 8 Oct 2017 15:11:48 -0000 @@ -0,0 +1,52 @@ +/* $OpenBSD: archdep.h,v 1.11 2017/01/21 01:15:00 guenther 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. + * + */ + +#ifndef _X86_64_ARCHDEP_H_ +#define _X86_64_ARCHDEP_H_ + +#define RELOC_TAG DT_RELA + +#define MACHID EM_AMD64 /* ELF e_machine ID value checked */ + +static inline void +RELOC_DYN(Elf64_Rela *r, const Elf64_Sym *s, Elf64_Addr *p, unsigned long v) +{ + if (ELF64_R_TYPE(r->r_info) == R_X86_64_RELATIVE) { + *p = v + r->r_addend; + } else if (ELF64_R_TYPE(r->r_info) == R_X86_64_GLOB_DAT) { + *p = v + s->st_value + r->r_addend; + } else if (ELF64_R_TYPE(r->r_info) == R_X86_64_64) { + *p = v + s->st_value + r->r_addend; + } else { + _dl_exit(6); + } +} + +#define RELOC_GOT(obj, offs) + +#endif /* _X86_64_ARCHDEP_H_ */ Index: common/Makefile.inc =================================================================== RCS file: /cvsroot/src/lib/csu/common/Makefile.inc,v retrieving revision 1.32 diff -u -p -r1.32 Makefile.inc --- common/Makefile.inc 1 Jun 2016 21:24:55 -0000 1.32 +++ common/Makefile.inc 8 Oct 2017 15:11:48 -0000 @@ -13,6 +13,9 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/libexec/ld. OBJS+= crt0.o gcrt0.o crti.o crtn.o OBJS+= crtbegin.o crtend.o OBJS+= sysident.o +.if ${MKSTATICPIE} == "yes" +OBJS+= rcrt0.o mcrt0.o +.endif .if ${MKPIC} == "yes" OBJS+= crtbeginS.o @@ -91,6 +94,21 @@ crt0.o: crt0.S crt0-common.c ${OBJCOPY} -R .ident ${.TARGET} .endif +boot.o: boot.c + ${COMPILE.c:S/-O2//} ${CFLAGS.boot.c:S/-O//} -I${ARCHDIR} -g3 ${MY_PICFLAGS} -DRCRT0 ${COMMON_DIR}/boot.c -o ${.TARGET} + +rcrt0.o: crt0.S crt0-common.c boot.o + ${_MKTARGET_COMPILE} + ${COMPILE.S} ${ARCHDIR}/crt0.S -o ${.TARGET}.S.o + ${COMPILE.c} ${CFLAGS.crt0-common.c} ${MY_PICFLAGS} -DRCRT0 ${COMMON_DIR}/crt0-common.c -o ${.TARGET}.c.o + ${LD} -r -o ${.TARGET}.o ${.TARGET}.S.o ${.TARGET}.c.o boot.o +# ${OBJCOPY} ${OBJCOPYLIBFLAGS} ${.TARGET}.o ${.TARGET} + cp ${.TARGET}.o ${.TARGET} + rm -f ${.TARGET}.S.o ${.TARGET}.c.o ${.TARGET}.o +.if ${MKSTRIPIDENT} != "no" + ${OBJCOPY} -R .ident ${.TARGET} +.endif + gcrt0.o: crt0.S crt0-common.c ${_MKTARGET_COMPILE} ${COMPILE.S} ${ARCHDIR}/crt0.S -o ${.TARGET}.S.o @@ -102,6 +120,18 @@ gcrt0.o: crt0.S crt0-common.c ${OBJCOPY} -R .ident ${.TARGET} .endif +mcrt0.o: crt0.S crt0-common.c boot.o + ${_MKTARGET_COMPILE} + ${COMPILE.S} ${ARCHDIR}/crt0.S -o ${.TARGET}.S.o + ${COMPILE.c} ${MY_PICFLAGS} -DRCRT0 -DMCRT0 ${COMMON_DIR}/crt0-common.c -o ${.TARGET}.c.o + ${LD} -r -o ${.TARGET}.o ${.TARGET}.S.o ${.TARGET}.c.o boot.o +# ${OBJCOPY} ${OBJCOPYLIBFLAGS} ${.TARGET}.o ${.TARGET} + cp ${.TARGET}.o ${.TARGET} + rm -f ${.TARGET}.S.o ${.TARGET}.c.o ${.TARGET}.o +.if ${MKSTRIPIDENT} != "no" +# ${OBJCOPY} -R .ident ${.TARGET} +.endif + .if ${MACHINE_ARCH} == "alpha" # can't do this in Makefile.inc otherwise it will before realall: crtfm.o: crtfm.c @@ -119,7 +149,7 @@ sysident_assym.h: ${GENASSYM_CONF} ${GEN ${GENASSYM_CPPFLAGS} > sysident_assym.h.tmp && \ mv -f sysident_assym.h.tmp sysident_assym.h -CLEANFILES+= sysident_assym.h +CLEANFILES+= sysident_assym.h boot.o crti.o: crti.S sysident_assym.h sysident.S crtn.o: crtn.S Index: common/boot.c =================================================================== RCS file: common/boot.c diff -N common/boot.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ common/boot.c 8 Oct 2017 15:11:48 -0000 @@ -0,0 +1,257 @@ +/* $OpenBSD: boot.h,v 1.28 2017/01/29 22:31:09 chl 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _dl_exit exit +#define _dl_memset memset +#define _dl_mprotect(addr, len, prot) \ + __syscall(SYS_mprotect, (addr), (len), (prot)) + +#include "archdep.h" +#include "boot.h" + + +#ifdef RCRT0 + +#if RELOC_TAG == DT_RELA +typedef Elf_Rela RELOC_TYPE; +#elif RELOC_TAG == DT_REL +typedef Elf_Rel RELOC_TYPE; +#else +# error "unknown RELOC_TAG" +#endif + +/* The set of dynamic tags that we're interested in for bootstrapping */ +struct boot_dyn { + RELOC_TYPE *dt_reloc; /* DT_RELA or DT_REL */ + Elf_Addr dt_relocsz; /* DT_RELASZ or DT_RELSZ */ + Elf_Addr *dt_pltgot; + Elf_Addr dt_pltrelsz; + const Elf_Sym *dt_symtab; + RELOC_TYPE *dt_jmprel; +#if DT_PROCNUM > 0 + u_long dt_proc[DT_PROCNUM]; +#endif +}; + +extern Elf_Dyn _DYNAMIC[]; + +/* + * Local decls. + */ + +void +_dl_boot_bind(const struct ps_strings *ps_strings) +{ + struct boot_dyn dynld; /* Resolver data for the loader */ + AuxInfo *aux; + Elf_Dyn *dynp; + long base; + Elf_Phdr *phdp; + RELOC_TYPE *rp; + Elf_Addr i, phnum; + void *auxstack; + + /* The array of AUX entries is just after the environment strings */ + auxstack = &ps_strings->ps_envstr[ps_strings->ps_nenvstr] + 1; + + /* extract the aux entries we need */ + for (aux = auxstack; aux->a_type != AT_NULL; aux++) { + switch (aux->a_type) { + case AT_BASE: + base = aux->a_v; + break; + case AT_PHDR: + phdp = (Elf_Phdr *)aux->a_v; + break; + case AT_PHNUM: + phnum = (Elf_Addr)aux->a_v; + break; + default: + break; + } + } + + /* + * 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. + */ + _dl_memset(&dynld, 0, sizeof(dynld)); + + /* Relocate _DYNAMIC so we can use it. */ + dynp = (void *)((char *)_DYNAMIC + base); + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_PLTGOT: + dynld.dt_pltgot = (void *)(dynp->d_un.d_ptr + base); + break; + case DT_SYMTAB: + dynld.dt_symtab = (void *)(dynp->d_un.d_ptr + base); + break; + case RELOC_TAG: /* DT_{RELA,REL} */ + dynld.dt_reloc = (void *)(dynp->d_un.d_ptr + base); + break; + case DT_JMPREL: + dynld.dt_jmprel = (void *)(dynp->d_un.d_ptr + base); + break; + case DT_PLTRELSZ: + dynld.dt_pltrelsz = dynp->d_un.d_val; + break; + case RELOC_TAG+1: /* DT_{RELA,REL}SZ */ + dynld.dt_relocsz = dynp->d_un.d_val; + break; + default: +#if DT_PROCNUM > 0 + if (dynp->d_tag < DT_LOPROC || + dynp->d_tag >= DT_LOPROC + DT_PROCNUM) + break; + dynld.dt_proc[dynp->d_tag - DT_LOPROC] = + dynp->d_un.d_val; +#endif /* DT_PROCNUM */ + break; + } + } + + rp = dynld.dt_jmprel; + for (i = 0; i < dynld.dt_pltrelsz; i += sizeof *rp) { + const Elf_Sym *sym; + + sym = dynld.dt_symtab + ELF_R_SYM(rp->r_info); + if (!ELF_R_SYM(rp->r_info) || sym->st_value != 0) { +#ifdef HAVE_JMPREL + Elf_Addr *ra = (Elf_Addr *)(rp->r_offset + base); + RELOC_JMPREL(rp, sym, ra, base, dynld.dt_pltgot); +#else + exit(6); +#endif + } + rp++; + } + + rp = dynld.dt_reloc; + for (i = 0; i < dynld.dt_relocsz; i += sizeof *rp) { + Elf_Addr *ra; + const Elf_Sym *sym; + + sym = dynld.dt_symtab + ELF_R_SYM(rp->r_info); + if (!ELF_R_SYM(rp->r_info) || sym->st_value != 0) { + ra = (Elf_Addr *)(rp->r_offset + base); + RELOC_DYN(rp, sym, ra, base); + } + rp++; + } + + RELOC_GOT(&dynld, base); + + /* + * we have been fully relocated here, so most things no longer + * need the base adjustment + */ + + /* + * No further changes to the PLT and/or GOT are needed so make + * them read-only. + */ + + /* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */ + for (i = 0; i < phnum; i++, phdp++) { + switch (phdp->p_type) { +#if defined(__alpha__) || defined(__hppa__) || defined(__powerpc__) || \ + defined(__sparc64__) + case PT_LOAD: + if ((phdp->p_flags & (PF_X | PF_W)) != (PF_X | PF_W)) + break; + _dl_mprotect((void *)(phdp->p_vaddr + base), + phdp->p_memsz, PROT_READ); + break; +#endif + case PT_GNU_RELRO: + _dl_mprotect((void *)(phdp->p_vaddr + base), + phdp->p_memsz, PROT_READ); + /* + * GNU_RELRO (a) covers the GOT, and (b) comes after + * all LOAD sections, so if we found it then we're done + */ + break; + } + } +} + +#ifdef __alpha__ + +void _reloc_alpha_got(Elf_Dyn *dynp, Elf_Addr relocbase); + +void +_reloc_alpha_got(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + const Elf_Rela *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + relalim = (const Elf_Rela *)((caddr_t)rela + relasz); + for (; rela < relalim; rela++) { + if (ELF64_R_TYPE(rela->r_info) != RELOC_RELATIVE) + continue; + where = (Elf_Addr *)(relocbase + rela->r_offset); + *where += (Elf_Addr)relocbase; + } +} + +#endif + +#endif /* RCRT0 */ Index: common/boot.h =================================================================== RCS file: common/boot.h diff -N common/boot.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ common/boot.h 8 Oct 2017 15:11:48 -0000 @@ -0,0 +1,3 @@ +/* $NetBSD$ */ + +void _dl_boot_bind(const struct ps_strings *); Index: common/crt0-common.c =================================================================== RCS file: /cvsroot/src/lib/csu/common/crt0-common.c,v retrieving revision 1.14 diff -u -p -r1.14 crt0-common.c --- common/crt0-common.c 7 Jun 2016 12:07:35 -0000 1.14 +++ common/crt0-common.c 8 Oct 2017 15:11:48 -0000 @@ -46,6 +46,7 @@ __RCSID("$NetBSD: crt0-common.c,v 1.14 2 #include #include "rtld.h" +#include "boot.h" extern int main(int, char **, char **); @@ -132,6 +133,9 @@ ___start(void (*cleanup)(void), /* fro const Obj_Entry *obj, /* from shared loader */ struct ps_strings *ps_strings) { +#ifdef RCRT0 + _dl_boot_bind(ps_strings); +#endif if (ps_strings == NULL) _FATAL("ps_strings missing\n"); @@ -150,6 +154,7 @@ ___start(void (*cleanup)(void), /* fro __progname = empty_string; } +#ifndef RCRT0 if (&rtld_DYNAMIC != NULL) { if (obj == NULL) _FATAL("NULL Obj_Entry pointer in GOT\n"); @@ -159,6 +164,7 @@ ___start(void (*cleanup)(void), /* fro _FATAL("Dynamic linker version mismatch\n"); atexit(cleanup); } +#endif _libc_init();