Merge branch 'master' into codesourcery.

All Matt's advices applied.
This commit is contained in:
Serge Vakulenko
2014-05-06 19:55:35 -07:00
67 changed files with 2355 additions and 1671 deletions

95
sys/kernel/exec_aout.c Normal file
View File

@@ -0,0 +1,95 @@
#include "param.h"
#include "systm.h"
#include "map.h"
#include "inode.h"
#include "user.h"
#include "proc.h"
#include "buf.h"
#include "namei.h"
#include "fs.h"
#include "mount.h"
#include "file.h"
#include "resource.h"
#include "exec.h"
#include "exec_aout.h"
#include "dir.h"
#include "uio.h"
#include "debug.h"
int exec_aout_check(struct exec_params *epp)
{
int error;
if (epp->hdr_len < sizeof(struct exec))
return ENOEXEC;
if (!(N_GETMID(epp->hdr.aout) == MID_ZERO &&
N_GETFLAG(epp->hdr.aout) == 0))
return ENOEXEC;
switch (N_GETMAGIC(epp->hdr.aout)) {
case OMAGIC:
epp->hdr.aout.a_data += epp->hdr.aout.a_text;
epp->hdr.aout.a_text = 0;
break;
default:
printf("Bad a.out magic = %0o\n", N_GETMAGIC(epp->hdr.aout));
return ENOEXEC;
}
/*
* Save arglist
*/
exec_save_args(epp);
DEBUG("Exec file header:\n");
DEBUG("a_midmag = %#x\n", epp->hdr.aout.a_midmag); /* magic number */
DEBUG("a_text = %d\n", epp->hdr.aout.a_text); /* size of text segment */
DEBUG("a_data = %d\n", epp->hdr.aout.a_data); /* size of initialized data */
DEBUG("a_bss = %d\n", epp->hdr.aout.a_bss); /* size of uninitialized data */
DEBUG("a_reltext = %d\n", epp->hdr.aout.a_reltext); /* size of text relocation info */
DEBUG("a_reldata = %d\n", epp->hdr.aout.a_reldata); /* size of data relocation info */
DEBUG("a_syms = %d\n", epp->hdr.aout.a_syms); /* size of symbol table */
DEBUG("a_entry = %#x\n", epp->hdr.aout.a_entry); /* entry point */
/*
* Set up memory allocation
*/
epp->text.vaddr = epp->heap.vaddr = NO_ADDR;
epp->text.len = epp->heap.len = 0;
epp->data.vaddr = (caddr_t)USER_DATA_START;
epp->data.len = epp->hdr.aout.a_data;
epp->bss.vaddr = epp->data.vaddr + epp->data.len;
epp->bss.len = epp->hdr.aout.a_bss;
epp->heap.vaddr = epp->bss.vaddr + epp->bss.len;
epp->heap.len = 0;
epp->stack.len = SSIZE + roundup(epp->argbc + epp->envbc, NBPW) + (epp->argc + epp->envc+4)*NBPW;
epp->stack.vaddr = (caddr_t)USER_DATA_END - epp->stack.len;
/*
* Allocate core at this point, committed to the new image.
* TODO: What to do for errors?
*/
exec_estab(epp);
/* read in text and data */
DEBUG("reading a.out image\n");
error = rdwri (UIO_READ, epp->ip,
(caddr_t)epp->data.vaddr, epp->hdr.aout.a_data,
sizeof(struct exec) + epp->hdr.aout.a_text, IO_UNIT, 0);
if (error)
DEBUG("read image returned error=%d\n", error);
if (error) {
/*
* Error - all is lost, when the old image is possible corrupt
* and we could not load a new.
*/
psignal (u.u_procp, SIGSEGV);
return error;
}
exec_clear(epp);
exec_setupstack(epp->hdr.aout.a_entry, epp);
return 0;
}

59
sys/kernel/exec_conf.c Normal file
View File

@@ -0,0 +1,59 @@
/* $NetBSD: exec_conf.c,v 1.43 2000/06/09 22:38:57 oki Exp $ */
/*
* Copyright (c) 1993, 1994 Christopher G. Demetriou
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christopher G. Demetriou.
* 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 "param.h"
#include "inode.h"
#include "exec.h"
#ifdef EXEC_SCRIPT
int exec_script_check(struct exec_params *epp);
#endif
#ifdef EXEC_AOUT
int exec_aout_check(struct exec_params *epp);
#endif
#ifdef EXEC_ELF
int exec_elf_check(struct exec_params *epp);
#endif
const struct execsw execsw[] = {
#ifdef EXEC_AOUT
{ exec_aout_check, "a.out" }, /* a.out binaries */
#endif
#ifdef EXEC_ELF
{ exec_elf_check, "elf" }, /* 32bit ELF bins */
#endif
#ifdef EXEC_SCRIPT
{ exec_script_check, "script" }, /* shell scripts */
#endif
};
int nexecs = (sizeof(execsw) / sizeof(*execsw));
int exec_maxhdrsz;

207
sys/kernel/exec_elf.c Normal file
View File

@@ -0,0 +1,207 @@
/* $NetBSD: exec_elf32.c,v 1.49.2.2 2000/11/03 20:00:38 tv Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* 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 the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/*
* Copyright (c) 1996 Christopher G. Demetriou
* 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 "param.h"
#include "systm.h"
#include "kernel.h"
#include "map.h"
#include "user.h"
#include "proc.h"
//#include "malloc.h"
#include "inode.h"
#include "namei.h"
//#include "vnode.h"
#include "exec.h"
#include "exec_elf.h"
#include "fcntl.h"
//#include "syscall.h"
#include "signalvar.h"
#include "mount.h"
#include "stat.h"
extern char sigcode[], esigcode[];
/* 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))
/*
* elf_check(): 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_elf_check(struct exec_params *epp)
{
struct elf_phdr *ph;
int error, i, phsize;
const char elfident[] = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV, 0};
/*
* Check that this is an ELF file that we can handle,
* and do some sanity checks on the header
*/
if (epp->hdr_len < sizeof(struct elf_ehdr))
return ENOEXEC;
for (i = 0; i < sizeof elfident; i++)
if (epp->hdr.elf.e_ident[i] != elfident[i])
return ENOEXEC;
if (epp->hdr.elf.e_type != ET_EXEC)
return ENOEXEC;
if (epp->hdr.elf.e_machine != EM_MIPS || epp->hdr.elf.e_version != EV_CURRENT)
return ENOEXEC;
if (epp->hdr.elf.e_phentsize != sizeof(struct elf_phdr) || epp->hdr.elf.e_phoff == 0 || epp->hdr.elf.e_phnum == 0)
return ENOEXEC;
if (epp->hdr.elf.e_shnum == 0 || epp->hdr.elf.e_shentsize != sizeof(struct elf_shdr))
return ENOEXEC;
/*
* Read program headers
*/
phsize = epp->hdr.elf.e_phnum * sizeof(struct elf_phdr);
ph = exec_alloc(phsize, NBPW, epp);
if (ph == NULL) {
printf("can't alloc ph[] sz=%d\n", phsize);
return ENOEXEC;
}
if ((error = rdwri(UIO_READ, epp->ip, (caddr_t)ph, phsize, epp->hdr.elf.e_phoff, IO_UNIT, 0)) != 0)
return ENOEXEC;
epp->text.len = epp->data.len = epp->bss.len = epp->stack.len = epp->heap.len = 0;
epp->text.vaddr = epp->data.vaddr = epp->bss.vaddr = epp->stack.vaddr = epp->heap.vaddr = NO_ADDR;
if (epp->hdr.elf.e_phnum == 1 && ph[0].p_type == PT_LOAD && ph[0].p_flags == (PF_R|PF_W|PF_X)) {
/*
* In the simple a.out type link, in elf format, there is only
* one loadable segment that is RWE containing everything
* Here we fix the memory allocation, and we are done.
*/
epp->data.vaddr = (caddr_t)ph[0].p_vaddr;
epp->data.len = ph[0].p_memsz;
epp->heap.vaddr = (caddr_t)ph[0].p_vaddr + ph[0].p_memsz;
epp->heap.len = 0;
epp->stack.len = SSIZE + epp->argbc + epp->envbc + (epp->argc+epp->envc+4)*NBPW;
epp->stack.vaddr = (caddr_t)USER_DATA_END - epp->stack.len;
/*
* We assume .bss is the different between the memory data
* section size and the file size.
*/
epp->bss.vaddr = epp->data.vaddr + ph[0].p_filesz;
epp->bss.len = ph[0].p_memsz - ph[0].p_filesz;
epp->data.len = epp->bss.vaddr - epp->data.vaddr;
} else {
/*
* At the current moment we don't handle anything else
* The rest of the code is implemented as need arise.
*/
return ENOEXEC;
}
/*
* Save arglist
*/
exec_save_args(epp);
/*
* Establish memory
*/
if ((error = exec_estab(epp)) != 0)
return error;
/*
* Now load the program sections into memory
*/
for (i = 0; i < epp->hdr.elf.e_phnum; i++) {
if (ph[i].p_type != PT_LOAD)
continue;
/*
* Sanity check that the load is to our intended address space.
*/
if (!((epp->text.vaddr != NO_ADDR
&& ((caddr_t)ph[i].p_vaddr >= epp->text.vaddr
&& (caddr_t)ph[i].p_vaddr + ph[i].p_filesz <= epp->text.vaddr + epp->text.len))
|| (epp->data.vaddr != NO_ADDR
&& (caddr_t)ph[i].p_vaddr >= epp->data.vaddr
&& (caddr_t)ph[i].p_vaddr + ph[i].p_filesz <= epp->data.vaddr + epp->data.len))
|| ph[i].p_filesz >= ph[i].p_memsz || ph[i].p_filesz <= 0)
return ENOEXEC;
error = rdwri(UIO_READ, epp->ip, (caddr_t)ph[i].p_vaddr, ph[i].p_filesz, ph[i].p_offset, IO_UNIT, 0);
}
exec_clear(epp);
exec_setupstack(epp->hdr.elf.e_entry, epp);
return 0;
}

96
sys/kernel/exec_script.c Normal file
View File

@@ -0,0 +1,96 @@
#include "param.h"
#include "inode.h"
#include "dir.h"
#include "namei.h"
#include "exec.h"
#include "user.h"
#include "systm.h"
int
exec_script_check(struct exec_params *epp)
{
char *cp;
struct nameidata nd;
struct nameidata *ndp;
int error;
struct inode *ip = 0;
/*
* We come here with the first line of the executable
* script file.
* Check is to see if it starts with the magic marker: #!
*/
if (epp->hdr.sh[0] != '#' || epp->hdr.sh[1] != '!' || epp->sh.interpreted)
return ENOEXEC;
epp->sh.interpreted = 1;
/*
* If setuid/gid scripts were to be disallowed this is where it would
* have to be done.
* u.u_uid = uid;
* u.u_gid = u_groups[0];
*/
/*
* The first line of the text file
* should be one line on the format:
* #! <interpreter-name> <interpreter-argument>\n
*/
cp = &epp->hdr.sh[2];
while (cp < &epp->hdr.sh[MIN(epp->hdr_len, SHSIZE)]) {
if (*cp == '\t')
*cp = ' ';
else if (*cp == '\n') {
*cp = '\0';
break;
}
cp++;
}
if (cp == &epp->hdr.sh[MIN(epp->hdr_len, SHSIZE)])
return ENOEXEC;
/*
* Pick up script interpreter file name
*/
cp = &epp->hdr.sh[2];
while (*cp == ' ')
cp++;
if (!*cp)
return ENOEXEC;
bzero(&nd, sizeof nd);
ndp = &nd;
ndp->ni_dirp = cp;
while (*cp && *cp != ' ')
cp++;
if (*cp != '\0') {
*cp++ = 0;
while (*cp && *cp == ' ')
cp++;
if (*cp) {
if ((error = copystr(cp, epp->sh.interparg, sizeof epp->sh.interparg, NULL)))
goto done;
}
}
/*
* the interpreter is the new file to exec
*/
ndp->ni_nameiop = LOOKUP | FOLLOW;
ip = namei (ndp);
if (ip == NULL)
return u.u_error;
if ((error = copystr(ndp->ni_dent.d_name, epp->sh.interpname, sizeof epp->sh.interpname, NULL)))
goto done;
/*
* Everything set up, do the recursive exec()
*/
if (epp->ip)
iput(epp->ip);
epp->ip = ip;
error = exec_check(epp);
done:
if (ip)
iput(ip);
return error;
}

425
sys/kernel/exec_subr.c Normal file
View File

@@ -0,0 +1,425 @@
#include "param.h"
#include "systm.h"
#include "map.h"
#include "inode.h"
#include "user.h"
#include "proc.h"
#include "buf.h"
#include "namei.h"
#include "fs.h"
#include "mount.h"
#include "file.h"
#include "resource.h"
#include "exec.h"
#include "dir.h"
#include "uio.h"
#include "debug.h"
/*
* How memory is set up.
*
* var a:
* USER_DATA_END: !----------!
* ! +P_ssize ! stack
* p_saddr -> ¡----------!
*
* !----------!
* ! +P_dsize ! .data + .bss + heap
* P_daddr -> !----------!
*
* var b:
*
* USER_DATA_END: !--------!
* ! +ssize ! stack
* saddr -> ¡--------!
* ! +hsize ! heap
* haddr -> !--------!
* ! +dsize ! .data + .bss
* daddr -> !--------!
* ! +tsize ! .text
* taddr -> !--------!
* paddr -> +psize
*
* var c:
* !--------!
* ! +tsize ! .text (read only section)
* taddr -> !--------!
* ! +ssize ! stack
* saddr -> ¡--------!
* ! +hsize ! heap
* haddr -> !--------!
* ! +dsize ! .data + .bss
* daddr -> !--------!
* paddr -> +psize
*
*/
/*
* Set up user memory.
*
* The following is a key to top of the stack and the variables used.
*
* topp-> [argv] top word for /bin/ps
* <0>
* n
* g
* r
* a
* ...
* <0>
* 0
* g
* r
* ucp -> a
* [0]
* [envn]
* ...
* envp -> [env0]
* [0]
* [argn] ptr to argn
* ...
* argp -> [arg0] ptr to arg0
* []
* []
* []
* sp -> []
*
*/
void exec_setupstack(unsigned entryaddr, struct exec_params *epp)
{
int nc,i;
u_int len;
char *ucp;
char **argp, **envp, ***topp;
DEBUG("exec_setupstack:\n");
/*
* Set up top of stack structure as above
* This depends on that kernel and user spaces
* map to the same addresses.
*/
topp = (char ***)(epp->stack.vaddr + epp->stack.len - NBPW); /* Last word of RAM */
ucp = (char *)((unsigned)topp - roundup(epp->envbc + epp->argbc,NBPW)); /* arg string space */
envp = (char **)(ucp - (epp->envc+1)*NBPW); /* Make place for envp[...], +1 for the 0 */
argp = envp - (epp->argc+1)*NBPW; /* Make place for argv[...] */
u.u_frame [FRAME_SP] = (int)(argp-16);
u.u_frame [FRAME_R4] = epp->argc; /* $a0 := argc */
u.u_frame [FRAME_R5] = (int)argp; /* $a1 := argp */
u.u_frame [FRAME_R6] = (int)envp; /* $a2 := env */
*topp = argp; /* for /bin/ps */
/*
* copy the arguments into the structure
*/
nc = 0;
for (i = 0; i < epp->argc; i++) {
argp[i] = (caddr_t)ucp;
if (copystr((caddr_t)epp->argp[i], (caddr_t)ucp, (caddr_t)topp-ucp, &len) == 0) {
nc += len;
ucp += len;
}
}
argp[epp->argc] = NULL;
for (i = 0; i < epp->envc; i++) {
envp[i] = ucp;
if (copystr((caddr_t)epp->envp[i], (caddr_t)ucp, (caddr_t)topp-ucp, &len) == 0) {
nc += len;
ucp += len;
}
}
envp[epp->envc] = NULL;
ucp = (caddr_t)roundup((unsigned)ucp, NBPW);
if ((caddr_t)ucp != (caddr_t)topp) {
DEBUG("Copying of arg list went wrong, ucp=%#x, topp=%#x\n", ucp, topp);
panic("exec check");
}
u.u_frame [FRAME_PC] = entryaddr;
DEBUG("Setting up new PC=%#x\n", entryaddr);
/*
* Remember file name for accounting.
*/
(void) copystr(argp[0], u.u_comm, MAXCOMLEN, 0);
}
/*
* A simple memory allocator used within exec code using file buffers as storage.
* Will return NULL if allocation is not possible.
* Total max memory allocatable is MAXALLOCBUF*MAXBSIZE
* Max size of allocatable chunk is MAXBSIZE
*
* All memory allocated with this function will be freed by a call
* to exec_alloc_freeall()
*/
void *exec_alloc(int size, int ru, struct exec_params *epp)
{
char *cp;
int i;
for (i = 0; i < MAXALLOCBUF; i++)
if (MAXBSIZE - (ru<=1?epp->alloc[i].fill:roundup(epp->alloc[i].fill,ru)) >= size)
break;
if (i == MAXALLOCBUF)
return NULL;
if (epp->alloc[i].bp == NULL) {
if ((epp->alloc[i].bp = geteblk()) == NULL) {
DEBUG("exec_alloc: no buf\n");
return NULL;
}
}
if (ru > 1)
epp->alloc[i].fill = roundup(epp->alloc[i].fill, ru);
cp = epp->alloc[i].bp->b_addr + epp->alloc[i].fill;
epp->alloc[i].fill += size;
bzero (cp, size);
return cp;
}
/*
* this will deallocate all memory allocated by exec_alloc
*/
void exec_alloc_freeall(struct exec_params *epp)
{
int i;
for (i = 0; i < MAXALLOCBUF; i++) {
if (epp->alloc[i].bp) {
brelse(epp->alloc[i].bp);
epp->alloc[i].bp = NULL;
epp->alloc[i].fill = 0;
}
}
}
/*
* Establish memory for the image based on the
* values picked up from the executable file and stored
* in the exec params block.
*/
int exec_estab(struct exec_params *epp)
{
DEBUG("text = %#x..%#x, len=%d\n", epp->text.vaddr, epp->text.vaddr+epp->text.len, epp->text.len);
DEBUG("data = %#x..%#x, len=%d\n", epp->data.vaddr, epp->data.vaddr+epp->data.len, epp->data.len);
DEBUG("bss = %#x..%#x, len=%d\n", epp->bss.vaddr, epp->bss.vaddr+epp->bss.len, epp->bss.len);
DEBUG("heap = %#x..%#x, len=%d\n", epp->heap.vaddr, epp->heap.vaddr+epp->heap.len, epp->heap.len);
DEBUG("stack = %#x..%#x, len=%d\n", epp->stack.vaddr, epp->stack.vaddr+epp->stack.len, epp->stack.len);
/*
* Right now we can only handle the simple original a.out
* case, so we double check for that case here.
*/
if (epp->text.vaddr != NO_ADDR || epp->data.vaddr == NO_ADDR
|| epp->data.vaddr != (caddr_t)USER_DATA_START || epp->stack.vaddr != (caddr_t)USER_DATA_END - epp->stack.len)
return ENOMEM;
/*
* Try out for overflow
*/
if (epp->text.len + epp->data.len + epp->heap.len + epp->stack.len > MAXMEM)
return ENOMEM;
if (roundup((unsigned)epp->data.vaddr + epp->data.len, NBPW) != roundup((unsigned)epp->bss.vaddr, NBPW)) {
DEBUG(".bss do not follow .data\n");
return ENOMEM;
}
/*
* Allocate core at this point, committed to the new image.
*/
u.u_prof.pr_scale = 0;
if (u.u_procp->p_flag & SVFORK)
endvfork();
u.u_procp->p_dsize = epp->data.len + epp->bss.len;
u.u_procp->p_daddr = (size_t)epp->data.vaddr;
u.u_procp->p_ssize = epp->stack.len;
u.u_procp->p_saddr = (size_t)epp->stack.vaddr;
DEBUG("core allocation: \n");
DEBUG("daddr =%#x..%#x\n", u.u_procp->p_daddr, u.u_procp->p_daddr + u.u_procp->p_dsize);
DEBUG("saddr =%#x..%#x\n", u.u_procp->p_saddr, u.u_procp->p_saddr + u.u_procp->p_ssize);
return 0;
}
/*
* Save argv[] and envp[]
*/
void exec_save_args(struct exec_params *epp)
{
unsigned len;
caddr_t cp;
int argc, i, l;
char **argp, *ap;
epp->argc = epp->envc = 0;
epp->argbc = epp->envbc = 0;
argc = 0;
if ((argp = epp->userargp) != NULL)
while (argp[argc])
argc++;
#ifdef EXEC_SCRIPT
if (epp->sh.interpreted) {
argc++;
if (epp->sh.interparg[0])
argc++;
}
#endif
if (argc != 0) {
if ((epp->argp = (char **)exec_alloc(argc * sizeof(char *), NBPW, epp)) == NULL)
return;
for (;;) {
/*
* For a interpreter script, the arg list is changed to
* #! <interpreter name> <interpreter arg>
* arg[0] - the interpreter executable name (path)
* arg[1] - interpreter arg (optional)
* arg[2 or 1] - script name
* arg[3 or 2...] - script arg[1...]
*/
if (argp)
ap = *argp++;
else
ap = NULL;
#ifdef EXEC_SCRIPT
if (epp->sh.interpreted) {
if (epp->argc == 0)
ap = epp->sh.interpname;
else if (epp->argc == 1 && epp->sh.interparg[0]) {
ap = epp->sh.interparg;
--argp;
} else if ((epp->argc == 1 || (epp->argc == 2 && epp->sh.interparg[0]))) {
ap = epp->userfname;
--argp;
}
}
#endif
if (ap == 0)
break;
l = strlen(ap)+1;
if ((cp = exec_alloc(l, 1, epp)) == NULL)
return;
if (copystr(ap, cp, l, &len) != 0)
return;
epp->argp[epp->argc++] = cp;
epp->argbc += len;;
}
}
argc = 0;
if ((argp = epp->userenvp) != NULL)
while (argp[argc])
argc++;
epp->envc = 0;
epp->envbc = 0;
if (argc != 0) {
if ((epp->envp = (char **)exec_alloc(argc * sizeof(char *), NBPW, epp)) == NULL)
return;
for (;;) {
if (argp)
ap = *argp++;
else
ap = NULL;
if (ap == 0)
break;
l = strlen(ap)+1;
if ((cp = exec_alloc(l, 1, epp)) == NULL)
return;
if (copystr(ap, cp, l, &len) != 0)
return;
epp->envp[epp->envc++] = cp;
epp->envbc += len;
}
}
for (i = 0; i < epp->argc; i++)
DEBUG("arg[%d] = \"%s\"\n", i, epp->argp[i]);
for (i = 0; i < epp->envc; i++)
DEBUG("env[%d] = \"%s\"\n", i, epp->envp[i]);
/*
* Number of string pool chars needed for this arg list
*/
// return (bc + NBPW-1) & ~(NBPW-1);
return;
}
void exec_clear(struct exec_params *epp)
{
char *cp;
int cc;
/* clear BSS */
if (epp->bss.len > 0)
bzero((void *)epp->bss.vaddr, epp->bss.len);
if (epp->heap.len > 0)
bzero((void *)epp->heap.vaddr, epp->heap.len);
/* Clear stack */
bzero((void *)epp->stack.vaddr, epp->stack.len);
/*
* set SUID/SGID protections, if no tracing
*/
if ((u.u_procp->p_flag & P_TRACED) == 0) {
u.u_uid = epp->uid;
u.u_procp->p_uid = epp->uid;
u.u_groups[0] = epp->gid;
} else
psignal (u.u_procp, SIGTRAP);
u.u_svuid = u.u_uid;
u.u_svgid = u.u_groups[0];
u.u_tsize = epp->text.len;
u.u_dsize = epp->data.len + epp->bss.len;
u.u_ssize = epp->stack.len;
/*
* Clear registers.
*/
u.u_frame [FRAME_R1] = 0; /* $at */
u.u_frame [FRAME_R2] = 0; /* $v0 */
u.u_frame [FRAME_R3] = 0; /* $v1 */
u.u_frame [FRAME_R7] = 0; /* $a3 */
u.u_frame [FRAME_R8] = 0; /* $t0 */
u.u_frame [FRAME_R9] = 0; /* $t1 */
u.u_frame [FRAME_R10] = 0; /* $t2 */
u.u_frame [FRAME_R11] = 0; /* $t3 */
u.u_frame [FRAME_R12] = 0; /* $t4 */
u.u_frame [FRAME_R13] = 0; /* $t5 */
u.u_frame [FRAME_R14] = 0; /* $t6 */
u.u_frame [FRAME_R15] = 0; /* $t7 */
u.u_frame [FRAME_R16] = 0; /* $s0 */
u.u_frame [FRAME_R17] = 0; /* $s1 */
u.u_frame [FRAME_R18] = 0; /* $s2 */
u.u_frame [FRAME_R19] = 0; /* $s3 */
u.u_frame [FRAME_R20] = 0; /* $s4 */
u.u_frame [FRAME_R21] = 0; /* $s5 */
u.u_frame [FRAME_R22] = 0; /* $s6 */
u.u_frame [FRAME_R23] = 0; /* $s7 */
u.u_frame [FRAME_R24] = 0; /* $t8 */
u.u_frame [FRAME_R25] = 0; /* $t9 */
u.u_frame [FRAME_FP] = 0;
u.u_frame [FRAME_RA] = 0;
u.u_frame [FRAME_LO] = 0;
u.u_frame [FRAME_HI] = 0;
u.u_frame [FRAME_GP] = 0;
execsigs (u.u_procp);
/*
* Clear (close) files
*/
for (cp = u.u_pofile, cc = 0; cc <= u.u_lastfile; cc++, cp++) {
if (*cp & UF_EXCLOSE) {
(void) closef (u.u_ofile [cc]);
u.u_ofile [cc] = NULL;
*cp = 0;
}
}
while (u.u_lastfile >= 0 && u.u_ofile [u.u_lastfile] == NULL)
u.u_lastfile--;
}

View File

@@ -6,15 +6,17 @@
#include "param.h"
#include "systm.h"
#include "map.h"
#include "inode.h"
#include "user.h"
#include "proc.h"
#include "buf.h"
#include "inode.h"
#include "namei.h"
#include "fs.h"
#include "mount.h"
#include "file.h"
#include "signalvar.h"
#include "exec.h"
#include "debug.h"
/*
* exec system call, with and without environments.
@@ -26,135 +28,70 @@ struct execa {
};
/*
* Reset signals for an exec of the specified process. In 4.4 this function
* was in kern_sig.c but since in 2.11 kern_sig and kern_exec will likely be
* in different overlays placing this here potentially saves a kernel overlay
* switch.
* This is the internal form of the exec() function.
*
* It is called with the inode of the executable
* and the exec_params structure, which is used to
* keep information during the exec.
*
* It returns the error code, and with the ip still locked.
*/
static void
execsigs(p)
register struct proc *p;
int exec_check(struct exec_params *epp)
{
register int nc;
unsigned long mask;
int error, i, r;
DEBUG("Entering exec_check\n");
if (access (epp->ip, IEXEC))
return ENOEXEC;
if ((u.u_procp->p_flag & P_TRACED) && access (epp->ip, IREAD))
return ENOEXEC;
if ((epp->ip->i_mode & IFMT) != IFREG ||
(epp->ip->i_mode & (IEXEC | (IEXEC>>3) | (IEXEC>>6))) == 0)
return EACCES;
/*
* Reset caught signals. Held signals remain held
* through p_sigmask (unless they were caught,
* and are now ignored by default).
* Read in first few bytes of file for segment sizes, magic number:
* 407 = plain executable
* Also an ASCII line beginning with #! is
* the file name of a ``interpreter'' and arguments may be prepended
* to the argument list if given here.
*
* INTERPRETER NAMES ARE LIMITED IN LENGTH.
*
* ONLY ONE ARGUMENT MAY BE PASSED TO THE INTERPRETER FROM
* THE ASCII LINE.
*/
while (p->p_sigcatch) {
nc = ffs(p->p_sigcatch);
mask = sigmask(nc);
p->p_sigcatch &= ~mask;
if (sigprop[nc] & SA_IGNORE) {
if (nc != SIGCONT)
p->p_sigignore |= mask;
p->p_sig &= ~mask;
}
u.u_signal[nc] = SIG_DFL;
/*
* Read the first 'SHSIZE' bytes from the file to execute
*/
DEBUG("Read header %d bytes from %d\n", sizeof(epp->hdr), 0);
#ifdef EXEC_SCRIPT
epp->hdr.sh[0] = '\0'; /* for zero length files */
#endif
error = rdwri (UIO_READ, epp->ip,
(caddr_t) &epp->hdr, sizeof(epp->hdr),
(off_t)0, IO_UNIT, &r);
if (error)
return error;
epp->hdr_len = sizeof(epp->hdr) - r;
/*
* Given the first part of the image
* loop through the exec file handlers to find
* someone who can handle this file format.
*/
error = ENOEXEC;
DEBUG("Trying %d exec formats\n", nexecs);
for (i = 0; i < nexecs && error != 0; i++) {
DEBUG("Trying exec format %d : %s\n", i, execsw[i].es_name);
if (execsw[i].es_check == NULL)
continue;
error = (*execsw[i].es_check)(epp);
if (error == 0)
break;
}
/*
* Reset stack state to the user stack (disable the alternate stack).
*/
u.u_sigstk.ss_flags = SA_DISABLE;
u.u_sigstk.ss_size = 0;
u.u_sigstk.ss_base = 0;
u.u_psflags = 0;
}
/*
* Read in and set up memory for executed file.
* u.u_error set on error
*/
static void
getxfile (ip, ep, nargc, uid, gid)
struct inode *ip;
register struct exec *ep;
int nargc, uid, gid;
{
u_int ds, ts, ss;
if (ep->a_magic == OMAGIC) {
ep->a_data += ep->a_text;
ep->a_text = 0;
}
if (ep->a_text != 0 && (ip->i_flag & ITEXT) == 0 &&
ip->i_count != 1) {
register struct file *fp;
for (fp = file; fp < file+NFILE; fp++) {
if (fp->f_type == DTYPE_INODE &&
fp->f_count > 0 &&
(struct inode*)fp->f_data == ip &&
(fp->f_flag & FWRITE)) {
u.u_error = ETXTBSY;
return;
}
}
}
/*
* find text and data sizes try; them out for possible
* overflow of max sizes
*/
ts = ep->a_text;
ds = ep->a_data + ep->a_bss;
ss = SSIZE + nargc;
//printf ("getxfile: size t/d/s = %u/%u/%u\n", ts, ds, ss);
if (ts + ds + ss > MAXMEM) {
u.u_error = ENOMEM;
return;
}
/*
* Allocate core at this point, committed to the new image.
*/
u.u_prof.pr_scale = 0;
if (u.u_procp->p_flag & SVFORK)
endvfork();
u.u_procp->p_dsize = ds;
u.u_procp->p_daddr = USER_DATA_START;
u.u_procp->p_ssize = ss;
u.u_procp->p_saddr = USER_DATA_END - ss;
/* read in text and data */
//printf ("getxfile: read %u bytes at %08x\n", ep->a_data, USER_DATA_START);
rdwri (UIO_READ, ip, (caddr_t) USER_DATA_START, ep->a_data,
sizeof(struct exec) + ep->a_text, IO_UNIT, (int*) 0);
/* clear BSS and stack */
//printf ("getxfile: clear %u bytes at %08x\n", USER_DATA_END - USER_DATA_START - ep->a_data, USER_DATA_START + ep->a_data);
bzero ((void*) (USER_DATA_START + ep->a_data),
USER_DATA_END - USER_DATA_START - ep->a_data);
/*
* set SUID/SGID protections, if no tracing
*/
if ((u.u_procp->p_flag & P_TRACED) == 0) {
u.u_uid = uid;
u.u_procp->p_uid = uid;
u.u_groups[0] = gid;
} else
psignal (u.u_procp, SIGTRAP);
u.u_svuid = u.u_uid;
u.u_svgid = u.u_groups[0];
u.u_tsize = ts;
u.u_dsize = ds;
u.u_ssize = ss;
}
void printmem (unsigned addr, int nbytes)
{
for (; nbytes>0; addr+=16, nbytes-=16) {
unsigned char *p = (unsigned char*) addr;
printf ("%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
addr, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
}
return error;
}
void
@@ -169,371 +106,51 @@ execv()
void
execve()
{
register char *cp;
register struct buf *bp;
struct execa *uap = (struct execa *)u.u_arg;
int nc, na, ne, ucp, ap, indir, uid, gid, resid, error;
register int cc;
unsigned len;
char *sharg;
int error;
struct inode *ip;
size_t bno;
char cfname [MAXCOMLEN + 1];
#define SHSIZE 32
char cfarg [SHSIZE];
union {
char ex_shell [SHSIZE]; /* #! and name of interpreter */
struct exec ex_exec;
} exdata;
struct nameidata nd;
register struct nameidata *ndp = &nd;
struct exec_params eparam;
//printf ("execve ('%s', ['%s', '%s', ...])\n", uap->fname, uap->argp[0], uap->argp[1]);
DEBUG("execve ('%s', ['%s', '%s', ...])\n", uap->fname, uap->argp[0], uap->argp[1]);
NDINIT (ndp, LOOKUP, FOLLOW, uap->fname);
ip = namei (ndp);
if (ip == NULL) {
//printf ("execve: file not found\n");
DEBUG("execve: file '%s' not found\n", uap->fname);
return;
}
bno = 0;
bp = 0;
indir = 0;
uid = u.u_uid;
gid = u.u_groups[0];
/*
* The exec_param structure is used to
* keep information about the executable during exec's processing
*/
bzero(&eparam, sizeof eparam);
eparam.userfname = uap->fname;
eparam.userargp = uap->argp;
eparam.userenvp = uap->envp;
eparam.uid = u.u_uid;
eparam.gid = u.u_groups[0];
if (ip->i_fs->fs_flags & MNT_NOEXEC) {
//printf ("execve: NOEXEC, flags=%o\n", ip->i_fs->fs_flags);
u.u_error = EACCES;
DEBUG("EACCES\n");
goto done;
}
if ((ip->i_fs->fs_flags & MNT_NOSUID) == 0) {
if (ip->i_mode & ISUID)
uid = ip->i_uid;
eparam.uid = ip->i_uid;
if (ip->i_mode & ISGID)
gid = ip->i_gid;
}
again:
if (access (ip, IEXEC)) {
//printf ("execve: no IEXEC\n");
goto done;
}
if ((u.u_procp->p_flag & P_TRACED) && access (ip, IREAD)) {
//printf ("execve: traced, but no IREAD\n");
goto done;
}
if ((ip->i_mode & IFMT) != IFREG ||
(ip->i_mode & (IEXEC | (IEXEC>>3) | (IEXEC>>6))) == 0) {
//printf ("execve: no IEXEC, mode=%o\n", ip->i_mode);
u.u_error = EACCES;
goto done;
eparam.gid = ip->i_gid;
}
/*
* Read in first few bytes of file for segment sizes, magic number:
* 407 = plain executable
* Also an ASCII line beginning with #! is
* the file name of a ``shell'' and arguments may be prepended
* to the argument list if given here.
*
* SHELL NAMES ARE LIMITED IN LENGTH.
*
* ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
* THE ASCII LINE.
*/
exdata.ex_shell[0] = '\0'; /* for zero length files */
u.u_error = rdwri (UIO_READ, ip, (caddr_t) &exdata, sizeof(exdata),
(off_t) 0, IO_UNIT, &resid);
if (u.u_error) {
//printf ("execve: rdwri error %d\n", u.u_error);
goto done;
}
if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
exdata.ex_shell[0] != '#') {
//printf ("execve: short read, resid = %d, shell=%.32s\n", resid, exdata.ex_shell);
u.u_error = ENOEXEC;
goto done;
}
//printf ("execve: text=%u, data=%u, bss=%u\n", exdata.ex_exec.a_text, exdata.ex_exec.a_data, exdata.ex_exec.a_bss);
switch ((int) exdata.ex_exec.a_magic) {
case OMAGIC:
case NMAGIC:
break;
default:
if (exdata.ex_shell[0] != '#' ||
exdata.ex_shell[1] != '!' ||
indir) {
//printf ("execve: bad shell=%.32s\n", exdata.ex_shell);
u.u_error = ENOEXEC;
goto done;
}
/*
* If setuid/gid scripts were to be disallowed this is where it would
* have to be done.
* u.u_uid = uid;
* u.u_gid = u_groups[0];
*/
cp = &exdata.ex_shell[2]; /* skip "#!" */
while (cp < &exdata.ex_shell[SHSIZE]) {
if (*cp == '\t')
*cp = ' ';
else if (*cp == '\n') {
*cp = '\0';
break;
}
cp++;
}
if (*cp != '\0') {
u.u_error = ENOEXEC;
goto done;
}
cp = &exdata.ex_shell[2];
while (*cp == ' ')
cp++;
ndp->ni_dirp = cp;
while (*cp && *cp != ' ')
cp++;
cfarg[0] = '\0';
if (*cp) {
*cp++ = '\0';
while (*cp == ' ')
cp++;
if (*cp)
bcopy ((caddr_t) cp, (caddr_t) cfarg, SHSIZE);
}
indir = 1;
iput (ip);
ndp->ni_nameiop = LOOKUP | FOLLOW;
ip = namei (ndp);
if (ip == NULL)
return;
bcopy ((caddr_t) ndp->ni_dent.d_name, (caddr_t) cfname, MAXCOMLEN);
cfname [MAXCOMLEN] = '\0';
goto again;
}
/*
* Collect arguments on "file" in swap space.
*/
na = 0;
ne = 0;
nc = 0;
cc = 0;
cp = 0;
bno = malloc (swapmap, btod (NCARGS + MAXBSIZE));
if (bno == 0) {
u.u_error = ENOMEM;
goto done;
}
/*
* Copy arguments into file in argdev area.
*/
if (uap->argp) for (;;) {
ap = NULL;
sharg = NULL;
if (indir && na == 0) {
sharg = cfname;
ap = (int) sharg;
uap->argp++; /* ignore argv[0] */
} else if (indir && (na == 1 && cfarg[0])) {
sharg = cfarg;
ap = (int) sharg;
} else if (indir && (na == 1 || (na == 2 && cfarg[0])))
ap = (int) uap->fname;
else if (uap->argp) {
ap = *(int*) uap->argp;
uap->argp++;
}
if (ap == NULL && uap->envp) {
uap->argp = NULL;
ap = *(int*) uap->envp;
if (ap != NULL)
uap->envp++, ne++;
}
if (ap == NULL)
break;
na++;
if (ap == -1) {
u.u_error = EFAULT;
break;
}
do {
if (cc <= 0) {
/*
* We depend on NCARGS being a multiple of
* DEV_BSIZE. This way we need only check
* overflow before each buffer allocation.
*/
if (nc >= NCARGS-1) {
//printf ("execve: too many args = %d\n", nc);
error = E2BIG;
break;
}
if (bp) {
bdwrite(bp);
}
cc = DEV_BSIZE;
bp = getblk (swapdev, dbtofsb(bno) + lblkno(nc));
cp = bp->b_addr;
}
if (sharg) {
error = copystr (sharg, cp, (unsigned) cc, &len);
//printf ("execve arg%d=%s: %u bytes from %08x to %08x\n", na-1, sharg, len, sharg, cp);
sharg += len;
} else {
error = copystr ((caddr_t) ap, cp, (unsigned) cc, &len);
//printf ("execve arg%d=%s: %u bytes from %08x to %08x\n", na-1, ap, len, ap, cp);
ap += len;
}
cp += len;
nc += len;
cc -= len;
} while (error == ENOENT);
if (error) {
//printf ("execve: copy arg error = %d\n", error);
u.u_error = error;
if (bp) {
bp->b_flags |= B_AGE;
bp->b_flags &= ~B_DELWRI;
brelse(bp);
}
bp = 0;
goto badarg;
}
}
//printf ("execve: argc=%d, envc=%d, total %d bytes\n", na, ne, nc);
if (bp) {
bdwrite (bp);
}
bp = 0;
nc = (nc + NBPW-1) & ~(NBPW-1);
getxfile (ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid);
if (u.u_error) {
//printf ("execve: getxfile error = %d\n", u.u_error);
badarg:
for (cc = 0; cc < nc; cc += DEV_BSIZE) {
daddr_t blkno;
blkno = dbtofsb(bno) + lblkno(cc);
if (incore (swapdev, blkno)) {
bp = bread (swapdev, blkno);
bp->b_flags |= B_AGE; /* throw away */
bp->b_flags &= ~B_DELWRI; /* cancel io */
brelse(bp);
bp = 0;
}
}
goto done;
}
iput(ip);
ip = NULL;
/*
* Copy back arglist.
*/
ucp = USER_DATA_END - nc - NBPW;
ap = ucp - na*NBPW - 2*NBPW;
u.u_frame [FRAME_SP] = ap - 16;
u.u_frame [FRAME_R4] = na - ne; /* $a0 := argc */
u.u_frame [FRAME_R5] = ap; /* $a1 := argv */
u.u_frame [FRAME_R6] = ap + (na-ne+1)*NBPW; /* $a2 := env */
*(int*) (USER_DATA_END - NBPW) = ap; /* for /bin/ps */
nc = 0;
cc = 0;
for (;;) {
if (na == ne) {
*(int*) ap = 0;
ap += NBPW;
}
if (--na < 0)
break;
*(int*) ap = ucp;
do {
if (cc <= 0) {
if (bp) {
brelse(bp);
}
cc = DEV_BSIZE;
bp = bread (swapdev, dbtofsb(bno) + lblkno(nc));
bp->b_flags |= B_AGE; /* throw away */
bp->b_flags &= ~B_DELWRI; /* cancel io */
cp = bp->b_addr;
}
error = copystr (cp, (caddr_t) ucp, (unsigned) cc,
&len);
//printf ("execve copy '%s' %u bytes from %08x to %08x\n", cp, len, cp, ucp);
ucp += len;
cp += len;
nc += len;
cc -= len;
} while (error == ENOENT);
if (error == EFAULT)
panic ("exec: EFAULT");
ap += NBPW;
}
*(int*) ap = 0;
if (bp) {
bp->b_flags |= B_AGE;
brelse (bp);
bp = NULL;
}
execsigs (u.u_procp);
for (cp = u.u_pofile, cc = 0; cc <= u.u_lastfile; cc++, cp++) {
if (*cp & UF_EXCLOSE) {
(void) closef (u.u_ofile [cc]);
u.u_ofile [cc] = NULL;
*cp = 0;
}
}
while (u.u_lastfile >= 0 && u.u_ofile [u.u_lastfile] == NULL)
u.u_lastfile--;
/*
* Clear registers.
*/
u.u_frame [FRAME_R1] = 0; /* $at */
u.u_frame [FRAME_R2] = 0; /* $v0 */
u.u_frame [FRAME_R3] = 0; /* $v1 */
u.u_frame [FRAME_R7] = 0; /* $a3 */
u.u_frame [FRAME_R8] = 0; /* $t0 */
u.u_frame [FRAME_R9] = 0; /* $t1 */
u.u_frame [FRAME_R10] = 0; /* $t2 */
u.u_frame [FRAME_R11] = 0; /* $t3 */
u.u_frame [FRAME_R12] = 0; /* $t4 */
u.u_frame [FRAME_R13] = 0; /* $t5 */
u.u_frame [FRAME_R14] = 0; /* $t6 */
u.u_frame [FRAME_R15] = 0; /* $t7 */
u.u_frame [FRAME_R16] = 0; /* $s0 */
u.u_frame [FRAME_R17] = 0; /* $s1 */
u.u_frame [FRAME_R18] = 0; /* $s2 */
u.u_frame [FRAME_R19] = 0; /* $s3 */
u.u_frame [FRAME_R20] = 0; /* $s4 */
u.u_frame [FRAME_R21] = 0; /* $s5 */
u.u_frame [FRAME_R22] = 0; /* $s6 */
u.u_frame [FRAME_R23] = 0; /* $s7 */
u.u_frame [FRAME_R24] = 0; /* $t8 */
u.u_frame [FRAME_R25] = 0; /* $t9 */
u.u_frame [FRAME_FP] = 0;
u.u_frame [FRAME_RA] = 0;
u.u_frame [FRAME_LO] = 0;
u.u_frame [FRAME_HI] = 0;
u.u_frame [FRAME_GP] = 0;
u.u_frame [FRAME_PC] = exdata.ex_exec.a_entry;
/*
* Remember file name for accounting.
*/
bcopy ((caddr_t) (indir ? cfname : ndp->ni_dent.d_name),
(caddr_t) u.u_comm, MAXCOMLEN);
eparam.ip = ip;
DEBUG("calling exec_check()\n");
if ((error = exec_check(&eparam)))
u.u_error = error;
DEBUG("back from exec_check()\n");
done:
//printf ("execve done: PC=%08x, SP=%08x, R4=%08x, R5=%08x, R6=%08x\n",
// u.u_frame [FRAME_PC], u.u_frame [FRAME_SP],
// u.u_frame [FRAME_R4], u.u_frame [FRAME_R5], u.u_frame [FRAME_R6]);
if (bp) {
bp->b_flags |= B_AGE;
brelse (bp);
}
if (bno)
mfree (swapmap, btod (NCARGS + MAXBSIZE), bno);
exec_alloc_freeall(&eparam);
if (ip)
iput(ip);
}

View File

@@ -662,3 +662,40 @@ postsig(sig)
}
exit(sig);
}
/*
* Reset signals for an exec of the specified process. In 4.4 this function
* was in kern_sig.c but since in 2.11 kern_sig and kern_exec will likely be
* in different overlays placing this here potentially saves a kernel overlay
* switch.
*/
void
execsigs(register struct proc *p)
{
register int nc;
unsigned long mask;
/*
* Reset caught signals. Held signals remain held
* through p_sigmask (unless they were caught,
* and are now ignored by default).
*/
while (p->p_sigcatch) {
nc = ffs(p->p_sigcatch);
mask = sigmask(nc);
p->p_sigcatch &= ~mask;
if (sigprop[nc] & SA_IGNORE) {
if (nc != SIGCONT)
p->p_sigignore |= mask;
p->p_sig &= ~mask;
}
u.u_signal[nc] = SIG_DFL;
}
/*
* Reset stack state to the user stack (disable the alternate stack).
*/
u.u_sigstk.ss_flags = SA_DISABLE;
u.u_sigstk.ss_size = 0;
u.u_sigstk.ss_base = 0;
u.u_psflags = 0;
}