From: Emilio Pozuelo Monfort <poch...@gmail.com> This is Emilios patch, slightly amended so that the code in hashexec.c actually uses the provided name. This makes it work in a fakerooted environment.
* hurd/exec.defs (exec_exec_file_name): New RPC. (exec_exec): Label as deprecated. * doc/hurd.texi: Updated. * exec/exec.c (S_exec_exec_file_name): New function. (S_exec_exec): Label as deprecated. (do_exec): Add argument. * exec/hashexec.c (check_hashbang): Add argument. Don't guess the file name if file_name_exec is set. * exec/priv.h (check_hashbang): Add argument. Signed-off-by: Jeremie Koenig <j...@jk.fr.eu.org> Signed-off-by: Justus Winter <4win...@informatik.uni-hamburg.de> --- doc/hurd.texi | 8 ++--- exec/exec.c | 48 ++++++++++++++++++++++++++--- exec/hashexec.c | 95 +++++++++++++++++++++++++++++++++------------------------ exec/priv.h | 4 ++- hurd/exec.defs | 19 ++++++++++-- 5 files changed, 123 insertions(+), 51 deletions(-) diff --git a/doc/hurd.texi b/doc/hurd.texi index 07ddfb4..49a8536 100644 --- a/doc/hurd.texi +++ b/doc/hurd.texi @@ -102,7 +102,7 @@ This file documents the GNU Hurd kernel component. This edition of the documentation was last updated for version @value{VERSION} of the Hurd. Copyright @copyright{} 1994, 1996, 1998, 1999, 2000, 2001, 2002, 2003, -2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. +2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. @quotation Permission is granted to make and distribute verbatim copies of @@ -2766,14 +2766,14 @@ If the setuid/setgid transformation adds a new uid or gid to the user's authentication handle that was not previously present (as opposed to merely reordering them), then the @code{EXEC_SECURE} and @code{EXEC_NEWTASK} flags should both be added in the call to -@code{exec_exec}. +@code{exec_exec_file_name}. The server then needs to open a new port onto the executed file which will not share any file pointers with the port the user passed in, opened with @code{O_READ}. Finally, all the information (mutated appropriately for setuid/setgid) should be sent to the execserver with -@code{exec_exec}. Whatever error code @code{exec_exec} returns should -returned to the caller of @code{file_exec}. +@code{exec_exec_file_name}. Whatever error code @code{exec_exec_file_name} +returns should be returned to the caller of @code{file_exec}. @node File Locking @subsection File Locking diff --git a/exec/exec.c b/exec/exec.c index 935762e..3d12e09 100644 --- a/exec/exec.c +++ b/exec/exec.c @@ -1,6 +1,6 @@ /* GNU Hurd standard exec server. - Copyright (C) 1992,93,94,95,96,98,99,2000,01,02,04 - Free Software Foundation, Inc. + Copyright (C) 1992 ,1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, + 2002, 2004, 2010 Free Software Foundation, Inc. Written by Roland McGrath. Can exec ELF format directly. @@ -738,6 +738,7 @@ static error_t do_exec (file_t file, task_t oldtask, int flags, + char *filename, char *argv, mach_msg_type_number_t argvlen, boolean_t argv_copy, char *envp, mach_msg_type_number_t envplen, boolean_t envp_copy, mach_port_t *dtable, mach_msg_type_number_t dtablesize, @@ -796,7 +797,7 @@ do_exec (file_t file, { /* Check for a #! executable file. */ check_hashbang (&e, - file, oldtask, flags, + file, oldtask, flags, filename, argv, argvlen, argv_copy, envp, envplen, envp_copy, dtable, dtablesize, dtable_copy, @@ -1371,6 +1372,7 @@ do_exec (file_t file, return e.error; } +/* Deprecated. */ kern_return_t S_exec_exec (struct trivfs_protid *protid, file_t file, @@ -1387,13 +1389,51 @@ S_exec_exec (struct trivfs_protid *protid, mach_port_t *deallocnames, mach_msg_type_number_t ndeallocnames, mach_port_t *destroynames, mach_msg_type_number_t ndestroynames) { + return S_exec_exec_file_name (protid, + file, + oldtask, + flags, + "", + argv, argvlen, argv_copy, + envp, envplen, envp_copy, + dtable, dtablesize, + dtable_copy, + portarray, nports, + portarray_copy, + intarray, nints, + intarray_copy, + deallocnames, ndeallocnames, + destroynames, ndestroynames); +} + +kern_return_t +S_exec_exec_file_name (struct trivfs_protid *protid, + file_t file, + task_t oldtask, + int flags, + char *filename, + char *argv, mach_msg_type_number_t argvlen, + boolean_t argv_copy, + char *envp, mach_msg_type_number_t envplen, + boolean_t envp_copy, + mach_port_t *dtable, mach_msg_type_number_t dtablesize, + boolean_t dtable_copy, + mach_port_t *portarray, mach_msg_type_number_t nports, + boolean_t portarray_copy, + int *intarray, mach_msg_type_number_t nints, + boolean_t intarray_copy, + mach_port_t *deallocnames, + mach_msg_type_number_t ndeallocnames, + mach_port_t *destroynames, + mach_msg_type_number_t ndestroynames) +{ if (! protid) return EOPNOTSUPP; /* There were no user-specified exec servers, or none of them could be found. */ - return do_exec (file, oldtask, flags, + return do_exec (file, oldtask, flags, filename, argv, argvlen, argv_copy, envp, envplen, envp_copy, dtable, dtablesize, dtable_copy, diff --git a/exec/hashexec.c b/exec/hashexec.c index 5641218..0065980 100644 --- a/exec/hashexec.c +++ b/exec/hashexec.c @@ -1,5 +1,6 @@ /* GNU Hurd standard exec server, #! script execution support. - Copyright (C) 1995,96,97,98,99,2000,02 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2010, + 2014 Free Software Foundation, Inc. Written by Roland McGrath. This file is part of the GNU Hurd. @@ -35,6 +36,7 @@ check_hashbang (struct execdata *e, file_t file, task_t oldtask, int flags, + char *file_name_exec, char *argv, u_int argvlen, boolean_t argv_copy, char *envp, u_int envplen, boolean_t envp_copy, mach_port_t *dtable, u_int dtablesize, boolean_t dtable_copy, @@ -225,10 +227,13 @@ check_hashbang (struct execdata *e, file_name = NULL; else if (! (flags & EXEC_SECURE)) { - /* Try to figure out the file's name. We guess that if ARGV[0] - contains a slash, it might be the name of the file; and that - if it contains no slash, looking for files named by ARGV[0] in - the `PATH' environment variable might find it. */ + /* Try to figure out the file's name. If FILE_NAME_EXEC + is not NULL and not the empty string, then it's the + file's name. Otherwise we guess that if ARGV[0] + contains a slash, it might be the name of the file; + and that if it contains no slash, looking for files + named by ARGV[0] in the `PATH' environment variable + might find it. */ error_t error; char *name; @@ -264,49 +269,59 @@ check_hashbang (struct execdata *e, return err; } - error = io_identity (file, &fileid, &filefsid, &fileno); - if (error) - goto out; - mach_port_deallocate (mach_task_self (), filefsid); - - if (memchr (argv, '\0', argvlen) == NULL) - { - name = alloca (argvlen + 1); - bcopy (argv, name, argvlen); - name[argvlen] = '\0'; - } + if (file_name_exec && file_name_exec[0] != '\0') + name = file_name_exec; else - name = argv; - - if (strchr (name, '/') != NULL) - error = lookup (name, 0, &name_file); - else if ((error = hurd_catch_signal - (sigmask (SIGBUS) | sigmask (SIGSEGV), - (vm_address_t) envp, (vm_address_t) envp + envplen, - &search_path, SIG_ERR))) - name_file = MACH_PORT_NULL; - - if (!error && name_file != MACH_PORT_NULL) { - mach_port_t id, fsid; - ino_t ino; - error = io_identity (name_file, &id, &fsid, &ino); - mach_port_deallocate (mach_task_self (), name_file); - if (!error) + /* Try to locate the file. */ + error = io_identity (file, &fileid, &filefsid, &fileno); + if (error) + goto out; + mach_port_deallocate (mach_task_self (), filefsid); + + if (memchr (argv, '\0', argvlen) == NULL) { - mach_port_deallocate (mach_task_self (), fsid); - mach_port_deallocate (mach_task_self (), id); + name = alloca (argvlen + 1); + bcopy (argv, name, argvlen); + name[argvlen] = '\0'; } - if (!error && id == fileid) + else + name = argv; + + if (strchr (name, '/') != NULL) + error = lookup (name, 0, &name_file); + else if ((error = hurd_catch_signal + (sigmask (SIGBUS) | sigmask (SIGSEGV), + (vm_address_t) envp, (vm_address_t) envp + envplen, + &search_path, SIG_ERR))) + name_file = MACH_PORT_NULL; + + /* See whether we found the right file. */ + if (!error && name_file != MACH_PORT_NULL) { - file_name = name; - free_file_name = free_name; + mach_port_t id, fsid; + ino_t ino; + error = io_identity (name_file, &id, &fsid, &ino); + mach_port_deallocate (mach_task_self (), name_file); + if (!error) + { + mach_port_deallocate (mach_task_self (), fsid); + mach_port_deallocate (mach_task_self (), id); + if (id != fileid) + error = 1; + } } - else if (free_name) - free (name); + + mach_port_deallocate (mach_task_self (), fileid); } - mach_port_deallocate (mach_task_self (), fileid); + if (!error) + { + file_name = name; + free_file_name = free_name; + } + else if (free_name) + free (name); } if (file_name == NULL) diff --git a/exec/priv.h b/exec/priv.h index 733f35c..862a33c 100644 --- a/exec/priv.h +++ b/exec/priv.h @@ -1,5 +1,6 @@ /* GNU Hurd standard exec server, private declarations. - Copyright (C) 1992,93,94,95,96,99,2000,02, 04 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2002, 2004, + 2010 Free Software Foundation, Inc. Written by Roland McGrath. This file is part of the GNU Hurd. @@ -135,6 +136,7 @@ void check_hashbang (struct execdata *e, file_t file, task_t oldtask, int flags, + char *filename, char *argv, u_int argvlen, boolean_t argv_copy, char *envp, u_int envplen, boolean_t envp_copy, mach_port_t *dtable, u_int dtablesize, diff --git a/hurd/exec.defs b/hurd/exec.defs index 2888fb1..ae4143b 100644 --- a/hurd/exec.defs +++ b/hurd/exec.defs @@ -1,5 +1,6 @@ /* Interface definitions for the exec servers. - Copyright (C) 1991,92,93,94,95,2001 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1994, 1995, 2001, 2010 + Free Software Foundation, Inc. This file is part of the GNU Hurd. @@ -29,6 +30,7 @@ EXEC_IMPORTS INTR_INTERFACE +/* Deprecated: use exec_exec_file_name instead. */ routine exec_exec ( execserver: file_t; file: mach_port_send_t; @@ -42,7 +44,20 @@ routine exec_exec ( deallocnames: mach_port_name_array_t; destroynames: mach_port_name_array_t); -skip; /* obsolete exec_startup */ +routine exec_exec_file_name ( + execserver: file_t; + file: mach_port_send_t; + oldtask: task_t; + flags: int; + filename: string_t; + argv: data_t SCP; + envp: data_t SCP; + dtable: portarray_t SCP; + portarray: portarray_t SCP; + intarray: intarray_t SCP; + deallocnames: mach_port_name_array_t; + destroynames: mach_port_name_array_t); + /* This call is made by the bootstrapping filesystem to give the execserver its auth handle. */ -- 1.9.1