diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 145 |
1 files changed, 29 insertions, 116 deletions
@@ -42,6 +42,9 @@ #include <asm/system.h> #include <asm/segment.h> +#include <asm/pgtable.h> + +#include <linux/config.h> asmlinkage int sys_exit(int exit_code); asmlinkage int sys_brk(unsigned long); @@ -50,6 +53,8 @@ static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); static int load_aout_library(int fd); static int aout_core_dump(long signr, struct pt_regs * regs); +extern void dump_thread(struct pt_regs *, struct user *); + /* * Here are the actual binaries that will be accepted: * add more with "register_binfmt()".. @@ -106,14 +111,16 @@ int open_inode(struct inode * inode, int mode) return -EINVAL; f = get_empty_filp(); if (!f) - return -EMFILE; + return -ENFILE; fd = 0; fpp = current->files->fd; for (;;) { if (!*fpp) break; - if (++fd > NR_OPEN) - return -ENFILE; + if (++fd >= NR_OPEN) { + f->f_count--; + return -EMFILE; + } fpp++; } *fpp = f; @@ -164,8 +171,7 @@ static int aout_core_dump(long signr, struct pt_regs * regs) unsigned short fs; int has_dumped = 0; char corefile[6+sizeof(current->comm)]; - int i; - register int dump_start, dump_size; + unsigned long dump_start, dump_size; struct user dump; if (!current->dumpable) @@ -206,55 +212,22 @@ static int aout_core_dump(long signr, struct pt_regs * regs) if (!file.f_op->write) goto close_coredump; has_dumped = 1; -/* changed the size calculations - should hopefully work better. lbt */ - dump.magic = CMAGIC; - dump.start_code = 0; -#if defined (__i386__) - dump.start_stack = regs->esp & ~(PAGE_SIZE - 1); -#elif defined (__mips__) - dump.start_stack = regs->reg29 & ~(PAGE_SIZE - 1); -#endif - dump.u_tsize = ((unsigned long) current->mm->end_code) >> 12; - dump.u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> 12; - dump.u_dsize -= dump.u_tsize; - dump.u_ssize = 0; - for(i=0; i<8; i++) dump.u_debugreg[i] = current->debugreg[i]; - if (dump.start_stack < TASK_SIZE) - dump.u_ssize = ((unsigned long) (TASK_SIZE - dump.start_stack)) >> 12; + strncpy(dump.u_comm, current->comm, sizeof(current->comm)); + dump.u_ar0 = (struct pt_regs *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump))); + dump.signal = signr; + dump_thread(regs, &dump); + /* If the size of the dump file exceeds the rlimit, then see what would happen if we wrote the stack, but not the data area. */ if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE > current->rlim[RLIMIT_CORE].rlim_cur) dump.u_dsize = 0; + /* Make sure we have enough room to write the stack and data areas. */ if ((dump.u_ssize+1) * PAGE_SIZE > current->rlim[RLIMIT_CORE].rlim_cur) dump.u_ssize = 0; - strncpy(dump.u_comm, current->comm, sizeof(current->comm)); - dump.u_ar0 = (struct pt_regs *)(((int)(&dump.regs)) -((int)(&dump))); - dump.signal = signr; - dump.regs = *regs; -#if defined (__i386__) -/* Flag indicating the math stuff is valid. We don't support this for the - soft-float routines yet */ - if (hard_math) { - if ((dump.u_fpvalid = current->used_math) != 0) { - if (last_task_used_math == current) - __asm__("clts ; fnsave %0": :"m" (dump.i387)); - else - memcpy(&dump.i387,¤t->tss.i387.hard,sizeof(dump.i387)); - } - } else { - /* we should dump the emulator state here, but we need to - convert it into standard 387 format first.. */ - dump.u_fpvalid = 0; - } -#elif defined (__mips__) - /* - * Dump the MIPS fpa. - * FIXME: not implemented yet. - */ -#endif + set_fs(KERNEL_DS); /* struct user */ DUMP_WRITE(&dump,sizeof(dump)); @@ -335,9 +308,8 @@ unsigned long * create_tables(char * p,int argc,int envc,int ibcs) mpnt->vm_task = current; mpnt->vm_start = PAGE_MASK & (unsigned long) p; mpnt->vm_end = TASK_SIZE; - mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY; + mpnt->vm_page_prot = PAGE_COPY; mpnt->vm_flags = VM_STACK_FLAGS; - mpnt->vm_share = NULL; mpnt->vm_ops = NULL; mpnt->vm_offset = 0; mpnt->vm_inode = NULL; @@ -462,7 +434,7 @@ unsigned long copy_strings(int argc,char ** argv,unsigned long *page, return p; } -unsigned long change_ldt(unsigned long text_size,unsigned long * page) +unsigned long setup_arg_pages(unsigned long text_size,unsigned long * page) { unsigned long code_limit,data_limit,code_base,data_base; int i; @@ -536,7 +508,6 @@ void flush_old_exec(struct linux_binprm * bprm) int i; int ch; char * name; - struct vm_area_struct * mpnt, *mpnt1; current->dumpable = 1; name = bprm->filename; @@ -548,43 +519,14 @@ void flush_old_exec(struct linux_binprm * bprm) current->comm[i++] = ch; } current->comm[i] = '\0'; - /* Release all of the old mmap stuff. */ - mpnt = current->mm->mmap; - current->mm->mmap = NULL; - while (mpnt) { - mpnt1 = mpnt->vm_next; - if (mpnt->vm_ops && mpnt->vm_ops->close) - mpnt->vm_ops->close(mpnt); - if (mpnt->vm_inode) - iput(mpnt->vm_inode); - kfree(mpnt); - mpnt = mpnt1; - } - -#if defined (__i386__) - /* Flush the old ldt stuff... */ - if (current->ldt) { - free_page((unsigned long) current->ldt); - current->ldt = NULL; - for (i=1 ; i<NR_TASKS ; i++) { - if (task[i] == current) { - set_ldt_desc(gdt+(i<<1)+ - FIRST_LDT_ENTRY,&default_ldt, 1); - load_ldt(i); - } - } - } + /* Release all of the old mmap stuff. */ + exit_mmap(current); - for (i=0 ; i<8 ; i++) current->debugreg[i] = 0; -#elif defined (__mips__) - /* - * Do MIPS specific magic - */ -#endif + flush_thread(); if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || - !permission(bprm->inode,MAY_READ)) + permission(bprm->inode,MAY_READ)) current->dumpable = 0; current->signal = 0; for (i=0 ; i<32 ; i++) { @@ -615,10 +557,6 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs int retval; int sh_bang = 0; -#if defined (__i386__) - if (regs->cs != USER_CS) - return -EINVAL; -#endif bprm.p = PAGE_SIZE*MAX_ARG_PAGES-4; for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ bprm.page[i] = 0; @@ -658,8 +596,9 @@ restart_interp: bprm.e_uid = (i & S_ISUID) ? bprm.inode->i_uid : current->euid; bprm.e_gid = (i & S_ISGID) ? bprm.inode->i_gid : current->egid; } - if (!permission(bprm.inode, MAY_EXEC) || - (!(bprm.inode->i_mode & 0111) && fsuser())) { + if ((retval = permission(bprm.inode, MAY_EXEC)) != 0) + goto exec_error2; + if (!(bprm.inode->i_mode & 0111) && fsuser()) { retval = -EACCES; goto exec_error2; } @@ -779,26 +718,6 @@ exec_error1: return(retval); } -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(struct pt_regs regs) -{ - int error; - char * filename; - -#if defined (__i386__) - error = getname((char *) regs.ebx, &filename); -#elif defined (__mips__) - error = getname((char *) regs.reg3, &filename); -#endif - if (error) - return error; - error = do_execve(filename, (char **) regs.reg4, (char **) regs.reg5, ®s); - putname(filename); - return error; -} - static void set_brk(unsigned long start, unsigned long end) { start = PAGE_ALIGN(start); @@ -915,19 +834,13 @@ beyond_if: set_brk(current->mm->start_brk, current->mm->brk); - p += change_ldt(ex.a_text,bprm->page); + p += setup_arg_pages(ex.a_text,bprm->page); p -= MAX_ARG_PAGES*PAGE_SIZE; p = (unsigned long)create_tables((char *)p, bprm->argc, bprm->envc, current->personality != PER_LINUX); current->mm->start_stack = p; -#if defined (__i386__) - regs->eip = ex.a_entry; /* eip, magic happens :-) */ - regs->esp = p; /* stack pointer */ -#elif defined (__mips__) - regs->cp0_epc = ex.a_entry; /* eip, magic happens :-) */ - regs->reg29 = p; /* stack pointer */ -#endif + start_thread(regs, ex.a_entry, p); if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); return 0; |