summaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c145
1 files changed, 29 insertions, 116 deletions
diff --git a/fs/exec.c b/fs/exec.c
index fe59a15ab..35ab4081d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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,&current->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, &regs);
- 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;