GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/csu/boot.h Lines: 49 50 98.0 %
Date: 2017-11-13 Branches: 35 38 92.1 %

Line Branch Exec Source
1
/*	$OpenBSD: boot.h,v 1.28 2017/01/29 22:31:09 chl 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.h>
40
#include <sys/sysctl.h>
41
#include <nlist.h>
42
#include <link.h>
43
#include <dlfcn.h>
44
45
#include "syscall.h"
46
#include "archdep.h"
47
#include "path.h"
48
#include "resolve.h"
49
#include "sod.h"
50
#include "stdlib.h"
51
52
/*
53
 * Use the internal, hidden name for any syscalls we need, to avoid
54
 * accidental override by application code
55
 */
56
#define REDIRECT_SYSCALL(x)	typeof(x) x asm("_libc_"#x) __dso_hidden
57
REDIRECT_SYSCALL(mprotect);
58
59
#ifdef RCRT0
60
61
#define	DT_PROC(n)	((n) - DT_LOPROC)
62
63
#if RELOC_TAG == DT_RELA
64
typedef	Elf_RelA	RELOC_TYPE;
65
#elif RELOC_TAG == DT_REL
66
typedef	Elf_Rel		RELOC_TYPE;
67
#else
68
# error "unknown RELOC_TAG"
69
#endif
70
71
/* The set of dynamic tags that we're interested in for bootstrapping */
72
struct boot_dyn {
73
	RELOC_TYPE	*dt_reloc;	/* DT_RELA   or DT_REL */
74
	Elf_Addr	dt_relocsz;	/* DT_RELASZ or DT_RELSZ */
75
	Elf_Addr	*dt_pltgot;
76
	Elf_Addr	dt_pltrelsz;
77
	const Elf_Sym	*dt_symtab;
78
	RELOC_TYPE	*dt_jmprel;
79
#if DT_PROCNUM > 0
80
	u_long		dt_proc[DT_PROCNUM];
81
#endif
82
};
83
84
/*
85
 * Local decls.
86
 */
87
void _dl_boot_bind(const long, long *, Elf_Dyn *);
88
89
void
90
_dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp)
91
{
92
30
	struct boot_dyn	dynld;		/* Resolver data for the loader */
93
	AuxInfo		*auxstack;
94
	long		*stack;
95
	Elf_Dyn		*dynp;
96
	int		n, argc;
97
	char		**argv, **envp;
98
	long		loff;
99
	RELOC_TYPE	*rp;
100
	Elf_Phdr	*phdp;
101
	Elf_Addr	i;
102
103
	/*
104
	 * Scan argument and environment vectors. Find dynamic
105
	 * data vector put after them.
106
	 */
107
15
	stack = (long *)sp;
108
15
	argc = *stack++;
109
15
	argv = (char **)stack;
110
15
	envp = &argv[argc + 1];
111
15
	stack = (long *)envp;
112
750
	while (*stack++ != 0L)
113
		;
114
115
	/*
116
	 * Zero out dl_data.
117
	 */
118
330
	for (n = 0; n <= AUX_entry; n++)
119
150
		dl_data[n] = 0;
120
121
	/*
122
	 * Dig out auxiliary data set up by exec call. Move all known
123
	 * tags to an indexed local table for easy access.
124
	 */
125
240
	for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null;
126
105
	    auxstack++) {
127
105
		if (auxstack->au_id > AUX_entry)
128
			continue;
129
105
		dl_data[auxstack->au_id] = auxstack->au_v;
130
105
	}
131
15
	loff = dl_data[AUX_base];	/* XXX assumes ld.so is linked at 0x0 */
132
133
	/*
134
	 * We need to do 'selfreloc' in case the code weren't
135
	 * loaded at the address it was linked to.
136
	 *
137
	 * Scan the DYNAMIC section for the loader.
138
	 * Cache the data for easier access.
139
	 */
140
	dynp = dynamicp;
141
142
15
	_dl_memset(&dynld, 0, sizeof(dynld));
143
450
	while (dynp->d_tag != DT_NULL) {
144
		/* first the tags that are pointers to be relocated */
145
210
		if (dynp->d_tag == DT_PLTGOT)
146
15
			dynld.dt_pltgot = (void *)(dynp->d_un.d_ptr + loff);
147
195
		else if (dynp->d_tag == DT_SYMTAB)
148
15
			dynld.dt_symtab = (void *)(dynp->d_un.d_ptr + loff);
149
180
		else if (dynp->d_tag == RELOC_TAG)	/* DT_{RELA,REL} */
150
15
			dynld.dt_reloc = (void *)(dynp->d_un.d_ptr + loff);
151
165
		else if (dynp->d_tag == DT_JMPREL)
152
15
			dynld.dt_jmprel = (void *)(dynp->d_un.d_ptr + loff);
153
154
		/* Now for the tags that are just sizes or counts */
155
150
		else if (dynp->d_tag == DT_PLTRELSZ)
156
15
			dynld.dt_pltrelsz = dynp->d_un.d_val;
157
135
		else if (dynp->d_tag == RELOC_TAG+1)	/* DT_{RELA,REL}SZ */
158
15
			dynld.dt_relocsz = dynp->d_un.d_val;
159
#if DT_PROCNUM > 0
160
		else if (dynp->d_tag >= DT_LOPROC &&
161
		    dynp->d_tag < DT_LOPROC + DT_PROCNUM)
162
			dynld.dt_proc[dynp->d_tag - DT_LOPROC] =
163
			    dynp->d_un.d_val;
164
#endif /* DT_PROCNUM */
165
210
		dynp++;
166
	}
167
168
15
	rp = dynld.dt_jmprel;
169
60
	for (i = 0; i < dynld.dt_pltrelsz; i += sizeof *rp) {
170
		const Elf_Sym *sp;
171
172
15
		sp = dynld.dt_symtab + ELF_R_SYM(rp->r_info);
173

30
		if (!ELF_R_SYM(rp->r_info) || sp->st_value != 0) {
174
#ifdef HAVE_JMPREL
175
			Elf_Addr *ra = (Elf_Addr *)(rp->r_offset + loff);
176
			RELOC_JMPREL(rp, sp, ra, loff, dynld.dt_pltgot);
177
#else
178
			_dl_exit(6);
179
#endif
180
		}
181
15
		rp++;
182
	}
183
184
15
	rp = dynld.dt_reloc;
185
40530
	for (i = 0; i < dynld.dt_relocsz; i += sizeof *rp) {
186
		Elf_Addr *ra;
187
		const Elf_Sym *sp;
188
189
20250
		sp = dynld.dt_symtab + ELF_R_SYM(rp->r_info);
190

20352
		if (!ELF_R_SYM(rp->r_info) || sp->st_value != 0) {
191
20235
			ra = (Elf_Addr *)(rp->r_offset + loff);
192
20235
			RELOC_DYN(rp, sp, ra, loff);
193
20235
		}
194
20250
		rp++;
195
	}
196
197
	RELOC_GOT(&dynld, loff);
198
199
	/*
200
	 * we have been fully relocated here, so most things no longer
201
	 * need the loff adjustment
202
	 */
203
204
	/*
205
	 * No further changes to the PLT and/or GOT are needed so make
206
	 * them read-only.
207
	 */
208
209
	/* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */
210
15
	phdp = (Elf_Phdr *)dl_data[AUX_phdr];
211
300
	for (i = 0; i < dl_data[AUX_phnum]; i++, phdp++) {
212
135
		switch (phdp->p_type) {
213
#if defined(__alpha__) || defined(__hppa__) || defined(__powerpc__) || \
214
    defined(__sparc64__)
215
		case PT_LOAD:
216
			if ((phdp->p_flags & (PF_X | PF_W)) != (PF_X | PF_W))
217
				break;
218
			mprotect((void *)(phdp->p_vaddr + loff), phdp->p_memsz,
219
			    PROT_READ);
220
			break;
221
#endif
222
		case PT_GNU_RELRO:
223
15
			mprotect((void *)(phdp->p_vaddr + loff), phdp->p_memsz,
224
			    PROT_READ);
225
			/*
226
			 * GNU_RELRO (a) covers the GOT, and (b) comes after
227
			 * all LOAD sections, so if we found it then we're done
228
			 */
229
15
			break;
230
		}
231
	}
232
15
}
233
234
#ifdef __alpha__
235
236
void	_reloc_alpha_got(Elf_Dyn *dynp, Elf_Addr relocbase);
237
238
void
239
_reloc_alpha_got(Elf_Dyn *dynp, Elf_Addr relocbase)
240
{
241
	const Elf_RelA *rela = 0, *relalim;
242
	Elf_Addr relasz = 0;
243
	Elf_Addr *where;
244
245
	for (; dynp->d_tag != DT_NULL; dynp++) {
246
		switch (dynp->d_tag) {
247
		case DT_RELA:
248
			rela = (const Elf_RelA *)(relocbase + dynp->d_un.d_ptr);
249
			break;
250
		case DT_RELASZ:
251
			relasz = dynp->d_un.d_val;
252
			break;
253
		}
254
	}
255
	relalim = (const Elf_RelA *)((caddr_t)rela + relasz);
256
	for (; rela < relalim; rela++) {
257
		if (ELF64_R_TYPE(rela->r_info) != RELOC_RELATIVE)
258
			continue;
259
		where = (Elf_Addr *)(relocbase + rela->r_offset);
260
		*where += (Elf_Addr)relocbase;
261
	}
262
}
263
264
#endif
265
266
#endif /* RCRT0 */