From: Arun Sharma <arun.sharma@intel.com>

A script such as

#!/bin/foo.bar
...

where /bin/foo.bar is handled by binfmt_misc, is not handled correctly i.e.
 the interpreter of foo.bar doesn't receive the correct arguments.

The binfmt_misc handler requires that bprm->filename is appropriately
filled so that the argv[1] could be correctly passed to the interpreter.

However, binfmt_script, as it exists today doesn't populate bprm->filename
correctly.

Another motivation for this patch is the output of ps.  Emulators which use
binfmt_misc may want to keep the output of ps consistent with native
execution.  This requires preserving bprm->filename.  The attached patch
guarantees this even if we have to go through several binfmt handlers
(think of finite loops involving binfmt_script and binfmt_misc).



 25-akpm/fs/binfmt_misc.c        |    6 +++---
 25-akpm/fs/binfmt_script.c      |    4 +++-
 25-akpm/fs/exec.c               |    1 +
 25-akpm/include/linux/binfmts.h |    5 ++++-
 4 files changed, 11 insertions(+), 5 deletions(-)

diff -puN fs/binfmt_misc.c~binfmt_script-argv0-fix fs/binfmt_misc.c
--- 25/fs/binfmt_misc.c~binfmt_script-argv0-fix	Mon Jul 28 14:31:50 2003
+++ 25-akpm/fs/binfmt_misc.c	Mon Jul 28 14:31:50 2003
@@ -62,7 +62,7 @@ static int entry_count;
  */
 static Node *check_file(struct linux_binprm *bprm)
 {
-	char *p = strrchr(bprm->filename, '.');
+	char *p = strrchr(bprm->interp, '.');
 	struct list_head *l;
 
 	list_for_each(l, &entries) {
@@ -127,13 +127,13 @@ static int load_misc_binary(struct linux
 	if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
 		remove_arg_zero(bprm);
 	}
-	retval = copy_strings_kernel(1, &bprm->filename, bprm);
+	retval = copy_strings_kernel(1, &bprm->interp, bprm);
 	if (retval < 0) goto _ret; 
 	bprm->argc++;
 	retval = copy_strings_kernel(1, &iname_addr, bprm);
 	if (retval < 0) goto _ret; 
 	bprm->argc++;
-	bprm->filename = iname;	/* for binfmt_script */
+	bprm->interp = iname;	/* for binfmt_script */
 
 	file = open_exec(iname);
 	retval = PTR_ERR(file);
diff -puN fs/binfmt_script.c~binfmt_script-argv0-fix fs/binfmt_script.c
--- 25/fs/binfmt_script.c~binfmt_script-argv0-fix	Mon Jul 28 14:31:50 2003
+++ 25-akpm/fs/binfmt_script.c	Mon Jul 28 14:31:50 2003
@@ -69,7 +69,7 @@ static int load_script(struct linux_binp
 	 * user environment and arguments are stored.
 	 */
 	remove_arg_zero(bprm);
-	retval = copy_strings_kernel(1, &bprm->filename, bprm);
+	retval = copy_strings_kernel(1, &bprm->interp, bprm);
 	if (retval < 0) return retval; 
 	bprm->argc++;
 	if (i_arg) {
@@ -80,6 +80,8 @@ static int load_script(struct linux_binp
 	retval = copy_strings_kernel(1, &i_name, bprm);
 	if (retval) return retval; 
 	bprm->argc++;
+	bprm->interp = interp;
+
 	/*
 	 * OK, now restart the process with the interpreter's dentry.
 	 */
diff -puN fs/exec.c~binfmt_script-argv0-fix fs/exec.c
--- 25/fs/exec.c~binfmt_script-argv0-fix	Mon Jul 28 14:31:50 2003
+++ 25-akpm/fs/exec.c	Mon Jul 28 14:31:50 2003
@@ -1053,6 +1053,7 @@ int do_execve(char * filename,
 
 	bprm.file = file;
 	bprm.filename = filename;
+	bprm.interp = filename;
 	bprm.sh_bang = 0;
 	bprm.loader = 0;
 	bprm.exec = 0;
diff -puN include/linux/binfmts.h~binfmt_script-argv0-fix include/linux/binfmts.h
--- 25/include/linux/binfmts.h~binfmt_script-argv0-fix	Mon Jul 28 14:31:50 2003
+++ 25-akpm/include/linux/binfmts.h	Mon Jul 28 14:31:50 2003
@@ -31,7 +31,10 @@ struct linux_binprm{
 	kernel_cap_t cap_inheritable, cap_permitted, cap_effective;
 	void *security;
 	int argc, envc;
-	char * filename;	/* Name of binary */
+	char * filename;	/* Name of binary as seen by procps */
+	char * interp;		/* Name of the binary really executed. Most
+				   of the time same as filename, but could be
+				   different for binfmt_{misc,script} */
 	unsigned long loader, exec;
 };
 

_