diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2014-12-22 03:51:09 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2014-12-22 03:51:09 +0000 |
commit | 4c3e2b03181a91c59b536d4cdec6f6f5d1cdf236 (patch) | |
tree | 85e45cf9486a5541d2fe1b1a8331d72958564c26 /lib/csu/boot.h | |
parent | d98892b19f775c4dd3ad9557727627fb148b2fd0 (diff) |
Introduce new csu0 variant for -static -pie binaries to use called
rcsu0.o where the initial 'r' is for relocatable. rcsu0.o performs
self-relocation on static pie binaries by calling a slightly modified
copy of ld.so's _dl_boot_bind() in boot.h.
The first arch implementatation is also included for amd64 where
__start calls _dl_boot_bind() and then calls ___start(). Includes
parts from kettenis@ to help get R_X86_64_64 relocations working
and proper handling for undefined weak symbols.
This is the first part of several to get static pie self-relocating
binaries working. binutils, gcc and kernel changes are forthcoming
to complete the solution, then per-arch implementations are needed
for MD_RCRT0_START in csu.
okay kettenis@ pascal@ deraadt@
Diffstat (limited to 'lib/csu/boot.h')
-rw-r--r-- | lib/csu/boot.h | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/lib/csu/boot.h b/lib/csu/boot.h new file mode 100644 index 00000000000..a5422d4cf15 --- /dev/null +++ b/lib/csu/boot.h @@ -0,0 +1,250 @@ +/* $OpenBSD: boot.h,v 1.1 2014/12/22 03:51:08 kurt 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 <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/os-note-elf.h" + +#ifdef RCRT0 +/* + * 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 + _dl_memset(dynld.Dyn.info, 0, sizeof(dynld.Dyn.info)); + 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 +#ifdef RCRT0 + continue; +#else + _dl_exit(6); +#endif + } + + 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 + */ +} +#endif /* RCRT0 */ |