From: Arun Sharma 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; }; _