Changes.old: Add missing entry in 5.13 changelog
[man-pages.git] / man2 / close_range.2
blobee2ab6afb1dc0208bbc96ce54f02c8bb04f2c412
1 .\" Copyright (c) 2020 Stephen Kitt <steve@sk2.org>
2 .\" and Copyright (c) 2021 Michael Kerrisk <mtk.manpages@gmail.com>
3 .\"
4 .\" %%%LICENSE_START(VERBATIM)
5 .\" Permission is granted to make and distribute verbatim copies of this
6 .\" manual provided the copyright notice and this permission notice are
7 .\" preserved on all copies.
8 .\"
9 .\" Permission is granted to copy and distribute modified versions of this
10 .\" manual under the conditions for verbatim copying, provided that the
11 .\" entire resulting derived work is distributed under the terms of a
12 .\" permission notice identical to this one.
13 .\"
14 .\" Since the Linux kernel and libraries are constantly changing, this
15 .\" manual page may be incorrect or out-of-date.  The author(s) assume no
16 .\" responsibility for errors or omissions, or for damages resulting from
17 .\" the use of the information contained herein.  The author(s) may not
18 .\" have taken the same level of care in the production of this manual,
19 .\" which is licensed free of charge, as they might when working
20 .\" professionally.
21 .\"
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
24 .\" %%%LICENSE_END
25 .\"
26 .TH CLOSE_RANGE 2 2021-08-27 "Linux" "Linux Programmer's Manual"
27 .SH NAME
28 close_range \- close all file descriptors in a given range
29 .SH SYNOPSIS
30 .nf
31 .B #include <linux/close_range.h>
32 .PP
33 .BI "int close_range(unsigned int " first ", unsigned int " last ,
34 .BI "                unsigned int " flags );
35 .fi
36 .SH DESCRIPTION
37 The
38 .BR close_range ()
39 system call closes all open file descriptors from
40 .I first
42 .I last
43 (included).
44 .PP
45 Errors closing a given file descriptor are currently ignored.
46 .PP
47 .I flags
48 is a bit mask containing 0 or more of the following:
49 .TP
50 .BR CLOSE_RANGE_CLOEXEC " (since Linux 5.11)"
51 Set the close-on-exec flag on the specified file descriptors,
52 rather than immediately closing them.
53 .TP
54 .B CLOSE_RANGE_UNSHARE
55 Unshare the specified file descriptors from any other processes
56 before closing them,
57 avoiding races with other threads sharing the file descriptor table.
58 .SH RETURN VALUE
59 On success,
60 .BR close_range ()
61 returns 0.
62 On error, \-1 is returned and
63 .I errno
64 is set to indicate the error.
65 .SH ERRORS
66 .TP
67 .B EINVAL
68 .I flags
69 is not valid, or
70 .I first
71 is greater than
72 .IR last .
73 .PP
74 The following can occur with
75 .B CLOSE_RANGE_UNSHARE
76 (when constructing the new descriptor table):
77 .TP
78 .B EMFILE
79 The number of open file descriptors exceeds the limit specified in
80 .IR /proc/sys/fs/nr_open
81 (see
82 .BR proc (5)).
83 This error can occur in situations where that limit was lowered before
84 a call to
85 .BR close_range ()
86 where the
87 .B CLOSE_RANGE_UNSHARE
88 flag is specified.
89 .TP
90 .B ENOMEM
91 Insufficient kernel memory was available.
92 .SH VERSIONS
93 .BR close_range ()
94 first appeared in Linux 5.9.
95 Library support was added in glibc in version 2.34.
96 .SH CONFORMING TO
97 .BR close_range ()
98 is a nonstandard function that is also present on FreeBSD.
99 .SH NOTES
100 .SS Closing all open file descriptors
101 .\" 278a5fbaed89dacd04e9d052f4594ffd0e0585de
102 To avoid blindly closing file descriptors
103 in the range of possible file descriptors,
104 this is sometimes implemented (on Linux)
105 by listing open file descriptors in
106 .I /proc/self/fd/
107 and calling
108 .BR close (2)
109 on each one.
110 .BR close_range ()
111 can take care of this without requiring
112 .I /proc
113 and within a single system call,
114 which provides significant performance benefits.
115 .SS Closing file descriptors before exec
116 .\" 60997c3d45d9a67daf01c56d805ae4fec37e0bd8
117 File descriptors can be closed safely using
119 .in +4n
121 /* we don't want anything past stderr here */
122 close_range(3, ~0U, CLOSE_RANGE_UNSHARE);
123 execve(....);
127 .B CLOSE_RANGE_UNSHARE
128 is conceptually equivalent to
130 .in +4n
132 unshare(CLONE_FILES);
133 close_range(first, last, 0);
137 but can be more efficient:
138 if the unshared range extends past
139 the current maximum number of file descriptors allocated
140 in the caller's file descriptor table
141 (the common case when
142 .I last
143 is ~0U),
144 the kernel will unshare a new file descriptor table for the caller up to
145 .IR first ,
146 copying as few file descriptors as possible.
147 This avoids subsequent
148 .BR close (2)
149 calls entirely;
150 the whole operation is complete once the table is unshared.
151 .SS Closing files on \fBexec\fP
152 .\" 582f1fb6b721facf04848d2ca57f34468da1813e
153 This is particularly useful in cases where multiple
154 .RB pre- exec
155 setup steps risk conflicting with each other.
156 For example, setting up a
157 .BR seccomp (2)
158 profile can conflict with a
159 .BR close_range ()
160 call:
161 if the file descriptors are closed before the
162 .BR seccomp (2)
163 profile is set up,
164 the profile setup can't use them itself,
165 or control their closure;
166 if the file descriptors are closed afterwards,
167 the seccomp profile can't block the
168 .BR close_range ()
169 call or any fallbacks.
170 Using
171 .B CLOSE_RANGE_CLOEXEC
172 avoids this:
173 the descriptors can be marked before the
174 .BR seccomp (2)
175 profile is set up,
176 and the profile can control access to
177 .BR close_range ()
178 without affecting the calling process.
179 .SH EXAMPLES
180 The program shown below opens the files named in its command-line arguments,
181 displays the list of files that it has opened
182 (by iterating through the entries in
183 .IR /proc/PID/fd ),
184 uses
185 .BR close_range ()
186 to close all file descriptors greater than or equal to 3,
187 and then once more displays the process's list of open files.
188 The following example demonstrates the use of the program:
190 .in +4n
192 $ \fBtouch /tmp/a /tmp/b /tmp/c\fP
193 $ \fB./a.out /tmp/a /tmp/b /tmp/c\fP
194 /tmp/a opened as FD 3
195 /tmp/b opened as FD 4
196 /tmp/c opened as FD 5
197 /proc/self/fd/0 ==> /dev/pts/1
198 /proc/self/fd/1 ==> /dev/pts/1
199 /proc/self/fd/2 ==> /dev/pts/1
200 /proc/self/fd/3 ==> /tmp/a
201 /proc/self/fd/4 ==> /tmp/b
202 /proc/self/fd/5 ==> /tmp/b
203 /proc/self/fd/6 ==> /proc/9005/fd
204 ========= About to call close_range() =======
205 /proc/self/fd/0 ==> /dev/pts/1
206 /proc/self/fd/1 ==> /dev/pts/1
207 /proc/self/fd/2 ==> /dev/pts/1
208 /proc/self/fd/3 ==> /proc/9005/fd
212 Note that the lines showing the pathname
213 .I /proc/9005/fd
214 result from the calls to
215 .BR opendir (3).
216 .SS Program source
219 #define _GNU_SOURCE
220 #include <fcntl.h>
221 #include <linux/close_range.h>
222 #include <stdio.h>
223 #include <stdlib.h>
224 #include <sys/syscall.h>
225 #include <string.h>
226 #include <unistd.h>
227 #include <dirent.h>
229 /* Show the contents of the symbolic links in /proc/self/fd */
231 static void
232 show_fds(void)
234     DIR *dirp = opendir("/proc/self/fd");
235     if (dirp  == NULL) {
236         perror("opendir");
237         exit(EXIT_FAILURE);
238     }
240     for (;;) {
241         struct dirent *dp = readdir(dirp);
242         if (dp == NULL)
243             break;
245         if (dp\->d_type == DT_LNK) {
246             char path[PATH_MAX], target[PATH_MAX];
247             snprintf(path, sizeof(path), "/proc/self/fd/%s",
248                      dp\->d_name);
250             ssize_t len = readlink(path, target, sizeof(target));
251             printf("%s ==> %.*s\en", path, (int) len, target);
252         }
253     }
255     closedir(dirp);
259 main(int argc, char *argv[])
261     for (int j = 1; j < argc; j++) {
262         int fd = open(argv[j], O_RDONLY);
263         if (fd == \-1) {
264             perror(argv[j]);
265             exit(EXIT_FAILURE);
266         }
267         printf("%s opened as FD %d\en", argv[j], fd);
268     }
270     show_fds();
272     printf("========= About to call close_range() =======\en");
274     if (syscall(__NR_close_range, 3, \(ti0U, 0) == \-1) {
275         perror("close_range");
276         exit(EXIT_FAILURE);
277     }
279     show_fds();
280     exit(EXIT_FAILURE);
283 .SH SEE ALSO
284 .BR close (2)