diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/freebsd/freebsd_exec.c | 8 | ||||
-rw-r--r-- | sys/compat/linux/linux_exec.c | 8 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_exec.c | 6 | ||||
-rw-r--r-- | sys/conf/files | 4 | ||||
-rw-r--r-- | sys/kern/exec_conf.c | 4 | ||||
-rw-r--r-- | sys/kern/exec_elf.c | 298 | ||||
-rw-r--r-- | sys/kern/exec_elf32.c | 7 | ||||
-rw-r--r-- | sys/kern/exec_elf64.c | 842 | ||||
-rw-r--r-- | sys/sys/exec_elf.h | 14 |
9 files changed, 201 insertions, 990 deletions
diff --git a/sys/compat/freebsd/freebsd_exec.c b/sys/compat/freebsd/freebsd_exec.c index 6ab5e3f081b..26090b38769 100644 --- a/sys/compat/freebsd/freebsd_exec.c +++ b/sys/compat/freebsd/freebsd_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: freebsd_exec.c,v 1.10 2001/02/02 18:34:15 tholo Exp $ */ +/* $OpenBSD: freebsd_exec.c,v 1.11 2001/09/19 13:28:43 art Exp $ */ /* $NetBSD: freebsd_exec.c,v 1.2 1996/05/18 16:02:08 christos Exp $ */ /* @@ -88,9 +88,9 @@ struct emul emul_elf_freebsd = { NULL, #endif FREEBSD_ELF_AUX_ARGSIZ, - elf_copyargs, + elf32_copyargs, setregs, - exec_elf_fixup, + exec_elf32_fixup, freebsd_sigcode, freebsd_esigcode, }; @@ -157,7 +157,7 @@ freebsd_elf_probe(p, epp, itp, pos, os) int error; size_t len; - brand = elf_check_brand(eh); + brand = elf32_check_brand(eh); if (brand == NULL || strcmp(brand, "FreeBSD")) return (EINVAL); if (itp[0]) { diff --git a/sys/compat/linux/linux_exec.c b/sys/compat/linux/linux_exec.c index 821eaca947b..350c153bf0f 100644 --- a/sys/compat/linux/linux_exec.c +++ b/sys/compat/linux/linux_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_exec.c,v 1.16 2001/08/11 23:21:14 art Exp $ */ +/* $OpenBSD: linux_exec.c,v 1.17 2001/09/19 13:28:43 art Exp $ */ /* $NetBSD: linux_exec.c,v 1.13 1996/04/05 00:01:10 christos Exp $ */ /* @@ -112,9 +112,9 @@ struct emul emul_linux_elf = { NULL, #endif LINUX_ELF_AUX_ARGSIZ, - elf_copyargs, + elf32_copyargs, setregs, - exec_elf_fixup, + exec_elf32_fixup, linux_sigcode, linux_esigcode, }; @@ -387,7 +387,7 @@ linux_elf_probe(p, epp, itp, pos, os) int error; size_t len; - brand = elf_check_brand(eh); + brand = elf32_check_brand(eh); if (brand && strcmp(brand, "Linux")) return (EINVAL); if (itp[0]) { diff --git a/sys/compat/svr4/svr4_exec.c b/sys/compat/svr4/svr4_exec.c index f8a494d2bdf..257d5e36b43 100644 --- a/sys/compat/svr4/svr4_exec.c +++ b/sys/compat/svr4/svr4_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: svr4_exec.c,v 1.11 2001/08/11 23:21:14 art Exp $ */ +/* $OpenBSD: svr4_exec.c,v 1.12 2001/09/19 13:28:43 art Exp $ */ /* $NetBSD: svr4_exec.c,v 1.16 1995/10/14 20:24:20 christos Exp $ */ /* @@ -76,7 +76,7 @@ struct emul emul_svr4 = { SVR4_AUX_ARGSIZ, svr4_copyargs, setregs, - exec_elf_fixup, + exec_elf32_fixup, svr4_sigcode, svr4_esigcode, }; @@ -90,7 +90,7 @@ svr4_copyargs(pack, arginfo, stack, argp) { AuxInfo *a; - if (!(a = (AuxInfo *)elf_copyargs(pack, arginfo, stack, argp))) + if (!(a = (AuxInfo *)elf32_copyargs(pack, arginfo, stack, argp))) return (NULL); #ifdef SVR4_COMPAT_SOLARIS2 if (pack->ep_emul_arg) { diff --git a/sys/conf/files b/sys/conf/files index 7c655e9c578..45358c1f083 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.224 2001/09/18 08:52:17 art Exp $ +# $OpenBSD: files,v 1.225 2001/09/19 13:28:43 art Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -437,7 +437,7 @@ file isofs/cd9660/cd9660_vnops.c cd9660 file kern/exec_aout.c file kern/exec_conf.c file kern/exec_ecoff.c -file kern/exec_elf.c +file kern/exec_elf32.c file kern/exec_elf64.c file kern/exec_script.c file kern/exec_subr.c diff --git a/sys/kern/exec_conf.c b/sys/kern/exec_conf.c index 52c3a8ac666..0153a4e3c60 100644 --- a/sys/kern/exec_conf.c +++ b/sys/kern/exec_conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_conf.c,v 1.10 1999/09/10 12:24:27 kstailey Exp $ */ +/* $OpenBSD: exec_conf.c,v 1.11 2001/09/19 13:28:43 art Exp $ */ /* $NetBSD: exec_conf.c,v 1.16 1995/12/09 05:34:47 cgd Exp $ */ /* @@ -87,7 +87,7 @@ struct execsw execsw[] = { { ECOFF_HDR_SIZE, exec_ecoff_makecmds, }, /* ecoff binaries */ #endif #ifdef _KERN_DO_ELF - { sizeof(Elf32_Ehdr), exec_elf_makecmds, }, /* elf binaries */ + { sizeof(Elf32_Ehdr), exec_elf32_makecmds, }, /* elf binaries */ #endif #ifdef _KERN_DO_ELF64 { sizeof(Elf64_Ehdr), exec_elf64_makecmds, }, /* elf binaries */ diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c index 869dcf9fb43..8a879c45253 100644 --- a/sys/kern/exec_elf.c +++ b/sys/kern/exec_elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_elf.c,v 1.34 2001/08/11 23:14:22 art Exp $ */ +/* $OpenBSD: exec_elf.c,v 1.35 2001/09/19 13:28:43 art Exp $ */ /* * Copyright (c) 1996 Per Fogelstrom @@ -40,9 +40,6 @@ #include <sys/namei.h> #include <sys/vnode.h> #include <sys/exec.h> - -#if defined(_KERN_DO_ELF) - #include <sys/exec_elf.h> #include <sys/exec_olf.h> #include <sys/file.h> @@ -69,11 +66,16 @@ #include <compat/freebsd/freebsd_exec.h> #endif -struct elf_probe_entry { +#ifdef COMPAT_NETBSD +#include <compat/netbsd/netbsd_exec.h> +#endif + +struct ELFNAME(probe_entry) { int (*func) __P((struct proc *, struct exec_package *, char *, u_long *, u_int8_t *)); int os_mask; -} elf_probes[] = { +} ELFNAME(probes)[] = { + /* XXX - bogus, shouldn't be size independent.. */ #ifdef COMPAT_FREEBSD { freebsd_elf_probe, 1 << OOS_FREEBSD }, #endif @@ -85,32 +87,33 @@ struct elf_probe_entry { #ifdef COMPAT_LINUX { linux_elf_probe, 1 << OOS_LINUX }, #endif +#ifdef COMPAT_NETBSD + { netbsd_elf64_probe, 1 << OOS_NETBSD }, +#endif { 0, 1 << OOS_OPENBSD } }; -int elf_load_file __P((struct proc *, char *, struct exec_package *, - struct elf_args *, u_long *)); - -int elf_check_header __P((Elf32_Ehdr *, int)); -int olf_check_header __P((Elf32_Ehdr *, int, u_int8_t *)); -int elf_read_from __P((struct proc *, struct vnode *, u_long, caddr_t, int)); -void elf_load_psection __P((struct exec_vmcmd_set *, struct vnode *, - Elf32_Phdr *, u_long *, u_long *, int *)); - -int exec_elf_fixup __P((struct proc *, struct exec_package *)); - -#define ELF_ALIGN(a, b) ((a) & ~((b) - 1)) - -/* - * This is the basic elf emul. elf_probe_funcs may change to other emuls. - */ +int ELFNAME(load_file)(struct proc *, char *, struct exec_package *, + struct elf_args *, Elf_Addr *); +int ELFNAME(check_header)(Elf_Ehdr *, int); +int ELFNAME(olf_check_header)(Elf_Ehdr *, int, u_int8_t *); +int ELFNAME(read_from)(struct proc *, struct vnode *, u_long, caddr_t, int); +void ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *, + Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *); extern char sigcode[], esigcode[]; #ifdef SYSCALL_DEBUG extern char *syscallnames[]; #endif -struct emul emul_elf = { +/* round up and down to page boundaries. */ +#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) +#define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) + +/* + * This is the basic elf emul. elf_probe_funcs may change to other emuls. + */ +struct emul ELFNAMEEND(emul) = { "native", NULL, sendsig, @@ -123,24 +126,20 @@ struct emul emul_elf = { NULL, #endif sizeof (AuxInfo) * ELF_AUX_ENTRIES, - elf_copyargs, + ELFNAME(copyargs), setregs, - exec_elf_fixup, + ELFNAME2(exec,fixup), sigcode, esigcode, }; - /* * Copy arguments onto the stack in the normal way, but add some * space for extra information in case of dynamic binding. */ void * -elf_copyargs(pack, arginfo, stack, argp) - struct exec_package *pack; - struct ps_strings *arginfo; - void *stack; - void *argp; +ELFNAME(copyargs)(struct exec_package *pack, struct ps_strings *arginfo, + void *stack, void *argp) { stack = copyargs(pack, arginfo, stack, argp); if (!stack) @@ -148,7 +147,7 @@ elf_copyargs(pack, arginfo, stack, argp) /* * Push space for extra arguments on the stack needed by - * dynamically linked binaries + * dynamically linked binaries. */ if (pack->ep_interp != NULL) { pack->ep_emul_argp = stack; @@ -158,18 +157,14 @@ elf_copyargs(pack, arginfo, stack, argp) } /* - * elf_check_header(): - * * Check header for validity; return 0 for ok, ENOEXEC if error */ int -elf_check_header(ehdr, type) - Elf32_Ehdr *ehdr; - int type; +ELFNAME(check_header)(Elf_Ehdr *ehdr, int type) { /* * We need to check magic, class size, endianess, and version before - * we look at the rest of the Elf32_Ehdr structure. These few elements + * we look at the rest of the Elf_Ehdr structure. These few elements * are represented in a machine independant fashion. */ if (!IS_ELF(*ehdr) || @@ -195,22 +190,17 @@ elf_check_header(ehdr, type) } /* - * olf_check_header(): - * * Check header for validity; return 0 for ok, ENOEXEC if error. * Remeber OS tag for callers sake. */ int -olf_check_header(ehdr, type, os) - Elf32_Ehdr *ehdr; - int type; - u_int8_t *os; +ELFNAME(olf_check_header)(Elf_Ehdr *ehdr, int type, u_int8_t *os) { int i; /* * We need to check magic, class size, endianess, version, and OS - * before we look at the rest of the Elf32_Ehdr structure. These few + * before we look at the rest of the Elf_Ehdr structure. These few * elements are represented in a machine independant fashion. */ if (!IS_OLF(*ehdr) || @@ -219,9 +209,12 @@ olf_check_header(ehdr, type, os) ehdr->e_ident[OI_VERSION] != ELF_TARG_VER) return (ENOEXEC); - for (i = 0; i < sizeof elf_probes / sizeof elf_probes[0]; i++) - if ((1 << ehdr->e_ident[OI_OS]) & elf_probes[i].os_mask) + for (i = 0; + i < sizeof(ELFNAME(probes)) / sizeof(ELFNAME(probes)[0]); + i++) { + if ((1 << ehdr->e_ident[OI_OS]) & ELFNAME(probes)[i].os_mask) goto os_ok; + } return (ENOEXEC); os_ok: @@ -243,18 +236,11 @@ os_ok: } /* - * elf_load_psection(): - * * Load a psection at the appropriate address */ void -elf_load_psection(vcset, vp, ph, addr, size, prot) - struct exec_vmcmd_set *vcset; - struct vnode *vp; - Elf32_Phdr *ph; - u_long *addr; - u_long *size; - int *prot; +ELFNAME(load_psection)(struct exec_vmcmd_set *vcset, struct vnode *vp, + Elf_Phdr *ph, Elf_Addr *addr, Elf_Addr *size, int *prot) { u_long uaddr, msize, psize, rm, rf; long diff, offset; @@ -262,17 +248,17 @@ elf_load_psection(vcset, vp, ph, addr, size, prot) /* * If the user specified an address, then we load there. */ - if (*addr != ELF32_NO_ADDR) { + if (*addr != ELFDEFNNAME(NO_ADDR)) { if (ph->p_align > 1) { - *addr = ELF_ALIGN(*addr + ph->p_align, ph->p_align); - uaddr = ELF_ALIGN(ph->p_vaddr, ph->p_align); + *addr = ELF_ROUND(*addr, ph->p_align); + uaddr = ELF_TRUNC(ph->p_vaddr, ph->p_align); } else uaddr = ph->p_vaddr; diff = ph->p_vaddr - uaddr; } else { *addr = uaddr = ph->p_vaddr; if (ph->p_align > 1) - *addr = ELF_ALIGN(uaddr, ph->p_align); + *addr = ELF_TRUNC(uaddr, ph->p_align); diff = uaddr - *addr; } @@ -287,7 +273,7 @@ elf_load_psection(vcset, vp, ph, addr, size, prot) /* * Because the pagedvn pager can't handle zero fill of the last - * data page if it's not page aligned we map the las page readvn. + * data page if it's not page aligned we map the last page readvn. */ if (ph->p_flags & PF_W) { psize = trunc_page(*size); @@ -316,17 +302,11 @@ elf_load_psection(vcset, vp, ph, addr, size, prot) } /* - * elf_read_from(): - * - * Read from vnode into buffer at offset. + * Read from vnode into buffer at offset. */ int -elf_read_from(p, vp, off, buf, size) - struct proc *p; - struct vnode *vp; - u_long off; - caddr_t buf; - int size; +ELFNAME(read_from)(struct proc *p, struct vnode *vp, u_long off, caddr_t buf, + int size) { int error; size_t resid; @@ -343,26 +323,20 @@ elf_read_from(p, vp, off, buf, size) } /* - * elf_load_file(): - * * Load a file (interpreter/library) pointed to by path [stolen from * coff_load_shlib()]. Made slightly generic so it might be used externally. */ int -elf_load_file(p, path, epp, ap, last) - struct proc *p; - char *path; - struct exec_package *epp; - struct elf_args *ap; - u_long *last; +ELFNAME(load_file)(struct proc *p, char *path, struct exec_package *epp, + struct elf_args *ap, Elf_Addr *last) { int error, i; struct nameidata nd; - Elf32_Ehdr eh; - Elf32_Phdr *ph = NULL; + Elf_Ehdr eh; + Elf_Phdr *ph = NULL; u_long phsize; char *bp = NULL; - u_long addr = *last; + Elf_Addr addr = *last; struct vnode *vp; u_int8_t os; /* Just a dummy in this routine */ @@ -384,20 +358,20 @@ elf_load_file(p, path, epp, ap, last) } if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0) goto bad1; - if ((error = elf_read_from(p, nd.ni_vp, 0, + if ((error = ELFNAME(read_from)(p, nd.ni_vp, 0, (caddr_t)&eh, sizeof(eh))) != 0) goto bad1; - if (elf_check_header(&eh, ET_DYN) && - olf_check_header(&eh, ET_DYN, &os)) { + if (ELFNAME(check_header)(&eh, ET_DYN) && + ELFNAME(olf_check_header)(&eh, ET_DYN, &os)) { error = ENOEXEC; goto bad1; } - phsize = eh.e_phnum * sizeof(Elf32_Phdr); - ph = (Elf32_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); + phsize = eh.e_phnum * sizeof(Elf_Phdr); + ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); - if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff, (caddr_t)ph, + if ((error = ELFNAME(read_from)(p, nd.ni_vp, eh.e_phoff, (caddr_t)ph, phsize)) != 0) goto bad1; @@ -405,22 +379,22 @@ elf_load_file(p, path, epp, ap, last) * Load all the necessary sections */ for (i = 0; i < eh.e_phnum; i++) { - u_long size = 0; + Elf_Addr size = 0; int prot = 0; #if defined(__mips__) - if (*last == ELF32_NO_ADDR) - addr = ELF32_NO_ADDR; /* GRRRRR!!!!! */ + if (*last == ELFDEFNNAME(NO_ADDR)) + addr = ELFDEFNNAME(NO_ADDR); /* GRRRRR!!!!! */ #endif switch (ph[i].p_type) { case PT_LOAD: - elf_load_psection(&epp->ep_vmcmds, nd.ni_vp, &ph[i], - &addr, &size, &prot); + ELFNAME(load_psection)(&epp->ep_vmcmds, nd.ni_vp, + &ph[i], &addr, &size, &prot); /* If entry is within this section it must be text */ if (eh.e_entry >= ph[i].p_vaddr && eh.e_entry < (ph[i].p_vaddr + size)) { epp->ep_entry = addr + eh.e_entry - - ELF_ALIGN(ph[i].p_vaddr,ph[i].p_align); + ELF_TRUNC(ph[i].p_vaddr,ph[i].p_align); ap->arg_interp = addr; } addr += size; @@ -448,7 +422,7 @@ bad: } /* - * exec_elf_makecmds(): Prepare an Elf binary's exec package + * Prepare an Elf binary's exec package * * First, set of the various offsets/lengths in the exec package. * @@ -457,23 +431,21 @@ bad: * stack segments. */ int -exec_elf_makecmds(p, epp) - struct proc *p; - struct exec_package *epp; +ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp) { - Elf32_Ehdr *eh = epp->ep_hdr; - Elf32_Phdr *ph, *pp; - Elf32_Addr phdr = 0; + Elf_Ehdr *eh = epp->ep_hdr; + Elf_Phdr *ph, *pp; + Elf_Addr phdr = 0; int error, i, nload; char interp[MAXPATHLEN]; u_long pos = 0, phsize; u_int8_t os = OOS_NULL; - if (epp->ep_hdrvalid < sizeof(Elf32_Ehdr)) + if (epp->ep_hdrvalid < sizeof(Elf_Ehdr)) return (ENOEXEC); - if (elf_check_header(eh, ET_EXEC) && - olf_check_header(eh, ET_EXEC, &os)) + if (ELFNAME(check_header)(eh, ET_EXEC) && + ELFNAME(olf_check_header)(eh, ET_EXEC, &os)) return (ENOEXEC); /* @@ -491,15 +463,15 @@ exec_elf_makecmds(p, epp) * Allocate space to hold all the program headers, and read them * from the file */ - phsize = eh->e_phnum * sizeof(Elf32_Phdr); - ph = (Elf32_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); + phsize = eh->e_phnum * sizeof(Elf_Phdr); + ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); - if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff, (caddr_t)ph, + if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, (caddr_t)ph, phsize)) != 0) goto bad; - epp->ep_tsize = ELF32_NO_ADDR; - epp->ep_dsize = ELF32_NO_ADDR; + epp->ep_tsize = ELFDEFNNAME(NO_ADDR); + epp->ep_dsize = ELFDEFNNAME(NO_ADDR); interp[0] = '\0'; @@ -508,8 +480,8 @@ exec_elf_makecmds(p, epp) if (pp->p_type == PT_INTERP) { if (pp->p_filesz >= sizeof(interp)) goto bad; - if ((error = elf_read_from(p, epp->ep_vp, pp->p_offset, - (caddr_t)interp, pp->p_filesz)) != 0) + if ((error = ELFNAME(read_from)(p, epp->ep_vp, + pp->p_offset, (caddr_t)interp, pp->p_filesz)) != 0) goto bad; break; } @@ -519,13 +491,12 @@ exec_elf_makecmds(p, epp) * OK, we want a slightly different twist of the * standard emulation package for "real" elf. */ - epp->ep_emul = &emul_elf; - pos = ELF32_NO_ADDR; + epp->ep_emul = &ELFNAMEEND(emul); + pos = ELFDEFNNAME(NO_ADDR); /* * On the same architecture, we may be emulating different systems. - * See which one will accept this executable. This currently only - * applies to Linux and SVR4 on the i386. + * See which one will accept this executable. * * Probe functions would normally see if the interpreter (if any) * exists. Emulation packages may possibly replace the interpreter in @@ -534,23 +505,32 @@ exec_elf_makecmds(p, epp) */ error = ENOEXEC; p->p_os = OOS_OPENBSD; - for (i = 0; i < sizeof elf_probes / sizeof elf_probes[0] && error; i++) - if (os == OOS_NULL || ((1 << os) & elf_probes[i].os_mask)) - error = elf_probes[i].func ? - (*elf_probes[i].func)(p, epp, interp, &pos, &os) : +#ifdef NATIVE_EXEC_ELF + if (ELFNAME(os_pt_note)(p, epp, epp->ep_hdr, "OpenBSD", 8, 4) == 0) { + goto native; + } +#endif + for (i = 0; + i < sizeof(ELFNAME(probes)) / sizeof(ELFNAME(probes)[0]) && error; + i++) { + if (os == OOS_NULL || ((1 << os) & ELFNAME(probes)[i].os_mask)) + error = ELFNAME(probes)[i].func ? + (*ELFNAME(probes)[i].func)(p, epp, interp, &pos, &os) : 0; + } if (!error) p->p_os = os; #ifndef NATIVE_EXEC_ELF else goto bad; +#else +native: #endif /* NATIVE_EXEC_ELF */ - /* * Load all the necessary sections */ for (i = nload = 0; i < eh->e_phnum; i++) { - u_long addr = ELF32_NO_ADDR, size = 0; + Elf_Addr addr = ELFDEFNNAME(NO_ADDR), size = 0; int prot = 0; pp = &ph[i]; @@ -563,8 +543,8 @@ exec_elf_makecmds(p, epp) */ if (nload++ == 2) goto bad; - elf_load_psection(&epp->ep_vmcmds, epp->ep_vp, &ph[i], - &addr, &size, &prot); + ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp, + &ph[i], &addr, &size, &prot); /* * Decide whether it's text or data by looking * at the entry point. @@ -573,6 +553,10 @@ exec_elf_makecmds(p, epp) eh->e_entry < (addr + size)) { epp->ep_taddr = addr; epp->ep_tsize = size; + if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) { + epp->ep_daddr = addr; + epp->ep_dsize = size; + } } else { epp->ep_daddr = addr; epp->ep_dsize = size; @@ -609,7 +593,7 @@ exec_elf_makecmds(p, epp) * function, pick the same address that a non-fixed mmap(0, ..) * would (i.e. something safely out of the way). */ - if (pos == ELF32_NO_ADDR) + if (pos == ELFDEFNNAME(NO_ADDR)) pos = round_page(epp->ep_daddr + MAXDSIZ); #endif @@ -666,15 +650,13 @@ bad: * when loading the program is available for setup of the interpreter. */ int -exec_elf_fixup(p, epp) - struct proc *p; - struct exec_package *epp; +ELFNAME2(exec,fixup)(struct proc *p, struct exec_package *epp) { char *interp; int error, i; struct elf_args *ap; AuxInfo ai[ELF_AUX_ENTRIES], *a; - u_long pos = epp->ep_interp_pos; + Elf_Addr pos = epp->ep_interp_pos; if (epp->ep_interp == 0) { return (0); @@ -683,7 +665,7 @@ exec_elf_fixup(p, epp) interp = (char *)epp->ep_interp; ap = (struct elf_args *)epp->ep_emul_arg; - if ((error = elf_load_file(p, interp, epp, ap, &pos)) != 0) { + if ((error = ELFNAME(load_file)(p, interp, epp, ap, &pos)) != 0) { free((char *)ap, M_TEMP); free((char *)interp, M_TEMP); kill_vmcmds(&epp->ep_vmcmds); @@ -747,12 +729,66 @@ exec_elf_fixup(p, epp) } char * -elf_check_brand(eh) - Elf32_Ehdr *eh; +ELFNAME(check_brand)(Elf_Ehdr *eh) { if (eh->e_ident[EI_BRAND] == '\0') return (NULL); return (&eh->e_ident[EI_BRAND]); } -#endif /* _KERN_DO_ELF */ +int +ELFNAME(os_pt_note)(struct proc *p, struct exec_package *epp, Elf_Ehdr *eh, + char *os_name, size_t name_size, size_t desc_size) +{ + Elf_Phdr *hph, *ph; + Elf_Note *np = NULL; + size_t phsize; + int error; + + phsize = eh->e_phnum * sizeof(Elf_Phdr); + hph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); + if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, + (caddr_t)hph, phsize)) != 0) + goto out1; + + for (ph = hph; ph < &hph[eh->e_phnum]; ph++) { + if (ph->p_type != PT_NOTE || + ph->p_filesz < sizeof(Elf_Note) + name_size) + continue; + + np = (Elf_Note *)malloc(ph->p_filesz, M_TEMP, M_WAITOK); + if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset, + (caddr_t)np, ph->p_filesz)) != 0) + goto out2; + +#if 0 + if (np->type != ELF_NOTE_TYPE_OSVERSION) { + free(np, M_TEMP); + np = NULL; + continue; + } +#endif + + /* Check the name and description sizes. */ + if (np->namesz != name_size || + np->descsz != desc_size) + goto out3; + + if (bcmp((np + 1), os_name, name_size)) + goto out3; + + /* XXX: We could check for the specific emulation here */ + /* All checks succeeded. */ + error = 0; + goto out2; + } + +out3: + error = ENOEXEC; +out2: + if (np) + free(np, M_TEMP); +out1: + free(hph, M_TEMP); + return error; +} diff --git a/sys/kern/exec_elf32.c b/sys/kern/exec_elf32.c new file mode 100644 index 00000000000..581425aa20f --- /dev/null +++ b/sys/kern/exec_elf32.c @@ -0,0 +1,7 @@ +#include <machine/exec.h> + +#ifdef _KERN_DO_ELF +#define ELFSIZE 32 +#include <kern/exec_elf.c> +#endif + diff --git a/sys/kern/exec_elf64.c b/sys/kern/exec_elf64.c index d3ac5d70090..aba08cf30a7 100644 --- a/sys/kern/exec_elf64.c +++ b/sys/kern/exec_elf64.c @@ -1,842 +1,6 @@ -/* $OpenBSD: exec_elf64.c,v 1.18 2001/08/11 23:14:22 art Exp $ */ - -/* - * Copyright (c) 1996 Per Fogelstrom - * All rights reserved. - * - * Copyright (c) 1994 Christos Zoulas - * All rights reserved. - * - * 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * 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. - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/malloc.h> -#include <sys/mount.h> -#include <sys/namei.h> -#include <sys/vnode.h> -#include <sys/exec.h> - -#if defined(_KERN_DO_ELF64) - -#include <sys/exec_elf.h> -#include <sys/exec_olf.h> -#include <sys/file.h> -#include <sys/syscall.h> -#include <sys/signalvar.h> -#include <sys/stat.h> - -#include <sys/mman.h> -#include <vm/vm.h> - -#include <machine/cpu.h> -#include <machine/reg.h> #include <machine/exec.h> -#ifdef COMPAT_LINUX -#include <compat/linux/linux_exec.h> -#endif - -#ifdef COMPAT_SVR4 -#include <compat/svr4/svr4_exec.h> -#endif - -#ifdef COMPAT_FREEBSD -#include <compat/freebsd/freebsd_exec.h> -#endif - -#ifdef COMPAT_NETBSD -#include <compat/netbsd/netbsd_exec.h> -#endif - -struct elf64_probe_entry { - int (*func) __P((struct proc *, struct exec_package *, char *, - u_long *, u_int8_t *)); - int os_mask; -} elf64_probes[] = { -#ifdef COMPAT_FREEBSD - { freebsd_elf64_probe, 1 << OOS_FREEBSD }, -#endif -#ifdef COMPAT_SVR4 - { svr4_elf64_probe, - 1 << OOS_SVR4 | 1 << OOS_ESIX | 1 << OOS_SOLARIS | 1 << OOS_SCO | - 1 << OOS_DELL | 1 << OOS_NCR }, -#endif -#ifdef COMPAT_LINUX - { linux_elf64_probe, 1 << OOS_LINUX }, -#endif -#ifdef COMPAT_NETBSD - { netbsd_elf64_probe, 1 << OOS_NETBSD }, -#endif -#ifdef NATIVE_EXEC_ELF - { 0, 1 << OOS_OPENBSD } -#endif -}; - -int elf64_load_file __P((struct proc *, char *, struct exec_package *, - struct elf_args *, u_long *)); - -int elf64_check_header __P((Elf64_Ehdr *, int)); -int olf64_check_header __P((Elf64_Ehdr *, int, u_int8_t *)); -int elf64_read_from __P((struct proc *, struct vnode *, u_long, caddr_t, int)); -void elf64_load_psection __P((struct exec_vmcmd_set *, struct vnode *, - Elf64_Phdr *, u_int64_t *, u_int64_t *, int *)); - -int exec_elf64_fixup __P((struct proc *, struct exec_package *)); - -/* round up and down to page boundaries. */ -#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) -#define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) - -/* - * This is the basic elf emul. elf64_probe_funcs may change to other emuls. - */ - -extern char sigcode[], esigcode[]; -#ifdef SYSCALL_DEBUG -extern char *syscallnames[]; -#endif - -struct emul emul_elf64 = { - "native", - NULL, - sendsig, - SYS_syscall, - SYS_MAXSYSCALL, - sysent, -#ifdef SYSCALL_DEBUG - syscallnames, -#else - NULL, -#endif - sizeof (AuxInfo) * ELF_AUX_ENTRIES, - elf64_copyargs, - setregs, - exec_elf64_fixup, - sigcode, - esigcode, -}; - -/* - * Copy arguments onto the stack in the normal way, but add some - * space for extra information in case of dynamic binding. - */ -void * -elf64_copyargs(pack, arginfo, stack, argp) - struct exec_package *pack; - struct ps_strings *arginfo; - void *stack; - void *argp; -{ - stack = copyargs(pack, arginfo, stack, argp); - if (!stack) - return (NULL); - - /* - * Push space for extra arguments on the stack needed by - * dynamically linked binaries - */ - if (pack->ep_interp != NULL) { - pack->ep_emul_argp = stack; - stack += ELF_AUX_ENTRIES * sizeof (AuxInfo); - } - return (stack); -} - -/* - * elf64_check_header(): - * - * Check header for validity; return 0 for ok, ENOEXEC if error - */ -int -elf64_check_header(ehdr, type) - Elf64_Ehdr *ehdr; - int type; -{ - /* - * We need to check magic, class size, endianess, and version before - * we look at the rest of the Elf64_Ehdr structure. These few elements - * are represented in a machine independant fashion. - */ - if (!IS_ELF(*ehdr) || - ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || - ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || - ehdr->e_ident[EI_VERSION] != ELF_TARG_VER) - return (ENOEXEC); - - /* Now check the machine dependant header */ - if (ehdr->e_machine != ELF_TARG_MACH || - ehdr->e_version != ELF_TARG_VER) - return (ENOEXEC); - - /* Check the type */ - if (ehdr->e_type != type) - return (ENOEXEC); - - if (ehdr->e_phnum > 128) - return (ENOEXEC); - - return (0); -} - -/* - * olf64_check_header(): - * - * Check header for validity; return 0 for ok, ENOEXEC if error. - * Remeber OS tag for callers sake. - */ -int -olf64_check_header(ehdr, type, os) - Elf64_Ehdr *ehdr; - int type; - u_int8_t *os; -{ - int i; - - /* - * We need to check magic, class size, endianess, version, and OS - * before we look at the rest of the Elf64_Ehdr structure. These few - * elements are represented in a machine independant fashion. - */ - if (!IS_OLF(*ehdr) || - ehdr->e_ident[OI_CLASS] != ELF_TARG_CLASS || - ehdr->e_ident[OI_DATA] != ELF_TARG_DATA || - ehdr->e_ident[OI_VERSION] != ELF_TARG_VER) - return (ENOEXEC); - - for (i = 0; i < sizeof elf64_probes / sizeof elf64_probes[0]; i++) - if ((1 << ehdr->e_ident[OI_OS]) & elf64_probes[i].os_mask) - goto os_ok; - return (ENOEXEC); - -os_ok: - /* Now check the machine dependant header */ - if (ehdr->e_machine != ELF_TARG_MACH || - ehdr->e_version != ELF_TARG_VER) - return (ENOEXEC); - - /* Check the type */ - if (ehdr->e_type != type) - return (ENOEXEC); - - /* Don't allow an insane amount of sections. */ - if (ehdr->e_phnum > 128) - return (ENOEXEC); - - *os = ehdr->e_ident[OI_OS]; - return (0); -} - -/* - * elf64_load_psection(): - * - * Load a psection at the appropriate address - */ -void -elf64_load_psection(vcset, vp, ph, addr, size, prot) - struct exec_vmcmd_set *vcset; - struct vnode *vp; - Elf64_Phdr *ph; - u_int64_t *addr; - u_int64_t *size; - int *prot; -{ - u_long uaddr, msize, psize, rm, rf; - long diff, offset; - - /* - * If the user specified an address, then we load there. - */ - if (*addr != ELF64_NO_ADDR) { - if (ph->p_align > 1) { - *addr = ELF_ROUND(*addr, ph->p_align); - uaddr = ELF_TRUNC(ph->p_vaddr, ph->p_align); - } else - uaddr = ph->p_vaddr; - diff = ph->p_vaddr - uaddr; - } else { - *addr = uaddr = ph->p_vaddr; - if (ph->p_align > 1) - *addr = ELF_TRUNC(uaddr, ph->p_align); - diff = uaddr - *addr; - } - - *prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0; - *prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0; - *prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0; - - offset = ph->p_offset - diff; - *size = ph->p_filesz + diff; - msize = ph->p_memsz + diff; - psize = round_page(*size); - - /* - * Because the pagedvn pager can't handle zero fill of the last - * data page if it's not page aligned we map the last page readvn. - */ - if (ph->p_flags & PF_W) { - psize = trunc_page(*size); - NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp, - offset, *prot); - if (psize != *size) { - NEW_VMCMD(vcset, vmcmd_map_readvn, *size - psize, - *addr + psize, vp, offset + psize, *prot); - } - } else { - NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp, offset, - *prot); - } - - /* - * Check if we need to extend the size of the segment - */ - rm = round_page(*addr + msize); - rf = round_page(*addr + *size); - - if (rm != rf) { - NEW_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0, - *prot); - *size = msize; - } -} - -/* - * elf64_read_from(): - * - * Read from vnode into buffer at offset. - */ -int -elf64_read_from(p, vp, off, buf, size) - struct proc *p; - struct vnode *vp; - u_long off; - caddr_t buf; - int size; -{ - int error; - size_t resid; - - if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE, - IO_NODELOCKED, p->p_ucred, &resid, p)) != 0) - return error; - /* - * See if we got all of it - */ - if (resid != 0) - return (ENOEXEC); - return (0); -} - -/* - * elf64_load_file(): - * - * Load a file (interpreter/library) pointed to by path [stolen from - * coff_load_shlib()]. Made slightly generic so it might be used externally. - */ -int -elf64_load_file(p, path, epp, ap, last) - struct proc *p; - char *path; - struct exec_package *epp; - struct elf_args *ap; - u_long *last; -{ - int error, i; - struct nameidata nd; - Elf64_Ehdr eh; - Elf64_Phdr *ph = NULL; - u_long phsize; - char *bp = NULL; - u_int64_t addr = *last; - struct vnode *vp; - u_int8_t os; /* Just a dummy in this routine */ - - bp = path; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p); - if ((error = namei(&nd)) != 0) { - return (error); - } - vp = nd.ni_vp; - if (vp->v_type != VREG) { - error = EACCES; - goto bad; - } - if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0) - goto bad; - if (vp->v_mount->mnt_flag & MNT_NOEXEC) { - error = EACCES; - goto bad; - } - if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0) - goto bad1; - if ((error = elf64_read_from(p, nd.ni_vp, 0, - (caddr_t)&eh, sizeof(eh))) != 0) - goto bad1; - - if (elf64_check_header(&eh, ET_DYN) && - olf64_check_header(&eh, ET_DYN, &os)) { - error = ENOEXEC; - goto bad1; - } - - phsize = eh.e_phnum * sizeof(Elf64_Phdr); - ph = (Elf64_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); - - if ((error = elf64_read_from(p, nd.ni_vp, eh.e_phoff, (caddr_t)ph, - phsize)) != 0) - goto bad1; - - /* - * Load all the necessary sections - */ - for (i = 0; i < eh.e_phnum; i++) { - u_int64_t size = 0; - int prot = 0; -#if defined(__mips__) - if (*last == ELF64_NO_ADDR) - addr = ELF64_NO_ADDR; /* GRRRRR!!!!! */ -#endif - - switch (ph[i].p_type) { - case PT_LOAD: - elf64_load_psection(&epp->ep_vmcmds, nd.ni_vp, &ph[i], - &addr, &size, &prot); - /* If entry is within this section it must be text */ - if (eh.e_entry >= ph[i].p_vaddr && - eh.e_entry < (ph[i].p_vaddr + size)) { - epp->ep_entry = addr + eh.e_entry - - ELF_TRUNC(ph[i].p_vaddr,ph[i].p_align); - ap->arg_interp = addr; - } - addr += size; - break; - - case PT_DYNAMIC: - case PT_PHDR: - case PT_NOTE: - break; - - default: - break; - } - } - -bad1: - VOP_CLOSE(nd.ni_vp, FREAD, p->p_ucred, p); -bad: - if (ph != NULL) - free((char *)ph, M_TEMP); - - *last = addr; - vput(nd.ni_vp); - return (error); -} - -/* - * exec_elf64_makecmds(): Prepare an Elf binary's exec package - * - * First, set of the various offsets/lengths in the exec package. - * - * Then, mark the text image busy (so it can be demand paged) or error out if - * this is not possible. Finally, set up vmcmds for the text, data, bss, and - * stack segments. - */ -int -exec_elf64_makecmds(p, epp) - struct proc *p; - struct exec_package *epp; -{ - Elf64_Ehdr *eh = epp->ep_hdr; - Elf64_Phdr *ph, *pp; - Elf64_Addr phdr = 0; - int error, i, nload; - char interp[MAXPATHLEN]; - u_long pos = 0, phsize; - u_int8_t os = OOS_NULL; - - if (epp->ep_hdrvalid < sizeof(Elf64_Ehdr)) - return (ENOEXEC); - - if (elf64_check_header(eh, ET_EXEC) && - olf64_check_header(eh, ET_EXEC, &os)) - return (ENOEXEC); - - /* - * check if vnode is in open for writing, because we want to demand- - * page out of it. if it is, don't do it, for various reasons. - */ - if (epp->ep_vp->v_writecount != 0) { -#ifdef DIAGNOSTIC - if (epp->ep_vp->v_flag & VTEXT) - panic("exec: a VTEXT vnode has writecount != 0"); -#endif - return (ETXTBSY); - } - /* - * Allocate space to hold all the program headers, and read them - * from the file - */ - phsize = eh->e_phnum * sizeof(Elf64_Phdr); - ph = (Elf64_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); - - if ((error = elf64_read_from(p, epp->ep_vp, eh->e_phoff, (caddr_t)ph, - phsize)) != 0) - goto bad; - - epp->ep_tsize = ELF64_NO_ADDR; - epp->ep_dsize = ELF64_NO_ADDR; - - interp[0] = '\0'; - - for (i = 0; i < eh->e_phnum; i++) { - pp = &ph[i]; - if (pp->p_type == PT_INTERP) { - if (pp->p_filesz >= sizeof(interp)) - goto bad; - if ((error = elf64_read_from(p, epp->ep_vp, - pp->p_offset, (caddr_t)interp, - pp->p_filesz)) != 0) - goto bad; - break; - } - } - - /* - * OK, we want a slightly different twist of the - * standard emulation package for "real" elf. - */ - epp->ep_emul = &emul_elf64; - pos = ELF64_NO_ADDR; - - /* - * On the same architecture, we may be emulating different systems. - * See which one will accept this executable. This currently only - * applies to Linux and SVR4 on the i386 and the Alpha. - * - * Probe functions would normally see if the interpreter (if any) - * exists. Emulation packages may possibly replace the interpreter in - * interp[] with a changed path (/emul/xxx/<path>), and also - * set the ep_emul field in the exec package structure. - */ - error = ENOEXEC; - p->p_os = OOS_OPENBSD; - -#ifdef NATIVE_EXEC_ELF - if (elf64_os_pt_note(p, epp, epp->ep_hdr, "OpenBSD", 8, 4) == 0) { - goto native; - } -#endif - for (i = 0; i < sizeof elf64_probes / sizeof elf64_probes[0] && error; - i++) - if (os == OOS_NULL || ((1 << os) & elf64_probes[i].os_mask)) - error = elf64_probes[i].func ? - (*elf64_probes[i].func)(p, epp, interp, &pos, &os) : - 0; - if (!error) - p->p_os = os; -#ifndef NATIVE_EXEC_ELF - else - goto bad; -#endif /* NATIVE_EXEC_ELF */ - -native: - /* - * Load all the necessary sections - */ - for (i = nload = 0; i < eh->e_phnum; i++) { - u_int64_t addr = ELF64_NO_ADDR, size = 0; - int prot = 0; - - pp = &ph[i]; - - switch (ph[i].p_type) { - case PT_LOAD: - /* - * XXX - * Can handle only 2 sections: text and data - */ - if (nload++ == 2) - goto bad; - elf64_load_psection(&epp->ep_vmcmds, epp->ep_vp, &ph[i], - &addr, &size, &prot); - /* - * Decide whether it's text or data by looking - * at the entry point. - */ - if (eh->e_entry >= addr && - eh->e_entry < (addr + size)) { - epp->ep_taddr = addr; - epp->ep_tsize = size; - if (epp->ep_daddr == ELF64_NO_ADDR) { - epp->ep_daddr = addr; - epp->ep_dsize = size; - } - } else { - epp->ep_daddr = addr; - epp->ep_dsize = size; - } - break; - - case PT_SHLIB: - error = ENOEXEC; - goto bad; - - case PT_INTERP: - /* Already did this one */ - case PT_DYNAMIC: - case PT_NOTE: - break; - - case PT_PHDR: - /* Note address of program headers (in text segment) */ - phdr = pp->p_vaddr; - break; - - default: - /* - * Not fatal, we don't need to understand everything - * :-) - */ - break; - } - } - -#if !defined(__mips__) - /* - * If no position to load the interpreter was set by a probe - * function, pick the same address that a non-fixed mmap(0, ..) - * would (i.e. something safely out of the way). - */ - if (pos == ELF64_NO_ADDR) - pos = round_page(epp->ep_daddr + MAXDSIZ); -#endif - - /* - * Check if we found a dynamically linked binary and arrange to load - * it's interpreter when the exec file is released. - */ - if (interp[0]) { - char *ip; - struct elf_args *ap; - - ip = (char *)malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - ap = (struct elf_args *) - malloc(sizeof(struct elf_args), M_TEMP, M_WAITOK); - - bcopy(interp, ip, MAXPATHLEN); - epp->ep_interp = ip; - epp->ep_interp_pos = pos; - - ap->arg_phaddr = phdr; - ap->arg_phentsize = eh->e_phentsize; - ap->arg_phnum = eh->e_phnum; - ap->arg_entry = eh->e_entry; - ap->arg_os = os; - - epp->ep_emul_arg = ap; - epp->ep_entry = eh->e_entry; /* keep check_exec() happy */ - } else { - epp->ep_interp = NULL; - epp->ep_entry = eh->e_entry; - } - -#if defined(COMPAT_SVR4) && defined(i386) -#ifndef ELF_MAP_PAGE_ZERO - /* Dell SVR4 maps page zero, yeuch! */ - if (p->p_os == OOS_DELL) -#endif - NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0, - epp->ep_vp, 0, VM_PROT_READ); -#endif - - free((char *)ph, M_TEMP); - epp->ep_vp->v_flag |= VTEXT; - return (exec_setup_stack(p, epp)); - -bad: - free((char *)ph, M_TEMP); - kill_vmcmds(&epp->ep_vmcmds); - return (ENOEXEC); -} - -/* - * Phase II of load. It is now safe to load the interpreter. Info collected - * when loading the program is available for setup of the interpreter. - */ -int -exec_elf64_fixup(p, epp) - struct proc *p; - struct exec_package *epp; -{ - char *interp; - int error, i; - struct elf_args *ap; - AuxInfo ai[ELF_AUX_ENTRIES], *a; - u_long pos = epp->ep_interp_pos; - - if (epp->ep_interp == 0) { - return (0); - } - - interp = (char *)epp->ep_interp; - ap = (struct elf_args *)epp->ep_emul_arg; - - if ((error = elf64_load_file(p, interp, epp, ap, &pos)) != 0) { - free((char *)ap, M_TEMP); - free((char *)interp, M_TEMP); - kill_vmcmds(&epp->ep_vmcmds); - return (error); - } - - /* - * We have to do this ourselves... - */ - for (i = 0; i < epp->ep_vmcmds.evs_used && !error; i++) { - struct exec_vmcmd *vcp; - - vcp = &epp->ep_vmcmds.evs_cmds[i]; - error = (*vcp->ev_proc)(p, vcp); - } - kill_vmcmds(&epp->ep_vmcmds); - - /* - * Push extra arguments on the stack needed by dynamically - * linked binaries - */ - if (error == 0) { - a = ai; - - a->au_id = AUX_phdr; - a->au_v = ap->arg_phaddr; - a++; - - a->au_id = AUX_phent; - a->au_v = ap->arg_phentsize; - a++; - - a->au_id = AUX_phnum; - a->au_v = ap->arg_phnum; - a++; - - a->au_id = AUX_pagesz; - a->au_v = PAGE_SIZE; - a++; - - a->au_id = AUX_base; - a->au_v = ap->arg_interp; - a++; - - a->au_id = AUX_flags; - a->au_v = 0; - a++; - - a->au_id = AUX_entry; - a->au_v = ap->arg_entry; - a++; - - a->au_id = AUX_null; - a->au_v = 0; - a++; - - error = copyout(ai, epp->ep_emul_argp, sizeof ai); - } - free((char *)ap, M_TEMP); - free((char *)interp, M_TEMP); - return (error); -} - -char * -elf64_check_brand(eh) - Elf64_Ehdr *eh; -{ - if (eh->e_ident[EI_BRAND] == '\0') - return (NULL); - return (&eh->e_ident[EI_BRAND]); -} - -int -elf64_os_pt_note(p, epp, eh, os_name, name_size, desc_size) - struct proc *p; - struct exec_package *epp; - Elf64_Ehdr *eh; - char *os_name; - size_t name_size, desc_size; -{ - Elf64_Phdr *hph, *ph; - Elf64_Note *np = NULL; - size_t phsize; - int error; - - phsize = eh->e_phnum * sizeof(Elf64_Phdr); - hph = (Elf64_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); - if ((error = elf64_read_from(p, epp->ep_vp, eh->e_phoff, - (caddr_t)hph, phsize)) != 0) - goto out1; - - for (ph = hph; ph < &hph[eh->e_phnum]; ph++) { - if (ph->p_type != PT_NOTE || - ph->p_filesz < sizeof(Elf64_Note) + name_size) - continue; - - np = (Elf64_Note *)malloc(ph->p_filesz, M_TEMP, M_WAITOK); - if ((error = elf64_read_from(p, epp->ep_vp, ph->p_offset, - (caddr_t)np, ph->p_filesz)) != 0) - goto out2; - -#if 0 - if (np->type != ELF_NOTE_TYPE_OSVERSION) { - free(np, M_TEMP); - np = NULL; - continue; - } -#endif - - /* Check the name and description sizes. */ - if (np->namesz != name_size || - np->descsz != desc_size) - goto out3; - - if (bcmp((np + 1), os_name, name_size)) - goto out3; - - /* XXX: We could check for the specific emulation here */ - /* All checks succeeded. */ - error = 0; - goto out2; - } - -out3: - error = ENOEXEC; -out2: - if (np) - free(np, M_TEMP); -out1: - free(hph, M_TEMP); - return error; -} - +#ifdef _KERN_DO_ELF64 +#define ELFSIZE 64 +#include <kern/exec_elf.c> #endif /* _KERN_DO_ELF64 */ diff --git a/sys/sys/exec_elf.h b/sys/sys/exec_elf.h index ecddaf92e7a..6d1ce2bf86e 100644 --- a/sys/sys/exec_elf.h +++ b/sys/sys/exec_elf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_elf.h,v 1.30 2001/08/19 15:20:25 art Exp $ */ +/* $OpenBSD: exec_elf.h,v 1.31 2001/09/19 13:28:43 art Exp $ */ /* * Copyright (c) 1995, 1996 Erik Theisen. All rights reserved. * @@ -522,6 +522,7 @@ struct elf_args { #define Elf_Addr Elf32_Addr #define Elf_Off Elf32_Off #define Elf_Nhdr Elf32_Nhdr +#define Elf_Note Elf32_Note #define ELF_R_SYM ELF32_R_SYM #define ELF_R_TYPE ELF32_R_TYPE @@ -546,6 +547,7 @@ struct elf_args { #define Elf_Addr Elf64_Addr #define Elf_Off Elf64_Off #define Elf_Nhdr Elf64_Nhdr +#define Elf_Note Elf64_Note #define ELF_R_SYM ELF64_R_SYM #define ELF_R_TYPE ELF64_R_TYPE @@ -570,11 +572,13 @@ int elf64_os_pt_note __P((struct proc *, struct exec_package *, Elf64_Ehdr *, char *, size_t, size_t)); #endif #ifdef _KERN_DO_ELF -int exec_elf_makecmds __P((struct proc *, struct exec_package *)); -void *elf_copyargs __P((struct exec_package *, struct ps_strings *, +int exec_elf32_makecmds __P((struct proc *, struct exec_package *)); +void *elf32_copyargs __P((struct exec_package *, struct ps_strings *, void *, void *)); -int exec_elf_fixup __P((struct proc *, struct exec_package *)); -char *elf_check_brand __P((Elf32_Ehdr *)); +int exec_elf32_fixup __P((struct proc *, struct exec_package *)); +char *elf32_check_brand __P((Elf32_Ehdr *)); +int elf32_os_pt_note __P((struct proc *, struct exec_package *, Elf32_Ehdr *, + char *, size_t, size_t)); #endif #endif /* _KERNEL */ |