From 629c1fe743c681c950805b2f3802c90026e58224 Mon Sep 17 00:00:00 2001 From: rsc Date: Mon, 27 Aug 2007 15:17:40 +0000 Subject: [PATCH] Edit exec. Do not commit to new memory image until nothing can go wrong, avoiding bad2 case. Be sure to allocate enough stack space for argv. Load executable before initializing stack, to keep ELF loops together. Make argv loop clearer. --- exec.c | 132 +++++++++++++++++++++++++-------------------------------- 1 file changed, 57 insertions(+), 75 deletions(-) diff --git a/exec.c b/exec.c index 4da73b2..9f06605 100644 --- a/exec.c +++ b/exec.c @@ -1,44 +1,35 @@ #include "types.h" -#include "stat.h" #include "param.h" #include "mmu.h" #include "proc.h" #include "defs.h" #include "x86.h" -#include "traps.h" -#include "syscall.h" -#include "spinlock.h" -#include "buf.h" #include "fs.h" -#include "fsvar.h" #include "elf.h" -#include "file.h" -#include "fcntl.h" int exec(char *path, char **argv) { - uint sz, sp, p1, p2; - int i, nargs, argbytes, len, off; - struct inode *ip; + char *mem, *s, *last; + int i, argc, arglen, len, off; + uint sz, sp, argp; struct elfhdr elf; + struct inode *ip; struct proghdr ph; - char *mem; - char *s, *last; - - sz = 0; - mem = 0; if((ip = namei(path)) == 0) return -1; ilock(ip); + // Compute memory size of new process. + mem = 0; + sz = 0; + + // Program segments. if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; - if(elf.magic != ELF_MAGIC) goto bad; - for(i=0, off=elf.phoff; i sz) + goto bad; + if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz) + goto bad; + memset(mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz); } - nargs = i; + iunlockput(ip); + + // Initialize stack. + sp = sz; + argp = sz - arglen; - // argn\0 - // ... - // arg0\0 - // 0 - // ptr to argn - // ... - // 12: ptr to arg0 - // 8: argv (points to ptr to arg0) - // 4: argc - // 0: fake return pc - sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4; - *(uint*)(mem + sp) = 0xffffffff; - *(uint*)(mem + sp + 4) = nargs; - *(uint*)(mem + sp + 8) = (uint)(sp + 12); - - p1 = sp + 12; - p2 = sp + 12 + (nargs + 1) * 4; - for(i = 0; i < nargs; i++){ - len = strlen(argv[i]); - memmove(mem + p2, argv[i], len + 1); - *(uint*)(mem + p1) = p2; - p1 += 4; - p2 += len + 1; + // Copy argv strings and pointers to stack. + *(uint*)(mem+argp + 4*argc) = 0; // argv[argc] + for(i=argc-1; i>=0; i--){ + len = strlen(argv[i]) + 1; + sp -= len; + memmove(mem+sp, argv[i], len); + *(uint*)(mem+argp + 4*i) = sp; // argv[i] } - *(uint*)(mem + p1) = 0; - // Save name for debugging. + // Stack frame for main(argc, argv), below arguments. + sp = argp; + sp -= 4; + *(uint*)(mem+sp) = argp; + sp -= 4; + *(uint*)(mem+sp) = argc; + sp -= 4; + *(uint*)(mem+sp) = 0xffffffff; // fake return pc + + // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(cp->name, last, sizeof(cp->name)); - // commit to the new image. + // Commit to the new image. kfree(cp->mem, cp->sz); - cp->sz = sz; cp->mem = mem; - mem = 0; - - for(i=0, off=elf.phoff; i sz) - goto bad2; - if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz) - goto bad2; - memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz); - } - iunlockput(ip); - - cp->tf->eip = elf.entry; + cp->sz = sz; + cp->tf->eip = elf.entry; // main cp->tf->esp = sp; setupsegs(cp); - return 0; bad: @@ -126,9 +113,4 @@ exec(char *path, char **argv) kfree(mem, sz); iunlockput(ip); return -1; - - bad2: - iunlockput(ip); - proc_exit(); - return 0; }