1CLOSE_RANGE(2) Linux Programmer's Manual CLOSE_RANGE(2)
2
3
4
6 close_range - close all file descriptors in a given range
7
9 #include <linux/close_range.h>
10
11 int close_range(unsigned int first, unsigned int last,
12 unsigned int flags);
13
14 Note: There is no glibc wrapper for this system call; see NOTES.
15
17 The close_range() system call closes all open file descriptors from
18 first to last (included).
19
20 Errors closing a given file descriptor are currently ignored.
21
22 flags is a bit mask containing 0 or more of the following:
23
24 CLOSE_RANGE_CLOEXEC (since Linux 5.11)
25 Set the close-on-exec flag on the specified file descriptors,
26 rather than immediately closing them.
27
28 CLOSE_RANGE_UNSHARE
29 Unshare the specified file descriptors from any other processes
30 before closing them, avoiding races with other threads sharing
31 the file descriptor table.
32
34 On success, close_range() returns 0. On error, -1 is returned and er‐
35 rno is set to indicate the error.
36
38 EINVAL flags is not valid, or first is greater than last.
39
40 The following can occur with CLOSE_RANGE_UNSHARE (when constructing the
41 new descriptor table):
42
43 EMFILE The number of open file descriptors exceeds the limit specified
44 in /proc/sys/fs/nr_open (see proc(5)). This error can occur in
45 situations where that limit was lowered before a call to
46 close_range() where the CLOSE_RANGE_UNSHARE flag is specified.
47
48 ENOMEM Insufficient kernel memory was available.
49
51 close_range() first appeared in Linux 5.9.
52
54 close_range() is a nonstandard function that is also present on Free‐
55 BSD.
56
58 Glibc does not provide a wrapper for this system call; call it using
59 syscall(2).
60
61 Closing all open file descriptors
62 To avoid blindly closing file descriptors in the range of possible file
63 descriptors, this is sometimes implemented (on Linux) by listing open
64 file descriptors in /proc/self/fd/ and calling close(2) on each one.
65 close_range() can take care of this without requiring /proc and within
66 a single system call, which provides significant performance benefits.
67
68 Closing file descriptors before exec
69 File descriptors can be closed safely using
70
71 /* we don't want anything past stderr here */
72 close_range(3, ~0U, CLOSE_RANGE_UNSHARE);
73 execve(....);
74
75 CLOSE_RANGE_UNSHARE is conceptually equivalent to
76
77 unshare(CLONE_FILES);
78 close_range(first, last, 0);
79
80 but can be more efficient: if the unshared range extends past the cur‐
81 rent maximum number of file descriptors allocated in the caller's file
82 descriptor table (the common case when last is ~0U), the kernel will
83 unshare a new file descriptor table for the caller up to first, copying
84 as few file descriptors as possible. This avoids subsequent close(2)
85 calls entirely; the whole operation is complete once the table is un‐
86 shared.
87
88 Closing files on exec
89 This is particularly useful in cases where multiple pre-exec setup
90 steps risk conflicting with each other. For example, setting up a sec‐
91 comp(2) profile can conflict with a close_range() call: if the file de‐
92 scriptors are closed before the seccomp(2) profile is set up, the pro‐
93 file setup can't use them itself, or control their closure; if the file
94 descriptors are closed afterwards, the seccomp profile can't block the
95 close_range() call or any fallbacks. Using CLOSE_RANGE_CLOEXEC avoids
96 this: the descriptors can be marked before the seccomp(2) profile is
97 set up, and the profile can control access to close_range() without af‐
98 fecting the calling process.
99
101 The program shown below opens the files named in its command-line argu‐
102 ments, displays the list of files that it has opened (by iterating
103 through the entries in /proc/PID/fd), uses close_range() to close all
104 file descriptors greater than or equal to 3, and then once more dis‐
105 plays the process's list of open files. The following example demon‐
106 strates the use of the program:
107
108 $ touch /tmp/a /tmp/b /tmp/c
109 $ ./a.out /tmp/a /tmp/b /tmp/c
110 /tmp/a opened as FD 3
111 /tmp/b opened as FD 4
112 /tmp/c opened as FD 5
113 /proc/self/fd/0 ==> /dev/pts/1
114 /proc/self/fd/1 ==> /dev/pts/1
115 /proc/self/fd/2 ==> /dev/pts/1
116 /proc/self/fd/3 ==> /tmp/a
117 /proc/self/fd/4 ==> /tmp/b
118 /proc/self/fd/5 ==> /tmp/b
119 /proc/self/fd/6 ==> /proc/9005/fd
120 ========= About to call close_range() =======
121 /proc/self/fd/0 ==> /dev/pts/1
122 /proc/self/fd/1 ==> /dev/pts/1
123 /proc/self/fd/2 ==> /dev/pts/1
124 /proc/self/fd/3 ==> /proc/9005/fd
125
126 Note that the lines showing the pathname /proc/9005/fd result from the
127 calls to opendir(3).
128
129 Program source
130
131 #define _GNU_SOURCE
132 #include <fcntl.h>
133 #include <linux/close_range.h>
134 #include <stdio.h>
135 #include <stdlib.h>
136 #include <sys/syscall.h>
137 #include <string.h>
138 #include <unistd.h>
139 #include <dirent.h>
140
141 /* Show the contents of the symbolic links in /proc/self/fd */
142
143 static void
144 show_fds(void)
145 {
146 DIR *dirp = opendir("/proc/self/fd");
147 if (dirp == NULL) {
148 perror("opendir");
149 exit(EXIT_FAILURE);
150 }
151
152 for (;;) {
153 struct dirent *dp = readdir(dirp);
154 if (dp == NULL)
155 break;
156
157 if (dp->d_type == DT_LNK) {
158 char path[PATH_MAX], target[PATH_MAX];
159 snprintf(path, sizeof(path), "/proc/self/fd/%s",
160 dp->d_name);
161
162 ssize_t len = readlink(path, target, sizeof(target));
163 printf("%s ==> %.*s\n", path, (int) len, target);
164 }
165 }
166
167 closedir(dirp);
168 }
169
170 int
171 main(int argc, char *argv[])
172 {
173 for (int j = 1; j < argc; j++) {
174 int fd = open(argv[j], O_RDONLY);
175 if (fd == -1) {
176 perror(argv[j]);
177 exit(EXIT_FAILURE);
178 }
179 printf("%s opened as FD %d\n", argv[j], fd);
180 }
181
182 show_fds();
183
184 printf("========= About to call close_range() =======\n");
185
186 if (syscall(__NR_close_range, 3, ~0U, 0) == -1) {
187 perror("close_range");
188 exit(EXIT_FAILURE);
189 }
190
191 show_fds();
192 exit(EXIT_FAILURE);
193 }
194
196 close(2)
197
199 This page is part of release 5.12 of the Linux man-pages project. A
200 description of the project, information about reporting bugs, and the
201 latest version of this page, can be found at
202 https://www.kernel.org/doc/man-pages/.
203
204
205
206Linux 2021-03-22 CLOSE_RANGE(2)