summaryrefslogtreecommitdiff
path: root/debian/patches/libpager-deadlock.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/libpager-deadlock.patch')
-rw-r--r--debian/patches/libpager-deadlock.patch1688
1 files changed, 1688 insertions, 0 deletions
diff --git a/debian/patches/libpager-deadlock.patch b/debian/patches/libpager-deadlock.patch
new file mode 100644
index 00000000..b4a1e015
--- /dev/null
+++ b/debian/patches/libpager-deadlock.patch
@@ -0,0 +1,1688 @@
+diff --git a/TODO b/TODO
+index d2500dc..297ac98 100644
+--- a/TODO
++++ b/TODO
+@@ -135,7 +135,7 @@ See `tasks', the exported task list.
+
+ ** libtrivfs
+ *** Allow for read/write/exec to be passed down.
+-*** Implement file_exec when appropriate. !!
++*** Implement file_exec_file_name when appropriate. !!
+ *** Provide for the visible owner, etc., to be held in command-line args
+ instead of the underlying node, when it's important. !!
+
+diff --git a/configure.ac b/configure.ac
+index b6f777e..a03b666 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -160,8 +160,8 @@ else
+ fi
+ AC_SUBST(VERSIONING)
+
+-# Check if libc contains getgrouplist and/or uselocale.
+-AC_CHECK_FUNCS(getgrouplist uselocale)
++# Check if libc contains these functions.
++AC_CHECK_FUNCS(getgrouplist uselocale file_exec_file_name exec_exec_file_name _hurd_exec_file_name)
+
+
+ # From glibc HEAD, 2007-11-07.
+diff --git a/doc/hurd.texi b/doc/hurd.texi
+index 07ddfb4..32a8194 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
+@@ -2737,10 +2737,10 @@ write the file.
+ @node Program Execution
+ @subsection Program Execution
+
+-@findex file_exec
++@findex file_exec_file_name
+ Execution of programs on the Hurd is done through fileservers with the
+-@code{file_exec} RPC. The fileserver is expected to verify that the
+-user is allowed to execute the file, make whatever modifications to the
++@code{file_exec_file_name} RPC. The fileserver is expected to verify that
++the user is allowed to execute the file, make whatever modifications to the
+ ports are necessary for setuid execution, and then invoke the standard
+ execserver found on @file{/servers/exec}.
+
+@@ -2752,13 +2752,13 @@ The file must be opened for execution; if it is not, @code{EBADF} should
+ be returned. In addition, at least one of the execute bits must be on. A
+ failure of this check should result in @code{EACCES}---not
+ @code{ENOEXEC}. It is not proper for the fileserver ever to respond to
+-the @code{file_exec} RPC with @code{ENOEXEC}.
++the @code{file_exec_file_name} RPC with @code{ENOEXEC}.
+
+ If either the setuid or setgid bits are set, the server needs to
+ construct a new authentication handle with the additional new ID's.
+-Then all the ports passed to @code{file_exec} need to be reauthenticated
+-with the new handle. If the fileserver is unable to make the new
+-authentication handle (for example, because it is not running as root)
++Then all the ports passed to @code{file_exec_file_name} need to be
++reauthenticated with the new handle. If the fileserver is unable to make the
++new authentication handle (for example, because it is not running as root)
+ it is not acceptable to return an error; in such a case the server
+ should simply silently fail to implement the setuid/setgid semantics.
+
+@@ -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_file_name}.
+
+ @node File Locking
+ @subsection File Locking
+diff --git a/exec/Makefile b/exec/Makefile
+index 3ef742d..a285c13 100644
+--- a/exec/Makefile
++++ b/exec/Makefile
+@@ -22,7 +22,7 @@ makemode := server
+
+ SRCS = exec.c main.c hashexec.c hostarch.c
+ OBJS = main.o hostarch.o exec.o hashexec.o \
+- execServer.o exec_startupServer.o
++ execServer.o exec_startupServer.o exec_experimentalServer.o
+
+ target = exec
+ #targets = exec exec.static
+@@ -30,6 +30,7 @@ HURDLIBS = trivfs fshelp iohelp ports ihash shouldbeinlibc
+ OTHERLIBS = -lpthread
+
+ exec-MIGSFLAGS = -imacros $(srcdir)/execmutations.h
++exec_experimental-MIGSFLAGS = -imacros $(srcdir)/execmutations.h
+
+ include ../Makeconf
+
+diff --git a/exec/exec.c b/exec/exec.c
+index e693f63..09e7df1 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..91dc9a6 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
++ Free Software Foundation, Inc.
+ Written by Roland McGrath.
+
+ This file is part of the GNU Hurd.
+@@ -23,6 +24,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ #include <unistd.h>
+ #include <envz.h>
+ #include <sys/param.h>
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++#include <hurd/fs_experimental.h>
++#endif
+
+ /* This is called to check E for a #! interpreter specification. E has
+ already been prepared (successfully) and checked (unsuccessfully). If
+@@ -35,6 +39,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 +230,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 +272,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)
+@@ -415,16 +433,32 @@ check_hashbang (struct execdata *e,
+ /* We cannot open the interpreter file to execute it. Lose! */
+ return;
+
++#ifdef HAVE_FILE_EXEC_FILE_NAME
+ /* Execute the interpreter program. */
+- e->error = file_exec (interp_file,
+- oldtask, flags,
+- new_argv, new_argvlen, envp, envplen,
+- new_dtable ?: dtable, MACH_MSG_TYPE_COPY_SEND,
+- new_dtable ? new_dtablesize : dtablesize,
+- portarray, MACH_MSG_TYPE_COPY_SEND, nports,
+- intarray, nints,
+- deallocnames, ndeallocnames,
+- destroynames, ndestroynames);
++ e->error = file_exec_file_name (interp_file,
++ oldtask, flags, interp,
++ new_argv, new_argvlen, envp, envplen,
++ new_dtable ?: dtable,
++ MACH_MSG_TYPE_COPY_SEND,
++ new_dtable ? new_dtablesize : dtablesize,
++ portarray, MACH_MSG_TYPE_COPY_SEND, nports,
++ intarray, nints,
++ deallocnames, ndeallocnames,
++ destroynames, ndestroynames);
++ /* For backwards compatibility. Just drop it when we kill file_exec. */
++ if (e->error == MIG_BAD_ID)
++#endif
++ e->error = file_exec (interp_file,
++ oldtask, flags,
++ new_argv, new_argvlen, envp, envplen,
++ new_dtable ?: dtable, MACH_MSG_TYPE_COPY_SEND,
++ new_dtable ? new_dtablesize : dtablesize,
++ portarray, MACH_MSG_TYPE_COPY_SEND, nports,
++ intarray, nints,
++ deallocnames, ndeallocnames,
++ destroynames, ndestroynames);
++
++
+ mach_port_deallocate (mach_task_self (), interp_file);
+ munmap (new_argv, new_argvlen);
+
+diff --git a/exec/main.c b/exec/main.c
+index 27f33b1..2987e2d 100644
+--- a/exec/main.c
++++ b/exec/main.c
+@@ -47,6 +47,7 @@ char **save_argv;
+
+
+ #include "exec_S.h"
++#include "exec_experimental_S.h"
+ #include "exec_startup_S.h"
+
+ static int
+@@ -54,6 +55,7 @@ exec_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
+ {
+ mig_routine_t routine;
+ if ((routine = exec_server_routine (inp)) ||
++ (routine = exec_experimental_server_routine (inp)) ||
+ (routine = NULL, trivfs_demuxer (inp, outp)) ||
+ (routine = exec_startup_server_routine (inp)))
+ {
+diff --git a/exec/priv.h b/exec/priv.h
+index 85e03ae..cfd73be 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.
+@@ -32,6 +33,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ #include <link.h> /* This gives us the ElfW macro. */
+ #include <fcntl.h>
+ #include "exec_S.h"
++#include "exec_experimental_S.h"
+
+
+ #ifndef exec_priv_h
+@@ -134,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..7433cc2 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;
+diff --git a/hurd/fs.defs b/hurd/fs.defs
+index 2452682..0f0b140 100644
+--- a/hurd/fs.defs
++++ b/hurd/fs.defs
+@@ -1,5 +1,6 @@
+ /* Definitions for the filesystem interface.
+- Copyright (C) 1994,95,96,97,98,99,2002 Free Software Foundation, Inc.
++ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2002, 2010
++ Free Software Foundation, Inc.
+
+ This file is part of the GNU Hurd.
+
+@@ -35,7 +36,8 @@ INTR_INTERFACE
+ /* Overlay a task with a file. Necessary initialization, including
+ authentication changes associated with set[ug]id execution must be
+ handled by the filesystem. Filesystems normally implement this by
+- using exec_newtask or exec_loadtask as appropriate. */
++ using exec_newtask or exec_loadtask as appropriate.
++ Deprecated: use file_exec_file_name instead. */
+ routine file_exec (
+ exec_file: file_t;
+ RPT
+@@ -129,8 +131,8 @@ routine file_lock_stat (
+ (regardless of the current open modes for this port). ALLOWED is a
+ bitwise OR of O_READ, O_WRITE, and O_EXEC. This is not necessarily the
+ same as what an open or exec would allow; O_EXEC is set for root even if
+- no executable bits are on (in which case file_exec should fail) and
+- O_WRITE is set a directory can be modified, even though it can't be
++ no executable bits are on (in which case file_exec_file_name should fail)
++ and O_WRITE is set a directory can be modified, even though it can't be
+ written directly. */
+ routine file_check_access (
+ file: file_t;
+diff --git a/hurd/hurd_types.h b/hurd/hurd_types.h
+index 7d1bb73..5e470eb 100644
+--- a/hurd/hurd_types.h
++++ b/hurd/hurd_types.h
+@@ -1,5 +1,6 @@
+ /* C declarations for Hurd server interfaces
+- Copyright (C) 1993,94,95,96,98,99,2001,02 Free Software Foundation, Inc.
++ Copyright (C) 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2002,
++ 2010 Free Software Foundation, Inc.
+
+ This file is part of the GNU Hurd.
+
+@@ -78,7 +79,7 @@ typedef struct timespec timespec_t;
+ /* Many such parameters and flags are also defined in various libc
+ headers. */
+
+-/* Bits for flags in fs.defs:file_exec and exec.defs:exec_* calls: */
++/* Bits for flags in fs.defs:file_exec_file_name and exec.defs:exec_* calls: */
+ #define EXEC_NEWTASK 0x00000001 /* Create new task; kill old one. */
+ #define EXEC_SECURE 0x00000002 /* Use secure values of portarray, etc. */
+ #define EXEC_DEFAULTS 0x00000004 /* Use defaults for unspecified ports. */
+@@ -344,7 +345,7 @@ typedef int *procinfo_t;
+ #define FSTYPE_MEMFS 0x00000019 /* In-core filesystem */
+ #define FSTYPE_ISO9660 0x0000001a /* ISO9660 */
+
+-/* Standard port assignments for file_exec and exec_* */
++/* Standard port assignments for file_exec_file_name and exec_* */
+ enum
+ {
+ INIT_PORT_CWDIR,
+@@ -358,7 +359,7 @@ enum
+ INIT_PORT_MAX
+ };
+
+-/* Standard ints for file_exec and exec_* */
++/* Standard ints for file_exec_file_name and exec_* */
+ enum
+ {
+ INIT_UMASK,
+diff --git a/hurd/process.defs b/hurd/process.defs
+index bf90556..8c17666 100644
+--- a/hurd/process.defs
++++ b/hurd/process.defs
+@@ -373,7 +373,11 @@ routine proc_getnports (
+
+ /*** Routines related to early server bootstrapping ***/
+
+-skip; /* Reserved for proc_set_init_task */
++/* Set the task of process HURD_PID_INIT. Only the startup process
++ HURD_PID_STARTUP may use this interface. */
++routine proc_set_init_task (
++ process: process_t;
++ task: task_t);
+
+ /* Inform the process server that the process is important. */
+ routine proc_mark_important (
+diff --git a/hurd/process_request.defs b/hurd/process_request.defs
+index 38e7146..cb8f083 100644
+--- a/hurd/process_request.defs
++++ b/hurd/process_request.defs
+@@ -374,7 +374,10 @@ simpleroutine proc_getnports_request (
+
+ /*** Routines related to early server bootstrapping ***/
+
+-skip; /* Reserved for proc_set_init_task */
++simpleroutine proc_set_init_task_request (
++ process: process_t;
++ ureplyport reply: reply_port_t;
++ task: task_t);
+
+ /* Inform the process server that the process is important. */
+ simpleroutine proc_mark_important_request (
+diff --git a/include/pids.h b/include/pids.h
+index 22415f4..dff7635 100644
+--- a/include/pids.h
++++ b/include/pids.h
+@@ -22,8 +22,9 @@
+ #ifndef _HURD_PROCESSES_H
+ #define _HURD_PROCESSES_H
+
+-#define HURD_PID_STARTUP 1
+-#define HURD_PID_KERNEL 2
+-#define HURD_PID_PROC 3
++#define HURD_PID_INIT 1
++#define HURD_PID_STARTUP 2
++#define HURD_PID_KERNEL 3
++#define HURD_PID_PROC 4
+
+ #endif /* _HURD_PROCESSES_H */
+diff --git a/init/init.c b/init/init.c
+index b7b40bd..e86be61 100644
+--- a/init/init.c
++++ b/init/init.c
+@@ -1,7 +1,7 @@
+ /* Start and maintain hurd core servers and system run state
+
+ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+- 2005, 2008, 2013 Free Software Foundation, Inc.
++ 2005, 2008, 2010, 2013 Free Software Foundation, Inc.
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+@@ -24,6 +24,9 @@
+ one file. */
+ #include <hurd.h>
+ #include <hurd/fs.h>
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++#include <hurd/fs_experimental.h>
++#endif
+ #include <hurd/fsys.h>
+ #include <device/device.h>
+ #include <stdio.h>
+@@ -376,13 +379,28 @@ run (const char *server, mach_port_t *ports, task_t *task)
+ printf ("Pausing for %s\n", prog);
+ getchar ();
+ }
+- err = file_exec (file, *task, 0,
+- (char *)prog, strlen (prog) + 1, /* Args. */
+- startup_envz, startup_envz_len,
+- default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
+- ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+- default_ints, INIT_INT_MAX,
+- NULL, 0, NULL, 0);
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++ err = file_exec_file_name (file, *task, 0, (char *)prog,
++ (char *)prog,
++ strlen (prog) + 1, /* Args. */
++ startup_envz, startup_envz_len,
++ default_dtable,
++ MACH_MSG_TYPE_COPY_SEND, 3,
++ ports, MACH_MSG_TYPE_COPY_SEND,
++ INIT_PORT_MAX,
++ default_ints, INIT_INT_MAX,
++ NULL, 0, NULL, 0);
++ /* For backwards compatibility. Just drop it when we kill
++ file_exec. */
++ if (err == MIG_BAD_ID)
++#endif
++ err = file_exec (file, *task, 0,
++ (char *)prog, strlen (prog) + 1, /* Args. */
++ startup_envz, startup_envz_len,
++ default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
++ ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
++ default_ints, INIT_INT_MAX,
++ NULL, 0, NULL, 0);
+ if (!err)
+ break;
+
+@@ -469,14 +487,27 @@ run_for_real (char *filename, char *args, int arglen, mach_port_t ctty,
+ ++progname;
+ else
+ progname = filename;
+- err = file_exec (file, task, 0,
+- args, arglen,
+- startup_envz, startup_envz_len,
+- default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
+- default_ports, MACH_MSG_TYPE_COPY_SEND,
+- INIT_PORT_MAX,
+- default_ints, INIT_INT_MAX,
+- NULL, 0, NULL, 0);
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++ err = file_exec_file_name (file, task, 0, filename,
++ args, arglen,
++ startup_envz, startup_envz_len,
++ default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
++ default_ports, MACH_MSG_TYPE_COPY_SEND,
++ INIT_PORT_MAX,
++ default_ints, INIT_INT_MAX,
++ NULL, 0, NULL, 0);
++ /* For backwards compatibility. Just drop it when we kill file_exec. */
++ if (err == MIG_BAD_ID)
++#endif
++ err = file_exec (file, task, 0,
++ args, arglen,
++ startup_envz, startup_envz_len,
++ default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
++ default_ports, MACH_MSG_TYPE_COPY_SEND,
++ INIT_PORT_MAX,
++ default_ints, INIT_INT_MAX,
++ NULL, 0, NULL, 0);
++
+ mach_port_deallocate (mach_task_self (), default_ports[INIT_PORT_PROC]);
+ mach_port_deallocate (mach_task_self (), task);
+ if (ctty != MACH_PORT_NULL)
+@@ -1058,7 +1089,7 @@ start_child (const char *prog, char **progargs)
+ NULL, 0, /* OSF Mach */
+ #endif
+ 0, &child_task);
+- proc_child (procserver, child_task);
++ proc_set_init_task (procserver, child_task);
+ proc_task2pid (procserver, child_task, &child_pid);
+ proc_task2proc (procserver, child_task, &default_ports[INIT_PORT_PROC]);
+
+@@ -1068,13 +1099,26 @@ start_child (const char *prog, char **progargs)
+ getchar ();
+ }
+
+- err = file_exec (file, child_task, 0,
+- args, arglen,
+- startup_envz, startup_envz_len,
+- NULL, MACH_MSG_TYPE_COPY_SEND, 0, /* No fds. */
+- default_ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+- default_ints, INIT_INT_MAX,
+- NULL, 0, NULL, 0);
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++ err = file_exec_file_name (file, child_task, 0, args,
++ args, arglen,
++ startup_envz, startup_envz_len,
++ NULL, MACH_MSG_TYPE_COPY_SEND, 0, /* No fds. */
++ default_ports, MACH_MSG_TYPE_COPY_SEND,
++ INIT_PORT_MAX,
++ default_ints, INIT_INT_MAX,
++ NULL, 0, NULL, 0);
++ /* For backwards compatibility. Just drop it when we kill file_exec. */
++ if (err == MIG_BAD_ID)
++#endif
++ err = file_exec (file, child_task, 0,
++ args, arglen,
++ startup_envz, startup_envz_len,
++ NULL, MACH_MSG_TYPE_COPY_SEND, 0, /* No fds. */
++ default_ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
++ default_ints, INIT_INT_MAX,
++ NULL, 0, NULL, 0);
++
+ proc_mark_important (default_ports[INIT_PORT_PROC]);
+ mach_port_deallocate (mach_task_self (), default_ports[INIT_PORT_PROC]);
+ mach_port_deallocate (mach_task_self (), file);
+diff --git a/libdiskfs/Makefile b/libdiskfs/Makefile
+index aeebe4e..636a83e 100644
+--- a/libdiskfs/Makefile
++++ b/libdiskfs/Makefile
+@@ -56,7 +56,7 @@ OTHERSRCS = conch-fetch.c conch-set.c dir-clear.c dir-init.c dir-renamed.c \
+ SRCS = $(OTHERSRCS) $(FSSRCS) $(IOSRCS) $(FSYSSRCS) $(IFSOCKSRCS)
+ installhdrs = diskfs.h diskfs-pager.h
+
+-MIGSTUBS = fsServer.o ioServer.o fsysServer.o exec_startupServer.o \
++MIGSTUBS = fsServer.o fs_experimentalServer.o ioServer.o fsysServer.o exec_startupServer.o \
+ fsys_replyUser.o fs_notifyUser.o ifsockServer.o \
+ startup_notifyServer.o
+ OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS))
+@@ -66,6 +66,7 @@ LDLIBS += -lpthread
+
+ fsys-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h -DREPLY_PORTS
+ fs-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h
++fs_experimental-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h
+ io-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h
+ ifsock-MIGSFLAGS = -imacros $(srcdir)/fsmutations.h
+ MIGCOMSFLAGS = -prefix diskfs_
+diff --git a/libdiskfs/boot-start.c b/libdiskfs/boot-start.c
+index 7b8a84f..9dd7ec8 100644
+--- a/libdiskfs/boot-start.c
++++ b/libdiskfs/boot-start.c
+@@ -196,7 +196,7 @@ diskfs_start_bootstrap ()
+ diskfs_exec_ctl = MACH_PORT_NULL; /* Not used after this. */
+ }
+
+- /* Cache the exec server port for file_exec to use. */
++ /* Cache the exec server port for file_exec_file_name to use. */
+ _hurd_port_set (&_diskfs_exec_portcell, diskfs_exec);
+
+ if (_diskfs_boot_command)
+diff --git a/libdiskfs/demuxer.c b/libdiskfs/demuxer.c
+index 4a1c4fb..ff33b1b 100644
+--- a/libdiskfs/demuxer.c
++++ b/libdiskfs/demuxer.c
+@@ -19,6 +19,7 @@
+
+ #include "io_S.h"
+ #include "fs_S.h"
++#include "fs_experimental_S.h"
+ #include "../libports/notify_S.h"
+ #include "fsys_S.h"
+ #include "../libports/interrupt_S.h"
+@@ -33,6 +34,7 @@ diskfs_demuxer (mach_msg_header_t *inp,
+ mig_routine_t routine;
+ if ((routine = diskfs_io_server_routine (inp)) ||
+ (routine = diskfs_fs_server_routine (inp)) ||
++ (routine = diskfs_fs_experimental_server_routine (inp)) ||
+ (routine = ports_notify_server_routine (inp)) ||
+ (routine = diskfs_fsys_server_routine (inp)) ||
+ (routine = ports_interrupt_server_routine (inp)) ||
+diff --git a/libdiskfs/file-exec.c b/libdiskfs/file-exec.c
+index 9572dbe..3fe4059 100644
+--- a/libdiskfs/file-exec.c
++++ b/libdiskfs/file-exec.c
+@@ -1,5 +1,6 @@
+-/* File execution (file_exec RPC) for diskfs servers, using exec server.
+- Copyright (C) 1993,94,95,96,97,98,2000,02 Free Software Foundation, Inc.
++/* File execution (file_exec_file_name RPC) for diskfs servers, using exec server.
++ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002,
++ 2010 Free Software Foundation, Inc.
+
+ This file is part of the GNU Hurd.
+
+@@ -21,10 +22,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #include "priv.h"
+ #include "fs_S.h"
++#include "fs_experimental_S.h"
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <hurd/exec.h>
+ #include <hurd/paths.h>
++#ifdef HAVE_EXEC_EXEC_FILE_NAME
++#include <hurd/exec_experimental.h>
++#endif
+ #include <string.h>
+ #include <idvec.h>
+
+@@ -47,6 +52,39 @@ diskfs_S_file_exec (struct protid *cred,
+ mach_port_t *destroynames,
+ size_t destroynameslen)
+ {
++ return diskfs_S_file_exec_file_name (cred,
++ task,
++ flags,
++ "",
++ argv, argvlen,
++ envp, envplen,
++ fds, fdslen,
++ portarray, portarraylen,
++ intarray, intarraylen,
++ deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++}
++
++kern_return_t
++diskfs_S_file_exec_file_name (struct protid *cred,
++ task_t task,
++ int flags,
++ char *filename,
++ char *argv,
++ size_t argvlen,
++ char *envp,
++ size_t envplen,
++ mach_port_t *fds,
++ size_t fdslen,
++ mach_port_t *portarray,
++ size_t portarraylen,
++ int *intarray,
++ size_t intarraylen,
++ mach_port_t *deallocnames,
++ size_t deallocnameslen,
++ mach_port_t *destroynames,
++ size_t destroynameslen)
++{
+ struct node *np;
+ uid_t uid;
+ gid_t gid;
+@@ -136,9 +174,9 @@ diskfs_S_file_exec (struct protid *cred,
+
+ if (! err)
+ /* Make a new peropen for the exec server to access the file, since any
+- seeking the exec server might want to do should not affect the
+- original peropen on which file_exec was called. (The new protid for
+- this peropen clones the caller's iouser to preserve the caller's
++ seeking the exec server might want to do should not affect the original
++ peropen on which file_exec_file_name was called. (The new protid
++ for this peropen clones the caller's iouser to preserve the caller's
+ authentication credentials.) The new peropen's openmodes must have
+ O_READ even if the caller had only O_EXEC privilege, so the exec
+ server can read the executable file. We also include O_EXEC so that
+@@ -159,14 +197,31 @@ diskfs_S_file_exec (struct protid *cred,
+ do
+ {
+ right = ports_get_send_right (newpi);
+- err = exec_exec (execserver,
+- right, MACH_MSG_TYPE_COPY_SEND,
+- task, flags, argv, argvlen, envp, envplen,
+- fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+- portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
+- intarray, intarraylen,
+- deallocnames, deallocnameslen,
+- destroynames, destroynameslen);
++#ifdef HAVE_EXEC_EXEC_FILE_NAME
++ err = exec_exec_file_name (execserver,
++ right, MACH_MSG_TYPE_COPY_SEND,
++ task, flags, filename,
++ argv, argvlen, envp, envplen,
++ fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
++ portarray, MACH_MSG_TYPE_COPY_SEND,
++ portarraylen,
++ intarray, intarraylen,
++ deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++ /* For backwards compatibility. Just drop it when we kill
++ exec_exec. */
++ if (err == MIG_BAD_ID)
++#endif
++ err = exec_exec (execserver,
++ right, MACH_MSG_TYPE_COPY_SEND,
++ task, flags, argv, argvlen, envp, envplen,
++ fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
++ portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
++ intarray, intarraylen,
++ deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++
++
+ mach_port_deallocate (mach_task_self (), right);
+ if (err == MACH_SEND_INVALID_DEST)
+ {
+diff --git a/libfshelp/start-translator-long.c b/libfshelp/start-translator-long.c
+index 64a20be..8927c0d 100644
+--- a/libfshelp/start-translator-long.c
++++ b/libfshelp/start-translator-long.c
+@@ -1,5 +1,6 @@
+ /*
+- Copyright (C) 1995,96,99,2000,02, 04 Free Software Foundation, Inc.
++ Copyright (C) 1995, 1996, 1999, 2000, 2002, 2004, 2010
++ Free Software Foundation, Inc.
+ Written by Miles Bader and Michael I. Bushnell.
+
+ This file is part of the GNU Hurd.
+@@ -27,6 +28,9 @@
+ #include <string.h>
+ #include <assert.h>
+ #include "fshelp.h"
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++#include <hurd/fs_experimental.h>
++#endif
+
+
+ /* The data passed in the various messages we're interested in. */
+@@ -272,12 +276,22 @@ fshelp_start_translator_long (fshelp_open_fn_t underlying_open_fn,
+ saveport = ports[INIT_PORT_BOOTSTRAP];
+ ports[INIT_PORT_BOOTSTRAP] = bootstrap;
+
++#ifdef HAVE_FILE_EXEC_FILE_NAME
+ /* Try and exec the translator in TASK... */
+- err = file_exec (executable, task, EXEC_DEFAULTS,
+- argz, argz_len, 0, 0,
+- fds, fds_type, fds_len,
+- ports, ports_type, ports_len,
+- ints, ints_len, 0, 0, 0, 0);
++ err = file_exec_file_name (executable, task, EXEC_DEFAULTS, name,
++ argz, argz_len, 0, 0,
++ fds, fds_type, fds_len,
++ ports, ports_type, ports_len,
++ ints, ints_len, 0, 0, 0, 0);
++ /* For backwards compatibility. Just drop it when we kill file_exec. */
++ if (err == MIG_BAD_ID)
++#endif
++ err = file_exec (executable, task, EXEC_DEFAULTS,
++ argz, argz_len, 0, 0,
++ fds, fds_type, fds_len,
++ ports, ports_type, ports_len,
++ ints, ints_len, 0, 0, 0, 0);
++
+ ports_moved = 1;
+
+ if (ports_type == MACH_MSG_TYPE_COPY_SEND)
+diff --git a/libnetfs/Makefile b/libnetfs/Makefile
+index c3830c0..4aade5a 100644
+--- a/libnetfs/Makefile
++++ b/libnetfs/Makefile
+@@ -59,12 +59,13 @@ SRCS= $(OTHERSRCS) $(FSSRCS) $(IOSRCS) $(FSYSSRCS) $(IFSOCKSRCS)
+
+ installhdrs=netfs.h
+
+-MIGSTUBS= ioServer.o fsServer.o fsysServer.o fsys_replyUser.o ifsockServer.o
++MIGSTUBS= ioServer.o fsServer.o fs_experimentalServer.o fsysServer.o fsys_replyUser.o ifsockServer.o
+
+ OBJS=$(sort $(SRCS:.c=.o) $(MIGSTUBS))
+
+ fsys-MIGSFLAGS = -imacros $(srcdir)/mutations.h -DREPLY_PORTS
+ fs-MIGSFLAGS = -imacros $(srcdir)/mutations.h
++fs_experimental-MIGSFLAGS = -imacros $(srcdir)/mutations.h
+ io-MIGSFLAGS = -imacros $(srcdir)/mutations.h
+ ifsock-MIGSFLAGS = -imacros $(srcdir)/mutations.h
+ MIGCOMSFLAGS = -prefix netfs_
+diff --git a/libnetfs/demuxer.c b/libnetfs/demuxer.c
+index 4c20ab6..bf78812 100644
+--- a/libnetfs/demuxer.c
++++ b/libnetfs/demuxer.c
+@@ -22,6 +22,7 @@
+
+ #include "io_S.h"
+ #include "fs_S.h"
++#include "fs_experimental_S.h"
+ #include "../libports/notify_S.h"
+ #include "fsys_S.h"
+ #include "../libports/interrupt_S.h"
+@@ -34,6 +35,7 @@ netfs_demuxer (mach_msg_header_t *inp,
+ mig_routine_t routine;
+ if ((routine = netfs_io_server_routine (inp)) ||
+ (routine = netfs_fs_server_routine (inp)) ||
++ (routine = netfs_fs_experimental_server_routine (inp)) ||
+ (routine = ports_notify_server_routine (inp)) ||
+ (routine = netfs_fsys_server_routine (inp)) ||
+ (routine = ports_interrupt_server_routine (inp)) ||
+diff --git a/libnetfs/file-exec.c b/libnetfs/file-exec.c
+index 638f0ae..ffaf598 100644
+--- a/libnetfs/file-exec.c
++++ b/libnetfs/file-exec.c
+@@ -1,5 +1,6 @@
+ /*
+- Copyright (C) 1996,97,2000,01,02 Free Software Foundation, Inc.
++ Copyright (C) 1996, 1997, 2000, 2001, 2002, 2010
++ Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ This file is part of the GNU Hurd.
+@@ -23,10 +24,14 @@
+ #include "netfs.h"
+ #include "execserver.h"
+ #include "fs_S.h"
++#include "fs_experimental_S.h"
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <hurd/exec.h>
+ #include <hurd/paths.h>
++#ifdef HAVE_EXEC_EXEC_FILE_NAME
++#include <hurd/exec_experimental.h>
++#endif
+ #include <string.h>
+ #include <idvec.h>
+
+@@ -49,6 +54,39 @@ netfs_S_file_exec (struct protid *cred,
+ mach_port_t *destroynames,
+ size_t destroynameslen)
+ {
++ return netfs_S_file_exec_file_name (cred,
++ task,
++ flags,
++ "",
++ argv, argvlen,
++ envp, envplen,
++ fds, fdslen,
++ portarray, portarraylen,
++ intarray, intarraylen,
++ deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++}
++
++kern_return_t
++netfs_S_file_exec_file_name (struct protid *cred,
++ task_t task,
++ int flags,
++ char *filename,
++ char *argv,
++ size_t argvlen,
++ char *envp,
++ size_t envplen,
++ mach_port_t *fds,
++ size_t fdslen,
++ mach_port_t *portarray,
++ size_t portarraylen,
++ int *intarray,
++ size_t intarraylen,
++ mach_port_t *deallocnames,
++ size_t deallocnameslen,
++ mach_port_t *destroynames,
++ size_t destroynameslen)
++{
+ struct node *np;
+ error_t err;
+ uid_t uid;
+@@ -133,14 +171,31 @@ netfs_S_file_exec (struct protid *cred,
+ if (newpi)
+ {
+ right = ports_get_send_right (newpi);
+- err = exec_exec (_netfs_exec,
+- right, MACH_MSG_TYPE_COPY_SEND,
+- task, flags, argv, argvlen, envp, envplen,
+- fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+- portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
+- intarray, intarraylen,
+- deallocnames, deallocnameslen,
+- destroynames, destroynameslen);
++#ifdef HAVE_EXEC_EXEC_FILE_NAME
++ err = exec_exec_file_name (_netfs_exec,
++ right, MACH_MSG_TYPE_COPY_SEND,
++ task, flags, filename,
++ argv, argvlen, envp, envplen,
++ fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
++ portarray, MACH_MSG_TYPE_COPY_SEND,
++ portarraylen,
++ intarray, intarraylen,
++ deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++ /* For backwards compatibility. Just drop it when we kill
++ exec_exec. */
++ if (err == MIG_BAD_ID)
++#endif
++ err = exec_exec (_netfs_exec,
++ right, MACH_MSG_TYPE_COPY_SEND,
++ task, flags, argv, argvlen, envp, envplen,
++ fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
++ portarray, MACH_MSG_TYPE_COPY_SEND,
++ portarraylen,
++ intarray, intarraylen,
++ deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++
+ mach_port_deallocate (mach_task_self (), right);
+ ports_port_deref (newpi);
+ }
+diff --git a/libpager/pager-attr.c b/libpager/pager-attr.c
+index 7629f1d..ad1560e 100644
+--- a/libpager/pager-attr.c
++++ b/libpager/pager-attr.c
+@@ -19,9 +19,9 @@
+ #include <assert.h>
+
+ /* Change the attributes of the memory object underlying pager P.
+- Args MAY_CACHE and COPY_STRATEGY are as for
+- memory_object_change_atributes. Wait for the kernel to report completion
+- off WAIT is set.*/
++ Arguments MAY_CACHE and COPY_STRATEGY are as for
++ memory_object_change_atributes. Wait for the kernel to report
++ completion if WAIT is set. */
+ void
+ pager_change_attributes (struct pager *p,
+ boolean_t may_cache,
+@@ -77,11 +77,14 @@ pager_change_attributes (struct pager *p,
+ }
+ }
+
++ pthread_mutex_unlock (&p->interlock);
+ memory_object_change_attributes (p->memobjcntl, may_cache, copy_strategy,
+ wait ? p->port.port_right : MACH_PORT_NULL);
+
+ if (wait)
+ {
++ pthread_mutex_lock (&p->interlock);
++
+ while (ar->attrs_pending)
+ pthread_cond_wait (&p->wakeup, &p->interlock);
+
+@@ -92,7 +95,7 @@ pager_change_attributes (struct pager *p,
+ ar->next->prevp = ar->prevp;
+ free (ar);
+ }
++
++ pthread_mutex_unlock (&p->interlock);
+ }
+-
+- pthread_mutex_unlock (&p->interlock);
+ }
+diff --git a/libpager/pager.h b/libpager/pager.h
+index 75ff108..d0572af 100644
+--- a/libpager/pager.h
++++ b/libpager/pager.h
+@@ -111,9 +111,9 @@ pager_offer_page (struct pager *pager,
+ vm_address_t buf);
+
+ /* Change the attributes of the memory object underlying pager PAGER.
+- Args MAY_CACHE and COPY_STRATEGY are as for
+- memory_object_change_atributes. Wait for the kernel to report completion
+- off WAIT is set.*/
++ Arguments MAY_CACHE and COPY_STRATEGY are as for
++ memory_object_change_atributes. Wait for the kernel to report
++ completion if WAIT is set. */
+ void
+ pager_change_attributes (struct pager *pager,
+ boolean_t may_cache,
+diff --git a/libtrivfs/Makefile b/libtrivfs/Makefile
+index 921acbe..f68aa7b 100644
+--- a/libtrivfs/Makefile
++++ b/libtrivfs/Makefile
+@@ -44,7 +44,7 @@ OTHERSRCS=demuxer.c protid-clean.c protid-dup.c cntl-create.c \
+
+ SRCS=$(FSSRCS) $(IOSRCS) $(FSYSSRCS) $(OTHERSRCS)
+
+-MIGSTUBS=fsServer.o ioServer.o fsysServer.o fsys_replyUser.o
++MIGSTUBS=fsServer.o fs_experimentalServer.o ioServer.o fsysServer.o fsys_replyUser.o
+
+ libname = libtrivfs
+ HURDLIBS = fshelp iohelp ports shouldbeinlibc
+@@ -54,7 +54,7 @@ MIGCOMSFLAGS = -prefix trivfs_
+ installhdrs := trivfs.h
+ mig-sheader-prefix = trivfs_
+ ifndef no_deps
+-installhdrs += $(patsubst %,trivfs_%_S.h,fs io fsys)
++installhdrs += $(patsubst %,trivfs_%_S.h,fs fs_experimental io fsys)
+ endif
+
+ include ../Makeconf
+diff --git a/libtrivfs/demuxer.c b/libtrivfs/demuxer.c
+index 306cd11..221d218 100644
+--- a/libtrivfs/demuxer.c
++++ b/libtrivfs/demuxer.c
+@@ -23,6 +23,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #include "trivfs_io_S.h"
+ #include "trivfs_fs_S.h"
++#include "trivfs_fs_experimental_S.h"
+ #include "../libports/notify_S.h"
+ #include "trivfs_fsys_S.h"
+ #include "../libports/interrupt_S.h"
+@@ -34,6 +35,7 @@ trivfs_demuxer (mach_msg_header_t *inp,
+ mig_routine_t routine;
+ if ((routine = trivfs_io_server_routine (inp)) ||
+ (routine = trivfs_fs_server_routine (inp)) ||
++ (routine = trivfs_fs_experimental_server_routine (inp)) ||
+ (routine = ports_notify_server_routine (inp)) ||
+ (routine = trivfs_fsys_server_routine (inp)) ||
+ (routine = ports_interrupt_server_routine (inp)))
+diff --git a/libtrivfs/file-exec.c b/libtrivfs/file-exec.c
+index a3ab048..f626955 100644
+--- a/libtrivfs/file-exec.c
++++ b/libtrivfs/file-exec.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 1994,2002 Free Software Foundation, Inc.
++ Copyright (C) 1994, 2002, 2010 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+@@ -40,3 +40,28 @@ trivfs_S_file_exec (trivfs_protid_t exec_file,
+ {
+ return EOPNOTSUPP;
+ }
++
++kern_return_t
++trivfs_S_file_exec_file_name (trivfs_protid_t exec_file,
++ mach_port_t reply,
++ mach_msg_type_name_t replyPoly,
++ mach_port_t exec_task,
++ int flags,
++ string_t filename,
++ data_t argv,
++ mach_msg_type_number_t argvCnt,
++ data_t envp,
++ mach_msg_type_number_t envpCnt,
++ portarray_t fdarray,
++ mach_msg_type_number_t fdarrayCnt,
++ portarray_t portarray,
++ mach_msg_type_number_t portarrayCnt,
++ intarray_t intarray,
++ mach_msg_type_number_t intarrayCnt,
++ mach_port_array_t deallocnames,
++ mach_msg_type_number_t deallocnamesCnt,
++ mach_port_array_t destroynames,
++ mach_msg_type_number_t destroynamesCnt)
++{
++ return EOPNOTSUPP;
++}
+diff --git a/proc/main.c b/proc/main.c
+index 73742ed..f1f4e1b 100644
+--- a/proc/main.c
++++ b/proc/main.c
+@@ -1,5 +1,5 @@
+ /* Initialization of the proc server
+- Copyright (C) 1993,94,95,96,97,99,2000,01 Free Software Foundation, Inc.
++ Copyright (C) 1993,94,95,96,97,99,2000,01,13 Free Software Foundation, Inc.
+
+ This file is part of the GNU Hurd.
+
+@@ -88,7 +88,12 @@ main (int argc, char **argv, char **envp)
+ generic_port = ports_get_right (genport);
+
+ /* Create the initial proc object for init (PID 1). */
+- startup_proc = create_startup_proc ();
++ init_proc = create_init_proc ();
++
++ /* Create the startup proc object for /hurd/init (PID 2). */
++ startup_proc = allocate_proc (MACH_PORT_NULL);
++ startup_proc->p_deadmsg = 1;
++ complete_proc (startup_proc, HURD_PID_STARTUP);
+
+ /* Create our own proc object. */
+ self_proc = allocate_proc (mach_task_self ());
+diff --git a/proc/mgt.c b/proc/mgt.c
+index 5e0accd..3ab7d8d 100644
+--- a/proc/mgt.c
++++ b/proc/mgt.c
+@@ -1,5 +1,6 @@
+ /* Process management
+- Copyright (C) 1992,93,94,95,96,99,2000,01,02 Free Software Foundation, Inc.
++ Copyright (C) 1992,93,94,95,96,99,2000,01,02,13
++ Free Software Foundation, Inc.
+
+ This file is part of the GNU Hurd.
+
+@@ -184,7 +185,7 @@ S_proc_child (struct proc *parentp,
+ /* Process hierarchy. Remove from our current location
+ and place us under our new parent. Sanity check to make sure
+ parent is currently init. */
+- assert (childp->p_parent == startup_proc);
++ assert (childp->p_parent == init_proc);
+ if (childp->p_sib)
+ childp->p_sib->p_prevsib = childp->p_prevsib;
+ *childp->p_prevsib = childp->p_sib;
+@@ -587,7 +588,7 @@ allocate_proc (task_t task)
+ /* Allocate and initialize the proc structure for init (PID 1),
+ the original parent of all other procs. */
+ struct proc *
+-create_startup_proc (void)
++create_init_proc (void)
+ {
+ static const uid_t zero;
+ struct proc *p;
+@@ -596,7 +597,7 @@ create_startup_proc (void)
+ p = allocate_proc (MACH_PORT_NULL);
+ assert (p);
+
+- p->p_pid = HURD_PID_STARTUP;
++ p->p_pid = HURD_PID_INIT;
+
+ p->p_parent = p;
+ p->p_sib = 0;
+@@ -644,7 +645,7 @@ proc_death_notify (struct proc *p)
+ }
+
+ /* Complete a new process that has been allocated but not entirely initialized.
+- This gets called for every process except startup_proc (PID 1). */
++ This gets called for every process except init_proc (PID 1). */
+ void
+ complete_proc (struct proc *p, pid_t pid)
+ {
+@@ -663,30 +664,47 @@ complete_proc (struct proc *p, pid_t pid)
+
+ p->p_pid = pid;
+
+- ids_ref (&nullids);
+- p->p_id = &nullids;
++ if (pid == HURD_PID_STARTUP)
++ {
++ /* Equip HURD_PID_STARTUP with the same credentials as
++ HURD_PID_INIT. */
++ static const uid_t zero;
++ p->p_id = make_ids (&zero, 1);
++ assert (p->p_id);
++ }
++ else
++ {
++ ids_ref (&nullids);
++ p->p_id = &nullids;
++ }
+
+ p->p_login = nulllogin;
+ p->p_login->l_refcnt++;
+
+ /* Our parent is init for now. */
+- p->p_parent = startup_proc;
++ p->p_parent = init_proc;
+
+- p->p_sib = startup_proc->p_ochild;
+- p->p_prevsib = &startup_proc->p_ochild;
++ p->p_sib = init_proc->p_ochild;
++ p->p_prevsib = &init_proc->p_ochild;
+ if (p->p_sib)
+ p->p_sib->p_prevsib = &p->p_sib;
+- startup_proc->p_ochild = p;
++ init_proc->p_ochild = p;
+ p->p_loginleader = 0;
+ p->p_ochild = 0;
+ p->p_parentset = 0;
+
+ p->p_noowner = 1;
+
+- p->p_pgrp = startup_proc->p_pgrp;
++ p->p_pgrp = init_proc->p_pgrp;
+
+- proc_death_notify (p);
+- add_proc_to_hash (p);
++ /* At this point, we do not know the task of the startup process,
++ defer registering death notifications and adding it to the hash
++ tables. */
++ if (pid != HURD_PID_STARTUP)
++ {
++ proc_death_notify (p);
++ add_proc_to_hash (p);
++ }
+ join_pgrp (p);
+ }
+
+@@ -748,7 +766,7 @@ process_has_exited (struct proc *p)
+ nowait_msg_proc_newids (tp->p_msgport, tp->p_task,
+ 1, tp->p_pgrp->pg_pgid,
+ !tp->p_pgrp->pg_orphcnt);
+- tp->p_parent = startup_proc;
++ tp->p_parent = init_proc;
+ if (tp->p_dead)
+ isdead = 1;
+ }
+@@ -756,17 +774,17 @@ process_has_exited (struct proc *p)
+ nowait_msg_proc_newids (tp->p_msgport, tp->p_task,
+ 1, tp->p_pgrp->pg_pgid,
+ !tp->p_pgrp->pg_orphcnt);
+- tp->p_parent = startup_proc;
++ tp->p_parent = init_proc;
+
+ /* And now append the lists. */
+- tp->p_sib = startup_proc->p_ochild;
++ tp->p_sib = init_proc->p_ochild;
+ if (tp->p_sib)
+ tp->p_sib->p_prevsib = &tp->p_sib;
+- startup_proc->p_ochild = p->p_ochild;
+- p->p_ochild->p_prevsib = &startup_proc->p_ochild;
++ init_proc->p_ochild = p->p_ochild;
++ p->p_ochild->p_prevsib = &init_proc->p_ochild;
+
+ if (isdead)
+- alert_parent (startup_proc);
++ alert_parent (init_proc);
+ }
+
+ /* If an operation is in progress for this process, cause it
+@@ -946,3 +964,21 @@ S_proc_get_code (struct proc *callerp,
+
+ return 0;
+ }
++
++/* Implement proc_set_init_task as described in <hurd/process.defs>. */
++error_t
++S_proc_set_init_task(struct proc *callerp,
++ task_t task)
++{
++ if (! callerp)
++ return EOPNOTSUPP;
++
++ if (callerp != startup_proc)
++ return EPERM;
++
++ init_proc->p_task = task;
++ proc_death_notify (init_proc);
++ add_proc_to_hash (init_proc);
++
++ return 0;
++}
+diff --git a/proc/proc.h b/proc/proc.h
+index 12f56da..8c8de08 100644
+--- a/proc/proc.h
++++ b/proc/proc.h
+@@ -1,5 +1,6 @@
+ /* Process server definitions
+- Copyright (C) 1992,93,94,95,96,99,2000,01 Free Software Foundation, Inc.
++ Copyright (C) 1992,93,94,95,96,99,2000,01,13
++ Free Software Foundation, Inc.
+
+ This file is part of the GNU Hurd.
+
+@@ -134,7 +135,8 @@ struct exc
+
+ mach_port_t authserver;
+ struct proc *self_proc; /* process HURD_PID_PROC (us) */
+-struct proc *startup_proc; /* process 1 (init) */
++struct proc *init_proc; /* process 1 (sysvinit) */
++struct proc *startup_proc; /* process 2 (hurd/init) */
+
+ struct port_bucket *proc_bucket;
+ struct port_class *proc_class;
+@@ -190,7 +192,7 @@ void exc_clean (void *);
+ struct proc *add_tasks (task_t);
+ int pidfree (pid_t);
+
+-struct proc *create_startup_proc (void);
++struct proc *create_init_proc (void);
+ struct proc *allocate_proc (task_t);
+ void proc_death_notify (struct proc *);
+ void complete_proc (struct proc *, pid_t);
+diff --git a/trans/fakeroot.c b/trans/fakeroot.c
+index c519180..07d9462 100644
+--- a/trans/fakeroot.c
++++ b/trans/fakeroot.c
+@@ -1,5 +1,5 @@
+ /* fakeroot -- a translator for faking actions that aren't really permitted
+- Copyright (C) 2002, 2003, 2008, 2013 Free Software Foundation, Inc.
++ Copyright (C) 2002, 2003, 2008, 2010, 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+@@ -28,6 +28,9 @@
+ #include <pthread.h>
+ #include <hurd/ihash.h>
+ #include <hurd/paths.h>
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++#include <hurd/fs_experimental.h>
++#endif
+
+ #include <version.h>
+
+@@ -784,6 +787,39 @@ netfs_S_file_exec (struct protid *user,
+ mach_port_t *destroynames,
+ size_t destroynameslen)
+ {
++ return netfs_S_file_exec_file_name (user,
++ task,
++ flags,
++ "",
++ argv, argvlen,
++ envp, envplen,
++ fds, fdslen,
++ portarray, portarraylen,
++ intarray, intarraylen,
++ deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++}
++
++kern_return_t
++netfs_S_file_exec_file_name (struct protid *user,
++ task_t task,
++ int flags,
++ char *filename,
++ char *argv,
++ size_t argvlen,
++ char *envp,
++ size_t envplen,
++ mach_port_t *fds,
++ size_t fdslen,
++ mach_port_t *portarray,
++ size_t portarraylen,
++ int *intarray,
++ size_t intarraylen,
++ mach_port_t *deallocnames,
++ size_t deallocnameslen,
++ mach_port_t *destroynames,
++ size_t destroynameslen)
++{
+ error_t err;
+ file_t file;
+
+@@ -800,13 +836,29 @@ netfs_S_file_exec (struct protid *user,
+
+ if (!err)
+ {
++#ifdef HAVE_FILE_EXEC_FILE_NAME
+ /* We cannot use MACH_MSG_TYPE_MOVE_SEND because we might need to
+ retry an interrupted call that would have consumed the rights. */
+- err = file_exec (user->po->np->nn->file, task, flags, argv, argvlen,
+- envp, envplen, fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
+- portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
+- intarray, intarraylen, deallocnames, deallocnameslen,
+- destroynames, destroynameslen);
++ err = file_exec_file_name (user->po->np->nn->file, task, flags,
++ filename,
++ argv, argvlen,
++ envp, envplen,
++ fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
++ portarray, MACH_MSG_TYPE_COPY_SEND,
++ portarraylen,
++ intarray, intarraylen,
++ deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++ /* For backwards compatibility. Just drop it when we kill
++ file_exec. */
++ if (err == MIG_BAD_ID)
++#endif
++ err = file_exec (user->po->np->nn->file, task, flags, argv, argvlen,
++ envp, envplen, fds, MACH_MSG_TYPE_COPY_SEND, fdslen,
++ portarray, MACH_MSG_TYPE_COPY_SEND, portarraylen,
++ intarray, intarraylen, deallocnames, deallocnameslen,
++ destroynames, destroynameslen);
++
+ mach_port_deallocate (mach_task_self (), file);
+ }
+
+@@ -936,6 +988,7 @@ netfs_demuxer (mach_msg_header_t *inp,
+ {
+ mig_routine_t netfs_io_server_routine (mach_msg_header_t *);
+ mig_routine_t netfs_fs_server_routine (mach_msg_header_t *);
++ mig_routine_t netfs_fs_experimental_server_routine (mach_msg_header_t *);
+ mig_routine_t ports_notify_server_routine (mach_msg_header_t *);
+ mig_routine_t netfs_fsys_server_routine (mach_msg_header_t *);
+ mig_routine_t ports_interrupt_server_routine (mach_msg_header_t *);
+@@ -943,6 +996,7 @@ netfs_demuxer (mach_msg_header_t *inp,
+ mig_routine_t routine;
+ if ((routine = netfs_io_server_routine (inp)) ||
+ (routine = netfs_fs_server_routine (inp)) ||
++ (routine = netfs_fs_experimental_server_routine (inp)) ||
+ (routine = ports_notify_server_routine (inp)) ||
+ (routine = netfs_fsys_server_routine (inp)) ||
+ /* XXX we should intercept interrupt_operation and do
+diff --git a/utils/fakeauth.c b/utils/fakeauth.c
+index 590a421..851772c 100644
+--- a/utils/fakeauth.c
++++ b/utils/fakeauth.c
+@@ -1,5 +1,5 @@
+ /* fakeauth -- proxy auth server to lie to users about what their IDs are
+- Copyright (C) 2002 Free Software Foundation, Inc.
++ Copyright (C) 2002, 2010 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+@@ -397,7 +397,7 @@ believe it has restricted them to different identities or no identity at all.\
+ /* We cannot use fork because it doesn't do the right thing with our send
+ rights that point to our own receive rights, i.e. the new auth port.
+ Since posix_spawn might be implemented with fork (prior to glibc 2.3),
+- we cannot use that simple interface either. We use _hurd_exec
++ we cannot use that simple interface either. We use _hurd_exec_file_name
+ directly to effect what posix_spawn does in the simple case. */
+ {
+ task_t newtask;
+@@ -422,7 +422,12 @@ believe it has restricted them to different identities or no identity at all.\
+ if (err)
+ error (3, err, "proc_child");
+
++#ifdef HAVE__HURD_EXEC_FILE_NAME
++ err = _hurd_exec_file_name (newtask, execfile, argv[argi],
++ &argv[argi], environ);
++#else
+ err = _hurd_exec (newtask, execfile, &argv[argi], environ);
++#endif
+ mach_port_deallocate (mach_task_self (), newtask);
+ mach_port_deallocate (mach_task_self (), execfile);
+ if (err)
+diff --git a/utils/login.c b/utils/login.c
+index cad3b1e..808a244 100644
+--- a/utils/login.c
++++ b/utils/login.c
+@@ -1,6 +1,7 @@
+ /* Hurdish login
+
+- Copyright (C) 1995,96,97,98,99,2002 Free Software Foundation, Inc.
++ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2002, 2010
++ Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.org>
+
+@@ -46,6 +47,9 @@
+ #include <error.h>
+ #include <timefmt.h>
+ #include <hurd/lookup.h>
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++#include <hurd/fs_experimental.h>
++#endif
+ #include <ugids.h>
+
+ const char *argp_program_version = STANDARD_HURD_VERSION (login);
+@@ -882,12 +886,22 @@ main(int argc, char *argv[])
+ }
+ }
+
+- err = file_exec (exec, mach_task_self (), EXEC_DEFAULTS,
+- sh_args, sh_args_len, env, env_len,
+- fds, MACH_MSG_TYPE_COPY_SEND, 3,
+- ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+- ints, INIT_INT_MAX,
+- 0, 0, 0, 0);
++#ifdef HAVE_FILE_EXEC_FILE_NAME
++ err = file_exec_file_name (exec, mach_task_self (), EXEC_DEFAULTS, shell,
++ sh_args, sh_args_len, env, env_len,
++ fds, MACH_MSG_TYPE_COPY_SEND, 3,
++ ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
++ ints, INIT_INT_MAX,
++ 0, 0, 0, 0);
++ /* Fallback in case the file server hasn't been restarted. */
++ if (err == MIG_BAD_ID)
++#endif
++ err = file_exec (exec, mach_task_self (), EXEC_DEFAULTS,
++ sh_args, sh_args_len, env, env_len,
++ fds, MACH_MSG_TYPE_COPY_SEND, 3,
++ ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
++ ints, INIT_INT_MAX,
++ 0, 0, 0, 0);
+ if (err)
+ error(5, err, "%s", shell);
+
+diff --git a/utils/rpctrace.c b/utils/rpctrace.c
+index d7ee203..e9b634a 100644
+--- a/utils/rpctrace.c
++++ b/utils/rpctrace.c
+@@ -1734,7 +1734,11 @@ traced_spawn (char **argv, char **envp)
+ /* Now actually run the command they told us to trace. We do the exec on
+ the actual task, so the RPCs to map in the program itself do not get
+ traced. Could have an option to use TASK_WRAPPER here instead. */
++#ifdef HAVE__HURD_EXEC_FILE_NAME
++ err = _hurd_exec_file_name (traced_task, file, *argv, argv, envp);
++#else
+ err = _hurd_exec (traced_task, file, argv, envp);
++#endif
+ if (err)
+ error (2, err, "cannot exec `%s'", argv[0]);
+
+diff --git a/utils/shd.c b/utils/shd.c
+index a1a4b26..855284f 100644
+--- a/utils/shd.c
++++ b/utils/shd.c
+@@ -1,5 +1,5 @@
+ /*
+- Copyright (C) 1994,95,99,2002 Free Software Foundation
++ Copyright (C) 1994, 1995, 1999, 2002, 2010 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+@@ -159,15 +159,18 @@ run (char **argv, int fd0, int fd1)
+ movefd (fd1, 1, &save1))
+ return -1;
+
++#ifdef HAVE__HURD_EXEC_FILE_NAME
++ err = _hurd_exec_file_name (task, file, program, argv, environ);
++#else
+ err = _hurd_exec (task, file, argv, environ);
+-
++#endif
+ if (restorefd (fd0, 0, &save0) ||
+ restorefd (fd1, 1, &save1))
+ return -1;
+
+ if (err)
+ {
+- error (0, err, "_hurd_exec");
++ error (0, err, "_hurd_exec_file_name");
+ err = task_terminate (task);
+ if (err)
+ error (0, err, "task_terminate");