From: Ben Gras Date: Wed, 30 May 2012 17:34:07 +0000 (+0200) Subject: exec() cleanup, generalization, improvement X-Git-Tag: v3.2.1~546 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/index.html?a=commitdiff_plain;h=040362e379bc2acf4861d4afae5563697dac9e57;p=minix.git exec() cleanup, generalization, improvement . make exec() callers (i.e. vfs and rs) determine the memory layout by explicitly reserving regions using mmap() calls on behalf of the exec()ing process, i.e. handling all of the exec logic, thereby eliminating all special exec() knowledge from VM. . the new procedure is: clear the exec()ing process first, then call third-party mmap()s to reserve memory, then copy the executable file section contents in, all using callbacks tailored to the caller's way of starting an executable . i.e. no more explicit EXEC_NEWMEM-style calls in PM or VM as with rigid 2-section arguments . this naturally allows generalizing exec() by simply loading all ELF sections . drop/merge of lots of duplicate exec() code into libexec . not copying the code sections to vfs and into the executable again is a measurable performance improvement (about 3.3% faster for 'make' in src/servers/) --- diff --git a/include/arch/i386/include/vmparam.h b/include/arch/i386/include/vmparam.h index 63aef5c2c..a8e217d49 100644 --- a/include/arch/i386/include/vmparam.h +++ b/include/arch/i386/include/vmparam.h @@ -49,4 +49,9 @@ #define PAGE_SIZE (1 << PAGE_SHIFT) #define PAGE_MASK (PAGE_SIZE - 1) +/* As visible from the user space process, where is the top of the + * stack (first non-stack byte), when in paged mode? + */ +#define VM_STACKTOP 0x80000000 + #endif /* _I386_VMPARAM_H_ */ diff --git a/include/minix/callnr.h b/include/minix/callnr.h index 519ca4154..6f145cf88 100644 --- a/include/minix/callnr.h +++ b/include/minix/callnr.h @@ -97,9 +97,7 @@ #define CPROF 99 /* to PM */ /* Calls provided by PM and FS that are not part of the API */ -#define EXEC_NEWMEM 100 /* from VFS or RS to PM: new memory map for - * exec - */ +#define PM_NEWEXEC 100 /* from VFS or RS to PM: new exec */ #define SRV_FORK 101 /* to PM: special fork call for RS */ #define EXEC_RESTART 102 /* to PM: final part of exec for RS */ #define GETPROCNR 104 /* to PM */ diff --git a/include/minix/sys_config.h b/include/minix/sys_config.h index 37083a549..168923cab 100644 --- a/include/minix/sys_config.h +++ b/include/minix/sys_config.h @@ -54,4 +54,7 @@ error "_MINIX_MACHINE has incorrect value (0)" #define _KMESS_BUF_SIZE 10000 +/* Default stack size (limit) */ +#define DEFAULT_STACK_LIMIT (64 * 1024 * 1024) + #endif /* _MINIX_SYS_CONFIG_H */ diff --git a/include/minix/type.h b/include/minix/type.h index bb038f27c..3ed23852e 100644 --- a/include/minix/type.h +++ b/include/minix/type.h @@ -166,26 +166,6 @@ struct mem_range phys_bytes mr_limit; /* Highest memory address in range */ }; -/* For EXEC_NEWMEM */ -struct exec_newmem -{ - vir_bytes text_addr; /* Starting address of text section */ - vir_bytes text_bytes; /* Length of text section (in bytes) */ - vir_bytes data_addr; /* Starting address of data section */ - vir_bytes data_bytes; /* Length of data section (in bytes) */ - vir_bytes tot_bytes; /* Minimum stack region size (in bytes) */ - vir_bytes args_bytes; /* Arguments/environ size on stack (in bytes) */ - int sep_id; /* Separate I&D? */ - int is_elf; /* Is ELF exe? */ - dev_t st_dev; /* Device holding executable file */ - ino_t st_ino; /* Inode of executable file */ - time_t enst_ctime; /* Last changed time of executable file */ - uid_t new_uid; /* Process UID after exec */ - gid_t new_gid; /* Process GID after exec */ - int setugid; /* Process is setuid or setgid */ - char progname[16]; /* Should be at least PROC_NAME_LEN */ -}; - /* Memory chunks. */ struct memory { phys_bytes base; diff --git a/include/minix/vm.h b/include/minix/vm.h index 3d46c5364..4f0978c1b 100644 --- a/include/minix/vm.h +++ b/include/minix/vm.h @@ -9,8 +9,6 @@ int vm_exit(endpoint_t ep); int vm_fork(endpoint_t ep, int slotno, endpoint_t *child_ep); int vm_brk(endpoint_t ep, char *newaddr); -int vm_exec_newmem(endpoint_t ep, struct exec_newmem *args, int - args_bytes, char **ret_stack_top, int *ret_flags); int vm_push_sig(endpoint_t ep, vir_bytes *old_sp); int vm_willexit(endpoint_t ep); int vm_adddma(endpoint_t proc_e, phys_bytes start, phys_bytes size); diff --git a/kernel/arch/i386/pre_init.c b/kernel/arch/i386/pre_init.c index 65fb69826..0a294669f 100644 --- a/kernel/arch/i386/pre_init.c +++ b/kernel/arch/i386/pre_init.c @@ -368,7 +368,7 @@ static void mb_extract_image(multiboot_info_t mbi) off_t text_offset, data_offset; /* Save memory map for kernel tasks */ - r = read_header_elf((const char *)MULTIBOOT_KERNEL_ADDR, + r = read_header_elf((char *) MULTIBOOT_KERNEL_ADDR, 4096, /* everything is there */ &text_vaddr, &text_paddr, &text_filebytes, &text_membytes, @@ -401,7 +401,7 @@ static void mb_extract_image(multiboot_info_t mbi) /* Load boot image services into memory and save memory map */ for (i = 0; module < &mb_module_info[mods_count]; ++module, ++i) { - r = read_header_elf((const char *)module->mod_start, + r = read_header_elf((char *) module->mod_start, module->mod_end - module->mod_start + 1, &text_vaddr, &text_paddr, &text_filebytes, &text_membytes, diff --git a/lib/libexec/Makefile b/lib/libexec/Makefile index d1f7b1d34..e02e248f8 100644 --- a/lib/libexec/Makefile +++ b/lib/libexec/Makefile @@ -2,7 +2,7 @@ LIB= exec INCS= libexec.h -SRCS= exec_aout.c exec_elf.c +SRCS= exec_aout.c exec_elf.c exec_general.c .if (${NBSD_LIBC} != "no") INCSDIR= /usr/include diff --git a/lib/libexec/exec_elf.c b/lib/libexec/exec_elf.c index 1f332685f..9bd3073eb 100644 --- a/lib/libexec/exec_elf.c +++ b/lib/libexec/exec_elf.c @@ -2,13 +2,18 @@ #include #include +#include +#include #include +#include #include #include #include #include #include #include +#include +#include /* For verbose logging */ #define ELF_DEBUG 0 @@ -18,9 +23,9 @@ #define SECTOR_SIZE 512 -static int check_header(const Elf_Ehdr *hdr); +static int check_header(Elf_Ehdr *hdr); -static int elf_sane(const Elf_Ehdr *hdr) +static int elf_sane(Elf_Ehdr *hdr) { if (check_header(hdr) != OK) { return 0; @@ -41,7 +46,7 @@ static int elf_sane(const Elf_Ehdr *hdr) return 1; } -static int elf_ph_sane(const Elf_Phdr *phdr) +static int elf_ph_sane(Elf_Phdr *phdr) { if (rounddown((uintptr_t)phdr, sizeof(Elf_Addr)) != (uintptr_t)phdr) { return 0; @@ -49,17 +54,17 @@ static int elf_ph_sane(const Elf_Phdr *phdr) return 1; } -static int elf_unpack(const char *exec_hdr, - int hdr_len, const Elf_Ehdr **hdr, const Elf_Phdr **phdr) +static int elf_unpack(char *exec_hdr, + int hdr_len, Elf_Ehdr **hdr, Elf_Phdr **phdr) { - *hdr = (const Elf_Ehdr *)exec_hdr; + *hdr = (Elf_Ehdr *) exec_hdr; if(!elf_sane(*hdr)) { #if ELF_DEBUG printf("elf_sane failed\n"); #endif return ENOEXEC; } - *phdr = (const Elf_Phdr *)(exec_hdr + (*hdr)->e_phoff); + *phdr = (Elf_Phdr *)(exec_hdr + (*hdr)->e_phoff); if(!elf_ph_sane(*phdr)) { #if ELF_DEBUG printf("elf_ph_sane failed\n"); @@ -73,23 +78,23 @@ static int elf_unpack(const char *exec_hdr, } int read_header_elf( - const char *exec_hdr, /* executable header */ - int hdr_len, /* significant bytes in exec_hdr */ - vir_bytes *text_vaddr, /* text virtual address */ - phys_bytes *text_paddr, /* text physical address */ - vir_bytes *text_filebytes, /* text segment size (in the file) */ - vir_bytes *text_membytes, /* text segment size (in memory) */ - vir_bytes *data_vaddr, /* data virtual address */ - phys_bytes *data_paddr, /* data physical address */ - vir_bytes *data_filebytes, /* data segment size (in the file) */ - vir_bytes *data_membytes, /* data segment size (in memory) */ - vir_bytes *pc, /* program entry point (initial PC) */ - off_t *text_offset, /* file offset to text segment */ - off_t *data_offset /* file offset to data segment */ + char *exec_hdr, /* executable header */ + int hdr_len, /* significant bytes in exec_hdr */ + vir_bytes *text_vaddr, /* text virtual address */ + phys_bytes *text_paddr, /* text physical address */ + vir_bytes *text_filebytes, /* text segment size (in the file) */ + vir_bytes *text_membytes, /* text segment size (in memory) */ + vir_bytes *data_vaddr, /* data virtual address */ + phys_bytes *data_paddr, /* data physical address */ + vir_bytes *data_filebytes, /* data segment size (in the file) */ + vir_bytes *data_membytes, /* data segment size (in memory) */ + vir_bytes *pc, /* program entry point (initial PC) */ + off_t *text_offset, /* file offset to text segment */ + off_t *data_offset /* file offset to data segment */ ) { - const Elf_Ehdr *hdr = NULL; - const Elf_Phdr *phdr = NULL; + Elf_Ehdr *hdr = NULL; + Elf_Phdr *phdr = NULL; unsigned long seg_filebytes, seg_membytes; int e, i = 0; @@ -101,9 +106,9 @@ int read_header_elf( if((e=elf_unpack(exec_hdr, hdr_len, &hdr, &phdr)) != OK) { #if ELF_DEBUG - printf("elf_unpack failed\n"); + printf("elf_unpack failed\n"); #endif - return e; + return e; } #if ELF_DEBUG @@ -120,30 +125,30 @@ int read_header_elf( for (i = 0; i < hdr->e_phnum; i++) { switch (phdr[i].p_type) { case PT_LOAD: - if (phdr[i].p_memsz == 0) - break; - seg_filebytes = phdr[i].p_filesz; - seg_membytes = round_page(phdr[i].p_memsz + phdr[i].p_vaddr - - trunc_page(phdr[i].p_vaddr)); - - if (hdr->e_entry >= phdr[i].p_vaddr && - hdr->e_entry < (phdr[i].p_vaddr + phdr[i].p_memsz)) { - *text_vaddr = phdr[i].p_vaddr; - *text_paddr = phdr[i].p_paddr; - *text_filebytes = seg_filebytes; - *text_membytes = seg_membytes; - *pc = (vir_bytes)hdr->e_entry; - *text_offset = phdr[i].p_offset; - } else { - *data_vaddr = phdr[i].p_vaddr; - *data_paddr = phdr[i].p_paddr; - *data_filebytes = seg_filebytes; - *data_membytes = seg_membytes; - *data_offset = phdr[i].p_offset; - } - break; + if (phdr[i].p_memsz == 0) + break; + seg_filebytes = phdr[i].p_filesz; + seg_membytes = round_page(phdr[i].p_memsz + phdr[i].p_vaddr - + trunc_page(phdr[i].p_vaddr)); + + if (hdr->e_entry >= phdr[i].p_vaddr && + hdr->e_entry < (phdr[i].p_vaddr + phdr[i].p_memsz)) { + *text_vaddr = phdr[i].p_vaddr; + *text_paddr = phdr[i].p_paddr; + *text_filebytes = seg_filebytes; + *text_membytes = seg_membytes; + *pc = (vir_bytes)hdr->e_entry; + *text_offset = phdr[i].p_offset; + } else { + *data_vaddr = phdr[i].p_vaddr; + *data_paddr = phdr[i].p_paddr; + *data_filebytes = seg_filebytes; + *data_membytes = seg_membytes; + *data_offset = phdr[i].p_offset; + } + break; default: - break; + break; } } @@ -169,7 +174,7 @@ int read_header_elf( (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ (ehdr).e_ident[EI_MAG3] == ELFMAG3) -static int check_header(const Elf_Ehdr *hdr) +static int check_header(Elf_Ehdr *hdr) { if (!IS_ELF(*hdr) || hdr->e_ident[EI_DATA] != ELF_TARG_DATA || @@ -181,46 +186,16 @@ static int check_header(const Elf_Ehdr *hdr) return OK; } -int elf_phdr(const char *exec_hdr, int hdr_len, vir_bytes *ret_phdr) -{ - const Elf_Ehdr *hdr = NULL; - const Elf_Phdr *phdr = NULL; - int e, i, have_computed_phdr = 1; - - if((e=elf_unpack(exec_hdr, hdr_len, &hdr, &phdr)) != OK) return e; - - for (i = 0; i < hdr->e_phnum; i++) { - switch (phdr[i].p_type) { - case PT_LOAD: - /* compute phdr based on this heuristic, to be used - * if there is no PT_PHDR - */ - if(phdr[i].p_offset == 0) { - *ret_phdr = phdr[i].p_vaddr + hdr->e_phoff; - have_computed_phdr = 1; - } - break; - case PT_PHDR: - *ret_phdr = phdr[i].p_vaddr; - return OK; - default: - break;; - } - } - if(have_computed_phdr) return OK; - return ENOENT; -} - /* Return >0 if there is an ELF interpreter (i.e. it is a dynamically linked * executable) and we could extract it successfully. * Return 0 if there isn't one. * Return <0 on error. */ -int elf_has_interpreter(const char *exec_hdr, /* executable header */ +int elf_has_interpreter(char *exec_hdr, /* executable header */ int hdr_len, char *interp, int maxsz) { - const Elf_Ehdr *hdr = NULL; - const Elf_Phdr *phdr = NULL; + Elf_Ehdr *hdr = NULL; + Elf_Phdr *phdr = NULL; int e, i; if((e=elf_unpack(exec_hdr, hdr_len, &hdr, &phdr)) != OK) return e; @@ -243,3 +218,95 @@ int elf_has_interpreter(const char *exec_hdr, /* executable header */ return 0; } +int libexec_load_elf(struct exec_info *execi) +{ + int r; + Elf_Ehdr *hdr = NULL; + Elf_Phdr *phdr = NULL; + int e, i = 0; + int first = 1; + vir_bytes startv, stacklow; + + assert(execi != NULL); + assert(execi->hdr != NULL); + + if((e=elf_unpack(execi->hdr, execi->hdr_len, &hdr, &phdr)) != OK) { + printf("libexec_load_elf: elf_unpack failed\n"); + return e; + } + + /* this function can load the dynamic linker, but that + * shouldn't require an interpreter itself. + */ + i = elf_has_interpreter(execi->hdr, execi->hdr_len, NULL, 0); + if(i > 0) { + printf("libexec: cannot load dynamically linked executable\n"); + return ENOEXEC; + } + + /* Make VM forget about all existing memory in process. */ + vm_procctl(execi->proc_e, VMPPARAM_CLEAR); + + execi->stack_size = roundup(execi->stack_size, PAGE_SIZE); + execi->stack_high = VM_STACKTOP; + assert(!(VM_STACKTOP % PAGE_SIZE)); + stacklow = execi->stack_high - execi->stack_size; + + for (i = 0; i < hdr->e_phnum; i++) { + vir_bytes seg_membytes, page_offset, vaddr; + Elf_Phdr *ph = &phdr[i]; + if (ph->p_type != PT_LOAD || ph->p_memsz == 0) continue; +#if 0 + printf("index %d memsz 0x%lx vaddr 0x%lx\n", i, ph->p_memsz, ph->p_vaddr); +#endif + vaddr = ph->p_vaddr; + seg_membytes = ph->p_memsz; + page_offset = vaddr % PAGE_SIZE; + vaddr -= page_offset; + seg_membytes += page_offset; + seg_membytes = roundup(seg_membytes, PAGE_SIZE); + if(first || startv > vaddr) startv = vaddr; + first = 0; + +#if 0 + printf("libexec_load_elf: mmap 0x%lx bytes at 0x%lx\n", + seg_membytes, vaddr); +#endif + + /* Tell VM to make us some memory */ + if(minix_mmap_for(execi->proc_e, (void *) vaddr, seg_membytes, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_ANON|MAP_PREALLOC|MAP_FIXED, -1, 0) == MAP_FAILED) { + printf("libexec_load_elf: mmap of 0x%lx bytes failed\n", seg_membytes); + vm_procctl(execi->proc_e, VMPPARAM_CLEAR); + return ENOMEM; + } + + /* Copy executable section into it */ + if(execi->load(execi, ph->p_offset, ph->p_vaddr, ph->p_filesz) != OK) { + printf("libexec_load_elf: load callback failed\n"); + vm_procctl(execi->proc_e, VMPPARAM_CLEAR); + return ENOMEM; + } + } + + /* Make it a stack */ + if(minix_mmap_for(execi->proc_e, (void *) stacklow, execi->stack_size, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_ANON|MAP_FIXED, -1, 0) == MAP_FAILED) { + printf("libexec_load_elf: mmap for stack failed\n"); + vm_procctl(execi->proc_e, VMPPARAM_CLEAR); + return ENOMEM; + } + + /* record entry point and lowest load vaddr for caller */ + execi->pc = hdr->e_entry; + execi->load_base = startv; + + if((r = libexec_pm_newexec(execi->proc_e, execi)) != OK) { + printf("libexec_load_elf: pm_newexec failed: %d\n", r); + } + + return(r); +} + diff --git a/lib/libexec/exec_general.c b/lib/libexec/exec_general.c new file mode 100644 index 000000000..4e5501584 --- /dev/null +++ b/lib/libexec/exec_general.c @@ -0,0 +1,57 @@ +#define _SYSTEM 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void libexec_patch_ptr(char stack[ARG_MAX], vir_bytes base) +{ +/* When doing an exec(name, argv, envp) call, the user builds up a stack + * image with arg and env pointers relative to the start of the stack. Now + * these pointers must be relocated, since the stack is not positioned at + * address 0 in the user's address space. + */ + + char **ap, flag; + vir_bytes v; + + flag = 0; /* counts number of 0-pointers seen */ + ap = (char **) stack; /* points initially to 'nargs' */ + ap++; /* now points to argv[0] */ + while (flag < 2) { + if (ap >= (char **) &stack[ARG_MAX]) return; /* too bad */ + if (*ap != NULL) { + v = (vir_bytes) *ap; /* v is relative pointer */ + v += base; /* relocate it */ + *ap = (char *) v; /* put it back */ + } else { + flag++; + } + ap++; + } +} + +int libexec_pm_newexec(endpoint_t proc_e, struct exec_info *e) +{ + int r; + message m; + + m.m_type = PM_NEWEXEC; + m.EXC_NM_PROC = proc_e; + m.EXC_NM_PTR = (char *)e; + if ((r = sendrec(PM_PROC_NR, &m)) != OK) return(r); + + e->allow_setuid = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); + + return(m.m_type); +} diff --git a/lib/libexec/libexec.h b/lib/libexec/libexec.h index decd9447b..282dc4e4c 100644 --- a/lib/libexec/libexec.h +++ b/lib/libexec/libexec.h @@ -3,15 +3,49 @@ #include -/* ELF routines */ -int read_header_elf(const char *exec_hdr, int hdr_len, +struct exec_info; + +typedef int (*libexec_loadfunc_t)(struct exec_info *execi, + off_t offset, off_t vaddr, size_t len); + +typedef int (*libexec_clearfunc_t)(struct exec_info *execi, + off_t vaddr, size_t len); + +struct exec_info { + /* Filled in by libexec caller */ + endpoint_t proc_e; /* Process endpoint */ + char *hdr; /* Header or full image */ + size_t hdr_len; /* Size of hdr */ + vir_bytes frame_len; /* Stack size */ + char progname[PROC_NAME_LEN]; /* Program name */ + uid_t new_uid; /* Process UID after exec */ + gid_t new_gid; /* Process GID after exec */ + int allow_setuid; /* Allow set{u,g}id execution? */ + libexec_loadfunc_t load; /* Load callback */ + libexec_clearfunc_t clear; /* Clear callback */ + void *opaque; /* Callback data */ + vir_bytes stack_size; /* Desired stack size */ + + /* Filled in by libexec load function */ + vir_bytes load_base; /* Where executable is loaded */ + vir_bytes pc; /* Entry point of exec file */ + vir_bytes stack_high; /* High stack addr */ +}; + +int elf_has_interpreter(char *exec_hdr, int hdr_len, char *interp, int maxsz); +int elf_phdr(char *exec_hdr, int hdr_len, vir_bytes *phdr); +int read_header_elf(char *exec_hdr, int hdr_len, vir_bytes *text_vaddr, phys_bytes *text_paddr, vir_bytes *text_filebytes, vir_bytes *text_membytes, vir_bytes *data_vaddr, phys_bytes *data_paddr, vir_bytes *data_filebytes, vir_bytes *data_membytes, vir_bytes *pc, off_t *text_offset, off_t *data_offset); -int elf_has_interpreter(const char *exec_hdr, int hdr_len, char *interp, int maxsz); -int elf_phdr(const char *exec_hdr, int hdr_len, vir_bytes *phdr); +void libexec_patch_ptr(char stack[ARG_MAX], vir_bytes base); +int libexec_pm_newexec(endpoint_t proc_e, struct exec_info *execi); + +typedef int (*libexec_exec_loadfunc_t)(struct exec_info *execi); + +int libexec_load_elf(struct exec_info *execi); #endif /* !_LIBEXEC_H_ */ diff --git a/lib/libminc/Makefile b/lib/libminc/Makefile index 2f2cf43fe..0c2fd3316 100644 --- a/lib/libminc/Makefile +++ b/lib/libminc/Makefile @@ -130,7 +130,7 @@ CPPFLAGS.${i}+= -I${LIBCSRCDIR}/include -I${LIBCSRCDIR}/locale link.c _mcontext.c mknod.c mmap.c nanosleep.c open.c \ read.c sbrk.c select.c setuid.c sigprocmask.c stat.c \ stime.c syscall.c _ucontext.c umask.c unlink.c waitpid.c \ - brksize.S _ipc.S _senda.S ucontext.S + brksize.S _ipc.S _senda.S ucontext.S mmap.c .PATH.c: ${LIBCSRCDIR}/sys-minix .PATH.S: ${LIBCSRCDIR}/arch/${MACHINE}/sys-minix SRCS+= ${i} diff --git a/lib/libsys/Makefile b/lib/libsys/Makefile index 19f1f11fd..07e40425b 100644 --- a/lib/libsys/Makefile +++ b/lib/libsys/Makefile @@ -118,7 +118,6 @@ SRCS= \ vbox.c \ vm_brk.c \ vm_dmacalls.c \ - vm_exec_newmem.c \ vm_exit.c \ vm_fork.c \ vm_info.c \ diff --git a/lib/libsys/vm_exec_newmem.c b/lib/libsys/vm_exec_newmem.c deleted file mode 100644 index 82d69e897..000000000 --- a/lib/libsys/vm_exec_newmem.c +++ /dev/null @@ -1,26 +0,0 @@ - -#include "syslib.h" - -#include - -/*===========================================================================* - * vm_exec_newmem * - *===========================================================================*/ -int vm_exec_newmem(endpoint_t ep, struct exec_newmem *args, - int argssize, char **ret_stack_top, int *ret_flags) -{ - message m; - int result; - - m.VMEN_ENDPOINT = ep; - m.VMEN_ARGSPTR = (void *) args; - m.VMEN_ARGSSIZE = argssize; - - result = _taskcall(VM_PROC_NR, VM_EXEC_NEWMEM, &m); - - *ret_stack_top = m.VMEN_STACK_TOP; - *ret_flags = m.VMEN_FLAGS; - - return result; -} - diff --git a/lib/libsys/vm_procctl.c b/lib/libsys/vm_procctl.c index a3081683c..dad82b9ce 100644 --- a/lib/libsys/vm_procctl.c +++ b/lib/libsys/vm_procctl.c @@ -20,3 +20,4 @@ int vm_procctl(endpoint_t ep, int param) result = _taskcall(VM_PROC_NR, VM_PROCCTL, &m); return(result); } + diff --git a/servers/pm/exec.c b/servers/pm/exec.c index 785b544e5..c29b5ec26 100644 --- a/servers/pm/exec.c +++ b/servers/pm/exec.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "mproc.h" #include "param.h" @@ -46,7 +47,7 @@ int do_exec() m.PM_PATH = m_in.exec_name; m.PM_PATH_LEN = m_in.exec_len; m.PM_FRAME = m_in.frame_ptr; - m.PM_FRAME_LEN = m_in.frame_len; + m.PM_FRAME_LEN = m_in.msg_frame_len; m.PM_EXECFLAGS = m_in.PMEXEC_FLAGS; tell_vfs(mp, &m); @@ -57,16 +58,15 @@ int do_exec() /*===========================================================================* - * do_exec_newmem * + * do_newexec * *===========================================================================*/ -int do_exec_newmem() +int do_newexec() { int proc_e, proc_n, allow_setuid; char *ptr; struct mproc *rmp; - struct exec_newmem args; + struct exec_info args; int r, flags; - char *stack_top; if (who_e != VFS_PROC_NR && who_e != RS_PROC_NR) return EPERM; @@ -82,50 +82,46 @@ int do_exec_newmem() if (r != OK) panic("do_exec_newmem: sys_datacopy failed: %d", r); - if ((r = vm_exec_newmem(proc_e, &args, sizeof(args), &stack_top, - &flags)) == OK) { - allow_setuid = 0; /* Do not allow setuid execution */ - rmp->mp_flags &= ~TAINTED; /* By default not tainted */ + allow_setuid = 0; /* Do not allow setuid execution */ + rmp->mp_flags &= ~TAINTED; /* By default not tainted */ - if (rmp->mp_tracer == NO_TRACER) { - /* Okay, setuid execution is allowed */ - allow_setuid = 1; - } + if (rmp->mp_tracer == NO_TRACER) { + /* Okay, setuid execution is allowed */ + allow_setuid = 1; + } - if (allow_setuid && args.setugid) { - rmp->mp_effuid = args.new_uid; - rmp->mp_effgid = args.new_gid; - } + if (allow_setuid && args.allow_setuid) { + rmp->mp_effuid = args.new_uid; + rmp->mp_effgid = args.new_gid; + } - /* A process is considered 'tainted' when it's executing with - * setuid or setgid bit set, or when the real{u,g}id doesn't - * match the eff{u,g}id, respectively. */ - if (allow_setuid && args.setugid) { - /* Program has setuid and/or setgid bits set */ - rmp->mp_flags |= TAINTED; - } else if (rmp->mp_effuid != rmp->mp_realuid || - rmp->mp_effgid != rmp->mp_realgid) { - rmp->mp_flags |= TAINTED; - } + /* A process is considered 'tainted' when it's executing with + * setuid or setgid bit set, or when the real{u,g}id doesn't + * match the eff{u,g}id, respectively. */ + if (allow_setuid && args.allow_setuid) { + /* Program has setuid and/or setgid bits set */ + rmp->mp_flags |= TAINTED; + } else if (rmp->mp_effuid != rmp->mp_realuid || + rmp->mp_effgid != rmp->mp_realgid) { + rmp->mp_flags |= TAINTED; + } - /* System will save command line for debugging, ps(1) output, etc. */ - strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1); - rmp->mp_name[PROC_NAME_LEN-1] = '\0'; + /* System will save command line for debugging, ps(1) output, etc. */ + strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1); + rmp->mp_name[PROC_NAME_LEN-1] = '\0'; - /* Save offset to initial argc (for procfs) */ - rmp->mp_frame_addr = (vir_bytes) stack_top - args.args_bytes; - rmp->mp_frame_len = args.args_bytes; + /* Save offset to initial argc (for procfs) */ + rmp->mp_frame_addr = (vir_bytes) args.stack_high - args.frame_len; + rmp->mp_frame_len = args.frame_len; - /* Kill process if something goes wrong after this point. */ - rmp->mp_flags |= PARTIAL_EXEC; + /* Kill process if something goes wrong after this point. */ + rmp->mp_flags |= PARTIAL_EXEC; + + mp->mp_reply.reply_res2= (vir_bytes) rmp->mp_frame_addr; + mp->mp_reply.reply_res3= flags; + if (allow_setuid && args.allow_setuid) + mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID; - mp->mp_reply.reply_res2= (vir_bytes) stack_top; - mp->mp_reply.reply_res3= flags; - if (allow_setuid && args.setugid) - mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID; - } else { - printf("PM: newmem failed for %s\n", args.progname); - } return r; } diff --git a/servers/pm/param.h b/servers/pm/param.h index 4c2863306..a4a2d9742 100644 --- a/servers/pm/param.h +++ b/servers/pm/param.h @@ -12,7 +12,7 @@ #define new_val m1_p1 #define old_val m1_p2 #define sig m6_i1 -#define frame_len m1_i2 +#define msg_frame_len m1_i2 #define frame_ptr m1_p2 #define status m1_i1 #define usr_id m1_i1 diff --git a/servers/pm/proto.h b/servers/pm/proto.h index 76148ae97..00646d3ed 100644 --- a/servers/pm/proto.h +++ b/servers/pm/proto.h @@ -18,7 +18,7 @@ int do_brk(void); /* exec.c */ int do_exec(void); -int do_exec_newmem(void); +int do_newexec(void); int do_execrestart(void); void exec_restart(struct mproc *rmp, int result, vir_bytes pc, vir_bytes sp); diff --git a/servers/pm/table.c b/servers/pm/table.c index 203b02f79..5051cec7d 100644 --- a/servers/pm/table.c +++ b/servers/pm/table.c @@ -111,7 +111,7 @@ int (*call_vec[])(void) = { no_sys, /* 97 = unused */ do_sprofile, /* 98 = sprofile */ do_cprofile, /* 99 = cprofile */ - do_exec_newmem, /* 100 = exec_newmem */ + do_newexec, /* 100 = newexec */ do_srv_fork, /* 101 = srv_fork */ do_execrestart, /* 102 = exec_restart */ no_sys, /* 103 = unused */ diff --git a/servers/rs/exec.c b/servers/rs/exec.c index e0faa0b3e..3eaad4ec7 100644 --- a/servers/rs/exec.c +++ b/servers/rs/exec.c @@ -2,30 +2,19 @@ #include #include #include -#include "exec.h" - -#define BLOCK_SIZE 1024 +#include static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, char *frame, int frame_len); -static int exec_newmem(int proc_e, vir_bytes text_addr, - vir_bytes text_bytes, vir_bytes data_addr, - vir_bytes data_bytes, vir_bytes tot_bytes, - vir_bytes frame_len, int sep_id, int is_elf, - dev_t st_dev, ino_t st_ino, time_t ctime, char *progname, - int new_uid, int new_gid, vir_bytes *stack_topp, - int *load_textp, int *allow_setuidp); -static void patch_ptr(char stack[ARG_MAX], vir_bytes base); static int exec_restart(int proc_e, int result, vir_bytes pc); static int read_seg(struct exec_info *execi, off_t off, - int proc_e, int seg, vir_bytes seg_addr, phys_bytes seg_bytes); -static int load_elf(struct exec_info *execi); + off_t seg_addr, size_t seg_bytes); /* Array of loaders for different object formats */ static struct exec_loaders { - int (*load_object)(struct exec_info *); + libexec_exec_loadfunc_t load_object; } const exec_loaders[] = { - { load_elf }, + { libexec_load_elf }, { NULL } }; @@ -128,12 +117,16 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, struct exec_info execi; int i; + memset(&execi, 0, sizeof(execi)); + + execi.stack_size = DEFAULT_STACK_LIMIT; execi.proc_e = proc_e; - execi.image = exec; - execi.image_len = exec_len; + execi.hdr = exec; + execi.hdr_len = exec_len; strncpy(execi.progname, progname, PROC_NAME_LEN-1); execi.progname[PROC_NAME_LEN-1] = '\0'; execi.frame_len = frame_len; + execi.load = read_seg; for(i = 0; exec_loaders[i].load_object != NULL; i++) { r = (*exec_loaders[i].load_object)(&execi); @@ -148,14 +141,12 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, } /* Patch up stack and copy it from RS to new core image. */ - vsp = execi.stack_top; + vsp = execi.stack_high; vsp -= frame_len; - patch_ptr(frame, vsp); + libexec_patch_ptr(frame, vsp); r = sys_datacopy(SELF, (vir_bytes) frame, proc_e, (vir_bytes) vsp, (phys_bytes)frame_len); if (r != OK) { - printf("RS: stack_top is 0x%lx; tried to copy to 0x%lx in %d\n", - execi.stack_top, vsp, proc_e); printf("do_exec: copying out new stack failed: %d\n", r); exec_restart(proc_e, r, execi.pc); return r; @@ -164,149 +155,6 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, return exec_restart(proc_e, OK, execi.pc); } -static int load_elf(struct exec_info *execi) -{ - int r; - int proc_e; - phys_bytes tot_bytes; /* total space for program, including gap */ - vir_bytes text_vaddr, text_paddr, text_filebytes, text_membytes; - vir_bytes data_vaddr, data_paddr, data_filebytes, data_membytes; - off_t text_offset, data_offset; - int sep_id, is_elf, load_text, allow_setuid; - uid_t new_uid; - gid_t new_gid; - - assert(execi != NULL); - assert(execi->image != NULL); - - proc_e = execi->proc_e; - - /* Read the file header and extract the segment sizes. */ - r = read_header_elf(execi->image, execi->image_len, &text_vaddr, &text_paddr, - &text_filebytes, &text_membytes, - &data_vaddr, &data_paddr, - &data_filebytes, &data_membytes, - &execi->pc, &text_offset, &data_offset); - if (r != OK) { - return(r); - } - - if(elf_has_interpreter(execi->image, execi->image_len, NULL, 0)) { - printf("RS: can't execute dynamically linked executables\n"); - return ENOEXEC; - } - - new_uid= getuid(); - new_gid= getgid(); - allow_setuid = 0; - - sep_id = 0; - is_elf = 1; - tot_bytes = 0; /* Use default stack size */ - - r = exec_newmem(proc_e, - trunc_page(text_vaddr), text_membytes, - trunc_page(data_vaddr), data_membytes, - tot_bytes, execi->frame_len, sep_id, is_elf, - 0 /*dev*/, proc_e /*inum*/, 0 /*ctime*/, - execi->progname, new_uid, new_gid, - &execi->stack_top, &load_text, &allow_setuid); - if (r != OK) - { - printf("RS: load_elf: exec_newmem failed: %d\n", r); - exec_restart(proc_e, r, execi->pc); - return r; - } - - /* Read in text and data segments. */ - if (load_text) { - r = read_seg(execi, text_offset, proc_e, T, text_vaddr, text_filebytes); - if (r != OK) - { - printf("RS: load_elf: read_seg failed: %d\n", r); - exec_restart(proc_e, r, execi->pc); - return r; - } - } - else - printf("RS: load_elf: not loading text segment\n"); - - r = read_seg(execi, data_offset, proc_e, D, data_vaddr, data_filebytes); - if (r != OK) - { - printf("RS: load_elf: read_seg failed: %d\n", r); - exec_restart(proc_e, r, execi->pc); - return r; - } - - return(OK); -} - -/*===========================================================================* - * exec_newmem * - *===========================================================================*/ -static int exec_newmem( - int proc_e, - vir_bytes text_addr, - vir_bytes text_bytes, - vir_bytes data_addr, - vir_bytes data_bytes, - vir_bytes tot_bytes, - vir_bytes frame_len, - int sep_id, - int is_elf, - dev_t st_dev, - ino_t st_ino, - time_t ctime, - char *progname, - int new_uid, - int new_gid, - vir_bytes *stack_topp, - int *load_textp, - int *allow_setuidp -) -{ - int r; - struct exec_newmem e; - message m; - - e.text_addr = text_addr; - e.text_bytes= text_bytes; - e.data_addr = data_addr; - e.data_bytes= data_bytes; - e.tot_bytes= tot_bytes; - e.args_bytes= frame_len; - e.sep_id= sep_id; - e.is_elf= is_elf; - e.st_dev= st_dev; - e.st_ino= st_ino; - e.enst_ctime= ctime; - e.new_uid= new_uid; - e.new_gid= new_gid; - e.setugid= *allow_setuidp; - strncpy(e.progname, progname, sizeof(e.progname)-1); - e.progname[sizeof(e.progname)-1]= '\0'; - - m.m_type= EXEC_NEWMEM; - m.EXC_NM_PROC= proc_e; - m.EXC_NM_PTR= (char *)&e; - r= sendrec(PM_PROC_NR, &m); - if (r != OK) - return r; -#if 0 - printf("exec_newmem: r = %d, m_type = %d\n", r, m.m_type); -#endif - *stack_topp= m.m1_i1; - *load_textp= !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT); - *allow_setuidp= !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); -#if 0 - printf("RS: exec_newmem: stack_top = 0x%x\n", *stack_topp); - printf("RS: exec_newmem: load_text = %d\n", *load_textp); -#endif - return m.m_type; -} - - /*===========================================================================* * exec_restart * *===========================================================================*/ @@ -326,48 +174,13 @@ static int exec_restart(int proc_e, int result, vir_bytes pc) } /*===========================================================================* - * patch_ptr * - *===========================================================================*/ -static void patch_ptr( -char stack[ARG_MAX], /* pointer to stack image within PM */ -vir_bytes base /* virtual address of stack base inside user */ -) -{ -/* When doing an exec(name, argv, envp) call, the user builds up a stack - * image with arg and env pointers relative to the start of the stack. Now - * these pointers must be relocated, since the stack is not positioned at - * address 0 in the user's address space. - */ - - char **ap, flag; - vir_bytes v; - - flag = 0; /* counts number of 0-pointers seen */ - ap = (char **) stack; /* points initially to 'nargs' */ - ap++; /* now points to argv[0] */ - while (flag < 2) { - if (ap >= (char **) &stack[ARG_MAX]) return; /* too bad */ - if (*ap != NULL) { - v = (vir_bytes) *ap; /* v is relative pointer */ - v += base; /* relocate it */ - *ap = (char *) v; /* put it back */ - } else { - flag++; - } - ap++; - } -} - -/*===========================================================================* - * read_seg * + * read_seg * *===========================================================================*/ static int read_seg( -struct exec_info *execi, /* various data needed for exec */ -off_t off, /* offset in file */ -int proc_e, /* process number (endpoint) */ -int seg, /* T, D, or S */ -vir_bytes seg_addr, /* address to load segment */ -phys_bytes seg_bytes /* how much is to be transferred? */ +struct exec_info *execi, /* various data needed for exec */ +off_t off, /* offset in file */ +off_t seg_addr, /* address to load segment */ +size_t seg_bytes /* how much is to be transferred? */ ) { /* @@ -378,9 +191,11 @@ phys_bytes seg_bytes /* how much is to be transferred? */ int r; - assert((seg == T)||(seg == D)); - - if (off+seg_bytes > execi->image_len) return ENOEXEC; - r= sys_vircopy(SELF, D, ((vir_bytes)execi->image)+off, proc_e, seg, seg_addr, seg_bytes); + if (off+seg_bytes > execi->hdr_len) return ENOEXEC; + if((r= sys_vircopy(SELF, D, ((vir_bytes)execi->hdr)+off, + execi->proc_e, D, seg_addr, seg_bytes)) != OK) { + printf("RS: exec read_seg: copy 0x%lx bytes into %d at 0x%lx failed: %d\n", + seg_bytes, execi->proc_e, seg_addr, r); + } return r; } diff --git a/servers/rs/exec.h b/servers/rs/exec.h deleted file mode 100644 index a395a5519..000000000 --- a/servers/rs/exec.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _RS_EXEC_H_ -#define _RS_EXEC_H_ 1 - -struct exec_info { - int proc_e; /* Process endpoint */ - char *image; /* Executable image */ - size_t image_len; /* Size of executable image */ - vir_bytes pc; /* Entry point of exec file */ - vir_bytes stack_top; /* Top of the stack */ - vir_bytes frame_len; /* Stack size */ - char progname[PROC_NAME_LEN]; /* Program name */ -}; - -#endif /* !_RS_EXEC_H_ */ diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index 6d2a01df6..9a363e224 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -34,45 +34,48 @@ #include #include #include -#include "exec.h" #define _KERNEL /* for ELF_AUX_ENTRIES */ #include +/* fields only used by elf and in VFS */ +struct vfs_exec_info { + struct exec_info args; /* libexec exec args */ + struct vnode *vp; /* Exec file's vnode */ + struct vmnt *vmp; /* Exec file's vmnt */ + struct stat sb; /* Exec file's stat structure */ + int userflags; /* exec() flags from userland */ + int is_dyn; /* Dynamically linked executable */ + int elf_main_fd; /* Dyn: FD of main program execuatble */ + char execname[PATH_MAX]; /* Full executable invocation */ +}; + static void lock_exec(void); static void unlock_exec(void); -static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes, - vir_bytes data_addr, vir_bytes data_bytes, vir_bytes tot_bytes, - vir_bytes frame_len, int sep_id, int is_elf, dev_t st_dev, - ino_t st_ino, time_t ctime, char *progname, int new_uid, int new_gid, - vir_bytes *stack_topp, int *load_textp, int *setugidp); static int patch_stack(struct vnode *vp, char stack[ARG_MAX], size_t *stk_bytes, char path[PATH_MAX]); -static int is_script(struct exec_info *execi); +static int is_script(struct vfs_exec_info *execi); static int insert_arg(char stack[ARG_MAX], size_t *stk_bytes, char *arg, int replace); -static void patch_ptr(char stack[ARG_MAX], vir_bytes base); static void clo_exec(struct fproc *rfp); -static int read_seg(struct vnode *vp, off_t off, int proc_e, int seg, - vir_bytes seg_addr, phys_bytes seg_bytes); -static int load_elf(struct exec_info *execi); -static int stack_prepare_elf(struct exec_info *execi, +static int stack_prepare_elf(struct vfs_exec_info *execi, char *curstack, size_t *frame_len, vir_bytes *vsp, int *extrabase); -static int map_header(struct exec_info *execi); +static int map_header(struct vfs_exec_info *execi); +static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t seg_bytes); #define PTRSIZE sizeof(char *) /* Size of pointers in argv[] and envp[]. */ /* Array of loaders for different object file formats */ -typedef int (*exechook_t)(struct exec_info *execpackage); -typedef int (*stackhook_t)(struct exec_info *execi, char *curstack, +typedef int (*exechook_t)(struct vfs_exec_info *execpackage); +typedef int (*stackhook_t)(struct vfs_exec_info *execi, char *curstack, size_t *frame_len, vir_bytes *, int *extrabase); struct exec_loaders { - exechook_t load_object; /* load executable into memory */ + libexec_exec_loadfunc_t load_object; /* load executable into memory */ stackhook_t setup_stack; /* prepare stack before argc and argv push */ }; static const struct exec_loaders exec_loaders[] = { - { load_elf, stack_prepare_elf }, + { libexec_load_elf, stack_prepare_elf }, { NULL, NULL } }; @@ -110,8 +113,8 @@ static void unlock_exec(void) /*===========================================================================* * get_read_vp * *===========================================================================*/ -static int get_read_vp(struct exec_info *execi, char *fullpath, - int copyprogname, int sugid, struct lookup *resolve, struct fproc *fp) +static int get_read_vp(struct vfs_exec_info *execi, + char *fullpath, int copyprogname, int sugid, struct lookup *resolve, struct fproc *fp) { /* Make the executable that we want to exec() into the binary pointed * to by 'fullpath.' This function fills in necessary details in the execi @@ -137,8 +140,8 @@ static int get_read_vp(struct exec_info *execi, char *fullpath, char *cp = strrchr(fullpath, '/'); if(cp) cp++; else cp = fullpath; - strncpy(execi->progname, cp, sizeof(execi->progname)-1); - execi->progname[sizeof(execi->progname)-1] = '\0'; + strncpy(execi->args.progname, cp, sizeof(execi->args.progname)-1); + execi->args.progname[sizeof(execi->args.progname)-1] = '\0'; } /* Open executable */ @@ -161,12 +164,12 @@ static int get_read_vp(struct exec_info *execi, char *fullpath, if (sugid) { /* Deal with setuid/setgid executables */ if (execi->vp->v_mode & I_SET_UID_BIT) { - execi->new_uid = execi->vp->v_uid; - execi->setugid = 1; + execi->args.new_uid = execi->vp->v_uid; + execi->args.allow_setuid = 1; } if (execi->vp->v_mode & I_SET_GID_BIT) { - execi->new_gid = execi->vp->v_gid; - execi->setugid = 1; + execi->args.new_gid = execi->vp->v_gid; + execi->args.allow_setuid = 1; } } @@ -198,7 +201,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, struct fproc *rfp; int extrabase = 0; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ - struct exec_info execi; + struct vfs_exec_info execi; int i; static char fullpath[PATH_MAX], elf_interpreter[PATH_MAX], @@ -213,6 +216,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, /* passed from exec() libc code */ execi.userflags = user_exec_flags; + execi.args.stack_size = DEFAULT_STACK_LIMIT; okendpt(proc_e, &slot); rfp = fp = &fproc[slot]; @@ -233,8 +237,8 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, } /* The default is to keep the original user and group IDs */ - execi.new_uid = rfp->fp_effuid; - execi.new_gid = rfp->fp_effgid; + execi.args.new_uid = rfp->fp_effuid; + execi.args.new_gid = rfp->fp_effgid; /* Get the exec file name. */ FAILCHECK(fetch_name(path, path_len, fullpath)); @@ -267,7 +271,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, * executable instead. But open the current executable in an * fd for the current process. */ - if(elf_has_interpreter(execi.hdr, execi.hdr_len, + if(elf_has_interpreter(execi.args.hdr, execi.args.hdr_len, elf_interpreter, sizeof(elf_interpreter))) { /* Switch the executable vnode to the interpreter */ execi.is_dyn = 1; @@ -292,11 +296,14 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, Get_read_vp(execi, fullpath, 0, 0, &resolve, fp); } - execi.proc_e = proc_e; - execi.frame_len = frame_len; + execi.args.opaque = &execi; + execi.args.load = &read_seg; + execi.args.clear = NULL; + execi.args.proc_e = proc_e; + execi.args.frame_len = frame_len; for (i = 0; exec_loaders[i].load_object != NULL; i++) { - r = (*exec_loaders[i].load_object)(&execi); + r = (*exec_loaders[i].load_object)(&execi.args); /* Loaded successfully, so no need to try other loaders */ if (r == OK) { makestack = exec_loaders[i].setup_stack; break; } } @@ -304,31 +311,31 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, FAILCHECK(r); /* Save off PC */ - *pc = execi.pc; + *pc = execi.args.pc; /* call a stack-setup function if this executable type wants it */ - vsp = execi.stack_top - frame_len; + vsp = execi.args.stack_high - frame_len; if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp, &extrabase)); /* Patch up stack and copy it from VFS to new core image. */ - patch_ptr(mbuf, vsp + extrabase); + libexec_patch_ptr(mbuf, vsp + extrabase); FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp, (phys_bytes)frame_len)); - + /* Return new stack pointer to caller */ *newsp = vsp; clo_exec(rfp); - if (execi.setugid) { + if (execi.args.allow_setuid) { /* If after loading the image we're still allowed to run with * setuid or setgid, change credentials now */ - rfp->fp_effuid = execi.new_uid; - rfp->fp_effgid = execi.new_gid; + rfp->fp_effuid = execi.args.new_uid; + rfp->fp_effgid = execi.args.new_gid; } /* Remember the new name of the process */ - strcpy(rfp->fp_name, execi.progname); + strcpy(rfp->fp_name, execi.args.progname); pm_execfinal: if (execi.vp != NULL) { @@ -339,7 +346,7 @@ pm_execfinal: return(r); } -static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *framelen, +static int stack_prepare_elf(struct vfs_exec_info *execi, char *frame, size_t *framelen, vir_bytes *newsp, int *extrabase) { AuxInfo *a, *term; @@ -351,8 +358,8 @@ static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *frame if(!execi->is_dyn) return OK; - assert(execi->hdr_len >= sizeof(*elf_header)); - elf_header = (Elf_Ehdr *) execi->hdr; + assert(execi->args.hdr_len >= sizeof(*elf_header)); + elf_header = (Elf_Ehdr *) execi->args.hdr; /* exec() promises stack space. Now find it. */ mysp++; /* skip argc */ @@ -399,12 +406,11 @@ static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *frame #define AUXINFO(type, value) \ { assert((char *) a < (char *) mysp_end); a->a_type = type; a->a_v = value; a++; } #if 0 - AUXINFO(AT_PHDR, execi->elf_phdr); AUXINFO(AT_PHENT, elf_header->e_phentsize); AUXINFO(AT_PHNUM, elf_header->e_phnum); #endif - AUXINFO(AT_BASE, execi->elf_base); - AUXINFO(AT_ENTRY, execi->pc); + AUXINFO(AT_BASE, execi->args.load_base); + AUXINFO(AT_ENTRY, execi->args.pc); AUXINFO(AT_PAGESZ, PAGE_SIZE); AUXINFO(AT_EXECFD, execi->elf_main_fd); @@ -439,150 +445,16 @@ static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *frame return OK; } -/*===========================================================================* - * load_elf * - *===========================================================================*/ -static int load_elf(struct exec_info *execi) -{ - int r; - struct vnode *vp; - int proc_e; - phys_bytes tot_bytes; /* total space for program, including gap */ - vir_bytes text_vaddr, text_paddr, text_filebytes, text_membytes; - vir_bytes data_vaddr, data_paddr, data_filebytes, data_membytes; - off_t text_offset, data_offset; - int sep_id, is_elf, i; - vir_bytes text_base, data_base; - - assert(execi != NULL); - assert(execi->hdr != NULL); - assert(execi->vp != NULL); - - proc_e = execi->proc_e; - vp = execi->vp; - - /* this function can load the dynamic linker, but that - * shouldn't require an interpreter itself. - */ - i = elf_has_interpreter(execi->hdr, execi->hdr_len, NULL, 0); - if(i > 0) { - printf("VFS: cannot load dynamically linked executable\n"); - return ENOEXEC; - } - - /* Read the file header and extract the segment sizes. */ - r = read_header_elf(execi->hdr, execi->hdr_len, &text_vaddr, &text_paddr, - &text_filebytes, &text_membytes, - &data_vaddr, &data_paddr, - &data_filebytes, &data_membytes, - &execi->pc, &text_offset, &data_offset); - - if (r != OK) { - return(r); - } - - if(elf_phdr(execi->hdr, execi->hdr_len, &execi->elf_phdr) == OK) - if(execi->elf_phdr == 0) /* 0 should indicate: not known */ - printf("VFS: warning: unexpected zero elf_phdr\n"); - - sep_id = 0; - is_elf = 1; - tot_bytes = 0; /* Use default stack size */ - text_base = trunc_page(text_vaddr); - data_base = trunc_page(data_vaddr); - execi->elf_base = MIN(text_base, data_base); - r = exec_newmem(proc_e, - text_base, text_membytes, - data_base, data_membytes, - tot_bytes, execi->frame_len, sep_id, is_elf, - vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime, - execi->progname, execi->new_uid, execi->new_gid, - &execi->stack_top, &execi->load_text, &execi->setugid); - - if (r != OK) { - printf("VFS: load_elf: exec_newmem failed: %d\n", r); - return(r); - } - - /* Read in text and data segments. */ - if (execi->load_text) - r = read_seg(vp, text_offset, proc_e, T, text_vaddr, text_filebytes); - - if (r == OK) - r = read_seg(vp, data_offset, proc_e, D, data_vaddr, data_filebytes); - - return(r); -} - -/*===========================================================================* - * exec_newmem * - *===========================================================================*/ -static int exec_newmem( - int proc_e, - vir_bytes text_addr, - vir_bytes text_bytes, - vir_bytes data_addr, - vir_bytes data_bytes, - vir_bytes tot_bytes, - vir_bytes frame_len, - int sep_id, - int is_elf, - dev_t st_dev, - ino_t st_ino, - time_t ctime, - char *progname, - int new_uid, - int new_gid, - vir_bytes *stack_topp, - int *load_textp, - int *setugidp -) -{ -/* Allocate a new memory map for a process that tries to exec */ - int r; - struct exec_newmem e; - message m; - - assert(setugidp != NULL); - - e.text_addr = text_addr; - e.text_bytes = text_bytes; - e.data_addr = data_addr; - e.data_bytes = data_bytes; - e.tot_bytes = tot_bytes; - e.args_bytes = frame_len; - e.sep_id = sep_id; - e.is_elf = is_elf; - e.st_dev = st_dev; - e.st_ino = st_ino; - e.enst_ctime = ctime; - e.new_uid = new_uid; - e.new_gid = new_gid; - e.setugid = *setugidp; - strncpy(e.progname, progname, sizeof(e.progname)-1); - e.progname[sizeof(e.progname)-1] = '\0'; - - m.m_type = EXEC_NEWMEM; - m.EXC_NM_PROC = proc_e; - m.EXC_NM_PTR = (char *)&e; - if ((r = sendrec(PM_PROC_NR, &m)) != OK) return(r); - - *stack_topp = m.m1_i1; - *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT); - *setugidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); - - return(m.m_type); -} - /*===========================================================================* * is_script * *===========================================================================*/ -static int is_script(struct exec_info *execi) +static int is_script(struct vfs_exec_info *execi) { /* Is Interpreted script? */ - assert(execi->hdr != NULL); + assert(execi->args.hdr != NULL); - return(execi->hdr[0] == '#' && execi->hdr[1] == '!' && execi->hdr_len >= 2); + return(execi->args.hdr[0] == '#' && execi->args.hdr[1] == '!' + && execi->args.hdr_len >= 2); } /*===========================================================================* @@ -713,56 +585,15 @@ int replace ((char **) stack)[0]++; /* nargs++; */ } /* Now patch up argv[] and envp[] by offset. */ - patch_ptr(stack, (vir_bytes) offset); + libexec_patch_ptr(stack, (vir_bytes) offset); ((char **) stack)[1] = (char *) a0; /* set argv[0] correctly */ return(TRUE); } - -/*===========================================================================* - * patch_ptr * - *===========================================================================*/ -static void patch_ptr( -char stack[ARG_MAX], /* pointer to stack image within PM */ -vir_bytes base /* virtual address of stack base inside user */ -) -{ -/* When doing an exec(name, argv, envp) call, the user builds up a stack - * image with arg and env pointers relative to the start of the stack. Now - * these pointers must be relocated, since the stack is not positioned at - * address 0 in the user's address space. - */ - - char **ap, flag; - vir_bytes v; - - flag = 0; /* counts number of 0-pointers seen */ - ap = (char **) stack; /* points initially to 'nargs' */ - ap++; /* now points to argv[0] */ - while (flag < 2) { - if (ap >= (char **) &stack[ARG_MAX]) return; /* too bad */ - if (*ap != NULL) { - v = (vir_bytes) *ap; /* v is relative pointer */ - v += base; /* relocate it */ - *ap = (char *) v; /* put it back */ - } else { - flag++; - } - ap++; - } -} - /*===========================================================================* * read_seg * *===========================================================================*/ -static int read_seg( -struct vnode *vp, /* inode descriptor to read from */ -off_t off, /* offset in file */ -int proc_e, /* process number (endpoint) */ -int seg, /* T, D, or S */ -vir_bytes seg_addr, /* address to load segment */ -phys_bytes seg_bytes /* how much is to be transferred? */ -) +static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t seg_bytes) { /* * The byte count on read is usually smaller than the segment count, because @@ -770,51 +601,16 @@ phys_bytes seg_bytes /* how much is to be transferred? */ * partially initialized. */ int r; - unsigned n, o; u64_t new_pos; unsigned int cum_io; - static char buf[128 * 1024]; - - assert((seg == T)||(seg == D)); + struct vnode *vp = ((struct vfs_exec_info *) execi->opaque)->vp; /* Make sure that the file is big enough */ if (off + seg_bytes > LONG_MAX) return(EIO); if ((unsigned long) vp->v_size < off+seg_bytes) return(EIO); - if (seg == T) { - /* We have to use a copy loop until safecopies support segments */ - o = 0; - while (o < seg_bytes) { - n = seg_bytes - o; - if (n > sizeof(buf)) - n = sizeof(buf); - - if ((r = req_readwrite(vp->v_fs_e,vp->v_inode_nr,cvul64(off+o), - READING, VFS_PROC_NR, buf, - n, &new_pos, &cum_io)) != OK) { - printf("VFS: read_seg: req_readwrite failed (text)\n"); - return(r); - } - - if (cum_io != n) { - printf( - "VFSread_seg segment has not been read properly by exec() \n"); - return(EIO); - } - - if ((r = sys_vircopy(VFS_PROC_NR, D, (vir_bytes)buf, proc_e, - seg, seg_addr + o, n)) != OK) { - printf("VFS: read_seg: copy failed (text)\n"); - return(r); - } - - o += n; - } - return(OK); - } else if (seg == D) { - if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING, - proc_e, (char*)seg_addr, seg_bytes, + execi->proc_e, (char*)seg_addr, seg_bytes, &new_pos, &cum_io)) != OK) { printf("VFS: read_seg: req_readwrite failed (data)\n"); return(r); @@ -824,9 +620,6 @@ phys_bytes seg_bytes /* how much is to be transferred? */ printf("VFS: read_seg segment has not been read properly\n"); return(r); - } - - return(OK); } @@ -848,7 +641,7 @@ static void clo_exec(struct fproc *rfp) /*===========================================================================* * map_header * *===========================================================================*/ -static int map_header(struct exec_info *execi) +static int map_header(struct vfs_exec_info *execi) { int r; u64_t new_pos; @@ -859,12 +652,12 @@ static int map_header(struct exec_info *execi) pos = 0; /* Read from the start of the file */ /* How much is sensible to read */ - execi->hdr_len = MIN(execi->vp->v_size, sizeof(hdr)); - execi->hdr = hdr; + execi->args.hdr_len = MIN(execi->vp->v_size, sizeof(hdr)); + execi->args.hdr = hdr; r = req_readwrite(execi->vp->v_fs_e, execi->vp->v_inode_nr, cvul64(pos), READING, VFS_PROC_NR, hdr, - execi->hdr_len, &new_pos, &cum_io); + execi->args.hdr_len, &new_pos, &cum_io); if (r != OK) { printf("VFS: exec: map_header: req_readwrite failed\n"); return(r); diff --git a/servers/vfs/exec.h b/servers/vfs/exec.h deleted file mode 100644 index 11dc85983..000000000 --- a/servers/vfs/exec.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _VFS_EXEC_H_ -#define _VFS_EXEC_H_ 1 - -struct exec_info { - int proc_e; /* Process endpoint */ - char *hdr; /* Exec file's header */ - int hdr_len; /* How many bytes are in hdr */ - vir_bytes pc; /* Entry point of exec file */ - vir_bytes stack_top; /* Top of the stack */ - vir_bytes frame_len; /* Stack size */ - uid_t new_uid; /* Process UID after exec */ - gid_t new_gid; /* Process GID after exec */ - int load_text; /* Load text section? */ - int setugid; /* Allow set{u,g}id execution? */ - struct vnode *vp; /* Exec file's vnode */ - struct vmnt *vmp; /* Exec file's vmnt */ - struct stat sb; /* Exec file's stat structure */ - char progname[PROC_NAME_LEN]; /* Program name */ - int userflags; /* exec() flags from userland */ - - /* fields only used by elf and in VFS */ - int is_dyn; /* Dynamically linked executable */ - vir_bytes elf_phdr; /* Program header location */ - vir_bytes elf_base; /* Userland addr load address */ - int elf_main_fd; /* Dyn: FD of main program execuatble */ - char execname[PATH_MAX]; /* Full executable invocation */ -}; - -#endif /* !_VFS_EXEC_H_ */ diff --git a/servers/vm/arch/i386/memory.h b/servers/vm/arch/i386/memory.h index ee129b9ab..6d84440cf 100644 --- a/servers/vm/arch/i386/memory.h +++ b/servers/vm/arch/i386/memory.h @@ -1,10 +1,5 @@ #include -/* As visible from the user space process, where is the top of the - * stack (first non-stack byte), when in paged mode? - */ -#define VM_STACKTOP 0x80000000 - /* And what is the highest addressable piece of memory, when in paged * mode? Some data for kernel and stack are subtracted from this, the * final results stored in bytes in arch.vm_data_top. diff --git a/servers/vm/exec.c b/servers/vm/exec.c index 69b53f839..9a0500880 100644 --- a/servers/vm/exec.c +++ b/servers/vm/exec.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -31,228 +32,6 @@ #include "memory.h" -static int new_mem(struct vmproc *vmp, vir_bytes text_addr, vir_bytes - text_bytes, vir_bytes data_addr, vir_bytes data_bytes, vir_bytes - stk_bytes, phys_bytes tot_bytes, vir_bytes *stack_top, int is_elf); - -/*===========================================================================* - * exec_newmem * - *===========================================================================*/ -int do_exec_newmem(message *msg) -{ - int r, proc_e, proc_n; - vir_bytes stack_top; - vir_clicks tc, dc, sc, totc, dvir, s_vir; - struct vmproc *vmp; - char *ptr; - struct exec_newmem args; - - SANITYCHECK(SCL_FUNCTIONS); - - proc_e= msg->VMEN_ENDPOINT; - if (vm_isokendpt(proc_e, &proc_n) != OK) - { - printf("VM: exec_newmem: bad endpoint %d from %d\n", - proc_e, msg->m_source); - return ESRCH; - } - vmp= &vmproc[proc_n]; - ptr= msg->VMEN_ARGSPTR; - - if(msg->VMEN_ARGSSIZE != sizeof(args)) { - printf("VM: exec_newmem: args size %d != %u\n", - msg->VMEN_ARGSSIZE, sizeof(args)); - return EINVAL; - } -SANITYCHECK(SCL_DETAIL); - - r= sys_datacopy(msg->m_source, (vir_bytes)ptr, - SELF, (vir_bytes)&args, sizeof(args)); - if (r != OK) - panic("exec_newmem: sys_datacopy failed: %d", r); - - /* Minimum stack region (not preallocated) - * Stopgap for better rlimit-based stack size system - */ - if(args.tot_bytes < MINSTACKREGION) { - args.tot_bytes = MINSTACKREGION; - } - - /* Check to see if segment sizes are feasible. */ - tc = (vir_clicks) (CLICK_CEIL(args.text_bytes) >> CLICK_SHIFT); - dc = (vir_clicks) (CLICK_CEIL(args.data_bytes) >> CLICK_SHIFT); - totc = (vir_clicks) (CLICK_CEIL(args.tot_bytes) >> CLICK_SHIFT); - sc = (vir_clicks) (CLICK_CEIL(args.args_bytes) >> CLICK_SHIFT); - if (dc >= totc) { - printf("VM: newmem: no stack?\n"); - return(ENOEXEC); /* stack must be at least 1 click */ - } - - dvir = (args.sep_id ? 0 : tc); - s_vir = dvir + (totc - sc); - r = (dvir + dc > s_vir) ? ENOMEM : OK; - if (r != OK) { - printf("VM: newmem: no virtual space?\n"); - return r; - } - - /* Allocate new memory and release old memory. Fix map and tell - * kernel. - */ - r = new_mem(vmp, args.text_addr, args.text_bytes, - args.data_addr, args.data_bytes, - args.args_bytes, args.tot_bytes, &stack_top, - args.is_elf); - if (r != OK) { - printf("VM: newmem: new_mem failed\n"); - return(r); - } - - /* Save file identification to allow it to be shared. */ - vmp->vm_ino = args.st_ino; - vmp->vm_dev = args.st_dev; - vmp->vm_ctime = args.enst_ctime; - - /* set/clear separate I&D flag */ - if (args.sep_id) - vmp->vm_flags |= VMF_SEPARATE; - else - vmp->vm_flags &= ~VMF_SEPARATE; - - msg->VMEN_STACK_TOP = (void *) stack_top; - msg->VMEN_FLAGS = 0; - msg->VMEN_FLAGS |= EXC_NM_RF_LOAD_TEXT; - - return OK; -} - -/*===========================================================================* - * new_mem * - *===========================================================================*/ -static int new_mem( - struct vmproc *rmp, /* process to get a new memory map */ - vir_bytes text_addr, /* text segement load address */ - vir_bytes text_bytes, /* text segment size in bytes */ - vir_bytes data_addr, /* data segment load address */ - vir_bytes data_bytes, /* size of data (incl bss) in bytes */ - vir_bytes stk_bytes, /* size of initial stack segment in bytes */ - phys_bytes tot_bytes, /* total memory to allocate, including gap */ - vir_bytes *stack_top, /* top of process stack */ - int is_elf -) -{ -/* Allocate new memory and release the old memory. Change the map and report - * the new map to the kernel. Zero the new core image's bss, gap and stack. - */ - - vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks; - int r, hadpt = 0; - struct vmproc *vmpold = &vmproc[VMP_EXECTMP]; - int ptok = 1; - - SANITYCHECK(SCL_FUNCTIONS); - - assert(rmp->vm_flags & VMF_HASPT); - - /* Acquire the new memory. Each of the 4 parts: text, (data+bss), gap, - * and stack occupies an integral number of clicks, starting at click - * boundary. The data and bss parts are run together with no space. - */ - text_clicks = (vir_clicks) (CLICK_CEIL(text_bytes) >> CLICK_SHIFT); - data_clicks = (vir_clicks) (CLICK_CEIL(data_bytes) >> CLICK_SHIFT); - stack_clicks = (vir_clicks) (CLICK_CEIL(stk_bytes) >> CLICK_SHIFT); - tot_clicks = (vir_clicks) (CLICK_CEIL(tot_bytes) >> CLICK_SHIFT); - gap_clicks = tot_clicks - data_clicks - stack_clicks; - if ( (int) gap_clicks < 0) { - printf("VM: new_mem: no gap?\n"); - return(ENOMEM); - } - - - /* Keep previous process state for recovery; the sanity check functions - * know about the 'vmpold' slot, so the memory that the exec()ing - * process is still holding is referenced there. - * - * Throw away the old page table to avoid having two process slots - * using the same vm_pt. - * Just recreate it in the case that we have to revert. - */ -SANITYCHECK(SCL_DETAIL); - rmp->vm_flags &= ~VMF_HASPT; - pt_free(&rmp->vm_pt); - - assert(!(vmpold->vm_flags & VMF_INUSE)); - *vmpold = *rmp; /* copy current state. */ -#if SANITYCHECKS - map_setparent(vmpold); -#endif - - region_init(&rmp->vm_regions_avl); /* exec()ing process regions thrown out. */ - rmp->vm_region_top = 0; -SANITYCHECK(SCL_DETAIL); - - /* Build new process in current slot, without freeing old - * one. If it fails, revert. - */ - SANITYCHECK(SCL_DETAIL); - if((r=pt_new(&rmp->vm_pt)) != OK) { - ptok = 0; - printf("exec_newmem: no new pagetable\n"); - } - - SANITYCHECK(SCL_DETAIL); - if(r != OK || (r=proc_new(rmp, - VM_PROCSTART, /* where to start the process in the page table */ - text_addr, /* text load address */ - CLICK2ABS(text_clicks),/* how big is the text in bytes, page-aligned */ - data_addr, /* data load address */ - CLICK2ABS(data_clicks),/* how big is data+bss, page-aligned */ - CLICK2ABS(stack_clicks),/* how big is stack, page-aligned */ - CLICK2ABS(gap_clicks), /* how big is gap, page-aligned */ - 0,0, /* not preallocated */ - VM_STACKTOP, /* regular stack top */ - 0, is_elf, 1)) != OK) { - SANITYCHECK(SCL_DETAIL); - printf("VM: new_mem: failed\n"); - if(ptok) { - rmp->vm_flags &= ~VMF_HASPT; - pt_free(&rmp->vm_pt); - } - *rmp = *vmpold; /* undo. */ - map_setparent(rmp); - clear_proc(vmpold); /* disappear. */ - SANITYCHECK(SCL_DETAIL); - if(hadpt) { - if(pt_new(&rmp->vm_pt) != OK) { - /* We secretly know that making a new pagetable - * in the same slot if one was there will never fail. - */ - panic("new_mem: pt_new failed: %d", ENOMEM); - } - rmp->vm_flags |= VMF_HASPT; - SANITYCHECK(SCL_DETAIL); - if(map_writept(rmp) != OK) { - printf("VM: warning: exec undo failed\n"); - } - SANITYCHECK(SCL_DETAIL); - } - return r; - } - SANITYCHECK(SCL_DETAIL); - /* new process is made; free and unreference - * page table and memory still held by exec()ing process. - */ - SANITYCHECK(SCL_DETAIL); - free_proc(vmpold); - clear_proc(vmpold); /* disappear. */ - SANITYCHECK(SCL_DETAIL); - *stack_top = VM_STACKTOP; - - SANITYCHECK(SCL_FUNCTIONS); - - return(OK); -} - /*===========================================================================* * find_kernel_top * *===========================================================================*/ @@ -273,6 +52,21 @@ phys_bytes find_kernel_top(void) return CLICK2ABS(kernel_top); } +void regular_segs(struct vmproc *vmp) +{ + int s; + memset(vmp->vm_arch.vm_seg, 0, sizeof(vmp->vm_arch.vm_seg)); + vmp->vm_arch.vm_seg[T].mem_phys = + vmp->vm_arch.vm_seg[D].mem_phys = ABS2CLICK(VM_PROCSTART); + vmp->vm_arch.vm_seg[T].mem_len = + vmp->vm_arch.vm_seg[D].mem_len = + vmp->vm_arch.vm_seg[S].mem_len = ABS2CLICK(VM_DATATOP-VM_PROCSTART); + if((s=sys_newmap(vmp->vm_endpoint, vmp->vm_arch.vm_seg)) != OK) + panic("regular_segs: sys_newmap failed: %d", s); + if((s=pt_bind(&vmp->vm_pt, vmp)) != OK) + panic("regular_segs: pt_bind failed: %d", s); +} + /*===========================================================================* * proc_new * *===========================================================================*/ diff --git a/servers/vm/exit.c b/servers/vm/exit.c index 202dc0ba4..247172bb9 100644 --- a/servers/vm/exit.c +++ b/servers/vm/exit.c @@ -27,6 +27,7 @@ void free_proc(struct vmproc *vmp) { map_free_proc(vmp); + vmp->vm_heap = NULL; if(vmp->vm_flags & VMF_HASPT) { vmp->vm_flags &= ~VMF_HASPT; pt_free(&vmp->vm_pt); @@ -135,6 +136,7 @@ int do_procctl(message *msg) pt_new(&vmp->vm_pt); vmp->vm_flags |= VMF_HASPT; pt_bind(&vmp->vm_pt, vmp); + regular_segs(vmp); return OK; default: return EINVAL; diff --git a/servers/vm/main.c b/servers/vm/main.c index 765852acb..487f1eb4e 100644 --- a/servers/vm/main.c +++ b/servers/vm/main.c @@ -344,7 +344,6 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info) CALLMAP(VM_EXIT, do_exit); CALLMAP(VM_FORK, do_fork); CALLMAP(VM_BRK, do_brk); - CALLMAP(VM_EXEC_NEWMEM, do_exec_newmem); CALLMAP(VM_PUSH_SIG, do_push_sig); CALLMAP(VM_WILLEXIT, do_willexit); CALLMAP(VM_ADDDMA, do_adddma); diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index 8bf843754..4b1141f99 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -93,7 +93,7 @@ int do_mmap(message *m) len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE); vr = NULL; - if (m->VMM_ADDR) { + if (m->VMM_ADDR || (m->VMM_FLAGS & MAP_FIXED)) { /* An address is given, first try at that address. */ addr = arch_vir2map(vmp, m->VMM_ADDR); vr = map_page_region(vmp, addr, 0, len, MAP_NONE, diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 3168ce9af..8cc9a2e37 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -65,6 +65,7 @@ int proc_new(struct vmproc *vmp, phys_bytes start, phys_bytes text_addr, phys_bytes stack, phys_bytes gap, phys_bytes text_here, phys_bytes data_here, vir_bytes stacktop, int prealloc_stack, int is_elf, int full); phys_bytes find_kernel_top(void); +void regular_segs(struct vmproc *); /* break.c */ int do_brk(message *msg); diff --git a/servers/vm/signal.c b/servers/vm/signal.c index 37c076869..50063a5e0 100644 --- a/servers/vm/signal.c +++ b/servers/vm/signal.c @@ -55,11 +55,6 @@ int do_push_sig(message *msg) sp -= sizeof(struct sigcontext) + 3 * sizeof(char *) + 2 * sizeof(int); - if ((r=adjust(vmp, vmp->vm_arch.vm_seg[D].mem_len, sp)) != OK) { - printf("VM: do_push_sig: adjust() failed: %d\n", r); - return r; - } - return OK; }