]> git.ipfire.org Git - thirdparty/man-pages.git/blobdiff - man2/execve.2
execve.2, setfsgid.2, setfsuid.2, splice.2, fopen.3, malloc_trim.3, posix_memalign...
[thirdparty/man-pages.git] / man2 / execve.2
index 66781aff7d583a9334288bffc89b98a7b5091acf..119af8d007185d36d0c700e2a09f412db00e7ec8 100644 (file)
@@ -1,8 +1,7 @@
-.\" Hey Emacs! This file is -*- nroff -*- source.
-.\"
 .\" Copyright (c) 1992 Drew Eckhardt (drew@cs.colorado.edu), March 28, 1992
 .\" and Copyright (c) 2006 Michael Kerrisk <mtk.manpages@gmail.com>
 .\"
+.\" %%%LICENSE_START(VERBATIM)
 .\" Permission is granted to make and distribute verbatim copies of this
 .\" manual provided the copyright notice and this permission notice are
 .\" preserved on all copies.
@@ -22,6 +21,7 @@
 .\"
 .\" Formatted or processed versions of this manual, if unaccompanied by
 .\" the source, must acknowledge the copyright and authors of this work.
+.\" %%%LICENSE_END
 .\"
 .\" Modified by Michael Haardt <michael@moria.de>
 .\" Modified 1993-07-21 by Rik Faith <faith@cs.unc.edu>
 .\" 2007-09-14 Ollie Wild <aaw@google.com>, mtk
 .\"     Add text describing limits on command-line arguments + environment
 .\"
-.TH EXECVE 2 2012-05-04 "Linux" "Linux Programmer's Manual"
+.TH EXECVE 2 2019-05-09 "Linux" "Linux Programmer's Manual"
 .SH NAME
 execve \- execute program
 .SH SYNOPSIS
 .B #include <unistd.h>
-.sp
-.BI "int execve(const char *" filename ", char *const " argv "[], "
+.PP
+.BI "int execve(const char *" pathname ", char *const " argv "[], "
 .br
 .BI "           char *const " envp []);
 .SH DESCRIPTION
 .BR execve ()
-executes the program pointed to by \fIfilename\fP.
-\fIfilename\fP must be either a binary executable, or a script
+executes the program referred to by \fIpathname\fP.
+This causes the program that is currently being run by the calling process
+to be replaced with a new program, with newly initialized stack, heap,
+and (initialized and uninitialized) data segments.
+.PP
+\fIpathname\fP must be either a binary executable, or a script
 starting with a line of the form:
-
+.PP
 .in +4n
-.nf
+.EX
 \fB#!\fP \fIinterpreter \fP[optional-arg]
-.fi
+.EE
 .in
-
+.PP
 For details of the latter case, see "Interpreter scripts" below.
-
+.PP
 \fIargv\fP is an array of argument strings passed to the new program.
-By convention, the first of these strings should contain the filename
-associated with the file being executed.
+By convention, the first of these strings (i.e.,
+.IR argv[0] )
+should contain the filename associated with the file being executed.
 \fIenvp\fP is an array of strings, conventionally of the form
 \fBkey=value\fP, which are passed as environment to the new program.
-Both \fIargv\fP and \fIenvp\fP must be terminated by a NULL pointer.
+The \fIargv\fP and \fIenvp\fP arrays must each include a null pointer
+at the end of the array.
+.PP
 The argument vector and environment can be accessed by the
 called program's main function, when it is defined as:
-
+.PP
 .in +4n
-.nf
+.EX
 int main(int argc, char *argv[], char *envp[])
-.fi
+.EE
 .in
-
+.PP
+Note, however, that the use of a third argument to the main function
+is not specified in POSIX.1;
+according to POSIX.1,
+the environment should be accessed via the external variable
+.BR environ (7).
+.PP
 .BR execve ()
-does not return on success, and the text, data, bss, and
-stack of the calling process are overwritten by that of the program
-loaded.
-
-If the current program is being ptraced, a \fBSIGTRAP\fP is sent to it
+does not return on success, and the text, initialized data,
+uninitialized data (bss), and stack of the calling process are overwritten
+according to the contents of the newly loaded program.
+.PP
+If the current program is being ptraced, a \fBSIGTRAP\fP signal is sent to it
 after a successful
 .BR execve ().
-
-If the set-user-ID bit is set on the program file pointed to by
-\fIfilename\fP,
-and the underlying file system is not mounted
-.I nosuid
-(the
-.B MS_NOSUID
-flag for
-.BR mount (2)),
-and the calling process is not being ptraced,
+.PP
+If the set-user-ID bit is set on the program file referred to by
+\fIpathname\fP,
 then the effective user ID of the calling process is changed
 to that of the owner of the program file.
 Similarly, when the set-group-ID
 bit of the program file is set the effective group ID of the calling
 process is set to the group of the program file.
-
+.PP
+The aforementioned transformations of the effective IDs are
+.I not
+performed (i.e., the set-user-ID and set-group-ID bits are ignored)
+if any of the following is true:
+.IP * 3
+the
+.I no_new_privs
+attribute is set for the calling thread (see
+.BR prctl (2));
+.IP *
+the underlying filesystem is mounted
+.I nosuid
+(the
+.B MS_NOSUID
+flag for
+.BR mount (2));
+or
+.IP *
+the calling process is being ptraced.
+.PP
+The capabilities of the program file (see
+.BR capabilities (7))
+are also ignored if any of the above are true.
+.PP
 The effective user ID of the process is copied to the saved set-user-ID;
 similarly, the effective group ID is copied to the saved set-group-ID.
 This copying takes place after any effective ID changes that occur
-because of the set-user-ID and set-group-ID permission bits.
-
+because of the set-user-ID and set-group-ID mode bits.
+.PP
+The process's real UID and real GID, as well its supplementary group IDs,
+are unchanged by a call to
+.BR execve ().
+.PP
 If the executable is an a.out dynamically linked
 binary executable containing
 shared-library stubs, the Linux dynamic linker
 .BR ld.so (8)
 is called at the start of execution to bring
-needed shared libraries into memory
+needed shared objects into memory
 and link the executable with them.
-
+.PP
 If the executable is a dynamically linked ELF executable, the
 interpreter named in the PT_INTERP segment is used to load the needed
-shared libraries.
+shared objects.
 This interpreter is typically
 .I /lib/ld-linux.so.2
-for binaries linked with glibc 2.
-(For binaries linked with the old Linux libc5, the interpreter was typically
-.IR /lib/ld-linux.so.1 .)
-
+for binaries linked with glibc (see
+.BR ld-linux.so (8)).
+.PP
 All process attributes are preserved during an
 .BR execve (),
 except the following:
@@ -132,7 +165,7 @@ Any alternate signal stack is not preserved
 Memory mappings are not preserved
 .RB ( mmap (2)).
 .IP *
-Attached System V shared memory segments are detached
+Attached System\ V shared memory segments are detached
 .RB ( shmat (2)).
 .IP *
 POSIX shared memory regions are unmapped
@@ -162,7 +195,7 @@ The floating-point environment is reset to the default (see
 .BR fenv (3)).
 .PP
 The process attributes in the preceding list are all specified
-in POSIX.1-2001.
+in POSIX.1.
 The following Linux-specific process attributes are also
 not preserved during an
 .BR execve ():
@@ -179,6 +212,13 @@ The
 .B PR_SET_KEEPCAPS
 flag is cleared.
 .IP *
+(Since Linux 2.4.36 / 2.6.23)
+If a set-user-ID or set-group-ID program is being executed,
+then the parent death signal set by
+.BR prctl (2)
+.B PR_SET_PDEATHSIG
+flag is cleared.
+.IP *
 The process name, as set by
 .BR prctl (2)
 .B PR_SET_NAME
@@ -186,10 +226,22 @@ The process name, as set by
 .IR "ps\ \-o comm" ),
 is reset to the name of the new executable file.
 .IP *
+The
+.B SECBIT_KEEP_CAPS
+.I securebits
+flag is cleared.
+See
+.BR capabilities (7).
+.IP *
 The termination signal is reset to
 .B SIGCHLD
 (see
 .BR clone (2)).
+.IP *
+The file descriptor table is unshared, undoing the effect of the
+.B CLONE_FILES
+flag of
+.BR clone (2).
 .PP
 Note the following further points:
 .IP * 3
@@ -200,9 +252,9 @@ Mutexes, condition variables, and other pthreads objects are not preserved.
 The equivalent of \fIsetlocale(LC_ALL, "C")\fP
 is executed at program start-up.
 .IP *
-POSIX.1-2001 specifies that the dispositions of any signals that
+POSIX.1 specifies that the dispositions of any signals that
 are ignored or set to the default are left unchanged.
-POSIX.1-2001 specifies one exception: if
+POSIX.1 specifies one exception: if
 .B SIGCHLD
 is being ignored,
 then an implementation may leave the disposition unchanged or
@@ -229,11 +281,11 @@ of all record locks obtained on the underlying file by this process.
 See
 .BR fcntl (2)
 for details.)
-POSIX.1-2001 says that if file descriptors 0, 1, and 2 would
+POSIX.1 says that if file descriptors 0, 1, and 2 would
 otherwise be closed after a successful
 .BR execve (),
-and the process would gain privilege because the set-user_ID or
-set-group_ID permission bit was set on the executed file,
+and the process would gain privilege because the set-user-ID or
+set-group_ID mode bit was set on the executed file,
 then the system may open an unspecified file for each of these
 file descriptors.
 As a general principle, no portable program, whether privileged or not,
@@ -246,43 +298,51 @@ closed across an
 .SS Interpreter scripts
 An interpreter script is a text file that has execute
 permission enabled and whose first line is of the form:
-
+.PP
 .in +4n
-.nf
+.EX
 \fB#!\fP \fIinterpreter \fP[optional-arg]
-.fi
+.EE
 .in
-
+.PP
 The
 .I interpreter
-must be a valid pathname for an
-executable which is not itself a script.
+must be a valid pathname for an executable file.
 If the
-.I filename
+.I pathname
 argument of
 .BR execve ()
 specifies an interpreter script, then
 .I interpreter
 will be invoked with the following arguments:
-
+.PP
 .in +4n
-.nf
-\fIinterpreter\fP [optional-arg] \fIfilename\fP arg...
-.fi
+.EX
+\fIinterpreter\fP [optional-arg] \fIpathname\fP arg...
+.EE
 .in
-
+.PP
 where
 .I arg...
 is the series of words pointed to by the
 .I argv
 argument of
-.BR execve ().
-
+.BR execve (),
+starting at
+.IR argv [1].
+.PP
 For portable use,
 .I optional-arg
 should either be absent, or be specified as a single word (i.e., it
 should not contain white space); see NOTES below.
-.SS "Limits on size of arguments and environment"
+.PP
+Since Linux 2.6.28,
+.\" commit bf2a9a39639b8b51377905397a5005f444e9a892
+the kernel permits the interpreter of a script to itself be a script.
+This permission is recursive, up to a limit of four recursions,
+so that the interpreter may be a script which is interpreted by a script,
+and so on.
+.SS Limits on size of arguments and environment
 Most UNIX implementations impose some limit on the total size
 of the command-line argument
 .RI ( argv )
@@ -295,14 +355,14 @@ constant (either defined in
 .I <limits.h>
 or available at run time using the call
 .IR "sysconf(_SC_ARG_MAX)" ).
-
+.PP
 On Linux prior to kernel 2.6.23, the memory used to store the
 environment and argument strings was limited to 32 pages
 (defined by the kernel constant
 .BR MAX_ARG_PAGES ).
 On architectures with a 4-kB page size,
-this yields a maximum size of 128 kB.
-
+this yields a maximum size of 128\ kB.
+.PP
 On kernel 2.6.23 and later, most architectures support a size limit
 derived from the soft
 .B RLIMIT_STACK
@@ -327,8 +387,12 @@ stack size.
 ensures that the new program always has some stack space.)
 .\" Ollie: That doesn't include the lists of pointers, though,
 .\" so the actual usage is a bit higher (1 pointer per argument).
+Additionally, the total size is limited to 3/4 of the value
+of the kernel constant
+.B _STK_LIM
+(8 Mibibytes).
 Since Linux 2.6.25,
-the kernel places a floor of 32 pages on this size limit,
+the kernel also places a floor of 32 pages on this size limit,
 so that, even when
 .BR RLIMIT_STACK
 is set very low,
@@ -338,7 +402,7 @@ environment space as was provided by Linux 2.6.23 and earlier.
 Additionally, the limit per string is 32 pages (the kernel constant
 .BR MAX_ARG_STRLEN ),
 and the maximum number of strings is 0x7FFFFFFF.
-.SH "RETURN VALUE"
+.SH RETURN VALUE
 On success,
 .BR execve ()
 does not return, on error \-1 is returned, and
@@ -355,7 +419,7 @@ is too large.
 .TP
 .B EACCES
 Search permission is denied on a component of the path prefix of
-.I filename
+.I pathname
 or the name of a script interpreter.
 (See also
 .BR path_resolution (7).)
@@ -367,11 +431,25 @@ The file or a script interpreter is not a regular file.
 Execute permission is denied for the file or a script or ELF interpreter.
 .TP
 .B EACCES
-The file system is mounted
+The filesystem is mounted
 .IR noexec .
 .TP
+.BR EAGAIN " (since Linux 3.1)"
+.\" commit 72fa59970f8698023045ab0713d66f3f4f96945c
+Having changed its real UID using one of the
+.BR set*uid ()
+calls, the caller was\(emand is now still\(emabove its
+.BR RLIMIT_NPROC
+resource limit (see
+.BR setrlimit (2)).
+For a more detailed explanation of this error, see NOTES.
+.TP
 .B EFAULT
-.I filename
+.I pathname
+or one of the pointers in the vectors
+.I argv
+or
+.I envp
 points outside your accessible address space.
 .TP
 .B EINVAL
@@ -389,24 +467,33 @@ An ELF interpreter was not in a recognized format.
 .TP
 .B ELOOP
 Too many symbolic links were encountered in resolving
-.I filename
+.I pathname
 or the name of a script or ELF interpreter.
 .TP
+.B ELOOP
+The maximum recursion limit was reached during recursive script
+interpretation (see "Interpreter scripts", above).
+Before Linux 3.8,
+.\" commit d740269867021faf4ce38a449353d2b986c34a67
+the error produced for this case was
+.BR ENOEXEC .
+.TP
 .B EMFILE
-The process has the maximum number of files open.
+The per-process limit on the number of open file descriptors has been reached.
 .TP
 .B ENAMETOOLONG
-.I filename
+.I pathname
 is too long.
 .TP
 .B ENFILE
-The system limit on the total number of open files has been reached.
+The system-wide limit on the total number of open files has been reached.
 .TP
 .B ENOENT
 The file
-.I filename
+.I pathname
 or a script or ELF interpreter does not exist, or a shared library
-needed for file or interpreter cannot be found.
+.\" FIXME but see http://sourceware.org/bugzilla/show_bug.cgi?id=12241
+needed for the file or interpreter cannot be found.
 .TP
 .B ENOEXEC
 An executable is not in a recognized format, is for the wrong
@@ -418,11 +505,11 @@ Insufficient kernel memory was available.
 .TP
 .B ENOTDIR
 A component of the path prefix of
-.I filename
+.I pathname
 or a script or ELF interpreter is not a directory.
 .TP
 .B EPERM
-The file system is mounted
+The filesystem is mounted
 .IR nosuid ,
 the user is not the superuser,
 and the file has the set-user-ID or set-group-ID bit set.
@@ -431,36 +518,104 @@ and the file has the set-user-ID or set-group-ID bit set.
 The process is being traced, the user is not the superuser and the
 file has the set-user-ID or set-group-ID bit set.
 .TP
+.B EPERM
+A "capability-dumb" applications would not obtain the full set of
+permitted capabilities granted by the executable file.
+See
+.BR capabilities (7).
+.TP
 .B ETXTBSY
-Executable was open for writing by one or more processes.
-.SH "CONFORMING TO"
-SVr4, 4.3BSD, POSIX.1-2001.
-POSIX.1-2001 does not document the #!  behavior
-but is otherwise compatible.
+The specified executable was open for writing by one or more processes.
+.SH CONFORMING TO
+POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
+POSIX does not document the #! behavior, but it exists
+(with some variations) on other UNIX systems.
 .\" SVr4 documents additional error
 .\" conditions EAGAIN, EINTR, ELIBACC, ENOLINK, EMULTIHOP; POSIX does not
 .\" document ETXTBSY, EPERM, EFAULT, ELOOP, EIO, ENFILE, EMFILE, EINVAL,
 .\" EISDIR or ELIBBAD error conditions.
 .SH NOTES
+One sometimes sees
+.BR execve ()
+(and the related functions described in
+.BR exec (3))
+described as "executing a
+.I new
+process" (or similar).
+This is a highly misleading description:
+there is no new process;
+many attributes of the calling process remain unchanged
+(in particular, its PID).
+All that
+.BR execve (2)
+does is arrange for an existing process (the calling process)
+to execute a new program.
+.PP
 Set-user-ID and set-group-ID processes can not be
 .BR ptrace (2)d.
-
-Linux ignores the set-user-ID and set-group-ID bits on scripts.
-
-The result of mounting a file system
+.PP
+The result of mounting a filesystem
 .I nosuid
 varies across Linux kernel versions:
 some will refuse execution of set-user-ID and set-group-ID
 executables when this would
-give the user powers she did not have already (and return
+give the user powers they did not have already (and return
 .BR EPERM ),
 some will just ignore the set-user-ID and set-group-ID bits and
 .BR exec ()
 successfully.
-
+.PP
+On Linux,
+.I argv
+and
+.I envp
+can be specified as NULL.
+In both cases, this has the same effect as specifying the argument
+as a pointer to a list containing a single null pointer.
+.B "Do not take advantage of this nonstandard and nonportable misfeature!"
+On many other UNIX systems, specifying
+.I argv
+as NULL will result in an error
+.RB ( EFAULT ).
+.I Some
+other UNIX systems treat the
+.I envp==NULL
+case the same as Linux.
+.\" e.g., EFAULT on Solaris 8 and FreeBSD 6.1; but
+.\" HP-UX 11 is like Linux -- mtk, Apr 2007
+.\" Bug filed 30 Apr 2007: http://bugzilla.kernel.org/show_bug.cgi?id=8408
+.\" Bug rejected (because fix would constitute an ABI change).
+.\"
+.PP
+POSIX.1 says that values returned by
+.BR sysconf (3)
+should be invariant over the lifetime of a process.
+However, since Linux 2.6.23, if the
+.BR RLIMIT_STACK
+resource limit changes, then the value reported by
+.B _SC_ARG_MAX
+will also change,
+to reflect the fact that the limit on space for holding
+command-line arguments and environment variables has changed.
+.PP
+In most cases where
+.BR execve ()
+fails, control returns to the original executable image,
+and the caller of
+.BR execve ()
+can then handle the error.
+However, in (rare) cases (typically caused by resource exhaustion),
+failure may occur past the point of no return:
+the original executable image has been torn down,
+but the new image could not be completely built.
+In such cases, the kernel kills the process with a
+.BR SIGKILL
+signal.
+.\"
+.SS Interpreter scripts
 A maximum line length of 127 characters is allowed for the first line in
-a #! executable shell script.
-
+an interpreter script.
+.PP
 The semantics of the
 .I optional-arg
 argument of an interpreter script vary across implementations.
@@ -479,32 +634,8 @@ an interpreter script can have multiple arguments,
 and white spaces in
 .I optional-arg
 are used to delimit the arguments.
-
-On Linux,
-.I argv
-can be specified as NULL,
-which has the same effect as specifying this argument
-as a pointer to a list containing a single NULL pointer.
-.B "Do not take advantage of this misfeature!"
-It is nonstandard and nonportable:
-on most other UNIX systems doing this will result in an error
-.RB ( EFAULT ).
-.\" e.g., EFAULT on Solaris 8 and FreeBSD 6.1; but
-.\" HP-UX 11 is like Linux -- mtk, Apr 2007
-.\" Bug filed 30 Apr 2007: http://bugzilla.kernel.org/show_bug.cgi?id=8408
-.\" Bug rejected (because fix would constitute an ABI change).
-.\"
-
-POSIX.1-2001 says that values returned by
-.BR sysconf (3)
-should be invariant over the lifetime of a process.
-However, since Linux 2.6.23, if the
-.BR RLIMIT_STACK
-resource limit changes, then the value reported by
-.B _SC_ARG_MAX
-will also change,
-to reflect the fact that the limit on space for holding
-command-line arguments and environment variables has changed.
+.PP
+Linux ignores the set-user-ID and set-group-ID bits on scripts.
 .\"
 .\" .SH BUGS
 .\" Some Linux versions have failed to check permissions on ELF
@@ -514,8 +645,83 @@ command-line arguments and environment variables has changed.
 .\" .BR execve ()
 .\" that could be exploited for denial of service by a suitably crafted
 .\" ELF binary. There are no known problems with 2.0.34 or 2.2.15.
+.SS execve() and EAGAIN
+A more detailed explanation of the
+.BR EAGAIN
+error that can occur (since Linux 3.1) when calling
+.BR execve ()
+is as follows.
+.PP
+The
+.BR EAGAIN
+error can occur when a
+.I preceding
+call to
+.BR setuid (2),
+.BR setreuid (2),
+or
+.BR setresuid (2)
+caused the real user ID of the process to change,
+and that change caused the process to exceed its
+.BR RLIMIT_NPROC
+resource limit (i.e., the number of processes belonging
+to the new real UID exceeds the resource limit).
+From Linux 2.6.0 to 3.0, this caused the
+.BR set*uid ()
+call to fail.
+(Prior to 2.6,
+.\" commit 909cc4ae86f3380152a18e2a3c44523893ee11c4
+the resource limit was not imposed on processes that
+changed their user IDs.)
+.PP
+Since Linux 3.1, the scenario just described no longer causes the
+.BR set*uid ()
+call to fail,
+because it too often led to security holes where buggy applications
+didn't check the return status and assumed
+that\(emif the caller had root privileges\(emthe call would always succeed.
+Instead, the
+.BR set*uid ()
+calls now successfully change the real UID,
+but the kernel sets an internal flag, named
+.BR PF_NPROC_EXCEEDED ,
+to note that the
+.BR RLIMIT_NPROC
+resource limit has been exceeded.
+If the
+.BR PF_NPROC_EXCEEDED
+flag is set and the resource limit is still
+exceeded at the time of a subsequent
+.BR execve ()
+call, that call fails with the error
+.BR EAGAIN .
+This kernel logic ensures that the
+.BR RLIMIT_NPROC
+resource limit is still enforced for the
+common privileged daemon workflow\(emnamely,
+.BR fork (2)
++
+.BR set*uid ()
++
+.BR execve ().
+.PP
+If the resource limit was not still exceeded at the time of the
+.BR execve ()
+call
+(because other processes belonging to this real UID terminated between the
+.BR set*uid ()
+call and the
+.BR execve ()
+call), then the
+.BR execve ()
+call succeeds and the kernel clears the
+.BR PF_NPROC_EXCEEDED
+process flag.
+The flag is also cleared if a subsequent call to
+.BR fork (2)
+by this process succeeds.
 .SS Historical
-With UNIX V6 the argument list of an
+With UNIX\ V6, the argument list of an
 .BR exec ()
 call was ended by 0,
 while the argument list of
@@ -524,13 +730,22 @@ was ended by \-1.
 Thus, this argument list was not directly usable in a further
 .BR exec ()
 call.
-Since UNIX V7 both are NULL.
+Since UNIX\ V7, both are NULL.
+.\"
+.\" .SH BUGS
+.\" Some Linux versions have failed to check permissions on ELF
+.\" interpreters.  This is a security hole, because it allows users to
+.\" open any file, such as a rewinding tape device, for reading.  Some
+.\" Linux versions have also had other security holes in
+.\" .BR execve ()
+.\" that could be exploited for denial of service by a suitably crafted
+.\" ELF binary. There are no known problems with 2.0.34 or 2.2.15.
 .SH EXAMPLE
 The following program is designed to be execed by the second program below.
-It just echoes its command-line one per line.
-
+It just echoes its command-line arguments, one per line.
+.PP
 .in +4n
-.nf
+.EX
 /* myecho.c */
 
 #include <stdio.h>
@@ -542,18 +757,18 @@ main(int argc, char *argv[])
     int j;
 
     for (j = 0; j < argc; j++)
-        printf("argv[%d]: %s\\n", j, argv[j]);
+        printf("argv[%d]: %s\en", j, argv[j]);
 
     exit(EXIT_SUCCESS);
 }
-.fi
+.EE
 .in
-
+.PP
 This program can be used to exec the program named in its command-line
 argument:
+.PP
 .in +4n
-.nf
-
+.EX
 /* execve.c */
 
 #include <stdio.h>
@@ -567,66 +782,69 @@ main(int argc, char *argv[])
     char *newenviron[] = { NULL };
 
     if (argc != 2) {
-       fprintf(stderr, "Usage: %s <file\-to\-exec>\\n", argv[0]);
-       exit(EXIT_FAILURE);
+        fprintf(stderr, "Usage: %s <file\-to\-exec>\en", argv[0]);
+        exit(EXIT_FAILURE);
     }
 
     newargv[0] = argv[1];
 
     execve(argv[1], newargv, newenviron);
-    perror("execve");   /* execve() only returns on error */
+    perror("execve");   /* execve() returns only on error */
     exit(EXIT_FAILURE);
 }
-.fi
+.EE
 .in
-
+.PP
 We can use the second program to exec the first as follows:
-
+.PP
 .in +4n
-.nf
+.EX
 .RB "$" " cc myecho.c \-o myecho"
 .RB "$" " cc execve.c \-o execve"
 .RB "$" " ./execve ./myecho"
 argv[0]: ./myecho
 argv[1]: hello
 argv[2]: world
-.fi
+.EE
 .in
-
+.PP
 We can also use these programs to demonstrate the use of a script
 interpreter.
 To do this we create a script whose "interpreter" is our
 .I myecho
 program:
-
+.PP
 .in +4n
-.nf
-.RB "$" " cat > script.sh"
-.B #! ./myecho script-arg
+.EX
+.RB "$" " cat > script"
+.B #!./myecho script-arg
 .B ^D
-.RB "$" " chmod +x script.sh"
-.fi
+.RB "$" " chmod +x script"
+.EE
 .in
-
+.PP
 We can then use our program to exec the script:
-
+.PP
 .in +4n
-.nf
-.RB "$" " ./execve ./script.sh"
+.EX
+.RB "$" " ./execve ./script"
 argv[0]: ./myecho
 argv[1]: script-arg
-argv[2]: ./script.sh
+argv[2]: ./script
 argv[3]: hello
 argv[4]: world
-.fi
+.EE
 .in
-.SH "SEE ALSO"
+.SH SEE ALSO
 .BR chmod (2),
+.BR execveat (2),
 .BR fork (2),
+.BR get_robust_list (2),
 .BR ptrace (2),
-.BR execl (3),
+.BR exec (3),
 .BR fexecve (3),
 .BR getopt (3),
+.BR system (3),
 .BR credentials (7),
 .BR environ (7),
 .BR path_resolution (7),