Line data Source code
1 : /* $OpenBSD: exec_elf.c,v 1.146 2018/08/05 14:23:57 beck Exp $ */
2 :
3 : /*
4 : * Copyright (c) 1996 Per Fogelstrom
5 : * All rights reserved.
6 : *
7 : * Copyright (c) 1994 Christos Zoulas
8 : * All rights reserved.
9 : *
10 : * Redistribution and use in source and binary forms, with or without
11 : * modification, are permitted provided that the following conditions
12 : * are met:
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : * 2. Redistributions in binary form must reproduce the above copyright
16 : * notice, this list of conditions and the following disclaimer in the
17 : * documentation and/or other materials provided with the distribution.
18 : * 3. The name of the author may not be used to endorse or promote products
19 : * derived from this software without specific prior written permission
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : /*
35 : * Copyright (c) 2001 Wasabi Systems, Inc.
36 : * All rights reserved.
37 : *
38 : * Written by Jason R. Thorpe for Wasabi Systems, Inc.
39 : *
40 : * Redistribution and use in source and binary forms, with or without
41 : * modification, are permitted provided that the following conditions
42 : * are met:
43 : * 1. Redistributions of source code must retain the above copyright
44 : * notice, this list of conditions and the following disclaimer.
45 : * 2. Redistributions in binary form must reproduce the above copyright
46 : * notice, this list of conditions and the following disclaimer in the
47 : * documentation and/or other materials provided with the distribution.
48 : * 3. All advertising materials mentioning features or use of this software
49 : * must display the following acknowledgement:
50 : * This product includes software developed for the NetBSD Project by
51 : * Wasabi Systems, Inc.
52 : * 4. The name of Wasabi Systems, Inc. may not be used to endorse
53 : * or promote products derived from this software without specific prior
54 : * written permission.
55 : *
56 : * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
57 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
58 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
59 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
60 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
61 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
62 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
63 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
64 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
65 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
66 : * POSSIBILITY OF SUCH DAMAGE.
67 : */
68 :
69 : #include <sys/param.h>
70 : #include <sys/systm.h>
71 : #include <sys/kernel.h>
72 : #include <sys/proc.h>
73 : #include <sys/malloc.h>
74 : #include <sys/pool.h>
75 : #include <sys/mount.h>
76 : #include <sys/namei.h>
77 : #include <sys/vnode.h>
78 : #include <sys/core.h>
79 : #include <sys/syslog.h>
80 : #include <sys/exec.h>
81 : #include <sys/exec_elf.h>
82 : #include <sys/fcntl.h>
83 : #include <sys/ptrace.h>
84 : #include <sys/syscall.h>
85 : #include <sys/signalvar.h>
86 : #include <sys/stat.h>
87 : #include <sys/pledge.h>
88 :
89 : #include <sys/mman.h>
90 :
91 : #include <uvm/uvm_extern.h>
92 :
93 : #include <machine/reg.h>
94 : #include <machine/exec.h>
95 :
96 : int elf_load_file(struct proc *, char *, struct exec_package *,
97 : struct elf_args *);
98 : int elf_check_header(Elf_Ehdr *);
99 : int elf_read_from(struct proc *, struct vnode *, u_long, void *, int);
100 : void elf_load_psection(struct exec_vmcmd_set *, struct vnode *,
101 : Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *, int);
102 : int coredump_elf(struct proc *, void *);
103 : void *elf_copyargs(struct exec_package *, struct ps_strings *, void *,
104 : void *);
105 : int exec_elf_fixup(struct proc *, struct exec_package *);
106 : int elf_os_pt_note(struct proc *, struct exec_package *, Elf_Ehdr *,
107 : char *, size_t, size_t);
108 :
109 : extern char sigcode[], esigcode[], sigcoderet[];
110 : #ifdef SYSCALL_DEBUG
111 : extern char *syscallnames[];
112 : #endif
113 :
114 : /* round up and down to page boundaries. */
115 : #define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
116 : #define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
117 :
118 : /*
119 : * We limit the number of program headers to 32, this should
120 : * be a reasonable limit for ELF, the most we have seen so far is 12
121 : */
122 : #define ELF_MAX_VALID_PHDR 32
123 :
124 : /*
125 : * How many entries are in the AuxInfo array we pass to the process?
126 : */
127 : #define ELF_AUX_ENTRIES 8
128 :
129 : /*
130 : * This is the OpenBSD ELF emul
131 : */
132 : struct emul emul_elf = {
133 : "native",
134 : NULL,
135 : SYS_syscall,
136 : SYS_MAXSYSCALL,
137 : sysent,
138 : #ifdef SYSCALL_DEBUG
139 : syscallnames,
140 : #else
141 : NULL,
142 : #endif
143 : (sizeof(AuxInfo) * ELF_AUX_ENTRIES / sizeof(char *)),
144 : elf_copyargs,
145 : setregs,
146 : exec_elf_fixup,
147 : coredump_elf,
148 : sigcode,
149 : esigcode,
150 : sigcoderet
151 : };
152 :
153 : /*
154 : * Copy arguments onto the stack in the normal way, but add some
155 : * space for extra information in case of dynamic binding.
156 : */
157 : void *
158 0 : elf_copyargs(struct exec_package *pack, struct ps_strings *arginfo,
159 : void *stack, void *argp)
160 : {
161 0 : stack = copyargs(pack, arginfo, stack, argp);
162 0 : if (!stack)
163 0 : return (NULL);
164 :
165 : /*
166 : * Push space for extra arguments on the stack needed by
167 : * dynamically linked binaries.
168 : */
169 0 : if (pack->ep_emul_arg != NULL) {
170 0 : pack->ep_emul_argp = stack;
171 0 : stack = (char *)stack + ELF_AUX_ENTRIES * sizeof (AuxInfo);
172 0 : }
173 0 : return (stack);
174 0 : }
175 :
176 : /*
177 : * Check header for validity; return 0 for ok, ENOEXEC if error
178 : */
179 : int
180 0 : elf_check_header(Elf_Ehdr *ehdr)
181 : {
182 : /*
183 : * We need to check magic, class size, endianess, and version before
184 : * we look at the rest of the Elf_Ehdr structure. These few elements
185 : * are represented in a machine independent fashion.
186 : */
187 0 : if (!IS_ELF(*ehdr) ||
188 0 : ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
189 0 : ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
190 0 : ehdr->e_ident[EI_VERSION] != ELF_TARG_VER)
191 0 : return (ENOEXEC);
192 :
193 : /* Now check the machine dependent header */
194 0 : if (ehdr->e_machine != ELF_TARG_MACH ||
195 0 : ehdr->e_version != ELF_TARG_VER)
196 0 : return (ENOEXEC);
197 :
198 : /* Don't allow an insane amount of sections. */
199 0 : if (ehdr->e_phnum > ELF_MAX_VALID_PHDR)
200 0 : return (ENOEXEC);
201 :
202 0 : return (0);
203 0 : }
204 :
205 : /*
206 : * Load a psection at the appropriate address
207 : */
208 : void
209 0 : elf_load_psection(struct exec_vmcmd_set *vcset, struct vnode *vp,
210 : Elf_Phdr *ph, Elf_Addr *addr, Elf_Addr *size, int *prot, int flags)
211 : {
212 : u_long msize, lsize, psize, rm, rf;
213 : long diff, offset, bdiff;
214 : Elf_Addr base;
215 :
216 : /*
217 : * If the user specified an address, then we load there.
218 : */
219 0 : if (*addr != ELF_NO_ADDR) {
220 0 : if (ph->p_align > 1) {
221 0 : *addr = ELF_TRUNC(*addr, ph->p_align);
222 0 : diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align);
223 : /* page align vaddr */
224 0 : base = *addr + trunc_page(ph->p_vaddr)
225 0 : - ELF_TRUNC(ph->p_vaddr, ph->p_align);
226 0 : } else {
227 : diff = 0;
228 0 : base = *addr + trunc_page(ph->p_vaddr) - ph->p_vaddr;
229 : }
230 : } else {
231 0 : *addr = ph->p_vaddr;
232 0 : if (ph->p_align > 1)
233 0 : *addr = ELF_TRUNC(*addr, ph->p_align);
234 0 : base = trunc_page(ph->p_vaddr);
235 0 : diff = ph->p_vaddr - *addr;
236 : }
237 0 : bdiff = ph->p_vaddr - trunc_page(ph->p_vaddr);
238 :
239 : /*
240 : * Enforce W^X and map W|X segments without X permission
241 : * initially. The dynamic linker will make these read-only
242 : * and add back X permission after relocation processing.
243 : * Static executables with W|X segments will probably crash.
244 : */
245 0 : *prot |= (ph->p_flags & PF_R) ? PROT_READ : 0;
246 0 : *prot |= (ph->p_flags & PF_W) ? PROT_WRITE : 0;
247 0 : if ((ph->p_flags & PF_W) == 0)
248 0 : *prot |= (ph->p_flags & PF_X) ? PROT_EXEC : 0;
249 :
250 0 : msize = ph->p_memsz + diff;
251 0 : offset = ph->p_offset - bdiff;
252 0 : lsize = ph->p_filesz + bdiff;
253 0 : psize = round_page(lsize);
254 :
255 : /*
256 : * Because the pagedvn pager can't handle zero fill of the last
257 : * data page if it's not page aligned we map the last page readvn.
258 : */
259 0 : if (ph->p_flags & PF_W) {
260 0 : psize = trunc_page(lsize);
261 0 : if (psize > 0)
262 0 : NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp,
263 : offset, *prot, flags);
264 0 : if (psize != lsize) {
265 0 : NEW_VMCMD2(vcset, vmcmd_map_readvn, lsize - psize,
266 : base + psize, vp, offset + psize, *prot, flags);
267 0 : }
268 : } else {
269 0 : NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp, offset,
270 : *prot, flags);
271 : }
272 :
273 : /*
274 : * Check if we need to extend the size of the segment
275 : */
276 0 : rm = round_page(*addr + ph->p_memsz + diff);
277 0 : rf = round_page(*addr + ph->p_filesz + diff);
278 :
279 0 : if (rm != rf) {
280 0 : NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0,
281 : *prot, flags);
282 0 : }
283 0 : *size = msize;
284 0 : }
285 :
286 : /*
287 : * Read from vnode into buffer at offset.
288 : */
289 : int
290 0 : elf_read_from(struct proc *p, struct vnode *vp, u_long off, void *buf,
291 : int size)
292 : {
293 : int error;
294 0 : size_t resid;
295 :
296 0 : if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE,
297 0 : 0, p->p_ucred, &resid, p)) != 0)
298 0 : return error;
299 : /*
300 : * See if we got all of it
301 : */
302 0 : if (resid != 0)
303 0 : return (ENOEXEC);
304 0 : return (0);
305 0 : }
306 :
307 : /*
308 : * Load a file (interpreter/library) pointed to by path [stolen from
309 : * coff_load_shlib()]. Made slightly generic so it might be used externally.
310 : */
311 : int
312 0 : elf_load_file(struct proc *p, char *path, struct exec_package *epp,
313 : struct elf_args *ap)
314 : {
315 : int error, i;
316 0 : struct nameidata nd;
317 0 : Elf_Ehdr eh;
318 : Elf_Phdr *ph = NULL;
319 : u_long phsize = 0;
320 0 : Elf_Addr addr;
321 : struct vnode *vp;
322 : Elf_Phdr *base_ph = NULL;
323 0 : struct interp_ld_sec {
324 : Elf_Addr vaddr;
325 : u_long memsz;
326 : } loadmap[ELF_MAX_VALID_PHDR];
327 : int nload, idx = 0;
328 : Elf_Addr pos;
329 : int file_align;
330 : int loop;
331 : size_t randomizequota = ELF_RANDOMIZE_LIMIT;
332 :
333 0 : NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
334 0 : nd.ni_pledge = PLEDGE_RPATH;
335 0 : nd.ni_unveil = UNVEIL_READ;
336 0 : if ((error = namei(&nd)) != 0) {
337 0 : return (error);
338 : }
339 0 : vp = nd.ni_vp;
340 0 : if (vp->v_type != VREG) {
341 : error = EACCES;
342 0 : goto bad;
343 : }
344 0 : if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0)
345 : goto bad;
346 0 : if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
347 : error = EACCES;
348 0 : goto bad;
349 : }
350 0 : if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0)
351 : goto bad1;
352 0 : if ((error = elf_read_from(p, nd.ni_vp, 0, &eh, sizeof(eh))) != 0)
353 : goto bad1;
354 :
355 0 : if (elf_check_header(&eh) || eh.e_type != ET_DYN) {
356 : error = ENOEXEC;
357 0 : goto bad1;
358 : }
359 :
360 0 : ph = mallocarray(eh.e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK);
361 0 : phsize = eh.e_phnum * sizeof(Elf_Phdr);
362 :
363 0 : if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff, ph, phsize)) != 0)
364 : goto bad1;
365 :
366 0 : for (i = 0; i < eh.e_phnum; i++) {
367 0 : if (ph[i].p_type == PT_LOAD) {
368 0 : if (ph[i].p_filesz > ph[i].p_memsz ||
369 0 : ph[i].p_memsz == 0) {
370 : error = EINVAL;
371 0 : goto bad1;
372 : }
373 0 : loadmap[idx].vaddr = trunc_page(ph[i].p_vaddr);
374 0 : loadmap[idx].memsz = round_page (ph[i].p_vaddr +
375 : ph[i].p_memsz - loadmap[idx].vaddr);
376 0 : file_align = ph[i].p_align;
377 0 : idx++;
378 0 : }
379 : }
380 : nload = idx;
381 :
382 : /*
383 : * Load the interpreter where a non-fixed mmap(NULL, ...)
384 : * would (i.e. something safely out of the way).
385 : */
386 0 : pos = uvm_map_hint(p->p_vmspace, PROT_EXEC, VM_MIN_ADDRESS,
387 : VM_MAXUSER_ADDRESS);
388 0 : pos = ELF_ROUND(pos, file_align);
389 :
390 : loop = 0;
391 0 : for (i = 0; i < nload;/**/) {
392 0 : vaddr_t addr;
393 : struct uvm_object *uobj;
394 : off_t uoff;
395 : size_t size;
396 :
397 : #ifdef this_needs_fixing
398 : if (i == 0) {
399 : uobj = &vp->v_uvm.u_obj;
400 : /* need to fix uoff */
401 : } else {
402 : #endif
403 : uobj = NULL;
404 : uoff = 0;
405 : #ifdef this_needs_fixing
406 : }
407 : #endif
408 :
409 0 : addr = trunc_page(pos + loadmap[i].vaddr);
410 0 : size = round_page(addr + loadmap[i].memsz) - addr;
411 :
412 : /* CRAP - map_findspace does not avoid daddr+BRKSIZ */
413 0 : if ((addr + size > (vaddr_t)p->p_vmspace->vm_daddr) &&
414 0 : (addr < (vaddr_t)p->p_vmspace->vm_daddr + BRKSIZ))
415 0 : addr = round_page((vaddr_t)p->p_vmspace->vm_daddr +
416 : BRKSIZ);
417 :
418 0 : if (uvm_map_mquery(&p->p_vmspace->vm_map, &addr, size,
419 0 : (i == 0 ? uoff : UVM_UNKNOWN_OFFSET), 0) != 0) {
420 0 : if (loop == 0) {
421 : loop = 1;
422 : i = 0;
423 : pos = 0;
424 0 : continue;
425 : }
426 : error = ENOMEM;
427 0 : goto bad1;
428 : }
429 0 : if (addr != pos + loadmap[i].vaddr) {
430 : /* base changed. */
431 0 : pos = addr - trunc_page(loadmap[i].vaddr);
432 0 : pos = ELF_ROUND(pos,file_align);
433 : i = 0;
434 0 : continue;
435 : }
436 :
437 0 : i++;
438 0 : }
439 :
440 : /*
441 : * Load all the necessary sections
442 : */
443 0 : for (i = 0; i < eh.e_phnum; i++) {
444 0 : Elf_Addr size = 0;
445 0 : int prot = 0;
446 : int flags;
447 :
448 0 : switch (ph[i].p_type) {
449 : case PT_LOAD:
450 0 : if (base_ph == NULL) {
451 : flags = VMCMD_BASE;
452 0 : addr = pos;
453 : base_ph = &ph[i];
454 0 : } else {
455 : flags = VMCMD_RELATIVE;
456 0 : addr = ph[i].p_vaddr - base_ph->p_vaddr;
457 : }
458 0 : elf_load_psection(&epp->ep_vmcmds, nd.ni_vp,
459 : &ph[i], &addr, &size, &prot, flags);
460 : /* If entry is within this section it must be text */
461 0 : if (eh.e_entry >= ph[i].p_vaddr &&
462 0 : eh.e_entry < (ph[i].p_vaddr + size)) {
463 0 : epp->ep_entry = addr + eh.e_entry -
464 0 : ELF_TRUNC(ph[i].p_vaddr,ph[i].p_align);
465 0 : if (flags == VMCMD_RELATIVE)
466 0 : epp->ep_entry += pos;
467 0 : ap->arg_interp = pos;
468 0 : }
469 0 : addr += size;
470 0 : break;
471 :
472 : case PT_DYNAMIC:
473 : case PT_PHDR:
474 : case PT_NOTE:
475 : break;
476 :
477 : case PT_OPENBSD_RANDOMIZE:
478 0 : if (ph[i].p_memsz > randomizequota) {
479 : error = ENOMEM;
480 0 : goto bad1;
481 : }
482 0 : randomizequota -= ph[i].p_memsz;
483 0 : NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize,
484 : ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0);
485 0 : break;
486 :
487 : default:
488 : break;
489 : }
490 0 : }
491 :
492 0 : vn_marktext(nd.ni_vp);
493 :
494 : bad1:
495 0 : VOP_CLOSE(nd.ni_vp, FREAD, p->p_ucred, p);
496 : bad:
497 0 : free(ph, M_TEMP, phsize);
498 :
499 0 : vput(nd.ni_vp);
500 0 : return (error);
501 0 : }
502 :
503 : /*
504 : * Prepare an Elf binary's exec package
505 : *
506 : * First, set of the various offsets/lengths in the exec package.
507 : *
508 : * Then, mark the text image busy (so it can be demand paged) or error out if
509 : * this is not possible. Finally, set up vmcmds for the text, data, bss, and
510 : * stack segments.
511 : */
512 : int
513 0 : exec_elf_makecmds(struct proc *p, struct exec_package *epp)
514 : {
515 0 : Elf_Ehdr *eh = epp->ep_hdr;
516 : Elf_Phdr *ph, *pp, *base_ph = NULL;
517 : Elf_Addr phdr = 0, exe_base = 0;
518 : int error, i, has_phdr = 0;
519 : char *interp = NULL;
520 : u_long phsize;
521 : size_t randomizequota = ELF_RANDOMIZE_LIMIT;
522 :
523 0 : if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
524 0 : return (ENOEXEC);
525 :
526 0 : if (elf_check_header(eh) ||
527 0 : (eh->e_type != ET_EXEC && eh->e_type != ET_DYN))
528 0 : return (ENOEXEC);
529 :
530 : /*
531 : * check if vnode is in open for writing, because we want to demand-
532 : * page out of it. if it is, don't do it, for various reasons.
533 : */
534 0 : if (epp->ep_vp->v_writecount != 0) {
535 : #ifdef DIAGNOSTIC
536 0 : if (epp->ep_vp->v_flag & VTEXT)
537 0 : panic("exec: a VTEXT vnode has writecount != 0");
538 : #endif
539 0 : return (ETXTBSY);
540 : }
541 : /*
542 : * Allocate space to hold all the program headers, and read them
543 : * from the file
544 : */
545 0 : ph = mallocarray(eh->e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK);
546 0 : phsize = eh->e_phnum * sizeof(Elf_Phdr);
547 :
548 0 : if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff, ph,
549 0 : phsize)) != 0)
550 : goto bad;
551 :
552 0 : epp->ep_tsize = ELF_NO_ADDR;
553 0 : epp->ep_dsize = ELF_NO_ADDR;
554 :
555 0 : for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
556 0 : if (pp->p_type == PT_INTERP && !interp) {
557 0 : if (pp->p_filesz < 2 || pp->p_filesz > MAXPATHLEN)
558 : goto bad;
559 0 : interp = pool_get(&namei_pool, PR_WAITOK);
560 0 : if ((error = elf_read_from(p, epp->ep_vp,
561 0 : pp->p_offset, interp, pp->p_filesz)) != 0) {
562 : goto bad;
563 : }
564 0 : if (interp[pp->p_filesz - 1] != '\0')
565 : goto bad;
566 0 : } else if (pp->p_type == PT_LOAD) {
567 0 : if (pp->p_filesz > pp->p_memsz ||
568 0 : pp->p_memsz == 0) {
569 : error = EINVAL;
570 0 : goto bad;
571 : }
572 0 : if (base_ph == NULL)
573 0 : base_ph = pp;
574 0 : } else if (pp->p_type == PT_PHDR) {
575 : has_phdr = 1;
576 0 : }
577 : }
578 :
579 0 : if (eh->e_type == ET_DYN) {
580 : /* need phdr and load sections for PIE */
581 0 : if (!has_phdr || base_ph == NULL) {
582 : error = EINVAL;
583 0 : goto bad;
584 : }
585 : /* randomize exe_base for PIE */
586 0 : exe_base = uvm_map_pie(base_ph->p_align);
587 0 : }
588 :
589 : /*
590 : * OK, we want a slightly different twist of the
591 : * standard emulation package for "real" elf.
592 : */
593 0 : epp->ep_emul = &emul_elf;
594 :
595 : /*
596 : * Verify this is an OpenBSD executable. If it's marked that way
597 : * via a PT_NOTE then also check for a PT_OPENBSD_WXNEEDED segment.
598 : */
599 0 : if (eh->e_ident[EI_OSABI] != ELFOSABI_OPENBSD && (error =
600 0 : elf_os_pt_note(p, epp, epp->ep_hdr, "OpenBSD", 8, 4)) != 0) {
601 : goto bad;
602 : }
603 :
604 : /*
605 : * Load all the necessary sections
606 : */
607 0 : for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
608 0 : Elf_Addr addr, size = 0;
609 0 : int prot = 0;
610 : int flags = 0;
611 :
612 0 : switch (pp->p_type) {
613 : case PT_LOAD:
614 0 : if (exe_base != 0) {
615 0 : if (pp == base_ph) {
616 : flags = VMCMD_BASE;
617 0 : addr = exe_base;
618 0 : } else {
619 : flags = VMCMD_RELATIVE;
620 0 : addr = pp->p_vaddr - base_ph->p_vaddr;
621 : }
622 : } else
623 0 : addr = ELF_NO_ADDR;
624 :
625 : /*
626 : * Calculates size of text and data segments
627 : * by starting at first and going to end of last.
628 : * 'rwx' sections are treated as data.
629 : * this is correct for BSS_PLT, but may not be
630 : * for DATA_PLT, is fine for TEXT_PLT.
631 : */
632 0 : elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
633 : pp, &addr, &size, &prot, flags);
634 :
635 : /*
636 : * Update exe_base in case alignment was off.
637 : * For PIE, addr is relative to exe_base so
638 : * adjust it (non PIE exe_base is 0 so no change).
639 : */
640 0 : if (flags == VMCMD_BASE)
641 0 : exe_base = addr;
642 : else
643 0 : addr += exe_base;
644 :
645 : /*
646 : * Decide whether it's text or data by looking
647 : * at the protection of the section
648 : */
649 0 : if (prot & PROT_WRITE) {
650 : /* data section */
651 0 : if (epp->ep_dsize == ELF_NO_ADDR) {
652 0 : epp->ep_daddr = addr;
653 0 : epp->ep_dsize = size;
654 0 : } else {
655 0 : if (addr < epp->ep_daddr) {
656 0 : epp->ep_dsize =
657 0 : epp->ep_dsize +
658 0 : epp->ep_daddr -
659 : addr;
660 0 : epp->ep_daddr = addr;
661 0 : } else
662 0 : epp->ep_dsize = addr+size -
663 : epp->ep_daddr;
664 : }
665 0 : } else if (prot & PROT_EXEC) {
666 : /* text section */
667 0 : if (epp->ep_tsize == ELF_NO_ADDR) {
668 0 : epp->ep_taddr = addr;
669 0 : epp->ep_tsize = size;
670 0 : } else {
671 0 : if (addr < epp->ep_taddr) {
672 0 : epp->ep_tsize =
673 0 : epp->ep_tsize +
674 0 : epp->ep_taddr -
675 : addr;
676 0 : epp->ep_taddr = addr;
677 0 : } else
678 0 : epp->ep_tsize = addr+size -
679 : epp->ep_taddr;
680 : }
681 : }
682 : break;
683 :
684 : case PT_SHLIB:
685 : error = ENOEXEC;
686 0 : goto bad;
687 :
688 : case PT_INTERP:
689 : /* Already did this one */
690 : case PT_DYNAMIC:
691 : case PT_NOTE:
692 : break;
693 :
694 : case PT_PHDR:
695 : /* Note address of program headers (in text segment) */
696 0 : phdr = pp->p_vaddr;
697 0 : break;
698 :
699 : case PT_OPENBSD_RANDOMIZE:
700 0 : if (ph[i].p_memsz > randomizequota) {
701 : error = ENOMEM;
702 0 : goto bad;
703 : }
704 0 : randomizequota -= ph[i].p_memsz;
705 0 : NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize,
706 : ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0, 0);
707 0 : break;
708 :
709 : default:
710 : /*
711 : * Not fatal, we don't need to understand everything
712 : * :-)
713 : */
714 : break;
715 : }
716 0 : }
717 :
718 0 : phdr += exe_base;
719 :
720 : /*
721 : * Strangely some linux programs may have all load sections marked
722 : * writeable, in this case, textsize is not -1, but rather 0;
723 : */
724 0 : if (epp->ep_tsize == ELF_NO_ADDR)
725 0 : epp->ep_tsize = 0;
726 : /*
727 : * Another possibility is that it has all load sections marked
728 : * read-only. Fake a zero-sized data segment right after the
729 : * text segment.
730 : */
731 0 : if (epp->ep_dsize == ELF_NO_ADDR) {
732 0 : epp->ep_daddr = round_page(epp->ep_taddr + epp->ep_tsize);
733 0 : epp->ep_dsize = 0;
734 0 : }
735 :
736 0 : epp->ep_interp = interp;
737 0 : epp->ep_entry = eh->e_entry + exe_base;
738 :
739 : /*
740 : * Check if we found a dynamically linked binary and arrange to load
741 : * its interpreter when the exec file is released.
742 : */
743 0 : if (interp || eh->e_type == ET_DYN) {
744 : struct elf_args *ap;
745 :
746 0 : ap = malloc(sizeof(*ap), M_TEMP, M_WAITOK);
747 :
748 0 : ap->arg_phaddr = phdr;
749 0 : ap->arg_phentsize = eh->e_phentsize;
750 0 : ap->arg_phnum = eh->e_phnum;
751 0 : ap->arg_entry = eh->e_entry + exe_base;
752 0 : ap->arg_interp = exe_base;
753 :
754 0 : epp->ep_emul_arg = ap;
755 0 : epp->ep_emul_argsize = sizeof *ap;
756 0 : }
757 :
758 0 : free(ph, M_TEMP, phsize);
759 0 : vn_marktext(epp->ep_vp);
760 0 : return (exec_setup_stack(p, epp));
761 :
762 : bad:
763 0 : if (interp)
764 0 : pool_put(&namei_pool, interp);
765 0 : free(ph, M_TEMP, phsize);
766 0 : kill_vmcmds(&epp->ep_vmcmds);
767 0 : if (error == 0)
768 0 : return (ENOEXEC);
769 0 : return (error);
770 0 : }
771 :
772 : /*
773 : * Phase II of load. It is now safe to load the interpreter. Info collected
774 : * when loading the program is available for setup of the interpreter.
775 : */
776 : int
777 0 : exec_elf_fixup(struct proc *p, struct exec_package *epp)
778 : {
779 : char *interp;
780 : int error = 0;
781 : struct elf_args *ap;
782 0 : AuxInfo ai[ELF_AUX_ENTRIES], *a;
783 :
784 0 : if (epp->ep_emul_arg == NULL) {
785 0 : return (0);
786 : }
787 :
788 0 : interp = epp->ep_interp;
789 0 : ap = epp->ep_emul_arg;
790 :
791 0 : if (interp &&
792 0 : (error = elf_load_file(p, interp, epp, ap)) != 0) {
793 0 : free(ap, M_TEMP, epp->ep_emul_argsize);
794 0 : pool_put(&namei_pool, interp);
795 0 : kill_vmcmds(&epp->ep_vmcmds);
796 0 : return (error);
797 : }
798 : /*
799 : * We have to do this ourselves...
800 : */
801 0 : error = exec_process_vmcmds(p, epp);
802 :
803 : /*
804 : * Push extra arguments on the stack needed by dynamically
805 : * linked binaries
806 : */
807 0 : if (error == 0) {
808 0 : memset(&ai, 0, sizeof ai);
809 0 : a = ai;
810 :
811 0 : a->au_id = AUX_phdr;
812 0 : a->au_v = ap->arg_phaddr;
813 0 : a++;
814 :
815 0 : a->au_id = AUX_phent;
816 0 : a->au_v = ap->arg_phentsize;
817 0 : a++;
818 :
819 0 : a->au_id = AUX_phnum;
820 0 : a->au_v = ap->arg_phnum;
821 0 : a++;
822 :
823 0 : a->au_id = AUX_pagesz;
824 0 : a->au_v = PAGE_SIZE;
825 0 : a++;
826 :
827 0 : a->au_id = AUX_base;
828 0 : a->au_v = ap->arg_interp;
829 0 : a++;
830 :
831 0 : a->au_id = AUX_flags;
832 0 : a->au_v = 0;
833 0 : a++;
834 :
835 0 : a->au_id = AUX_entry;
836 0 : a->au_v = ap->arg_entry;
837 0 : a++;
838 :
839 0 : a->au_id = AUX_null;
840 0 : a->au_v = 0;
841 : a++;
842 :
843 0 : error = copyout(ai, epp->ep_emul_argp, sizeof ai);
844 0 : }
845 0 : free(ap, M_TEMP, epp->ep_emul_argsize);
846 0 : if (interp)
847 0 : pool_put(&namei_pool, interp);
848 0 : return (error);
849 0 : }
850 :
851 : int
852 0 : elf_os_pt_note(struct proc *p, struct exec_package *epp, Elf_Ehdr *eh,
853 : char *os_name, size_t name_size, size_t desc_size)
854 : {
855 0 : char pathbuf[MAXPATHLEN];
856 : Elf_Phdr *hph, *ph;
857 : Elf_Note *np = NULL;
858 : size_t phsize;
859 : int error;
860 :
861 0 : hph = mallocarray(eh->e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK);
862 0 : phsize = eh->e_phnum * sizeof(Elf_Phdr);
863 0 : if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff,
864 0 : hph, phsize)) != 0)
865 : goto out1;
866 :
867 0 : for (ph = hph; ph < &hph[eh->e_phnum]; ph++) {
868 0 : if (ph->p_type == PT_OPENBSD_WXNEEDED) {
869 0 : int wxallowed = (epp->ep_vp->v_mount &&
870 0 : (epp->ep_vp->v_mount->mnt_flag & MNT_WXALLOWED));
871 :
872 0 : if (!wxallowed) {
873 0 : error = copyinstr(epp->ep_name, &pathbuf,
874 : sizeof(pathbuf), NULL);
875 0 : log(LOG_NOTICE,
876 : "%s(%d): W^X binary outside wxallowed mountpoint\n",
877 0 : error ? "" : pathbuf, p->p_p->ps_pid);
878 : error = EACCES;
879 0 : goto out1;
880 : }
881 0 : epp->ep_flags |= EXEC_WXNEEDED;
882 0 : break;
883 : }
884 : }
885 :
886 0 : for (ph = hph; ph < &hph[eh->e_phnum]; ph++) {
887 0 : if (ph->p_type != PT_NOTE ||
888 0 : ph->p_filesz > 1024 ||
889 0 : ph->p_filesz < sizeof(Elf_Note) + name_size)
890 : continue;
891 :
892 0 : np = malloc(ph->p_filesz, M_TEMP, M_WAITOK);
893 0 : if ((error = elf_read_from(p, epp->ep_vp, ph->p_offset,
894 0 : np, ph->p_filesz)) != 0)
895 : goto out2;
896 :
897 : #if 0
898 : if (np->type != ELF_NOTE_TYPE_OSVERSION) {
899 : free(np, M_TEMP, ph->p_filesz);
900 : np = NULL;
901 : continue;
902 : }
903 : #endif
904 :
905 : /* Check the name and description sizes. */
906 0 : if (np->namesz != name_size ||
907 0 : np->descsz != desc_size)
908 : goto out3;
909 :
910 0 : if (memcmp((np + 1), os_name, name_size))
911 : goto out3;
912 :
913 : /* XXX: We could check for the specific emulation here */
914 : /* All checks succeeded. */
915 : error = 0;
916 0 : goto out2;
917 : }
918 :
919 : out3:
920 0 : error = ENOEXEC;
921 : out2:
922 0 : free(np, M_TEMP, ph->p_filesz);
923 : out1:
924 0 : free(hph, M_TEMP, phsize);
925 0 : return error;
926 0 : }
927 :
928 : /*
929 : * Start of routines related to dumping core
930 : */
931 :
932 : #ifdef SMALL_KERNEL
933 : int
934 : coredump_elf(struct proc *p, void *cookie)
935 : {
936 : return EPERM;
937 : }
938 : #else /* !SMALL_KERNEL */
939 :
940 : struct writesegs_state {
941 : off_t notestart;
942 : off_t secstart;
943 : off_t secoff;
944 : struct proc *p;
945 : void *iocookie;
946 : Elf_Phdr *psections;
947 : size_t psectionslen;
948 : size_t notesize;
949 : int npsections;
950 : };
951 :
952 : uvm_coredump_setup_cb coredump_setup_elf;
953 : uvm_coredump_walk_cb coredump_walk_elf;
954 :
955 : int coredump_notes_elf(struct proc *, void *, size_t *);
956 : int coredump_note_elf(struct proc *, void *, size_t *);
957 : int coredump_writenote_elf(struct proc *, void *, Elf_Note *,
958 : const char *, void *);
959 :
960 : #define ELFROUNDSIZE 4 /* XXX Should it be sizeof(Elf_Word)? */
961 : #define elfround(x) roundup((x), ELFROUNDSIZE)
962 :
963 : int
964 0 : coredump_elf(struct proc *p, void *cookie)
965 : {
966 : #ifdef DIAGNOSTIC
967 : off_t offset;
968 : #endif
969 0 : struct writesegs_state ws;
970 0 : size_t notesize;
971 : int error, i;
972 :
973 0 : ws.p = p;
974 0 : ws.iocookie = cookie;
975 0 : ws.psections = NULL;
976 :
977 : /*
978 : * Walk the map to get all the segment offsets and lengths,
979 : * write out the ELF header.
980 : */
981 0 : error = uvm_coredump_walkmap(p, coredump_setup_elf,
982 : coredump_walk_elf, &ws);
983 0 : if (error)
984 : goto out;
985 :
986 0 : error = coredump_write(cookie, UIO_SYSSPACE, ws.psections,
987 0 : ws.psectionslen);
988 0 : if (error)
989 : goto out;
990 :
991 : /* Write out the notes. */
992 0 : error = coredump_notes_elf(p, cookie, ¬esize);
993 0 : if (error)
994 : goto out;
995 :
996 : #ifdef DIAGNOSTIC
997 0 : if (notesize != ws.notesize)
998 0 : panic("coredump: notesize changed: %zu != %zu",
999 : ws.notesize, notesize);
1000 0 : offset = ws.notestart + notesize;
1001 0 : if (offset != ws.secstart)
1002 0 : panic("coredump: offset %lld != secstart %lld",
1003 : (long long) offset, (long long) ws.secstart);
1004 : #endif
1005 :
1006 : /* Pass 3: finally, write the sections themselves. */
1007 0 : for (i = 0; i < ws.npsections - 1; i++) {
1008 0 : Elf_Phdr *pent = &ws.psections[i];
1009 0 : if (pent->p_filesz == 0)
1010 0 : continue;
1011 :
1012 : #ifdef DIAGNOSTIC
1013 0 : if (offset != pent->p_offset)
1014 0 : panic("coredump: offset %lld != p_offset[%d] %lld",
1015 : (long long) offset, i,
1016 : (long long) pent->p_filesz);
1017 : #endif
1018 :
1019 0 : error = coredump_write(cookie, UIO_USERSPACE,
1020 0 : (void *)(vaddr_t)pent->p_vaddr, pent->p_filesz);
1021 0 : if (error)
1022 0 : goto out;
1023 :
1024 0 : coredump_unmap(cookie, (vaddr_t)pent->p_vaddr,
1025 0 : (vaddr_t)pent->p_vaddr + pent->p_filesz);
1026 :
1027 : #ifdef DIAGNOSTIC
1028 0 : offset += ws.psections[i].p_filesz;
1029 : #endif
1030 0 : }
1031 :
1032 : out:
1033 0 : free(ws.psections, M_TEMP, ws.psectionslen);
1034 0 : return (error);
1035 0 : }
1036 :
1037 :
1038 :
1039 : int
1040 0 : coredump_setup_elf(int segment_count, void *cookie)
1041 : {
1042 0 : Elf_Ehdr ehdr;
1043 0 : struct writesegs_state *ws = cookie;
1044 : Elf_Phdr *note;
1045 : int error;
1046 :
1047 : /* Get the count of segments, plus one for the PT_NOTE */
1048 0 : ws->npsections = segment_count + 1;
1049 :
1050 : /* Get the size of the notes. */
1051 0 : error = coredump_notes_elf(ws->p, NULL, &ws->notesize);
1052 0 : if (error)
1053 0 : return error;
1054 :
1055 : /* Setup the ELF header */
1056 0 : memset(&ehdr, 0, sizeof(ehdr));
1057 0 : memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
1058 0 : ehdr.e_ident[EI_CLASS] = ELF_TARG_CLASS;
1059 0 : ehdr.e_ident[EI_DATA] = ELF_TARG_DATA;
1060 0 : ehdr.e_ident[EI_VERSION] = EV_CURRENT;
1061 : /* XXX Should be the OSABI/ABI version of the executable. */
1062 0 : ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
1063 0 : ehdr.e_ident[EI_ABIVERSION] = 0;
1064 0 : ehdr.e_type = ET_CORE;
1065 : /* XXX This should be the e_machine of the executable. */
1066 0 : ehdr.e_machine = ELF_TARG_MACH;
1067 0 : ehdr.e_version = EV_CURRENT;
1068 0 : ehdr.e_entry = 0;
1069 0 : ehdr.e_phoff = sizeof(ehdr);
1070 0 : ehdr.e_shoff = 0;
1071 0 : ehdr.e_flags = 0;
1072 0 : ehdr.e_ehsize = sizeof(ehdr);
1073 0 : ehdr.e_phentsize = sizeof(Elf_Phdr);
1074 0 : ehdr.e_phnum = ws->npsections;
1075 0 : ehdr.e_shentsize = 0;
1076 0 : ehdr.e_shnum = 0;
1077 0 : ehdr.e_shstrndx = 0;
1078 :
1079 : /* Write out the ELF header. */
1080 0 : error = coredump_write(ws->iocookie, UIO_SYSSPACE, &ehdr, sizeof(ehdr));
1081 0 : if (error)
1082 0 : return error;
1083 :
1084 : /*
1085 : * Allocate the segment header array and setup to collect
1086 : * the section sizes and offsets
1087 : */
1088 0 : ws->psections = mallocarray(ws->npsections, sizeof(Elf_Phdr),
1089 : M_TEMP, M_WAITOK|M_ZERO);
1090 0 : ws->psectionslen = ws->npsections * sizeof(Elf_Phdr);
1091 :
1092 0 : ws->notestart = sizeof(ehdr) + ws->psectionslen;
1093 0 : ws->secstart = ws->notestart + ws->notesize;
1094 0 : ws->secoff = ws->secstart;
1095 :
1096 : /* Fill in the PT_NOTE segment header in the last slot */
1097 0 : note = &ws->psections[ws->npsections - 1];
1098 0 : note->p_type = PT_NOTE;
1099 0 : note->p_offset = ws->notestart;
1100 0 : note->p_vaddr = 0;
1101 0 : note->p_paddr = 0;
1102 0 : note->p_filesz = ws->notesize;
1103 0 : note->p_memsz = 0;
1104 0 : note->p_flags = PF_R;
1105 0 : note->p_align = ELFROUNDSIZE;
1106 :
1107 0 : return (0);
1108 0 : }
1109 :
1110 : int
1111 0 : coredump_walk_elf(vaddr_t start, vaddr_t realend, vaddr_t end, vm_prot_t prot,
1112 : int nsegment, void *cookie)
1113 : {
1114 0 : struct writesegs_state *ws = cookie;
1115 : Elf_Phdr phdr;
1116 : vsize_t size, realsize;
1117 :
1118 0 : size = end - start;
1119 0 : realsize = realend - start;
1120 :
1121 : phdr.p_type = PT_LOAD;
1122 0 : phdr.p_offset = ws->secoff;
1123 : phdr.p_vaddr = start;
1124 : phdr.p_paddr = 0;
1125 : phdr.p_filesz = realsize;
1126 : phdr.p_memsz = size;
1127 : phdr.p_flags = 0;
1128 0 : if (prot & PROT_READ)
1129 0 : phdr.p_flags |= PF_R;
1130 0 : if (prot & PROT_WRITE)
1131 0 : phdr.p_flags |= PF_W;
1132 0 : if (prot & PROT_EXEC)
1133 0 : phdr.p_flags |= PF_X;
1134 : phdr.p_align = PAGE_SIZE;
1135 :
1136 0 : ws->secoff += phdr.p_filesz;
1137 0 : ws->psections[nsegment] = phdr;
1138 :
1139 0 : return (0);
1140 : }
1141 :
1142 : int
1143 0 : coredump_notes_elf(struct proc *p, void *iocookie, size_t *sizep)
1144 : {
1145 0 : struct ps_strings pss;
1146 0 : struct iovec iov;
1147 0 : struct uio uio;
1148 0 : struct elfcore_procinfo cpi;
1149 0 : Elf_Note nhdr;
1150 0 : struct process *pr = p->p_p;
1151 : struct proc *q;
1152 0 : size_t size, notesize;
1153 : int error;
1154 :
1155 : size = 0;
1156 :
1157 : /* First, write an elfcore_procinfo. */
1158 0 : notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
1159 : elfround(sizeof(cpi));
1160 0 : if (iocookie) {
1161 0 : memset(&cpi, 0, sizeof(cpi));
1162 :
1163 0 : cpi.cpi_version = ELFCORE_PROCINFO_VERSION;
1164 0 : cpi.cpi_cpisize = sizeof(cpi);
1165 0 : cpi.cpi_signo = p->p_sisig;
1166 0 : cpi.cpi_sigcode = p->p_sicode;
1167 :
1168 0 : cpi.cpi_sigpend = p->p_siglist;
1169 0 : cpi.cpi_sigmask = p->p_sigmask;
1170 0 : cpi.cpi_sigignore = pr->ps_sigacts->ps_sigignore;
1171 0 : cpi.cpi_sigcatch = pr->ps_sigacts->ps_sigcatch;
1172 :
1173 0 : cpi.cpi_pid = pr->ps_pid;
1174 0 : cpi.cpi_ppid = pr->ps_pptr->ps_pid;
1175 0 : cpi.cpi_pgrp = pr->ps_pgid;
1176 0 : if (pr->ps_session->s_leader)
1177 0 : cpi.cpi_sid = pr->ps_session->s_leader->ps_pid;
1178 : else
1179 0 : cpi.cpi_sid = 0;
1180 :
1181 0 : cpi.cpi_ruid = p->p_ucred->cr_ruid;
1182 0 : cpi.cpi_euid = p->p_ucred->cr_uid;
1183 0 : cpi.cpi_svuid = p->p_ucred->cr_svuid;
1184 :
1185 0 : cpi.cpi_rgid = p->p_ucred->cr_rgid;
1186 0 : cpi.cpi_egid = p->p_ucred->cr_gid;
1187 0 : cpi.cpi_svgid = p->p_ucred->cr_svgid;
1188 :
1189 0 : (void)strlcpy(cpi.cpi_name, pr->ps_comm, sizeof(cpi.cpi_name));
1190 :
1191 0 : nhdr.namesz = sizeof("OpenBSD");
1192 0 : nhdr.descsz = sizeof(cpi);
1193 0 : nhdr.type = NT_OPENBSD_PROCINFO;
1194 :
1195 0 : error = coredump_writenote_elf(p, iocookie, &nhdr,
1196 : "OpenBSD", &cpi);
1197 0 : if (error)
1198 0 : return (error);
1199 : }
1200 0 : size += notesize;
1201 :
1202 : /* Second, write an NT_OPENBSD_AUXV note. */
1203 0 : notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
1204 0 : elfround(pr->ps_emul->e_arglen * sizeof(char *));
1205 0 : if (iocookie) {
1206 0 : iov.iov_base = &pss;
1207 0 : iov.iov_len = sizeof(pss);
1208 0 : uio.uio_iov = &iov;
1209 0 : uio.uio_iovcnt = 1;
1210 0 : uio.uio_offset = (off_t)pr->ps_strings;
1211 0 : uio.uio_resid = sizeof(pss);
1212 0 : uio.uio_segflg = UIO_SYSSPACE;
1213 0 : uio.uio_rw = UIO_READ;
1214 0 : uio.uio_procp = NULL;
1215 :
1216 0 : error = uvm_io(&p->p_vmspace->vm_map, &uio, 0);
1217 0 : if (error)
1218 0 : return (error);
1219 :
1220 0 : if (pss.ps_envstr == NULL)
1221 0 : return (EIO);
1222 :
1223 0 : nhdr.namesz = sizeof("OpenBSD");
1224 0 : nhdr.descsz = pr->ps_emul->e_arglen * sizeof(char *);
1225 0 : nhdr.type = NT_OPENBSD_AUXV;
1226 :
1227 0 : error = coredump_write(iocookie, UIO_SYSSPACE,
1228 : &nhdr, sizeof(nhdr));
1229 0 : if (error)
1230 0 : return (error);
1231 :
1232 0 : error = coredump_write(iocookie, UIO_SYSSPACE,
1233 0 : "OpenBSD", elfround(nhdr.namesz));
1234 0 : if (error)
1235 0 : return (error);
1236 :
1237 0 : error = coredump_write(iocookie, UIO_USERSPACE,
1238 0 : pss.ps_envstr + pss.ps_nenvstr + 1, nhdr.descsz);
1239 0 : if (error)
1240 0 : return (error);
1241 : }
1242 0 : size += notesize;
1243 :
1244 : #ifdef PT_WCOOKIE
1245 : notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
1246 : elfround(sizeof(register_t));
1247 : if (iocookie) {
1248 : register_t wcookie;
1249 :
1250 : nhdr.namesz = sizeof("OpenBSD");
1251 : nhdr.descsz = sizeof(register_t);
1252 : nhdr.type = NT_OPENBSD_WCOOKIE;
1253 :
1254 : wcookie = process_get_wcookie(p);
1255 : error = coredump_writenote_elf(p, iocookie, &nhdr,
1256 : "OpenBSD", &wcookie);
1257 : if (error)
1258 : return (error);
1259 : }
1260 : size += notesize;
1261 : #endif
1262 :
1263 : /*
1264 : * Now write the register info for the thread that caused the
1265 : * coredump.
1266 : */
1267 0 : error = coredump_note_elf(p, iocookie, ¬esize);
1268 0 : if (error)
1269 0 : return (error);
1270 0 : size += notesize;
1271 :
1272 : /*
1273 : * Now, for each thread, write the register info and any other
1274 : * per-thread notes. Since we're dumping core, all the other
1275 : * threads in the process have been stopped and the list can't
1276 : * change.
1277 : */
1278 0 : TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) {
1279 0 : if (q == p) /* we've taken care of this thread */
1280 : continue;
1281 0 : error = coredump_note_elf(q, iocookie, ¬esize);
1282 0 : if (error)
1283 0 : return (error);
1284 0 : size += notesize;
1285 0 : }
1286 :
1287 0 : *sizep = size;
1288 0 : return (0);
1289 0 : }
1290 :
1291 : int
1292 0 : coredump_note_elf(struct proc *p, void *iocookie, size_t *sizep)
1293 : {
1294 0 : Elf_Note nhdr;
1295 : int size, notesize, error;
1296 : int namesize;
1297 0 : char name[64+ELFROUNDSIZE];
1298 0 : struct reg intreg;
1299 : #ifdef PT_GETFPREGS
1300 0 : struct fpreg freg;
1301 : #endif
1302 :
1303 : size = 0;
1304 :
1305 0 : snprintf(name, sizeof(name)-ELFROUNDSIZE, "%s@%d",
1306 0 : "OpenBSD", p->p_tid + THREAD_PID_OFFSET);
1307 0 : namesize = strlen(name) + 1;
1308 0 : memset(name + namesize, 0, elfround(namesize) - namesize);
1309 :
1310 0 : notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(intreg));
1311 0 : if (iocookie) {
1312 0 : error = process_read_regs(p, &intreg);
1313 0 : if (error)
1314 0 : return (error);
1315 :
1316 0 : nhdr.namesz = namesize;
1317 0 : nhdr.descsz = sizeof(intreg);
1318 0 : nhdr.type = NT_OPENBSD_REGS;
1319 :
1320 0 : error = coredump_writenote_elf(p, iocookie, &nhdr,
1321 : name, &intreg);
1322 0 : if (error)
1323 0 : return (error);
1324 :
1325 : }
1326 : size += notesize;
1327 :
1328 : #ifdef PT_GETFPREGS
1329 0 : notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(freg));
1330 0 : if (iocookie) {
1331 0 : error = process_read_fpregs(p, &freg);
1332 0 : if (error)
1333 0 : return (error);
1334 :
1335 0 : nhdr.namesz = namesize;
1336 0 : nhdr.descsz = sizeof(freg);
1337 0 : nhdr.type = NT_OPENBSD_FPREGS;
1338 :
1339 0 : error = coredump_writenote_elf(p, iocookie, &nhdr, name, &freg);
1340 0 : if (error)
1341 0 : return (error);
1342 : }
1343 0 : size += notesize;
1344 : #endif
1345 :
1346 0 : *sizep = size;
1347 : /* XXX Add hook for machdep per-LWP notes. */
1348 0 : return (0);
1349 0 : }
1350 :
1351 : int
1352 0 : coredump_writenote_elf(struct proc *p, void *cookie, Elf_Note *nhdr,
1353 : const char *name, void *data)
1354 : {
1355 : int error;
1356 :
1357 0 : error = coredump_write(cookie, UIO_SYSSPACE, nhdr, sizeof(*nhdr));
1358 0 : if (error)
1359 0 : return error;
1360 :
1361 0 : error = coredump_write(cookie, UIO_SYSSPACE, name,
1362 0 : elfround(nhdr->namesz));
1363 0 : if (error)
1364 0 : return error;
1365 :
1366 0 : return coredump_write(cookie, UIO_SYSSPACE, data, nhdr->descsz);
1367 0 : }
1368 : #endif /* !SMALL_KERNEL */
|