This source file includes following definitions.
- ELFNAME
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/proc.h>
38 #include <sys/malloc.h>
39 #include <sys/pool.h>
40 #include <sys/mount.h>
41 #include <sys/namei.h>
42 #include <sys/vnode.h>
43 #include <sys/exec.h>
44 #include <sys/exec_elf.h>
45 #include <sys/exec_olf.h>
46 #include <sys/file.h>
47 #include <sys/syscall.h>
48 #include <sys/signalvar.h>
49 #include <sys/stat.h>
50
51 #include <sys/mman.h>
52 #include <uvm/uvm_extern.h>
53
54 #include <machine/cpu.h>
55 #include <machine/reg.h>
56 #include <machine/exec.h>
57
58 #ifdef COMPAT_LINUX
59 #include <compat/linux/linux_exec.h>
60 #endif
61
62 #ifdef COMPAT_SVR4
63 #include <compat/svr4/svr4_exec.h>
64 #endif
65
66 #ifdef COMPAT_FREEBSD
67 #include <compat/freebsd/freebsd_exec.h>
68 #endif
69
70 struct ELFNAME(probe_entry) {
71 int (*func)(struct proc *, struct exec_package *, char *,
72 u_long *, u_int8_t *);
73 int os_mask;
74 } ELFNAME(probes)[] = {
75
76 #ifdef COMPAT_FREEBSD
77 { freebsd_elf_probe, 1 << OOS_FREEBSD },
78 #endif
79 #ifdef COMPAT_SVR4
80 { svr4_elf_probe,
81 1 << OOS_SVR4 | 1 << OOS_ESIX | 1 << OOS_SOLARIS | 1 << OOS_SCO |
82 1 << OOS_DELL | 1 << OOS_NCR },
83 #endif
84 #ifdef COMPAT_LINUX
85 { linux_elf_probe, 1 << OOS_LINUX },
86 #endif
87 { 0, 1 << OOS_OPENBSD }
88 };
89
90 int ELFNAME(load_file)(struct proc *, char *, struct exec_package *,
91 struct elf_args *, Elf_Addr *);
92 int ELFNAME(check_header)(Elf_Ehdr *, int);
93 int ELFNAME(olf_check_header)(Elf_Ehdr *, int, u_int8_t *);
94 int ELFNAME(read_from)(struct proc *, struct vnode *, u_long, caddr_t, int);
95 void ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *,
96 Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *, int);
97
98 extern char sigcode[], esigcode[];
99 #ifdef SYSCALL_DEBUG
100 extern char *syscallnames[];
101 #endif
102
103
104 #define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
105 #define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
106
107
108
109
110
111 #define ELF_MAX_VALID_PHDR 32
112
113
114
115
116 struct emul ELFNAMEEND(emul) = {
117 "native",
118 NULL,
119 sendsig,
120 SYS_syscall,
121 SYS_MAXSYSCALL,
122 sysent,
123 #ifdef SYSCALL_DEBUG
124 syscallnames,
125 #else
126 NULL,
127 #endif
128 sizeof (AuxInfo) * ELF_AUX_ENTRIES,
129 ELFNAME(copyargs),
130 setregs,
131 ELFNAME2(exec,fixup),
132 sigcode,
133 esigcode,
134 EMUL_ENABLED | EMUL_NATIVE,
135 };
136
137
138
139
140
141 void *
142 ELFNAME(copyargs)(struct exec_package *pack, struct ps_strings *arginfo,
143 void *stack, void *argp)
144 {
145 stack = copyargs(pack, arginfo, stack, argp);
146 if (!stack)
147 return (NULL);
148
149
150
151
152
153 if (pack->ep_interp != NULL) {
154 pack->ep_emul_argp = stack;
155 stack = (char *)stack + ELF_AUX_ENTRIES * sizeof (AuxInfo);
156 }
157 return (stack);
158 }
159
160
161
162
163 int
164 ELFNAME(check_header)(Elf_Ehdr *ehdr, int type)
165 {
166
167
168
169
170
171 if (!IS_ELF(*ehdr) ||
172 ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
173 ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
174 ehdr->e_ident[EI_VERSION] != ELF_TARG_VER)
175 return (ENOEXEC);
176
177
178 if (ehdr->e_machine != ELF_TARG_MACH ||
179 ehdr->e_version != ELF_TARG_VER)
180 return (ENOEXEC);
181
182
183 if (ehdr->e_type != type)
184 return (ENOEXEC);
185
186
187 if (ehdr->e_phnum > ELF_MAX_VALID_PHDR)
188 return (ENOEXEC);
189
190 return (0);
191 }
192
193 #ifndef SMALL_KERNEL
194
195
196
197
198 int
199 ELFNAME(olf_check_header)(Elf_Ehdr *ehdr, int type, u_int8_t *os)
200 {
201 int i;
202
203
204
205
206
207
208 if (!IS_OLF(*ehdr) ||
209 ehdr->e_ident[OI_CLASS] != ELF_TARG_CLASS ||
210 ehdr->e_ident[OI_DATA] != ELF_TARG_DATA ||
211 ehdr->e_ident[OI_VERSION] != ELF_TARG_VER)
212 return (ENOEXEC);
213
214 for (i = 0;
215 i < sizeof(ELFNAME(probes)) / sizeof(ELFNAME(probes)[0]);
216 i++) {
217 if ((1 << ehdr->e_ident[OI_OS]) & ELFNAME(probes)[i].os_mask)
218 goto os_ok;
219 }
220 return (ENOEXEC);
221
222 os_ok:
223
224 if (ehdr->e_machine != ELF_TARG_MACH ||
225 ehdr->e_version != ELF_TARG_VER)
226 return (ENOEXEC);
227
228
229 if (ehdr->e_type != type)
230 return (ENOEXEC);
231
232
233 if (ehdr->e_phnum > ELF_MAX_VALID_PHDR)
234 return (ENOEXEC);
235
236 *os = ehdr->e_ident[OI_OS];
237 return (0);
238 }
239 #endif
240
241
242
243
244 void
245 ELFNAME(load_psection)(struct exec_vmcmd_set *vcset, struct vnode *vp,
246 Elf_Phdr *ph, Elf_Addr *addr, Elf_Addr *size, int *prot, int flags)
247 {
248 u_long uaddr, msize, lsize, psize, rm, rf;
249 long diff, offset, bdiff;
250 Elf_Addr base;
251
252
253
254
255 if (*addr != ELFDEFNNAME(NO_ADDR)) {
256 if (ph->p_align > 1) {
257 *addr = ELF_TRUNC(*addr, ph->p_align);
258 diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align);
259
260 base = *addr + trunc_page(ph->p_vaddr)
261 - ELF_TRUNC(ph->p_vaddr, ph->p_align);
262
263 bdiff = ph->p_vaddr - trunc_page(ph->p_vaddr);
264
265 } else
266 diff = 0;
267 } else {
268 *addr = uaddr = ph->p_vaddr;
269 if (ph->p_align > 1)
270 *addr = ELF_TRUNC(uaddr, ph->p_align);
271 base = trunc_page(uaddr);
272 bdiff = uaddr - base;
273 diff = uaddr - *addr;
274 }
275
276 *prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0;
277 *prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0;
278 *prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0;
279
280 msize = ph->p_memsz + diff;
281 offset = ph->p_offset - bdiff;
282 lsize = ph->p_filesz + bdiff;
283 psize = round_page(lsize);
284
285
286
287
288
289 if (ph->p_flags & PF_W) {
290 psize = trunc_page(lsize);
291 if (psize > 0)
292 NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp,
293 offset, *prot, flags);
294 if (psize != lsize) {
295 NEW_VMCMD2(vcset, vmcmd_map_readvn, lsize - psize,
296 base + psize, vp, offset + psize, *prot, flags);
297 }
298 } else {
299 NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp, offset,
300 *prot, flags);
301 }
302
303
304
305
306 rm = round_page(*addr + ph->p_memsz + diff);
307 rf = round_page(*addr + ph->p_filesz + diff);
308
309 if (rm != rf) {
310 NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0,
311 *prot, flags);
312 }
313 *size = msize;
314 }
315
316
317
318
319 int
320 ELFNAME(read_from)(struct proc *p, struct vnode *vp, u_long off, caddr_t buf,
321 int size)
322 {
323 int error;
324 size_t resid;
325
326 if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE,
327 0, p->p_ucred, &resid, p)) != 0)
328 return error;
329
330
331
332 if (resid != 0)
333 return (ENOEXEC);
334 return (0);
335 }
336
337
338
339
340
341 int
342 ELFNAME(load_file)(struct proc *p, char *path, struct exec_package *epp,
343 struct elf_args *ap, Elf_Addr *last)
344 {
345 int error, i;
346 struct nameidata nd;
347 Elf_Ehdr eh;
348 Elf_Phdr *ph = NULL;
349 u_long phsize;
350 Elf_Addr addr;
351 struct vnode *vp;
352 #ifndef SMALL_KERNEL
353 u_int8_t os;
354 #endif
355 Elf_Phdr *base_ph = NULL;
356 struct interp_ld_sec {
357 Elf_Addr vaddr;
358 u_long memsz;
359 } loadmap[ELF_MAX_VALID_PHDR];
360 int nload, idx = 0;
361 Elf_Addr pos = *last;
362 int file_align;
363
364 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
365 if ((error = namei(&nd)) != 0) {
366 return (error);
367 }
368 vp = nd.ni_vp;
369 if (vp->v_type != VREG) {
370 error = EACCES;
371 goto bad;
372 }
373 if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0)
374 goto bad;
375 if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
376 error = EACCES;
377 goto bad;
378 }
379 if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0)
380 goto bad1;
381 if ((error = ELFNAME(read_from)(p, nd.ni_vp, 0,
382 (caddr_t)&eh, sizeof(eh))) != 0)
383 goto bad1;
384
385 if (ELFNAME(check_header)(&eh, ET_DYN)
386 #ifndef SMALL_KERNEL
387 && ELFNAME(olf_check_header)(&eh, ET_DYN, &os)
388 #endif
389 ) {
390 error = ENOEXEC;
391 goto bad1;
392 }
393
394 phsize = eh.e_phnum * sizeof(Elf_Phdr);
395 ph = malloc(phsize, M_TEMP, M_WAITOK);
396
397 if ((error = ELFNAME(read_from)(p, nd.ni_vp, eh.e_phoff, (caddr_t)ph,
398 phsize)) != 0)
399 goto bad1;
400
401 for (i = 0; i < eh.e_phnum; i++) {
402 if (ph[i].p_type == PT_LOAD) {
403 loadmap[idx].vaddr = trunc_page(ph[i].p_vaddr);
404 loadmap[idx].memsz = round_page (ph[i].p_vaddr +
405 ph[i].p_memsz - loadmap[idx].vaddr);
406 file_align = ph[i].p_align;
407 idx++;
408 }
409 }
410 nload = idx;
411
412
413
414
415
416
417 if (pos == ELFDEFNNAME(NO_ADDR)) {
418 pos = uvm_map_hint(p, VM_PROT_EXECUTE);
419 }
420
421 pos = ELF_ROUND(pos, file_align);
422 *last = epp->ep_interp_pos = pos;
423 for (i = 0; i < nload;) {
424 vaddr_t addr;
425 struct uvm_object *uobj;
426 off_t uoff;
427 size_t size;
428
429 #ifdef this_needs_fixing
430 if (i == 0) {
431 uobj = &vp->v_uvm.u_obj;
432
433 } else {
434 #endif
435 uobj = NULL;
436 uoff = 0;
437 #ifdef this_needs_fixing
438 }
439 #endif
440
441 addr = trunc_page(pos + loadmap[i].vaddr);
442 size = round_page(addr + loadmap[i].memsz) - addr;
443
444
445 if ((addr + size > (vaddr_t)p->p_vmspace->vm_daddr) &&
446 (addr < (vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ))
447 addr = round_page((vaddr_t)p->p_vmspace->vm_daddr +
448 MAXDSIZ);
449
450 if (uvm_map_findspace(&p->p_vmspace->vm_map, addr, size,
451 &addr, uobj, uoff, 0, UVM_FLAG_FIXED) == NULL) {
452 if (uvm_map_findspace(&p->p_vmspace->vm_map, addr, size,
453 &addr, uobj, uoff, 0, 0) == NULL) {
454 error = ENOMEM;
455 goto bad1;
456 }
457 }
458 if (addr != pos + loadmap[i].vaddr) {
459
460 pos = addr - trunc_page(loadmap[i].vaddr);
461 pos = ELF_ROUND(pos,file_align);
462 epp->ep_interp_pos = *last = pos;
463 i = 0;
464 continue;
465 }
466
467 i++;
468 }
469
470
471
472
473 for (i = 0; i < eh.e_phnum; i++) {
474 Elf_Addr size = 0;
475 int prot = 0;
476 int flags;
477
478 switch (ph[i].p_type) {
479 case PT_LOAD:
480 if (base_ph == NULL) {
481 flags = VMCMD_BASE;
482 addr = *last;
483 base_ph = &ph[i];
484 } else {
485 flags = VMCMD_RELATIVE;
486 addr = ph[i].p_vaddr - base_ph->p_vaddr;
487 }
488 ELFNAME(load_psection)(&epp->ep_vmcmds, nd.ni_vp,
489 &ph[i], &addr, &size, &prot, flags);
490
491 if (eh.e_entry >= ph[i].p_vaddr &&
492 eh.e_entry < (ph[i].p_vaddr + size)) {
493 epp->ep_entry = addr + eh.e_entry -
494 ELF_TRUNC(ph[i].p_vaddr,ph[i].p_align);
495 ap->arg_interp = addr;
496 }
497 addr += size;
498 break;
499
500 case PT_DYNAMIC:
501 case PT_PHDR:
502 case PT_NOTE:
503 break;
504
505 default:
506 break;
507 }
508 }
509
510 vn_marktext(nd.ni_vp);
511
512 bad1:
513 VOP_CLOSE(nd.ni_vp, FREAD, p->p_ucred, p);
514 bad:
515 if (ph != NULL)
516 free(ph, M_TEMP);
517
518 *last = addr;
519 vput(nd.ni_vp);
520 return (error);
521 }
522
523
524
525
526
527
528
529
530
531
532 int
533 ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp)
534 {
535 Elf_Ehdr *eh = epp->ep_hdr;
536 Elf_Phdr *ph, *pp;
537 Elf_Addr phdr = 0;
538 int error, i;
539 char *interp = NULL;
540 u_long pos = 0, phsize;
541 u_int8_t os = OOS_NULL;
542
543 if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
544 return (ENOEXEC);
545
546 if (ELFNAME(check_header)(eh, ET_EXEC)
547 #ifndef SMALL_KERNEL
548 && ELFNAME(olf_check_header)(eh, ET_EXEC, &os)
549 #endif
550 )
551 return (ENOEXEC);
552
553
554
555
556
557 if (epp->ep_vp->v_writecount != 0) {
558 #ifdef DIAGNOSTIC
559 if (epp->ep_vp->v_flag & VTEXT)
560 panic("exec: a VTEXT vnode has writecount != 0");
561 #endif
562 return (ETXTBSY);
563 }
564
565
566
567
568 phsize = eh->e_phnum * sizeof(Elf_Phdr);
569 ph = malloc(phsize, M_TEMP, M_WAITOK);
570
571 if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, (caddr_t)ph,
572 phsize)) != 0)
573 goto bad;
574
575 epp->ep_tsize = ELFDEFNNAME(NO_ADDR);
576 epp->ep_dsize = ELFDEFNNAME(NO_ADDR);
577
578 for (i = 0; i < eh->e_phnum; i++) {
579 pp = &ph[i];
580 if (pp->p_type == PT_INTERP) {
581 if (pp->p_filesz >= MAXPATHLEN)
582 goto bad;
583 interp = pool_get(&namei_pool, PR_WAITOK);
584 if ((error = ELFNAME(read_from)(p, epp->ep_vp,
585 pp->p_offset, interp, pp->p_filesz)) != 0) {
586 goto bad;
587 }
588 break;
589 }
590 }
591
592
593
594
595
596 epp->ep_emul = &ELFNAMEEND(emul);
597 pos = ELFDEFNNAME(NO_ADDR);
598
599
600
601
602
603
604
605
606
607
608 error = ENOEXEC;
609 p->p_os = OOS_OPENBSD;
610 #ifdef NATIVE_EXEC_ELF
611 if (ELFNAME(os_pt_note)(p, epp, epp->ep_hdr, "OpenBSD", 8, 4) == 0) {
612 goto native;
613 }
614 #endif
615 for (i = 0;
616 i < sizeof(ELFNAME(probes)) / sizeof(ELFNAME(probes)[0]) && error;
617 i++) {
618 if (os == OOS_NULL || ((1 << os) & ELFNAME(probes)[i].os_mask))
619 error = ELFNAME(probes)[i].func ?
620 (*ELFNAME(probes)[i].func)(p, epp, interp, &pos, &os) :
621 0;
622 }
623 if (!error)
624 p->p_os = os;
625 #ifndef NATIVE_EXEC_ELF
626 else
627 goto bad;
628 #else
629 native:
630 #endif
631
632
633
634 for (i = 0; i < eh->e_phnum; i++) {
635 Elf_Addr addr = ELFDEFNNAME(NO_ADDR), size = 0;
636 int prot = 0;
637
638 pp = &ph[i];
639
640 switch (ph[i].p_type) {
641 case PT_LOAD:
642
643
644
645
646
647
648
649 ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp,
650 &ph[i], &addr, &size, &prot, 0);
651
652
653
654
655 if (prot & VM_PROT_WRITE) {
656
657 if (epp->ep_dsize == ELFDEFNNAME(NO_ADDR)) {
658 epp->ep_daddr = addr;
659 epp->ep_dsize = size;
660 } else {
661 if (addr < epp->ep_daddr) {
662 epp->ep_dsize =
663 epp->ep_dsize +
664 epp->ep_daddr -
665 addr;
666 epp->ep_daddr = addr;
667 } else
668 epp->ep_dsize = addr+size -
669 epp->ep_daddr;
670 }
671 } else if (prot & VM_PROT_EXECUTE) {
672
673 if (epp->ep_tsize == ELFDEFNNAME(NO_ADDR)) {
674 epp->ep_taddr = addr;
675 epp->ep_tsize = size;
676 } else {
677 if (addr < epp->ep_taddr) {
678 epp->ep_tsize =
679 epp->ep_tsize +
680 epp->ep_taddr -
681 addr;
682 epp->ep_taddr = addr;
683 } else
684 epp->ep_tsize = addr+size -
685 epp->ep_taddr;
686 }
687 }
688 break;
689
690 case PT_SHLIB:
691 error = ENOEXEC;
692 goto bad;
693
694 case PT_INTERP:
695
696 case PT_DYNAMIC:
697 case PT_NOTE:
698 break;
699
700 case PT_PHDR:
701
702 phdr = pp->p_vaddr;
703 break;
704
705 default:
706
707
708
709
710 break;
711 }
712 }
713
714
715
716
717
718 if (epp->ep_tsize == ELFDEFNNAME(NO_ADDR))
719 epp->ep_tsize = 0;
720
721
722
723
724
725 if (epp->ep_dsize == ELFDEFNNAME(NO_ADDR)) {
726 epp->ep_daddr = round_page(epp->ep_taddr + epp->ep_tsize);
727 epp->ep_dsize = 0;
728 }
729
730 epp->ep_interp = interp;
731 epp->ep_entry = eh->e_entry;
732
733
734
735
736
737 if (interp) {
738 struct elf_args *ap;
739
740 ap = malloc(sizeof(struct elf_args), M_TEMP, M_WAITOK);
741
742 ap->arg_phaddr = phdr;
743 ap->arg_phentsize = eh->e_phentsize;
744 ap->arg_phnum = eh->e_phnum;
745 ap->arg_entry = eh->e_entry;
746 ap->arg_os = os;
747
748 epp->ep_emul_arg = ap;
749 epp->ep_interp_pos = pos;
750 }
751
752 #if defined(COMPAT_SVR4) && defined(i386)
753 #ifndef ELF_MAP_PAGE_ZERO
754
755 if (p->p_os == OOS_DELL)
756 #endif
757 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0,
758 epp->ep_vp, 0, VM_PROT_READ);
759 #endif
760
761 free(ph, M_TEMP);
762 vn_marktext(epp->ep_vp);
763 return (exec_setup_stack(p, epp));
764
765 bad:
766 if (interp)
767 pool_put(&namei_pool, interp);
768 free(ph, M_TEMP);
769 kill_vmcmds(&epp->ep_vmcmds);
770 return (ENOEXEC);
771 }
772
773
774
775
776
777 int
778 ELFNAME2(exec,fixup)(struct proc *p, struct exec_package *epp)
779 {
780 char *interp;
781 int error;
782 struct elf_args *ap;
783 AuxInfo ai[ELF_AUX_ENTRIES], *a;
784 Elf_Addr pos = epp->ep_interp_pos;
785
786 if (epp->ep_interp == NULL) {
787 return (0);
788 }
789
790 interp = epp->ep_interp;
791 ap = epp->ep_emul_arg;
792
793 if ((error = ELFNAME(load_file)(p, interp, epp, ap, &pos)) != 0) {
794 free(ap, M_TEMP);
795 pool_put(&namei_pool, interp);
796 kill_vmcmds(&epp->ep_vmcmds);
797 return (error);
798 }
799
800
801
802 error = exec_process_vmcmds(p, epp);
803
804
805
806
807
808 if (error == 0) {
809 a = ai;
810
811 a->au_id = AUX_phdr;
812 a->au_v = ap->arg_phaddr;
813 a++;
814
815 a->au_id = AUX_phent;
816 a->au_v = ap->arg_phentsize;
817 a++;
818
819 a->au_id = AUX_phnum;
820 a->au_v = ap->arg_phnum;
821 a++;
822
823 a->au_id = AUX_pagesz;
824 a->au_v = PAGE_SIZE;
825 a++;
826
827 a->au_id = AUX_base;
828 a->au_v = ap->arg_interp;
829 a++;
830
831 a->au_id = AUX_flags;
832 a->au_v = 0;
833 a++;
834
835 a->au_id = AUX_entry;
836 a->au_v = ap->arg_entry;
837 a++;
838
839 a->au_id = AUX_null;
840 a->au_v = 0;
841 a++;
842
843 error = copyout(ai, epp->ep_emul_argp, sizeof ai);
844 }
845 free(ap, M_TEMP);
846 pool_put(&namei_pool, interp);
847 return (error);
848 }
849
850
851
852
853
854 char *
855 ELFNAME(check_brand)(Elf_Ehdr *eh)
856 {
857 if (eh->e_ident[EI_ABIVERSION] == '\0')
858 return (NULL);
859 return (&eh->e_ident[EI_ABIVERSION]);
860 }
861
862 int
863 ELFNAME(os_pt_note)(struct proc *p, struct exec_package *epp, Elf_Ehdr *eh,
864 char *os_name, size_t name_size, size_t desc_size)
865 {
866 Elf_Phdr *hph, *ph;
867 Elf_Note *np = NULL;
868 size_t phsize;
869 int error;
870
871 phsize = eh->e_phnum * sizeof(Elf_Phdr);
872 hph = malloc(phsize, M_TEMP, M_WAITOK);
873 if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
874 (caddr_t)hph, phsize)) != 0)
875 goto out1;
876
877 for (ph = hph; ph < &hph[eh->e_phnum]; ph++) {
878 if (ph->p_type != PT_NOTE ||
879 ph->p_filesz > 1024 ||
880 ph->p_filesz < sizeof(Elf_Note) + name_size)
881 continue;
882
883 np = malloc(ph->p_filesz, M_TEMP, M_WAITOK);
884 if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset,
885 (caddr_t)np, ph->p_filesz)) != 0)
886 goto out2;
887
888 #if 0
889 if (np->type != ELF_NOTE_TYPE_OSVERSION) {
890 free(np, M_TEMP);
891 np = NULL;
892 continue;
893 }
894 #endif
895
896
897 if (np->namesz != name_size ||
898 np->descsz != desc_size)
899 goto out3;
900
901 if (bcmp((np + 1), os_name, name_size))
902 goto out3;
903
904
905
906 error = 0;
907 goto out2;
908 }
909
910 out3:
911 error = ENOEXEC;
912 out2:
913 if (np)
914 free(np, M_TEMP);
915 out1:
916 free(hph, M_TEMP);
917 return error;
918 }