execveat(2)
๐ execveat(2) โ the "run this program, but like, relative to a dirfd" girlie ๐
okay bestie, come sit with me โ this is page 2 of the System Calls Manual, and today we're talking about execveat, the syscall that's basically execve(2)'s cooler cousin who shows up with a directory file descriptor and a vibe. ๐ฆ
โจ NAME โจ
execveat โ execute program relative to a directory file descriptor
๐ LIBRARY ๐
Standard C library (libc, -lc)
๐ SYNOPSIS ๐
#include <linux/fcntl.h> /* Definition of AT_* constants */
#include <unistd.h>
int execveat(int dirfd, const char *path,
char *const _Nullable argv[],
char *const _Nullable envp[],
int flags);
๐ธ DESCRIPTION ๐ธ
So the execveat() system call executes the program referred to by the combination of dirfd and path. It operates in exactly the same way as execve(2) โ like, literally the same energy โ except for the differences described in this manual page. No cap. ๐
If path is relative, then it is interpreted relative to the directory referred to by the file descriptor dirfd (rather than relative to the current working directory of the calling process, as is done by execve(2) for a relative pathname). That's the whole glow-up, bestie.
If path is relative and dirfd is the special value AT_FDCWD, then path is interpreted relative to the current working directory of the calling process (like execve(2)). So it's the same old behavior, but make it fashion. โจ
If path is absolute, then dirfd is ignored. Not even looked at. She's not the main character in that scene. ๐
If path is an empty string and the AT_EMPTY_PATH flag is specified, then the file descriptor dirfd specifies the file to be executed (i.e., dirfd refers to an executable file, rather than a directory). Iconic behavior honestly. ๐
The flags argument is a bit mask that can include zero or more of the following flags:
AT_EMPTY_PATHโ Ifpathis an empty string, operate on the file referred to bydirfd(which may have been obtained using theopen(2)O_PATHflag). Empty string, but make it count. ๐ซถAT_SYMLINK_NOFOLLOWโ If the file identified bydirfdand a non-NULLpathis a symbolic link, then the call fails with the errorELOOP. Do not pass go, do not collect $200, justELOOP. ๐ญ
โญ RETURN VALUE โญ
On success, execveat() does not return. Like, she's gone, she left the group chat, she is the new program now. ๐ On error, -1 is returned, and errno is set to indicate the error.
๐ ERRORS ๐
The same errors that occur for execve(2) can also occur for execveat(). The following additional errors can occur for execveat():
<unnamed>โpathis relative butdirfdis neitherAT_FDCWDnor a valid file descriptor.EINVALโ Invalid flag specified inflags.ELOOPโflagsincludesAT_SYMLINK_NOFOLLOWand the file identified bydirfdand a non-NULLpathis a symbolic link.ENOENTโ The program identified bydirfdandpathrequires the use of an interpreter program (such as a script starting with"#!"), but the file descriptordirfdwas opened with theO_CLOEXECflag, with the result that the program file is inaccessible to the launched interpreter. See BUGS.ENOTDIRโpathis relative anddirfdis a file descriptor referring to a file other than a directory.
ngl bestie the ENOENT one is spicy โ it's not "file not found", it's "the interpreter literally can't reach the file". Lowkey the plot twist of this whole page. ๐
๐ง STANDARDS ๐ง
Linux.
๐ HISTORY ๐
Linux 3.19, glibc 2.34.
๐ NOTES ๐
In addition to the reasons explained in openat(2), the execveat() system call is also needed to allow fexecve(3) to be implemented on systems that do not have the /proc filesystem mounted. Yes queen, she's carrying the whole /proc-less team on her back. ๐
When asked to execute a script file, the argv[0] that is passed to the script interpreter is a string of the form /dev/fd/N or /dev/fd/N/P, where N is the number of the file descriptor passed via the dirfd argument. A string of the first form occurs when AT_EMPTY_PATH is employed. A string of the second form occurs when the script is specified via both dirfd and path; in this case, P is the value given in path. โจ two forms, one legend.
For the same reasons described in fexecve(3), the natural idiom when using execveat() is to set the close-on-exec flag on dirfd. (But see BUGS.) ๐
๐ BUGS ๐
The ENOENT error described above means that it is not possible to set the close-on-exec flag on the file descriptor given to a call of the form:
execveat(fd, "", argv, envp, AT_EMPTY_PATH);
However, the inability to set the close-on-exec flag means that a file descriptor referring to the script leaks through to the script itself. As well as wasting a file descriptor, this leakage can lead to file-descriptor exhaustion in scenarios where scripts recursively employ execveat(). ๐ญ
Not the recursive leak. Bestie please close your fds, I am BEGGING. ๐
๐ฆ SEE ALSO ๐ฆ
and that's the whole page, pookie ๐ This little love letter comes to you from Linux man-pages 6.20, dated 2026-02-08, and yes, execveat(2) is still out here executing programs relative to directory file descriptors like the icon she is. Slay, stay safe, and set your O_CLOEXEC flags. ๐โจ๐
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- Copyright 2014, Google, Inc
- Copyright 2015, Michael Kerrisk <mtk.manpages@gmail.com>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms