1 /* $OpenBSD: boot.h,v 1.32 2021/11/16 02:46:46 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 1998 Per Fogelstrom, Opsycon AB 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 /* 30 * IMPORTANT: any functions below are NOT protected by SSP. Please 31 * do not add anything except what is required to reach GOT with 32 * an adjustment. 33 */ 34 35 #define _DYN_LOADER 36 37 #include <sys/types.h> 38 #include <sys/mman.h> 39 #include <sys/exec_elf.h> 40 41 #include "archdep.h" 42 43 /* 44 * Use the internal, hidden name for any syscalls we need, to avoid 45 * accidental override by application code 46 */ 47 #define REDIRECT_SYSCALL(x) typeof(x) x asm("_libc_"#x) __dso_hidden 48 REDIRECT_SYSCALL(mprotect); 49 50 #ifdef RCRT0 51 52 #if RELOC_TAG == DT_RELA 53 typedef Elf_RelA RELOC_TYPE; 54 #elif RELOC_TAG == DT_REL 55 typedef Elf_Rel RELOC_TYPE; 56 #else 57 # error "unknown RELOC_TAG" 58 #endif 59 60 static void *relro_addr; 61 static size_t relro_size; 62 #define RCRT0_RELRO() \ 63 do { \ 64 if (relro_addr != NULL && relro_size != 0) \ 65 mprotect(relro_addr, relro_size, PROT_READ); \ 66 } while (0) 67 68 /* 69 * Local decls. 70 */ 71 void _dl_boot_bind(const long, long *, Elf_Dyn *); 72 73 void 74 _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynp) 75 { 76 AuxInfo *auxstack; 77 long *stack; 78 int n, argc; 79 char **argv, **envp; 80 long loff; 81 RELOC_TYPE *dt_reloc, *rend; /* DT_RELA or DT_REL */ 82 Elf_Word dt_relocsz; /* DT_RELASZ or DT_RELSZ */ 83 const Elf_Sym *dt_symtab; 84 Elf_Phdr *phdp; 85 Elf_Addr i; 86 87 /* 88 * Scan argument and environment vectors. Find dynamic 89 * data vector put after them. 90 */ 91 stack = (long *)sp; 92 argc = *stack++; 93 argv = (char **)stack; 94 envp = &argv[argc + 1]; 95 stack = (long *)envp; 96 while (*stack++ != 0L) 97 ; 98 99 /* 100 * Zero out dl_data. 101 */ 102 for (n = 0; n <= AUX_entry; n++) 103 dl_data[n] = 0; 104 105 /* 106 * Dig out auxiliary data set up by exec call. Move all known 107 * tags to an indexed local table for easy access. 108 */ 109 for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null; 110 auxstack++) { 111 if (auxstack->au_id > AUX_entry) 112 continue; 113 dl_data[auxstack->au_id] = auxstack->au_v; 114 } 115 loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */ 116 117 /* 118 * Scan the DYNAMIC section for the items we need 119 */ 120 dt_reloc = NULL; 121 dt_relocsz = 0; 122 while (dynp->d_tag != DT_NULL) { 123 /* first the tags that are pointers to be relocated */ 124 if (dynp->d_tag == DT_SYMTAB) 125 dt_symtab = (void *)(dynp->d_un.d_ptr + loff); 126 else if (dynp->d_tag == RELOC_TAG) /* DT_{RELA,REL} */ 127 dt_reloc = (void *)(dynp->d_un.d_ptr + loff); 128 129 /* Now for the tags that are just sizes or counts */ 130 else if (dynp->d_tag == RELOC_TAG+1) /* DT_{RELA,REL}SZ */ 131 dt_relocsz = dynp->d_un.d_val; 132 dynp++; 133 } 134 135 rend = (RELOC_TYPE *)((char *)dt_reloc + dt_relocsz); 136 for (; dt_reloc < rend; dt_reloc++) { 137 Elf_Addr *ra; 138 const Elf_Sym *sp; 139 140 sp = dt_symtab + ELF_R_SYM(dt_reloc->r_info); 141 if (!ELF_R_SYM(dt_reloc->r_info) || sp->st_value != 0) { 142 ra = (Elf_Addr *)(dt_reloc->r_offset + loff); 143 RELOC_DYN(dt_reloc, sp, ra, loff); 144 } 145 } 146 147 /* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */ 148 phdp = (Elf_Phdr *)dl_data[AUX_phdr]; 149 for (i = 0; i < dl_data[AUX_phnum]; i++, phdp++) { 150 switch (phdp->p_type) { 151 #if defined(__alpha__) || defined(__powerpc__) || defined(__sparc64__) 152 case PT_LOAD: 153 if ((phdp->p_flags & (PF_X | PF_W)) != (PF_X | PF_W)) 154 break; 155 mprotect((void *)(phdp->p_vaddr + loff), phdp->p_memsz, 156 PROT_READ); 157 break; 158 #endif 159 case PT_GNU_RELRO: 160 relro_addr = (void *)(phdp->p_vaddr + loff); 161 relro_size = phdp->p_memsz; 162 /* 163 * GNU_RELRO (a) covers the GOT, and (b) comes after 164 * all LOAD sections, so if we found it then we're done 165 */ 166 break; 167 } 168 } 169 } 170 171 #endif /* RCRT0 */ 172