]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] binfmt_script argv[0] fix
authorAndrew Morton <akpm@osdl.org>
Fri, 1 Aug 2003 03:10:26 +0000 (20:10 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Fri, 1 Aug 2003 03:10:26 +0000 (20:10 -0700)
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).

fs/binfmt_misc.c
fs/binfmt_script.c
fs/exec.c
include/linux/binfmts.h

index bc72ed4d368e72b1098c13949c55e1fa8c28b0e3..8b1b6e03c36fce2e8c91fe7985b4ba908fde0ee4 100644 (file)
@@ -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_binprm *bprm, struct pt_regs *regs)
        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);
index d6d7293f8ec73de0afffed785293d0a54fa0b671..a302e036310a148326d427f1e2fa01ecc52e14b4 100644 (file)
@@ -69,7 +69,7 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
         * 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_binprm *bprm,struct pt_regs *regs)
        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.
         */
index e09896366cad65ab04cdf19b62f89e22cd8b3dc8..c738d07f7a7d351a81a6d5e45632ef5be11c387c 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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;
index 753cef720f66541b0cb7b4db908858a1657d5ded..3d9a86eff6abf8b19c49bfec69fb313529c074f9 100644 (file)
@@ -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;
 };