выполнить программу (execute program)
Примечание (Note)
One sometimes sees execve
() (and the related functions described
in exec(3)) described as "executing a 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 execve
() does is arrange for an
existing process (the calling process) to execute a new program.
Set-user-ID and set-group-ID processes can not be ptrace(2)d.
The result of mounting a filesystem 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
they did not have already (and return EPERM
), some will just
ignore the set-user-ID and set-group-ID bits and exec
()
successfully.
On Linux, argv and 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. Do not take
advantage of this nonstandard and nonportable misfeature!
On
many other UNIX systems, specifying argv as NULL will result in
an error (EFAULT
). Some other UNIX systems treat the envp==NULL
case the same as Linux.
POSIX.1 says that values returned by sysconf(3) should be
invariant over the lifetime of a process. However, since Linux
2.6.23, if the RLIMIT_STACK
resource limit changes, then the
value reported by _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.
In most cases where execve
() fails, control returns to the
original executable image, and the caller of 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 SIGSEGV
(SIGKILL
until Linux
3.17) signal.
Interpreter scripts
The kernel imposes a maximum length on the text that follows the
"#!" characters at the start of a script; characters beyond the
limit are ignored. Before Linux 5.1, the limit is 127
characters. Since Linux 5.1, the limit is 255 characters.
The semantics of the optional-arg argument of an interpreter
script vary across implementations. On Linux, the entire string
following the interpreter name is passed as a single argument to
the interpreter, and this string can include white space.
However, behavior differs on some other systems. Some systems
use the first white space to terminate optional-arg. On some
systems, an interpreter script can have multiple arguments, and
white spaces in optional-arg are used to delimit the arguments.
Linux (like most other modern UNIX systems) ignores the set-user-
ID and set-group-ID bits on scripts.
execve() and EAGAIN
A more detailed explanation of the EAGAIN
error that can occur
(since Linux 3.1) when calling execve
() is as follows.
The EAGAIN
error can occur when a preceding call to setuid(2),
setreuid(2), or setresuid(2) caused the real user ID of the
process to change, and that change caused the process to exceed
its 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 set*uid
() call to fail.
(Prior to 2.6, the resource limit was not imposed on processes
that changed their user IDs.)
Since Linux 3.1, the scenario just described no longer causes the
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—if the caller had root privileges—the call would
always succeed. Instead, the set*uid
() calls now successfully
change the real UID, but the kernel sets an internal flag, named
PF_NPROC_EXCEEDED
, to note that the RLIMIT_NPROC
resource limit
has been exceeded. If the PF_NPROC_EXCEEDED
flag is set and the
resource limit is still exceeded at the time of a subsequent
execve
() call, that call fails with the error EAGAIN
. This
kernel logic ensures that the RLIMIT_NPROC
resource limit is
still enforced for the common privileged daemon workflow—namely,
fork(2) + set*uid
() + execve
().
If the resource limit was not still exceeded at the time of the
execve
() call (because other processes belonging to this real UID
terminated between the set*uid
() call and the execve
() call),
then the execve
() call succeeds and the kernel clears the
PF_NPROC_EXCEEDED
process flag. The flag is also cleared if a
subsequent call to fork(2) by this process succeeds.
Historical
With UNIX V6, the argument list of an exec
() call was ended by 0,
while the argument list of main was ended by -1. Thus, this
argument list was not directly usable in a further exec
() call.
Since UNIX V7, both are NULL.