diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:40:15 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:40:15 +0000 |
commit | 399644e47874bff147afb19c89228901ac39340e (patch) | |
tree | 1c4c0b733f4c16b5783b41bebb19194a9ef62ad1 /man2/close_range.2 | |
parent | Initial commit. (diff) | |
download | manpages-399644e47874bff147afb19c89228901ac39340e.tar.xz manpages-399644e47874bff147afb19c89228901ac39340e.zip |
Adding upstream version 6.05.01.upstream/6.05.01
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'man2/close_range.2')
-rw-r--r-- | man2/close_range.2 | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/man2/close_range.2 b/man2/close_range.2 new file mode 100644 index 0000000..c1aa3db --- /dev/null +++ b/man2/close_range.2 @@ -0,0 +1,273 @@ +.\" Copyright (c) 2020 Stephen Kitt <steve@sk2.org> +.\" and Copyright (c) 2021 Michael Kerrisk <mtk.manpages@gmail.com> +.\" +.\" SPDX-License-Identifier: Linux-man-pages-copyleft +.\" +.TH close_range 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +close_range \- close all file descriptors in a given range +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.B #include <linux/close_range.h> +.PP +.BI "int close_range(unsigned int " first ", unsigned int " last , +.BI " unsigned int " flags ); +.fi +.SH DESCRIPTION +The +.BR close_range () +system call closes all open file descriptors from +.I first +to +.I last +(included). +.PP +Errors closing a given file descriptor are currently ignored. +.PP +.I flags +is a bit mask containing 0 or more of the following: +.TP +.BR CLOSE_RANGE_CLOEXEC " (since Linux 5.11)" +Set the close-on-exec flag on the specified file descriptors, +rather than immediately closing them. +.TP +.B CLOSE_RANGE_UNSHARE +Unshare the specified file descriptors from any other processes +before closing them, +avoiding races with other threads sharing the file descriptor table. +.SH RETURN VALUE +On success, +.BR close_range () +returns 0. +On error, \-1 is returned and +.I errno +is set to indicate the error. +.SH ERRORS +.TP +.B EINVAL +.I flags +is not valid, or +.I first +is greater than +.IR last . +.PP +The following can occur with +.B CLOSE_RANGE_UNSHARE +(when constructing the new descriptor table): +.TP +.B EMFILE +The number of open file descriptors exceeds the limit specified in +.I /proc/sys/fs/nr_open +(see +.BR proc (5)). +This error can occur in situations where that limit was lowered before +a call to +.BR close_range () +where the +.B CLOSE_RANGE_UNSHARE +flag is specified. +.TP +.B ENOMEM +Insufficient kernel memory was available. +.SH STANDARDS +None. +.SH HISTORY +FreeBSD. +Linux 5.9, +glibc 2.34. +.SH NOTES +.SS Closing all open file descriptors +.\" 278a5fbaed89dacd04e9d052f4594ffd0e0585de +To avoid blindly closing file descriptors +in the range of possible file descriptors, +this is sometimes implemented (on Linux) +by listing open file descriptors in +.I /proc/self/fd/ +and calling +.BR close (2) +on each one. +.BR close_range () +can take care of this without requiring +.I /proc +and within a single system call, +which provides significant performance benefits. +.SS Closing file descriptors before exec +.\" 60997c3d45d9a67daf01c56d805ae4fec37e0bd8 +File descriptors can be closed safely using +.PP +.in +4n +.EX +/* we don't want anything past stderr here */ +close_range(3, \[ti]0U, CLOSE_RANGE_UNSHARE); +execve(....); +.EE +.in +.PP +.B CLOSE_RANGE_UNSHARE +is conceptually equivalent to +.PP +.in +4n +.EX +unshare(CLONE_FILES); +close_range(first, last, 0); +.EE +.in +.PP +but can be more efficient: +if the unshared range extends past +the current maximum number of file descriptors allocated +in the caller's file descriptor table +(the common case when +.I last +is \[ti]0U), +the kernel will unshare a new file descriptor table for the caller up to +.IR first , +copying as few file descriptors as possible. +This avoids subsequent +.BR close (2) +calls entirely; +the whole operation is complete once the table is unshared. +.SS Closing files on \fBexec\fP +.\" 582f1fb6b721facf04848d2ca57f34468da1813e +This is particularly useful in cases where multiple +.RB pre- exec +setup steps risk conflicting with each other. +For example, setting up a +.BR seccomp (2) +profile can conflict with a +.BR close_range () +call: +if the file descriptors are closed before the +.BR seccomp (2) +profile is set up, +the profile setup can't use them itself, +or control their closure; +if the file descriptors are closed afterwards, +the seccomp profile can't block the +.BR close_range () +call or any fallbacks. +Using +.B CLOSE_RANGE_CLOEXEC +avoids this: +the descriptors can be marked before the +.BR seccomp (2) +profile is set up, +and the profile can control access to +.BR close_range () +without affecting the calling process. +.SH EXAMPLES +The program shown below opens the files named in its command-line arguments, +displays the list of files that it has opened +(by iterating through the entries in +.IR /proc/PID/fd ), +uses +.BR close_range () +to close all file descriptors greater than or equal to 3, +and then once more displays the process's list of open files. +The following example demonstrates the use of the program: +.PP +.in +4n +.EX +$ \fBtouch /tmp/a /tmp/b /tmp/c\fP +$ \fB./a.out /tmp/a /tmp/b /tmp/c\fP +/tmp/a opened as FD 3 +/tmp/b opened as FD 4 +/tmp/c opened as FD 5 +/proc/self/fd/0 ==> /dev/pts/1 +/proc/self/fd/1 ==> /dev/pts/1 +/proc/self/fd/2 ==> /dev/pts/1 +/proc/self/fd/3 ==> /tmp/a +/proc/self/fd/4 ==> /tmp/b +/proc/self/fd/5 ==> /tmp/b +/proc/self/fd/6 ==> /proc/9005/fd +========= About to call close_range() ======= +/proc/self/fd/0 ==> /dev/pts/1 +/proc/self/fd/1 ==> /dev/pts/1 +/proc/self/fd/2 ==> /dev/pts/1 +/proc/self/fd/3 ==> /proc/9005/fd +.EE +.in +.PP +Note that the lines showing the pathname +.I /proc/9005/fd +result from the calls to +.BR opendir (3). +.SS Program source +\& +.\" SRC BEGIN (close_range.c) +.EX +#define _GNU_SOURCE +#include <dirent.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/syscall.h> +#include <unistd.h> +\& +/* Show the contents of the symbolic links in /proc/self/fd */ +\& +static void +show_fds(void) +{ + DIR *dirp; + char path[PATH_MAX], target[PATH_MAX]; + ssize_t len; + struct dirent *dp; +\& + dirp = opendir("/proc/self/fd"); + if (dirp == NULL) { + perror("opendir"); + exit(EXIT_FAILURE); + } +\& + for (;;) { + dp = readdir(dirp); + if (dp == NULL) + break; +\& + if (dp\->d_type == DT_LNK) { + snprintf(path, sizeof(path), "/proc/self/fd/%s", + dp\->d_name); +\& + len = readlink(path, target, sizeof(target)); + printf("%s ==> %.*s\en", path, (int) len, target); + } + } +\& + closedir(dirp); +} +\& +int +main(int argc, char *argv[]) +{ + int fd; +\& + for (size_t j = 1; j < argc; j++) { + fd = open(argv[j], O_RDONLY); + if (fd == \-1) { + perror(argv[j]); + exit(EXIT_FAILURE); + } + printf("%s opened as FD %d\en", argv[j], fd); + } +\& + show_fds(); +\& + printf("========= About to call close_range() =======\en"); +\& + if (syscall(SYS_close_range, 3, \[ti]0U, 0) == \-1) { + perror("close_range"); + exit(EXIT_FAILURE); + } +\& + show_fds(); + exit(EXIT_FAILURE); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR close (2) |