Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F132158937
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
28 KB
Referenced Files
None
Subscribers
None
View Options
Index: head/sys/compat/pecoff/imgact_pecoff.c
===================================================================
--- head/sys/compat/pecoff/imgact_pecoff.c (revision 103046)
+++ head/sys/compat/pecoff/imgact_pecoff.c (revision 103047)
@@ -1,661 +1,675 @@
/* $NetBSD$ */
/* $FreeBSD$ */
/*
* Copyright (c) 2000 Masaru OKI
* Copyright (c) 1994, 1995, 1998 Scott Bartram
* Copyright (c) 1994 Adam Glass
* Copyright (c) 1993, 1994 Christopher G. Demetriou
*
* originally from NetBSD kern/exec_ecoff.c
*
* Copyright (c) 2000 Takanori Watanabe
* Copyright (c) 2000 KUROSAWA Takahiro
* Copyright (c) 1995-1996 Sen Schmidt
* Copyright (c) 1996 Peter Wemm
* All rights reserved.
*
* originally from FreeBSD kern/imgact_elf.c
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Masaru OKI.
* 4. 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 "opt_kstack_pages.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/imgact.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/sysent.h>
#include <sys/vnode.h>
#include <machine/reg.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
#include <sys/user.h>
#include <sys/exec.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/cpu.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <machine/md_var.h>
#include <machine/pecoff_machdep.h>
#include <compat/pecoff/imgact_pecoff.h>
#include "opt_pecoff.h"
#define PECOFF_PE_SIGNATURE "PE\0\0"
static int pecoff_fixup(register_t **, struct image_params *);
static int
pecoff_coredump(register struct thread *, register struct vnode *,
off_t);
#ifndef PECOFF_DEBUG
#define DPRINTF(a)
#else
#define DPRINTF(a) printf a
#endif
static struct sysentvec pecoff_sysvec = {
SYS_MAXSYSCALL,
sysent,
0,
0,
NULL,
0,
NULL,
NULL,
pecoff_fixup,
sendsig,
sigcode,
&szsigcode,
0,
"FreeBSD PECoff",
pecoff_coredump,
NULL,
MINSIGSTKSZ,
PAGE_SIZE,
VM_MIN_ADDRESS,
VM_MAXUSER_ADDRESS,
USRSTACK,
PS_STRINGS,
VM_PROT_ALL,
exec_copyout_strings,
exec_setregs
};
static const char signature[] = PECOFF_PE_SIGNATURE;
static int
exec_pecoff_coff_prep_omagic(struct image_params *,
struct coff_filehdr *,
struct coff_aouthdr *, int peoffs);
static int
exec_pecoff_coff_prep_nmagic(struct image_params *,
struct coff_filehdr *,
struct coff_aouthdr *, int peoffs);
static int
exec_pecoff_coff_prep_zmagic(struct image_params *,
struct coff_filehdr *,
struct coff_aouthdr *, int peoffs);
static int
exec_pecoff_coff_makecmds(struct image_params *,
struct coff_filehdr *, int);
static int pecoff_signature(struct thread *, struct vnode *, const struct pecoff_dos_filehdr *);
static int pecoff_read_from(struct thread *, struct vnode *, int, caddr_t, int);
static int
pecoff_load_section(struct thread * td,
struct vmspace * vmspace, struct vnode * vp,
vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
vm_prot_t prot);
static int
pecoff_fixup(register_t ** stack_base, struct image_params * imgp)
{
int len = sizeof(struct pecoff_args);
struct pecoff_imghdr *ap;
register_t *pos;
pos = *stack_base + (imgp->argc + imgp->envc + 2);
ap = (struct pecoff_imghdr *) imgp->auxargs;
if (copyout(ap, pos, len)) {
return 0;
}
free(ap, M_TEMP);
imgp->auxargs = NULL;
(*stack_base)--;
suword(*stack_base, (long) imgp->argc);
return 0;
}
static int
pecoff_coredump(register struct thread * td, register struct vnode * vp,
off_t limit)
{
register struct ucred *cred = td->td_ucred;
struct proc *p = td->td_proc;
register struct vmspace *vm = p->p_vmspace;
+ caddr_t tempuser;
int error;
#ifdef PECOFF_DEBUG
struct vm_map *map;
struct vm_map_entry *ent;
struct reg regs;
#endif
if (ctob((UAREA_PAGES+KSTACK_PAGES) + vm->vm_dsize + vm->vm_ssize) >= limit)
return (EFAULT);
+ tempuser = malloc(ctob(UAREA_PAGES + KSTACK_PAGES), M_TEMP,
+ M_WAITOK | M_ZERO);
+ if (tempuser == NULL)
+ return (ENOMEM);
+ bcopy(p->p_uarea, tempuser, sizeof(struct user));
+ tempuser + ctob(UAREA_PAGES) +
+ ((caddr_t) td->td_frame - (caddr_t) td->td_kstack),
+ sizeof(struct trapframe));
PROC_LOCK(p);
fill_kinfo_proc(p, &p->p_uarea->u_kproc);
PROC_UNLOCK(p);
#if PECOFF_DEBUG
fill_regs(td, ®s);
printf("EIP%x\n", regs.r_eip);
printf("EAX%x EBX%x ECX%x EDI%x\n",
regs.r_eax, regs.r_ebx, regs.r_ecx, regs.r_edi);
map = &vm->vm_map;
ent = &map->header;
printf("%p %p %p\n", ent, ent->prev, ent->next);
#endif
- error = cpu_coredump(td, vp, cred);
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t) tempuser,
+ ctob(UAREA_PAGES + KSTACK_PAGES),
+ (off_t)0, UIO_SYSSPACE, IO_UNIT, cred, NOCRED,
+ (int *)NULL, td);
+ free(tempuser, M_TEMP);
if (error == 0)
error = vn_rdwr_inchunks(UIO_WRITE, vp, vm->vm_daddr,
(int)ctob(vm->vm_dsize),
(off_t)ctob((UAREA_PAGES+KSTACK_PAGES)),
UIO_USERSPACE, IO_UNIT, cred, NOCRED, (int *)NULL, td);
if (error == 0)
error = vn_rdwr_inchunks(UIO_WRITE, vp,
(caddr_t)trunc_page(USRSTACK - ctob(vm->vm_ssize)),
round_page(ctob(vm->vm_ssize)),
(off_t)ctob((UAREA_PAGES+KSTACK_PAGES)) +
ctob(vm->vm_dsize),
UIO_USERSPACE, IO_UNIT, cred, NOCRED, (int *)NULL, td);
return (error);
}
static int
pecoff_load_section(struct thread * td, struct vmspace * vmspace, struct vnode * vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
{
size_t map_len;
vm_offset_t map_addr;
int error, rv;
size_t copy_len;
size_t copy_map_len;
size_t copy_start;
vm_object_t object;
vm_offset_t copy_map_offset;
vm_offset_t file_addr;
vm_offset_t data_buf = 0;
object = vp->v_object;
error = 0;
map_addr = trunc_page((vm_offset_t) vmaddr);
file_addr = trunc_page(offset);
DPRINTF(("SECARG:%x %p %x %x\n", offset, vmaddr, memsz, filsz));
if (file_addr != offset) {
/*
* The section is not on page boundary. We can't use
* vm_map_insert(). Use copyin instead.
*/
map_len = round_page(memsz);
copy_len = filsz;
copy_map_offset = file_addr;
copy_map_len = round_page(offset + filsz) - file_addr;
copy_start = offset - file_addr;
DPRINTF(("offset=%x vmaddr=%lx filsz=%x memsz=%x\n",
offset, (long)vmaddr, filsz, memsz));
DPRINTF(("map_len=%x copy_len=%x copy_map_offset=%x"
" copy_map_len=%x copy_start=%x\n",
map_len, copy_len, copy_map_offset,
copy_map_len, copy_start));
} else {
map_len = trunc_page(filsz);
if (map_len != 0) {
vm_object_reference(object);
vm_map_lock(&vmspace->vm_map);
rv = vm_map_insert(&vmspace->vm_map,
object,
file_addr, /* file offset */
map_addr, /* virtual start */
map_addr + map_len, /* virtual end */
prot,
VM_PROT_ALL,
MAP_COPY_ON_WRITE | MAP_PREFAULT);
vm_map_unlock(&vmspace->vm_map);
if (rv != KERN_SUCCESS) {
vm_object_deallocate(object);
return EINVAL;
}
/* we can stop now if we've covered it all */
if (memsz == filsz)
return 0;
}
copy_map_offset = trunc_page(offset + filsz);
copy_map_len = PAGE_SIZE;
copy_start = 0;
copy_len = (offset + filsz) - trunc_page(offset + filsz);
map_addr = trunc_page((vm_offset_t) vmaddr + filsz);
map_len = round_page((vm_offset_t) vmaddr + memsz) - map_addr;
}
if (map_len != 0) {
vm_map_lock(&vmspace->vm_map);
rv = vm_map_insert(&vmspace->vm_map, NULL, 0,
map_addr, map_addr + map_len,
VM_PROT_ALL, VM_PROT_ALL, 0);
vm_map_unlock(&vmspace->vm_map);
DPRINTF(("EMP-rv:%d,%x %x\n", rv, map_addr, map_addr + map_len));
if (rv != KERN_SUCCESS) {
return EINVAL;
}
}
DPRINTF(("COPYARG %x %x\n", map_addr, copy_len));
if (copy_len != 0) {
vm_object_reference(object);
rv = vm_map_find(exec_map,
object,
copy_map_offset,
&data_buf,
copy_map_len,
TRUE,
VM_PROT_READ,
VM_PROT_ALL,
MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
if (rv != KERN_SUCCESS) {
vm_object_deallocate(object);
return EINVAL;
}
/* send the page fragment to user space */
error = copyout((caddr_t) data_buf + copy_start,
(caddr_t) map_addr, copy_len);
vm_map_remove(exec_map, data_buf, data_buf + copy_map_len);
DPRINTF(("%d\n", error));
if (error)
return (error);
}
/*
* set it to the specified protection
*/
vm_map_protect(&vmspace->vm_map, map_addr,
map_addr + map_len, prot,
FALSE);
return error;
}
static int
pecoff_load_file(struct thread * td, const char *file, u_long * addr, u_long * entry, u_long * ldexport)
{
struct nameidata nd;
struct pecoff_dos_filehdr dh;
struct coff_filehdr *fp = 0;
struct coff_aouthdr *ap;
struct pecoff_opthdr *wp;
struct coff_scnhdr *sh = 0;
struct vmspace *vmspace = td->td_proc->p_vmspace;
struct vattr attr;
struct image_params image_params, *imgp;
int peofs;
int error, i, scnsiz;
imgp = &image_params;
/*
* Initialize part of the common data
*/
imgp->proc = td->td_proc;
imgp->uap = NULL;
imgp->attr = &attr;
imgp->firstpage = NULL;
NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, td);
if ((error = namei(&nd)) != 0) {
nd.ni_vp = NULL;
goto fail;
}
NDFREE(&nd, NDF_ONLY_PNBUF);
imgp->vp = nd.ni_vp;
/*
* Check permissions, modes, uid, etc on the file, and "open" it.
*/
error = exec_check_permissions(imgp);
if (error) {
VOP_UNLOCK(nd.ni_vp, 0, td);
goto fail;
}
VOP_UNLOCK(nd.ni_vp, 0, td);
if (error)
goto fail;
if ((error = pecoff_read_from(td, imgp->vp, 0, (caddr_t) & dh, sizeof(dh))) != 0)
goto fail;
if ((error = pecoff_signature(td, imgp->vp, &dh) != 0))
goto fail;
fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
peofs = dh.d_peofs + sizeof(signature) - 1;
if ((error = pecoff_read_from(td, imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE) != 0))
goto fail;
if (COFF_BADMAG(fp)) {
error = ENOEXEC;
goto fail;
}
ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
/* read section header */
scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
sh = malloc(scnsiz, M_TEMP, M_WAITOK);
if ((error = pecoff_read_from(td, imgp->vp, peofs + PECOFF_HDR_SIZE,
(caddr_t) sh, scnsiz)) != 0)
goto fail;
/*
* Read Section infomation and map sections.
*/
for (i = 0; i < fp->f_nscns; i++) {
int prot = 0;
if (sh[i].s_flags & COFF_STYP_DISCARD)
continue;
/* XXX ? */
if ((sh[i].s_flags & COFF_STYP_TEXT) &&
(sh[i].s_flags & COFF_STYP_EXEC) == 0)
continue;
if ((sh[i].s_flags & (COFF_STYP_TEXT | COFF_STYP_DATA | COFF_STYP_BSS)) == 0)
continue;
prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
sh[i].s_vaddr += wp->w_base; /* RVA --> VA */
if ((error = pecoff_load_section(td, vmspace, imgp->vp, sh[i].s_scnptr
,(caddr_t) sh[i].s_vaddr,
sh[i].s_paddr, sh[i].s_size
,prot)) != 0)
goto fail;
}
*entry = wp->w_base + ap->a_entry;
*addr = wp->w_base;
*ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base;
fail:
if (fp)
free(fp, M_TEMP);
if (sh)
free(sh, M_TEMP);
if (nd.ni_vp)
vrele(nd.ni_vp);
return error;
}
static int
exec_pecoff_coff_prep_omagic(struct image_params * imgp,
struct coff_filehdr * fp,
struct coff_aouthdr * ap, int peofs)
{
return ENOEXEC;
}
static int
exec_pecoff_coff_prep_nmagic(struct image_params * imgp,
struct coff_filehdr * fp,
struct coff_aouthdr * ap, int peofs)
{
return ENOEXEC;
}
static int
exec_pecoff_coff_prep_zmagic(struct image_params * imgp,
struct coff_filehdr * fp,
struct coff_aouthdr * ap, int peofs)
{
int scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
int error = ENOEXEC, i;
int prot;
u_long text_size = 0, data_size = 0, dsize;
u_long text_addr = 0, data_addr = VM_MAXUSER_ADDRESS;
u_long ldexport, ldbase;
struct pecoff_opthdr *wp;
struct coff_scnhdr *sh;
struct vmspace *vmspace;
struct pecoff_args *argp = NULL;
sh = malloc(scnsiz, M_TEMP, M_WAITOK);
wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp,
peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz);
if ((error = exec_extract_strings(imgp)) != 0)
goto fail;
exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
vmspace = imgp->proc->p_vmspace;
for (i = 0; i < fp->f_nscns; i++) {
prot = VM_PROT_WRITE; /* XXX for relocation? */
prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
sh[i].s_vaddr += wp->w_base;
if (sh[i].s_flags & COFF_STYP_DISCARD)
continue;
if ((sh[i].s_flags & COFF_STYP_TEXT) != 0) {
error = pecoff_load_section(
FIRST_THREAD_IN_PROC(imgp->proc),
vmspace, imgp->vp, sh[i].s_scnptr,
(caddr_t) sh[i].s_vaddr, sh[i].s_paddr,
sh[i].s_size ,prot);
DPRINTF(("ERROR%d\n", error));
if (error)
goto fail;
text_addr = trunc_page(sh[i].s_vaddr);
text_size = trunc_page(sh[i].s_size + sh[i].s_vaddr - text_addr);
}
if ((sh[i].s_flags & (COFF_STYP_DATA|COFF_STYP_BSS)) != 0) {
if (pecoff_load_section(
FIRST_THREAD_IN_PROC(imgp->proc), vmspace,
imgp->vp, sh[i].s_scnptr, (caddr_t) sh[i].s_vaddr,
sh[i].s_paddr, sh[i].s_size, prot) != 0)
goto fail;
data_addr = min(trunc_page(sh[i].s_vaddr), data_addr);
dsize = round_page(sh[i].s_vaddr + sh[i].s_paddr)
- data_addr;
data_size = max(dsize, data_size);
}
}
vmspace->vm_tsize = text_size >> PAGE_SHIFT;
vmspace->vm_taddr = (caddr_t) (uintptr_t) text_addr;
vmspace->vm_dsize = data_size >> PAGE_SHIFT;
vmspace->vm_daddr = (caddr_t) (uintptr_t) data_addr;
argp = malloc(sizeof(struct pecoff_args), M_TEMP, M_WAITOK);
if (argp == NULL) {
error = ENOMEM;
goto fail;
}
argp->a_base = wp->w_base;
argp->a_entry = wp->w_base + ap->a_entry;
argp->a_end = data_addr + data_size;
argp->a_subsystem = wp->w_subvers;
error = pecoff_load_file(FIRST_THREAD_IN_PROC(imgp->proc),
"/usr/libexec/ld.so.dll", &ldbase, &imgp->entry_addr, &ldexport);
if (error)
goto fail;
argp->a_ldbase = ldbase;
argp->a_ldexport = ldexport;
memcpy(argp->a_imghdr, wp->w_imghdr, sizeof(struct pecoff_imghdr) * 16);
for (i = 0; i < 16; i++) {
argp->a_imghdr[i].i_vaddr += wp->w_base;
}
imgp->proc->p_sysent = &pecoff_sysvec;
if (error)
goto fail;
imgp->auxargs = argp;
imgp->auxarg_size = sizeof(struct pecoff_args);
imgp->interpreted = 0;
if (sh != NULL)
free(sh, M_TEMP);
return 0;
fail:
error = (error) ? error : ENOEXEC;
if (sh != NULL)
free(sh, M_TEMP);
if (argp != NULL)
free(argp, M_TEMP);
return error;
}
int
exec_pecoff_coff_makecmds(struct image_params * imgp,
struct coff_filehdr * fp, int peofs)
{
struct coff_aouthdr *ap;
int error;
if (COFF_BADMAG(fp)) {
return ENOEXEC;
}
ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
switch (ap->a_magic) {
case COFF_OMAGIC:
error = exec_pecoff_coff_prep_omagic(imgp, fp, ap, peofs);
break;
case COFF_NMAGIC:
error = exec_pecoff_coff_prep_nmagic(imgp, fp, ap, peofs);
break;
case COFF_ZMAGIC:
error = exec_pecoff_coff_prep_zmagic(imgp, fp, ap, peofs);
break;
default:
return ENOEXEC;
}
return error;
}
static int
pecoff_signature(td, vp, dp)
struct thread *td;
struct vnode *vp;
const struct pecoff_dos_filehdr *dp;
{
int error;
char buf[512];
char *pesig;
if (DOS_BADMAG(dp)) {
return ENOEXEC;
}
error = pecoff_read_from(td, vp, dp->d_peofs, buf, sizeof(buf));
if (error) {
return error;
}
pesig = buf;
if (memcmp(pesig, signature, sizeof(signature) - 1) == 0) {
return 0;
}
return EFTYPE;
}
int
pecoff_read_from(td, vp, pos, buf, siz)
struct thread *td;
struct vnode *vp;
int pos;
caddr_t buf;
int siz;
{
int error;
size_t resid;
error = vn_rdwr(UIO_READ, vp, buf, siz, pos,
UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
&resid, td);
if (error)
return error;
if (resid != 0) {
return ENOEXEC;
}
return 0;
}
static int
imgact_pecoff(struct image_params * imgp)
{
const struct pecoff_dos_filehdr *dp = (const struct pecoff_dos_filehdr *)
imgp->image_header;
struct coff_filehdr *fp;
int error, peofs;
struct thread *td = curthread;
error = pecoff_signature(FIRST_THREAD_IN_PROC(imgp->proc),
imgp->vp, dp);
if (error) {
return -1;
}
VOP_UNLOCK(imgp->vp, 0, td);
peofs = dp->d_peofs + sizeof(signature) - 1;
fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc),
imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE);
if (error)
goto fail;
error = exec_pecoff_coff_makecmds(imgp, fp, peofs);
fail:
free(fp, M_TEMP);
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td);
return error;
}
static struct execsw pecoff_execsw = {imgact_pecoff, "FreeBSD PEcoff"};
EXEC_SET(pecoff, pecoff_execsw);
Index: head/sys/kern/imgact_aout.c
===================================================================
--- head/sys/kern/imgact_aout.c (revision 103046)
+++ head/sys/kern/imgact_aout.c (revision 103047)
@@ -1,304 +1,319 @@
/*
* Copyright (c) 1993, David Greenman
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*
* $FreeBSD$
*/
#include "opt_kstack_pages.h"
#include <sys/param.h>
#include <sys/exec.h>
#include <sys/fcntl.h>
#include <sys/imgact.h>
#include <sys/imgact_aout.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/pioctl.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/systm.h>
#include <sys/signalvar.h>
#include <sys/stat.h>
#include <sys/sysent.h>
#include <sys/syscall.h>
#include <sys/vnode.h>
#include <sys/user.h>
#include <machine/md_var.h>
+#include <machine/frame.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
static int exec_aout_imgact(struct image_params *imgp);
static int aout_fixup(register_t **stack_base, struct image_params *imgp);
struct sysentvec aout_sysvec = {
SYS_MAXSYSCALL,
sysent,
0,
0,
NULL,
0,
NULL,
NULL,
aout_fixup,
sendsig,
sigcode,
&szsigcode,
NULL,
"FreeBSD a.out",
aout_coredump,
NULL,
MINSIGSTKSZ,
PAGE_SIZE,
VM_MIN_ADDRESS,
VM_MAXUSER_ADDRESS,
USRSTACK,
PS_STRINGS,
VM_PROT_ALL,
exec_copyout_strings,
exec_setregs
};
static int
aout_fixup(stack_base, imgp)
register_t **stack_base;
struct image_params *imgp;
{
return (suword(--(*stack_base), imgp->argc));
}
static int
exec_aout_imgact(imgp)
struct image_params *imgp;
{
const struct exec *a_out = (const struct exec *) imgp->image_header;
struct vmspace *vmspace;
struct vnode *vp;
vm_map_t map;
vm_object_t object;
vm_offset_t text_end, data_end;
unsigned long virtual_offset;
unsigned long file_offset;
unsigned long bss_size;
int error;
GIANT_REQUIRED;
/*
* Linux and *BSD binaries look very much alike,
* only the machine id is different:
* 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI.
* NetBSD is in network byte order.. ugh.
*/
if (((a_out->a_magic >> 16) & 0xff) != 0x86 &&
((a_out->a_magic >> 16) & 0xff) != 0 &&
((((int)ntohl(a_out->a_magic)) >> 16) & 0xff) != 0x86)
return -1;
/*
* Set file/virtual offset based on a.out variant.
* We do two cases: host byte order and network byte order
* (for NetBSD compatibility)
*/
switch ((int)(a_out->a_magic & 0xffff)) {
case ZMAGIC:
virtual_offset = 0;
if (a_out->a_text) {
file_offset = PAGE_SIZE;
} else {
/* Bill's "screwball mode" */
file_offset = 0;
}
break;
case QMAGIC:
virtual_offset = PAGE_SIZE;
file_offset = 0;
/* Pass PS_STRINGS for BSD/OS binaries only. */
if (N_GETMID(*a_out) == MID_ZERO)
imgp->ps_strings = PS_STRINGS;
break;
default:
/* NetBSD compatibility */
switch ((int)(ntohl(a_out->a_magic) & 0xffff)) {
case ZMAGIC:
case QMAGIC:
virtual_offset = PAGE_SIZE;
file_offset = 0;
break;
default:
return (-1);
}
}
bss_size = roundup(a_out->a_bss, PAGE_SIZE);
/*
* Check various fields in header for validity/bounds.
*/
if (/* entry point must lay with text region */
a_out->a_entry < virtual_offset ||
a_out->a_entry >= virtual_offset + a_out->a_text ||
/* text and data size must each be page rounded */
a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
return (-1);
/* text + data can't exceed file size */
if (a_out->a_data + a_out->a_text > imgp->attr->va_size)
return (EFAULT);
/*
* text/data/bss must not exceed limits
*/
mtx_assert(&Giant, MA_OWNED);
if (/* text can't exceed maximum text size */
a_out->a_text > maxtsiz ||
/* data + bss can't exceed rlimit */
a_out->a_data + bss_size >
imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur)
return (ENOMEM);
/* copy in arguments and/or environment from old process */
error = exec_extract_strings(imgp);
if (error)
return (error);
/*
* Destroy old process VM and create a new one (with a new stack)
*/
exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
/*
* The vm space can be changed by exec_new_vmspace
*/
vmspace = imgp->proc->p_vmspace;
vp = imgp->vp;
object = imgp->object;
map = &vmspace->vm_map;
vm_map_lock(map);
vm_object_reference(object);
text_end = virtual_offset + a_out->a_text;
error = vm_map_insert(map, object,
file_offset,
virtual_offset, text_end,
VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL,
MAP_COPY_ON_WRITE | MAP_PREFAULT);
if (error) {
vm_map_unlock(map);
return (error);
}
data_end = text_end + a_out->a_data;
if (a_out->a_data) {
vm_object_reference(object);
error = vm_map_insert(map, object,
file_offset + a_out->a_text,
text_end, data_end,
VM_PROT_ALL, VM_PROT_ALL,
MAP_COPY_ON_WRITE | MAP_PREFAULT);
if (error) {
vm_map_unlock(map);
return (error);
}
}
if (bss_size) {
error = vm_map_insert(map, NULL, 0,
data_end, data_end + bss_size,
VM_PROT_ALL, VM_PROT_ALL, 0);
if (error) {
vm_map_unlock(map);
return (error);
}
}
vm_map_unlock(map);
/* Fill in process VM information */
vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT;
vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT;
vmspace->vm_taddr = (caddr_t) (uintptr_t) virtual_offset;
vmspace->vm_daddr = (caddr_t) (uintptr_t)
(virtual_offset + a_out->a_text);
/* Fill in image_params */
imgp->interpreted = 0;
imgp->entry_addr = a_out->a_entry;
imgp->proc->p_sysent = &aout_sysvec;
return (0);
}
/*
* Dump core, into a file named as described in the comments for
* expand_name(), unless the process was setuid/setgid.
*/
int
aout_coredump(td, vp, limit)
register struct thread *td;
register struct vnode *vp;
off_t limit;
{
struct proc *p = td->td_proc;
register struct ucred *cred = td->td_ucred;
register struct vmspace *vm = p->p_vmspace;
+ caddr_t tempuser;
int error;
if (ctob((UAREA_PAGES + KSTACK_PAGES)
+ vm->vm_dsize + vm->vm_ssize) >= limit)
return (EFAULT);
+ tempuser = malloc(ctob(UAREA_PAGES + KSTACK_PAGES), M_TEMP,
+ M_WAITOK | M_ZERO);
+ if (tempuser == NULL)
+ return (ENOMEM);
+ bcopy(p->p_uarea, tempuser, sizeof(struct user));
+ bcopy(td->td_frame,
+ tempuser + ctob(UAREA_PAGES) +
+ ((caddr_t) td->td_frame - (caddr_t) td->td_kstack),
+ sizeof(struct trapframe));
PROC_LOCK(p);
fill_kinfo_proc(p, &p->p_uarea->u_kproc);
PROC_UNLOCK(p);
- error = cpu_coredump(td, vp, cred);
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t) tempuser,
+ ctob(UAREA_PAGES + KSTACK_PAGES),
+ (off_t)0, UIO_SYSSPACE, IO_UNIT, cred, NOCRED,
+ (int *)NULL, td);
+ free(tempuser, M_TEMP);
if (error == 0)
error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
(int)ctob(vm->vm_dsize),
(off_t)ctob(UAREA_PAGES + KSTACK_PAGES), UIO_USERSPACE,
IO_UNIT | IO_DIRECT, cred, NOCRED, (int *) NULL, td);
if (error == 0)
error = vn_rdwr_inchunks(UIO_WRITE, vp,
(caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)),
round_page(ctob(vm->vm_ssize)),
(off_t)ctob(UAREA_PAGES + KSTACK_PAGES) +
ctob(vm->vm_dsize), UIO_USERSPACE,
IO_UNIT | IO_DIRECT, cred, NOCRED, (int *) NULL, td);
return (error);
}
/*
* Tell kern_execve.c about it, with a little help from the linker.
*/
static struct execsw aout_execsw = { exec_aout_imgact, "a.out" };
EXEC_SET(aout, aout_execsw);
File Metadata
Details
Attached
Mime Type
application/octet-stream
Expires
Thu, Oct 16, 7:33 AM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23747556
Default Alt Text
(28 KB)
Attached To
Mode
rS FreeBSD src repository - subversion
Attached
Detach File
Event Timeline
Log In to Comment