Blob Blame History Raw
From f16317f50e663ac0343bc96c01496f6b94c6211c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nikola=20Forr=C3=B3?= <nforro@redhat.com>
Date: Mon, 26 Nov 2018 17:10:36 +0100
Subject: [PATCH] execve.2: document EAGAIN error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 man-pages/man2/execve.2 | 78 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/man-pages/man2/execve.2 b/man-pages/man2/execve.2
index 3343372..192b90a 100644
--- a/man-pages/man2/execve.2
+++ b/man-pages/man2/execve.2
@@ -384,6 +384,16 @@ Execute permission is denied for the file or a script or ELF interpreter.
 The file system 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
 points outside your accessible address space.
@@ -530,6 +540,74 @@ 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.
+
+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).
+In Linux 3.0 and earlier, this caused the
+.BR set*uid ()
+call to fail.
+
+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 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 ().
+
+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
 .BR exec ()
-- 
2.17.2