1openat2(2) System Calls Manual openat2(2)
2
3
4
6 openat2 - open and possibly create a file (extended)
7
9 Standard C library (libc, -lc)
10
12 #include <fcntl.h> /* Definition of O_* and S_* constants */
13 #include <linux/openat2.h> /* Definition of RESOLVE_* constants */
14 #include <sys/syscall.h> /* Definition of SYS_* constants */
15 #include <unistd.h>
16
17 long syscall(SYS_openat2, int dirfd, const char *pathname,
18 struct open_how *how, size_t size);
19
20 Note: glibc provides no wrapper for openat2(), necessitating the use of
21 syscall(2).
22
24 The openat2() system call is an extension of openat(2) and provides a
25 superset of its functionality.
26
27 The openat2() system call opens the file specified by pathname. If the
28 specified file does not exist, it may optionally (if O_CREAT is speci‐
29 fied in how.flags) be created.
30
31 As with openat(2), if pathname is a relative pathname, then it is in‐
32 terpreted relative to the directory referred to by the file descriptor
33 dirfd (or the current working directory of the calling process, if
34 dirfd is the special value AT_FDCWD). If pathname is an absolute path‐
35 name, then dirfd is ignored (unless how.resolve contains RE‐
36 SOLVE_IN_ROOT, in which case pathname is resolved relative to dirfd).
37
38 Rather than taking a single flags argument, an extensible structure
39 (how) is passed to allow for future extensions. The size argument must
40 be specified as sizeof(struct open_how).
41
42 The open_how structure
43 The how argument specifies how pathname should be opened, and acts as a
44 superset of the flags and mode arguments to openat(2). This argument
45 is a pointer to an open_how structure, described in open_how(2type).
46
47 Any future extensions to openat2() will be implemented as new fields
48 appended to the open_how structure, with a zero value in a new field
49 resulting in the kernel behaving as though that extension field was not
50 present. Therefore, the caller must zero-fill this structure on ini‐
51 tialization. (See the "Extensibility" section of the NOTES for more
52 detail on why this is necessary.)
53
54 The fields of the open_how structure are as follows:
55
56 flags This field specifies the file creation and file status flags to
57 use when opening the file. All of the O_* flags defined for
58 openat(2) are valid openat2() flag values.
59
60 Whereas openat(2) ignores unknown bits in its flags argument,
61 openat2() returns an error if unknown or conflicting flags are
62 specified in how.flags.
63
64 mode This field specifies the mode for the new file, with identical
65 semantics to the mode argument of openat(2).
66
67 Whereas openat(2) ignores bits other than those in the range
68 07777 in its mode argument, openat2() returns an error if
69 how.mode contains bits other than 07777. Similarly, an error is
70 returned if openat2() is called with a nonzero how.mode and
71 how.flags does not contain O_CREAT or O_TMPFILE.
72
73 resolve
74 This is a bit-mask of flags that modify the way in which all
75 components of pathname will be resolved. (See path_resolu‐
76 tion(7) for background information.)
77
78 The primary use case for these flags is to allow trusted pro‐
79 grams to restrict how untrusted paths (or paths inside untrusted
80 directories) are resolved. The full list of resolve flags is as
81 follows:
82
83 RESOLVE_BENEATH
84 Do not permit the path resolution to succeed if any com‐
85 ponent of the resolution is not a descendant of the di‐
86 rectory indicated by dirfd. This causes absolute sym‐
87 bolic links (and absolute values of pathname) to be re‐
88 jected.
89
90 Currently, this flag also disables magic-link resolution
91 (see below). However, this may change in the future.
92 Therefore, to ensure that magic links are not resolved,
93 the caller should explicitly specify RESOLVE_NO_MAGI‐
94 CLINKS.
95
96 RESOLVE_IN_ROOT
97 Treat the directory referred to by dirfd as the root di‐
98 rectory while resolving pathname. Absolute symbolic
99 links are interpreted relative to dirfd. If a prefix
100 component of pathname equates to dirfd, then an immedi‐
101 ately following .. component likewise equates to dirfd
102 (just as /.. is traditionally equivalent to /). If path‐
103 name is an absolute path, it is also interpreted relative
104 to dirfd.
105
106 The effect of this flag is as though the calling process
107 had used chroot(2) to (temporarily) modify its root di‐
108 rectory (to the directory referred to by dirfd). How‐
109 ever, unlike chroot(2) (which changes the filesystem root
110 permanently for a process), RESOLVE_IN_ROOT allows a pro‐
111 gram to efficiently restrict path resolution on a per-
112 open basis.
113
114 Currently, this flag also disables magic-link resolution.
115 However, this may change in the future. Therefore, to
116 ensure that magic links are not resolved, the caller
117 should explicitly specify RESOLVE_NO_MAGICLINKS.
118
119 RESOLVE_NO_MAGICLINKS
120 Disallow all magic-link resolution during path resolu‐
121 tion.
122
123 Magic links are symbolic link-like objects that are most
124 notably found in proc(5); examples include /proc/pid/exe
125 and /proc/pid/fd/*. (See symlink(7) for more details.)
126
127 Unknowingly opening magic links can be risky for some ap‐
128 plications. Examples of such risks include the follow‐
129 ing:
130
131 • If the process opening a pathname is a controlling
132 process that currently has no controlling terminal
133 (see credentials(7)), then opening a magic link inside
134 /proc/pid/fd that happens to refer to a terminal would
135 cause the process to acquire a controlling terminal.
136
137 • In a containerized environment, a magic link inside
138 /proc may refer to an object outside the container,
139 and thus may provide a means to escape from the con‐
140 tainer.
141
142 Because of such risks, an application may prefer to dis‐
143 able magic link resolution using the RESOLVE_NO_MAGI‐
144 CLINKS flag.
145
146 If the trailing component (i.e., basename) of pathname is
147 a magic link, how.resolve contains RESOLVE_NO_MAGICLINKS,
148 and how.flags contains both O_PATH and O_NOFOLLOW, then
149 an O_PATH file descriptor referencing the magic link will
150 be returned.
151
152 RESOLVE_NO_SYMLINKS
153 Disallow resolution of symbolic links during path resolu‐
154 tion. This option implies RESOLVE_NO_MAGICLINKS.
155
156 If the trailing component (i.e., basename) of pathname is
157 a symbolic link, how.resolve contains RESOLVE_NO_SYM‐
158 LINKS, and how.flags contains both O_PATH and O_NOFOLLOW,
159 then an O_PATH file descriptor referencing the symbolic
160 link will be returned.
161
162 Note that the effect of the RESOLVE_NO_SYMLINKS flag,
163 which affects the treatment of symbolic links in all of
164 the components of pathname, differs from the effect of
165 the O_NOFOLLOW file creation flag (in how.flags), which
166 affects the handling of symbolic links only in the final
167 component of pathname.
168
169 Applications that employ the RESOLVE_NO_SYMLINKS flag are
170 encouraged to make its use configurable (unless it is
171 used for a specific security purpose), as symbolic links
172 are very widely used by end-users. Setting this flag in‐
173 discriminately—i.e., for purposes not specifically re‐
174 lated to security—for all uses of openat2() may result in
175 spurious errors on previously functional systems. This
176 may occur if, for example, a system pathname that is used
177 by an application is modified (e.g., in a new distribu‐
178 tion release) so that a pathname component (now) contains
179 a symbolic link.
180
181 RESOLVE_NO_XDEV
182 Disallow traversal of mount points during path resolution
183 (including all bind mounts). Consequently, pathname must
184 either be on the same mount as the directory referred to
185 by dirfd, or on the same mount as the current working di‐
186 rectory if dirfd is specified as AT_FDCWD.
187
188 Applications that employ the RESOLVE_NO_XDEV flag are en‐
189 couraged to make its use configurable (unless it is used
190 for a specific security purpose), as bind mounts are
191 widely used by end-users. Setting this flag indiscrimi‐
192 nately—i.e., for purposes not specifically related to se‐
193 curity—for all uses of openat2() may result in spurious
194 errors on previously functional systems. This may occur
195 if, for example, a system pathname that is used by an ap‐
196 plication is modified (e.g., in a new distribution re‐
197 lease) so that a pathname component (now) contains a bind
198 mount.
199
200 RESOLVE_CACHED
201 Make the open operation fail unless all path components
202 are already present in the kernel's lookup cache. If any
203 kind of revalidation or I/O is needed to satisfy the
204 lookup, openat2() fails with the error EAGAIN . This is
205 useful in providing a fast-path open that can be per‐
206 formed without resorting to thread offload, or other
207 mechanisms that an application might use to offload
208 slower operations.
209
210 If any bits other than those listed above are set in how.re‐
211 solve, an error is returned.
212
214 On success, a new file descriptor is returned. On error, -1 is re‐
215 turned, and errno is set to indicate the error.
216
218 The set of errors returned by openat2() includes all of the errors re‐
219 turned by openat(2), as well as the following additional errors:
220
221 E2BIG An extension that this kernel does not support was specified in
222 how. (See the "Extensibility" section of NOTES for more detail
223 on how extensions are handled.)
224
225 EAGAIN how.resolve contains either RESOLVE_IN_ROOT or RESOLVE_BENEATH,
226 and the kernel could not ensure that a ".." component didn't es‐
227 cape (due to a race condition or potential attack). The caller
228 may choose to retry the openat2() call.
229
230 EAGAIN RESOLVE_CACHED was set, and the open operation cannot be per‐
231 formed using only cached information. The caller should retry
232 without RESOLVE_CACHED set in how.resolve .
233
234 EINVAL An unknown flag or invalid value was specified in how.
235
236 EINVAL mode is nonzero, but how.flags does not contain O_CREAT or
237 O_TMPFILE.
238
239 EINVAL size was smaller than any known version of struct open_how.
240
241 ELOOP how.resolve contains RESOLVE_NO_SYMLINKS, and one of the path
242 components was a symbolic link (or magic link).
243
244 ELOOP how.resolve contains RESOLVE_NO_MAGICLINKS, and one of the path
245 components was a magic link.
246
247 EXDEV how.resolve contains either RESOLVE_IN_ROOT or RESOLVE_BENEATH,
248 and an escape from the root during path resolution was detected.
249
250 EXDEV how.resolve contains RESOLVE_NO_XDEV, and a path component
251 crosses a mount point.
252
254 Linux.
255
257 Linux 5.6.
258
259 The semantics of RESOLVE_BENEATH were modeled after FreeBSD's O_BE‐
260 NEATH.
261
263 Extensibility
264 In order to allow for future extensibility, openat2() requires the
265 user-space application to specify the size of the open_how structure
266 that it is passing. By providing this information, it is possible for
267 openat2() to provide both forwards- and backwards-compatibility, with
268 size acting as an implicit version number. (Because new extension
269 fields will always be appended, the structure size will always in‐
270 crease.) This extensibility design is very similar to other system
271 calls such as sched_setattr(2), perf_event_open(2), and clone3(2).
272
273 If we let usize be the size of the structure as specified by the user-
274 space application, and ksize be the size of the structure which the
275 kernel supports, then there are three cases to consider:
276
277 • If ksize equals usize, then there is no version mismatch and how can
278 be used verbatim.
279
280 • If ksize is larger than usize, then there are some extension fields
281 that the kernel supports which the user-space application is unaware
282 of. Because a zero value in any added extension field signifies a
283 no-op, the kernel treats all of the extension fields not provided by
284 the user-space application as having zero values. This provides
285 backwards-compatibility.
286
287 • If ksize is smaller than usize, then there are some extension fields
288 which the user-space application is aware of but which the kernel
289 does not support. Because any extension field must have its zero
290 values signify a no-op, the kernel can safely ignore the unsupported
291 extension fields if they are all-zero. If any unsupported extension
292 fields are nonzero, then -1 is returned and errno is set to E2BIG.
293 This provides forwards-compatibility.
294
295 Because the definition of struct open_how may change in the future
296 (with new fields being added when system headers are updated), user-
297 space applications should zero-fill struct open_how to ensure that re‐
298 compiling the program with new headers will not result in spurious er‐
299 rors at runtime. The simplest way is to use a designated initializer:
300
301 struct open_how how = { .flags = O_RDWR,
302 .resolve = RESOLVE_IN_ROOT };
303
304 or explicitly using memset(3) or similar:
305
306 struct open_how how;
307 memset(&how, 0, sizeof(how));
308 how.flags = O_RDWR;
309 how.resolve = RESOLVE_IN_ROOT;
310
311 A user-space application that wishes to determine which extensions the
312 running kernel supports can do so by conducting a binary search on size
313 with a structure which has every byte nonzero (to find the largest
314 value which doesn't produce an error of E2BIG).
315
317 openat(2), open_how(2type), path_resolution(7), symlink(7)
318
319
320
321Linux man-pages 6.04 2023-03-30 openat2(2)