patch-2.4.22 linux-2.4.22/fs/binfmt_elf.c

Next file: linux-2.4.22/fs/binfmt_som.c
Previous file: linux-2.4.22/fs/bfs/dir.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/fs/binfmt_elf.c linux-2.4.22/fs/binfmt_elf.c
@@ -444,6 +444,7 @@
 	struct elfhdr interp_elf_ex;
   	struct exec interp_ex;
 	char passed_fileno[6];
+	struct files_struct *files;
 	
 	/* Get the exec-header */
 	elf_ex = *((struct elfhdr *) bprm->buf);
@@ -475,10 +476,21 @@
 	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;
+	if (files == current->files) {
+		put_files_struct(files);
+		files = NULL;
+	}
 
+	/* 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 +605,13 @@
 	if (retval)
 		goto out_free_dentry;
 
+	/* Discard our unneeded old files struct */
+	if (files) {
+		steal_locks(files);
+		put_files_struct(files);
+		files = NULL;
+	}
+
 	/* OK, This is the point of no return */
 	current->mm->start_data = 0;
 	current->mm->end_data = 0;
@@ -702,17 +721,16 @@
 			elf_entry = load_elf_interp(&interp_elf_ex,
 						    interpreter,
 						    &interp_load_addr);
-
-		allow_write_access(interpreter);
-		fput(interpreter);
-		kfree(elf_interpreter);
-
 		if (BAD_ADDR(elf_entry)) {
 			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_free_dentry;
 		}
+
+		allow_write_access(interpreter);
+		fput(interpreter);
+		kfree(elf_interpreter);
 	}
 
 	kfree(elf_phdata);
@@ -797,6 +815,11 @@
 		kfree(elf_interpreter);
 out_free_file:
 	sys_close(elf_exec_fileno);
+out_free_fh:
+	if (files) {
+		put_files_struct(current->files);
+		current->files = files;
+	}
 out_free_ph:
 	kfree(elf_phdata);
 	goto out;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)