From f16317f50e663ac0343bc96c01496f6b94c6211c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= 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