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