binfmt handler searching issues
Subsystems (2)
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).
-Arun
fs/exec.c renamed from fs/exec.c- +1 -0
@@ -882,6 +882,7 @@ bprm.file = file; bprm.filename = filename; + bprm.interp = filename; bprm.sh_bang =0 ; bprm.loader =0 ; bprm.exec =0 ;
fs/binfmt_script.c renamed from fs/binfmt_script.c- +2 -0
@@ -78,6 +78,8 @@ 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. */
include/linux/binfmts.h renamed from include/linux/binfmts.h- +4 -1
@@ -30,7 +30,10 @@int e_uid, e_gid;kernel_cap_t cap_inheritable, cap_permitted, cap_effective;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; };
fs/binfmt_script.c renamed from fs/binfmt_script.c- +1 -1
@@ -67,7 +67,7 @@* 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) {
fs/binfmt_misc.c renamed from fs/binfmt_misc.c.orig +3 -3
@@ -58,7 +58,7 @@*/ static Node *check_file (struct linux_binprm *bprm) { -char *p =strrchr (bprm->filename,'.' ); +char *p =strrchr (bprm->interp,'.' );struct list_head *l;for (l = entries.next; l != &entries; l = l->next) {
@@ -125,13 +125,13 @@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);