This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[HURD PATCH 1/7] Use the new file_exec_file_name RPC


From: Emilio Pozuelo Monfort <pochu27@gmail.com>

Pass the file name of executable to the exec server, which it needs to
execute #!-scripts.  Currently, the exec server tries to guess the name
from argv[0] but argv[0] only contains the executable name by convention.

	* hurd/hurdexec.c (_hurd_exec): Deprecate it.
	(_hurd_exec_file_name): New function.
	* hurd/hurd.h (_hurd_exec): Deprecate it.
	(_hurd_exec_file_name): Declare it.
	* hurd/Versions: Export it.
	* sysdeps/mach/hurd/execve.c: Use it.
	* sysdeps/mach/hurd/fexecve.c: Likewise.
	* sysdeps/mach/hurd/spawni.c: Likewise.

Signed-off-by: Jeremie Koenig <jk@jk.fr.eu.org>
---
 hurd/Versions               |    3 ++
 hurd/hurd.h                 |   14 ++++++++--
 hurd/hurdexec.c             |   52 ++++++++++++++++++++++++++++++-------
 sysdeps/mach/hurd/execve.c  |    6 +++-
 sysdeps/mach/hurd/fexecve.c |    7 +++--
 sysdeps/mach/hurd/spawni.c  |   59 +++++++++++++++++++++++++-----------------
 6 files changed, 99 insertions(+), 42 deletions(-)

diff --git a/hurd/Versions b/hurd/Versions
index 9c4699e..b701c79 100644
--- a/hurd/Versions
+++ b/hurd/Versions
@@ -154,24 +154,27 @@ libc {
   }
   GLIBC_2.2.6 {
     # functions used in macros & inline functions
     __errno_location;
   }
   GLIBC_2.13_DEBIAN_12 {
     # functions used by libpthread and <hurd/signal.h>
     _hurd_sigstate_set_global_rcv;
     _hurd_sigstate_lock;
     _hurd_sigstate_pending;
     _hurd_sigstate_unlock;
     _hurd_sigstate_delete;
+
+    # "quasi-internal" functions
+    _hurd_exec_file_name;
   }
 
 %if !SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
   HURD_CTHREADS_0.3 {
     # weak refs to libthreads functions that libc calls iff libthreads in use
     cthread_fork; cthread_detach;
 
     # variables used for detecting cthreads
     _cthread_exit_routine; _cthread_init_routine;
 
     # cthreads functions with stubs in libc
     cthread_keycreate; cthread_getspecific; cthread_setspecific;
diff --git a/hurd/hurd.h b/hurd/hurd.h
index 642ea43..3429f66 100644
--- a/hurd/hurd.h
+++ b/hurd/hurd.h
@@ -1,13 +1,13 @@
-/* Copyright (C) 1993,94,95,96,97,98,99,2001,2002,2007
+/* Copyright (C) 1993,94,95,96,97,98,99,2001,2002,2007,2010
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
@@ -234,30 +234,38 @@ extern file_t file_name_path_lookup (const char *file_name, const char *path,
    close).  */
 
 extern int openport (io_t port, int flags);
 
 /* Open a stream on a port.  MODE is as for `fopen'.
    If successful, this consumes a user reference for PORT
    (which will be deallocated on fclose).  */
 
 extern FILE *fopenport (io_t port, const char *mode);
 extern FILE *__fopenport (io_t port, const char *mode);
 
 
-/* Execute a file, replacing TASK's current program image.  */
+/* Deprecated: use _hurd_exec_file_name instead.  */
 
 extern error_t _hurd_exec (task_t task,
 			   file_t file,
 			   char *const argv[],
-			   char *const envp[]);
+			   char *const envp[]) __attribute_deprecated__;
+
+/* Execute a file, replacing TASK's current program image.  */
+
+extern error_t _hurd_exec_file_name (task_t task,
+				     file_t file,
+				     const char *filename,
+				     char *const argv[],
+				     char *const envp[]);
 
 
 /* Inform the proc server we have exited with STATUS, and kill the
    task thoroughly.  This function never returns, no matter what.  */
 
 extern void _hurd_exit (int status) __attribute__ ((noreturn));
 
 
 /* Initialize the library data structures from the
    ints and ports passed to us by the exec server.
    Then vm_deallocate PORTARRAY and INTARRAY.  */
 
diff --git a/hurd/hurdexec.c b/hurd/hurdexec.c
index ee3162f..c2f45cf 100644
--- a/hurd/hurdexec.c
+++ b/hurd/hurdexec.c
@@ -1,13 +1,13 @@
-/* Copyright (C) 1991,92,93,94,95,96,97,99,2001,2002,2011
+/* Copyright (C) 1991,92,93,94,95,96,97,99,2001,2002,2010,2011
    	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
@@ -23,29 +23,47 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 #include <hurd.h>
 #include <hurd/fd.h>
 #include <hurd/signal.h>
 #include <hurd/id.h>
 #include <assert.h>
 #include <argz.h>
 
 /* Overlay TASK, executing FILE with arguments ARGV and environment ENVP.
    If TASK == mach_task_self (), some ports are dealloc'd by the exec server.
-   ARGV and ENVP are terminated by NULL pointers.  */
+   ARGV and ENVP are terminated by NULL pointers.
+   Deprecated: use _hurd_exec_file_name instead.  */
 error_t
 _hurd_exec (task_t task, file_t file,
 	    char *const argv[], char *const envp[])
 {
+  return _hurd_exec_file_name (task, file, NULL, argv, envp);
+}
+
+link_warning (_hurd_exec,
+	      "_hurd_exec is deprecated, use _hurd_exec_file_name instead");
+
+/* Overlay TASK, executing FILE with arguments ARGV and environment ENVP.
+   If TASK == mach_task_self (), some ports are dealloc'd by the exec server.
+   ARGV and ENVP are terminated by NULL pointers.  FILENAME is the path
+   (either absolute or relative) to FILE.  Passing NULL, though possible,
+   should be avoided, since then the exec server may not know the path to
+   FILE if FILE is a script, and will then pass /dev/fd/N to the
+   interpreter.  */
+error_t
+_hurd_exec_file_name (task_t task, file_t file, const char *filename,
+		      char *const argv[], char *const envp[])
+{
   error_t err;
   char *args, *env;
   size_t argslen, envlen;
   int ints[INIT_INT_MAX];
   mach_port_t ports[_hurd_nports];
   struct hurd_userlink ulink_ports[_hurd_nports];
   inline void free_port (unsigned int i)
     {
       _hurd_port_free (&_hurd_ports[i], &ulink_ports[i], ports[i]);
     }
   file_t *dtable;
   unsigned int dtablesize, i;
@@ -210,25 +228,25 @@ _hurd_exec (task_t task, file_t file,
      approach is to reauthenticate all the io ports so that no state anywhere
      reflects that our whole ID set differs from what we've set it to.  */
   __mutex_lock (&_hurd_id.lock);
   err = _hurd_check_ids ();
   if (err == 0 && ((_hurd_id.aux.nuids >= 2 && _hurd_id.gen.nuids >= 1
 		    && _hurd_id.aux.uids[1] != _hurd_id.gen.uids[0])
 		   || (_hurd_id.aux.ngids >= 2 && _hurd_id.gen.ngids >= 1
 		       && _hurd_id.aux.gids[1] != _hurd_id.gen.gids[0])))
     {
       /* We have euid != svuid or egid != svgid.  POSIX.1 says that exec
 	 sets svuid = euid and svgid = egid.  So we must get a new auth
 	 port and reauthenticate everything with it.  We'll pass the new
-	 ports in file_exec instead of our own ports.  */
+	 ports in file_exec_file_name instead of our own ports.  */
 
       auth_t newauth;
 
       _hurd_id.aux.uids[1] = _hurd_id.gen.uids[0];
       _hurd_id.aux.gids[1] = _hurd_id.gen.gids[0];
       _hurd_id.valid = 0;
       if (_hurd_id.rid_auth != MACH_PORT_NULL)
 	{
 	  __mach_port_deallocate (__mach_task_self (), _hurd_id.rid_auth);
 	  _hurd_id.rid_auth = MACH_PORT_NULL;
 	}
 
@@ -354,31 +372,45 @@ _hurd_exec (task_t task, file_t file,
 	    *pdp++ = dtable[i];
 	}
 
       flags = 0;
 #ifdef EXEC_SIGTRAP
       /* PTRACE_TRACEME sets all bits in _hurdsig_traced, which is
 	 propagated through exec by INIT_TRACEMASK, so this checks if
 	 PTRACE_TRACEME has been called in this process in any of its
 	 current or prior lives.  */
       if (__sigismember (&_hurdsig_traced, SIGKILL))
 	flags |= EXEC_SIGTRAP;
 #endif
-      err = __file_exec (file, task, flags,
-			 args, argslen, env, envlen,
-			 dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
-			 ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
-			 ints, INIT_INT_MAX,
-			 please_dealloc, pdp - please_dealloc,
-			 &_hurd_msgport, task == __mach_task_self () ? 1 : 0);
+      err = __file_exec_file_name (file, task, flags,
+				   filename ? filename : "",
+				   args, argslen, env, envlen,
+				   dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
+				   ports, MACH_MSG_TYPE_COPY_SEND,
+				   _hurd_nports,
+				   ints, INIT_INT_MAX,
+				   please_dealloc, pdp - please_dealloc,
+				   &_hurd_msgport,
+				   task == __mach_task_self () ? 1 : 0);
+      /* Fall back for backwards compatibility.  This can just be removed
+         when __file_exec goes away.  */
+      if (err == MIG_BAD_ID)
+	err = __file_exec (file, task, flags,
+			   args, argslen, env, envlen,
+			   dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
+			   ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
+			   ints, INIT_INT_MAX,
+			   please_dealloc, pdp - please_dealloc,
+			   &_hurd_msgport,
+			   task == __mach_task_self () ? 1 : 0);
     }
 
   /* Release references to the standard ports.  */
   for (i = 0; i < _hurd_nports; ++i)
     if ((i == INIT_PORT_PROC && task != __mach_task_self ())
 	|| (reauth && (i == INIT_PORT_AUTH
 		       || i == INIT_PORT_CRDIR || i == INIT_PORT_CWDIR)))
       __mach_port_deallocate (__mach_task_self (), ports[i]);
     else
       free_port (i);
 
   /* Release references to the file descriptor ports.  */
diff --git a/sysdeps/mach/hurd/execve.c b/sysdeps/mach/hurd/execve.c
index 8af8b33..ba5f5a9 100644
--- a/sysdeps/mach/hurd/execve.c
+++ b/sysdeps/mach/hurd/execve.c
@@ -1,13 +1,14 @@
-/* Copyright (C) 1991, 92, 93, 94, 95, 97 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 93, 94, 95, 97, 2010
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
 
@@ -26,21 +27,22 @@ int
 __execve (file_name, argv, envp)
      const char *file_name;
      char *const argv[];
      char *const envp[];
 {
   error_t err;
   file_t file = __file_name_lookup (file_name, O_EXEC, 0);
 
   if (file == MACH_PORT_NULL)
     return -1;
 
   /* Hopefully this will not return.  */
-  err = _hurd_exec (__mach_task_self (), file, argv, envp);
+  err = _hurd_exec_file_name (__mach_task_self (), file,
+			      file_name, argv, envp);
 
   /* Oh well.  Might as well be tidy.  */
   __mach_port_deallocate (__mach_task_self (), file);
 
   return __hurd_fail (err);
 }
 
 weak_alias (__execve, execve)
diff --git a/sysdeps/mach/hurd/fexecve.c b/sysdeps/mach/hurd/fexecve.c
index d6eb7c0..e925d68 100644
--- a/sysdeps/mach/hurd/fexecve.c
+++ b/sysdeps/mach/hurd/fexecve.c
@@ -1,13 +1,13 @@
-/* Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1997, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
 
@@ -17,18 +17,19 @@
    02111-1307 USA.  */
 
 #include <unistd.h>
 #include <hurd.h>
 #include <hurd/fd.h>
 #include <errno.h>
 
 /* Execute the file FD refers to, overlaying the running program image.  */
 
 int
 fexecve (int fd, char *const argv[], char *const envp[])
 {
-  error_t err = HURD_DPORT_USE (fd, _hurd_exec (__mach_task_self (), port,
-						argv, envp));
+  error_t err = HURD_DPORT_USE (fd, _hurd_exec_file_name (__mach_task_self (),
+							  port, NULL,
+							  argv, envp));
   if (! err)
     err = EGRATUITOUS;
   return __hurd_fail (err);
 }
diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
index 2442e6f..01f2da5 100644
--- a/sysdeps/mach/hurd/spawni.c
+++ b/sysdeps/mach/hurd/spawni.c
@@ -1,14 +1,14 @@
 /* spawn a new process running an executable.  Hurd version.
-   Copyright (C) 2001,2002,2004,2011 Free Software Foundation, Inc.
+   Copyright (C) 2001,2002,2004,2010,2011 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation; either version 2.1 of the
    License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
 
@@ -35,48 +35,48 @@
 #include "spawn_int.h"
 
 /* Spawn a new process executing PATH with the attributes describes in *ATTRP.
    Before running the process perform the actions described in FILE-ACTIONS. */
 int
 __spawni (pid_t *pid, const char *file,
 	  const posix_spawn_file_actions_t *file_actions,
 	  const posix_spawnattr_t *attrp,
 	  char *const argv[], char *const envp[],
 	  int use_path)
 {
   pid_t new_pid;
-  char *path, *p, *name;
+  char *path, *p, *name, *filename;
   size_t len;
   size_t pathlen;
   short int flags;
 
   /* The generic POSIX.1 implementation of posix_spawn uses fork and exec.
      In traditional POSIX systems (Unix, Linux, etc), the only way to
      create a new process is by fork, which also copies all the things from
      the parent process that will be immediately wiped and replaced by the
      exec.
 
      This Hurd implementation works by doing an exec on a fresh task,
      without ever doing all the work of fork.  The only work done by fork
      that remains visible after an exec is registration with the proc
      server, and the inheritance of various values and ports.  All those
      inherited values and ports are what get collected up and passed in the
-     file_exec RPC by an exec call.  So we do the proc server registration
-     here, following the model of fork (see fork.c).  We then collect up
-     the inherited values and ports from this (parent) process following
-     the model of exec (see hurd/hurdexec.c), modify or replace each value
-     that fork would (plus the specific changes demanded by ATTRP and
-     FILE_ACTIONS), and make the file_exec RPC on the requested executable
-     file with the child process's task port rather than our own.  This
-     should be indistinguishable from the fork + exec implementation,
+     file_exec_file_name RPC by an exec call.  So we do the proc server
+     registration here, following the model of fork (see fork.c).  We then
+     collect up the inherited values and ports from this (parent) process
+     following the model of exec (see hurd/hurdexec.c), modify or replace each
+     value that fork would (plus the specific changes demanded by ATTRP and
+     FILE_ACTIONS), and make the file_exec_file_name RPC on the requested
+     executable file with the child process's task port rather than our own.
+     This should be indistinguishable from the fork + exec implementation,
      except that all errors will be detected here (in the parent process)
      and return proper errno codes rather than the child dying with 127.
 
      XXX The one exception to this supposed indistinguishableness is that
      when posix_spawn_file_actions_addopen has been used, the parent
      process can do various filesystem RPCs on the child's behalf, rather
      than the child process doing it.  If these block due to a broken or
      malicious filesystem server or just a blocked network fs or a serial
      port waiting for carrier detect (!!), the parent's posix_spawn call
      can block arbitrarily rather than just the child blocking.  Possible
      solutions include:
      * punt to plain fork + exec implementation if addopen was used
@@ -539,25 +539,25 @@ __spawni (pid_t *pid, const char *file,
   if (err)
     goto out;
 
   /* Now we are ready to open the executable file using the child's ports.
      We do this after performing all the file actions so the order of
      events is the same as for a fork, exec sequence.  This affects things
      like the meaning of a /dev/fd file name, as well as which error
      conditions are diagnosed first and what side effects (file creation,
      etc) can be observed before what errors.  */
 
   if (! use_path || strchr (file, '/') != NULL)
     /* The FILE parameter is actually a path.  */
-    err = child_lookup (file, O_EXEC, 0, &execfile);
+    err = child_lookup (filename = file, O_EXEC, 0, &execfile);
   else
     {
       /* We have to search for FILE on the path.  */
       path = getenv ("PATH");
       if (path == NULL)
 	{
 	  /* There is no `PATH' in the environment.
 	     The default search path is the current directory
 	     followed by the path `confstr' returns for `_CS_PATH'.  */
 	  len = confstr (_CS_PATH, (char *) NULL, 0);
 	  path = (char *) __alloca (1 + len);
 	  path[0] = ':';
@@ -566,38 +566,36 @@ __spawni (pid_t *pid, const char *file,
 
       len = strlen (file) + 1;
       pathlen = strlen (path);
       name = __alloca (pathlen + len + 1);
       /* Copy the file name at the top.  */
       name = (char *) memcpy (name + pathlen + 1, file, len);
       /* And add the slash.  */
       *--name = '/';
 
       p = path;
       do
 	{
-	  char *startp;
-
 	  path = p;
 	  p = __strchrnul (path, ':');
 
 	  if (p == path)
 	    /* Two adjacent colons, or a colon at the beginning or the end
 	       of `PATH' means to search the current directory.  */
-	    startp = name + 1;
+	    filename = name + 1;
 	  else
-	    startp = (char *) memcpy (name - (p - path), path, p - path);
+	    filename = (char *) memcpy (name - (p - path), path, p - path);
 
 	  /* Try to open this file name.  */
-	  err = child_lookup (startp, O_EXEC, 0, &execfile);
+	  err = child_lookup (filename, O_EXEC, 0, &execfile);
 	  switch (err)
 	    {
 	    case EACCES:
 	    case ENOENT:
 	    case ESTALE:
 	    case ENOTDIR:
 	      /* Those errors indicate the file is missing or not executable
 		 by us, in which case we want to just try the next path
 		 directory.  */
 	      continue;
 
 	    case 0:		/* Success! */
@@ -616,32 +614,45 @@ __spawni (pid_t *pid, const char *file,
   if (err)
     goto out;
 
   /* Almost there!  */
   {
     mach_port_t ports[_hurd_nports];
     struct hurd_userlink ulink_ports[_hurd_nports];
     char *args = NULL, *env = NULL;
     size_t argslen = 0, envlen = 0;
 
     inline error_t exec (file_t file)
       {
-	return __file_exec (file, task,
-			    (__sigismember (&_hurdsig_traced, SIGKILL)
-			     ? EXEC_SIGTRAP : 0),
-			    args, argslen, env, envlen,
-			    dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
-			    ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
-			    ints, INIT_INT_MAX,
-			    NULL, 0, NULL, 0);
+	error_t err = __file_exec_file_name
+	  (file, task,
+	   __sigismember (&_hurdsig_traced, SIGKILL) ? EXEC_SIGTRAP : 0,
+	   filename, args, argslen, env, envlen,
+	   dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
+	   ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
+	   ints, INIT_INT_MAX, NULL, 0, NULL, 0);
+
+	/* Fallback for backwards compatibility.  This can just be removed
+	   when __file_exec goes away.  */
+	if (err == MIG_BAD_ID)
+	  return __file_exec (file, task,
+			      (__sigismember (&_hurdsig_traced, SIGKILL)
+			      ? EXEC_SIGTRAP : 0),
+			      args, argslen, env, envlen,
+			      dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
+			      ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
+			      ints, INIT_INT_MAX,
+			      NULL, 0, NULL, 0);
+
+	return err;
       }
 
     /* Now we are out of things that can fail before the file_exec RPC,
        for which everything else must be prepared.  The only thing left
        to do is packing up the argument and environment strings,
        and the array of init ports.  */
 
     if (argv != NULL)
       err = __argz_create (argv, &args, &argslen);
     if (!err && envp != NULL)
       err = __argz_create (envp, &env, &envlen);
 
-- 
1.7.5.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]