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 (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 (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 (allow_setuid && args.setugid) { - 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; - } - - /* 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; - - /* Kill process if something goes wrong after this point. */ - rmp->mp_flags |= PARTIAL_EXEC; - - 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); + if (rmp->mp_tracer == NO_TRACER) { + /* Okay, setuid execution is allowed */ + allow_setuid = 1; } + + 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.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'; + + /* 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; + + 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; + 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; }