diff -purN linux-2.4.21/fs/binfmt_elf.c linux-f/fs/binfmt_elf.c
--- linux-2.4.21/fs/binfmt_elf.c	2002-08-03 02:39:45.000000000 +0200
+++ linux-f/fs/binfmt_elf.c	2003-07-14 22:10:29.000000000 +0200
@@ -375,7 +375,6 @@ static unsigned long load_aout_interp(st
 	unsigned long text_data, elf_entry = ~0UL;
 	char * addr;
 	loff_t offset;
-	int retval;
 
 	current->mm->end_code = interp_ex->a_text;
 	text_data = interp_ex->a_text + interp_ex->a_data;
@@ -397,11 +396,9 @@ static unsigned long load_aout_interp(st
 	}
 
 	do_brk(0, text_data);
-	retval = -ENOEXEC;
 	if (!interpreter->f_op || !interpreter->f_op->read)
 		goto out;
-	retval = interpreter->f_op->read(interpreter, addr, text_data, &offset);
-	if (retval < 0)
+	if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
 		goto out;
 	flush_icache_range((unsigned long)addr,
 	                   (unsigned long)addr + text_data);
@@ -444,6 +441,7 @@ static int load_elf_binary(struct linux_
 	struct elfhdr interp_elf_ex;
   	struct exec interp_ex;
 	char passed_fileno[6];
+	struct files_struct *files, *ftmp;
 	
 	/* Get the exec-header */
 	elf_ex = *((struct elfhdr *) bprm->buf);
@@ -475,10 +473,17 @@ static int load_elf_binary(struct linux_
 	retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *) elf_phdata, size);
 	if (retval < 0)
 		goto out_free_ph;
+		
+	files = current->files;		/* Refcounted so ok */
+	if(unshare_files() < 0)
+		goto out_free_ph;
 
+	/* exec will make our files private anyway, but for the a.out
+	   loader stuff we need to do it earlier */
+	   
 	retval = get_unused_fd();
 	if (retval < 0)
-		goto out_free_ph;
+		goto out_free_fh;
 	get_file(bprm->file);
 	fd_install(elf_exec_fileno = retval, bprm->file);
 
@@ -593,6 +598,9 @@ static int load_elf_binary(struct linux_
 	if (retval)
 		goto out_free_dentry;
 
+	/* Discard our unneeded old files struct */
+	put_files_struct(files);
+
 	/* OK, This is the point of no return */
 	current->mm->start_data = 0;
 	current->mm->end_data = 0;
@@ -711,7 +719,8 @@ static int load_elf_binary(struct linux_
 			printk(KERN_ERR "Unable to load interpreter\n");
 			kfree(elf_phdata);
 			send_sig(SIGSEGV, current, 0);
-			return 0;
+			retval = -ENOEXEC; /* Nobody gets to see this, but.. */
+			goto out;
 		}
 	}
 
@@ -797,6 +806,10 @@ out_free_interp:
 		kfree(elf_interpreter);
 out_free_file:
 	sys_close(elf_exec_fileno);
+out_free_fh:
+	ftmp = current->files;
+	current->files = files;
+	put_files_struct(ftmp);
 out_free_ph:
 	kfree(elf_phdata);
 	goto out;
diff -purN linux-2.4.21/fs/exec.c linux-f/fs/exec.c
--- linux-2.4.21/fs/exec.c	2003-06-13 16:51:37.000000000 +0200
+++ linux-f/fs/exec.c	2003-07-14 22:10:29.000000000 +0200
@@ -557,6 +570,7 @@ int flush_old_exec(struct linux_binprm *
 	char * name;
 	int i, ch, retval;
 	struct signal_struct * oldsig;
+	struct files_struct * files;
 
 	/*
 	 * Make sure we have a private signal table
@@ -565,6 +579,18 @@ int flush_old_exec(struct linux_binprm *
 	retval = make_private_signals();
 	if (retval) goto flush_failed;
 
+	/*
+	 * Make sure we have private file handles. Ask the
+	 * fork helper to do the work for us and the exit
+	 * helper to do the cleanup of the old one.
+	 */
+	 
+	files = current->files;		/* refcounted so safe to hold */
+	retval = unshare_files();
+	if(retval)
+		goto flush_failed;
+	put_files_struct(files);
+	
 	/* 
 	 * Release all of the old mmap stuff
 	 */
diff -purN linux-2.4.21/include/linux/fs.h linux-f/include/linux/fs.h
--- linux-2.4.21/include/linux/fs.h	2003-06-13 16:51:38.000000000 +0200
+++ linux-f/include/linux/fs.h	2003-07-14 22:10:31.000000000 +0200
@@ -1523,6 +1578,9 @@ extern int generic_osync_inode(struct in
 extern int inode_change_ok(struct inode *, struct iattr *);
 extern int inode_setattr(struct inode *, struct iattr *);
 
+/* kernel/fork.c */
+extern int unshare_files(void);
+
 /*
  * Common dentry functions for inclusion in the VFS
  * or in other stackable file systems.  Some of these
diff -purN linux-2.4.21/kernel/fork.c linux-f/kernel/fork.c
--- linux-2.4.21/kernel/fork.c	2003-06-13 16:51:39.000000000 +0200
+++ linux-f/kernel/fork.c	2003-07-14 22:10:31.000000000 +0200
@@ -22,6 +22,7 @@
 #include <linux/namespace.h>
 #include <linux/personality.h>
 #include <linux/compiler.h>
+#include <linux/mman.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -537,6 +555,33 @@ out_release:
 	goto out;
 }
 
+/*
+ *	Helper to unshare the files of the current task. 
+ *	We don't want to expose copy_files internals to 
+ *	the exec layer of the kernel.
+ */
+
+int unshare_files(void)
+{
+	struct files_struct *files  = current->files;
+	int rc;
+	
+	if(!files)
+		BUG();
+		
+	/* This can race but the race causes us to copy when we don't
+	   need to and drop the copy */
+	if(atomic_read(&files->count) == 1)
+	{
+		atomic_inc(&files->count);
+		return 0;
+	}
+	rc = copy_files(0, current);
+	if(rc)
+		current->files = files;
+	return rc;
+}		
+
 static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
 {
 	struct signal_struct *sig;

