]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
linux: Add openat2 (BZ 31664) azanella/bz31664-openat2
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 23 Apr 2024 19:45:59 +0000 (16:45 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 23 Apr 2024 19:53:42 +0000 (16:53 -0300)
It was added on Linux 5.6, as an extension of openat.  Different
than other open-like function, the kernel only provides the LFS
variant (so files larger than 4GB always succeed, as other functions
with offset larget than off_t).  Similar to other open function,
the new symbol is a cancellable entrypoint.

The testcase added only stress some of the syscall provided
functionalities and it is based on existent kernel selftest.  Since
the prototype does not use variadic arguments, there is no need to
add fortify wrapper to catch wrong usages.

Checked on x86_64-linux-gnu.

35 files changed:
NEWS
sysdeps/unix/sysv/linux/Makefile
sysdeps/unix/sysv/linux/Versions
sysdeps/unix/sysv/linux/aarch64/libc.abilist
sysdeps/unix/sysv/linux/alpha/libc.abilist
sysdeps/unix/sysv/linux/arc/libc.abilist
sysdeps/unix/sysv/linux/arm/le/libc.abilist
sysdeps/unix/sysv/linux/bits/fcntl-linux.h
sysdeps/unix/sysv/linux/bits/openat2.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/csky/libc.abilist
sysdeps/unix/sysv/linux/hppa/libc.abilist
sysdeps/unix/sysv/linux/i386/libc.abilist
sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
sysdeps/unix/sysv/linux/nios2/libc.abilist
sysdeps/unix/sysv/linux/openat2.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/or1k/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
sysdeps/unix/sysv/linux/sh/le/libc.abilist
sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
sysdeps/unix/sysv/linux/tst-openat2-consts.py [new file with mode: 0755]
sysdeps/unix/sysv/linux/tst-openat2.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist

diff --git a/NEWS b/NEWS
index cf6078cf200e8502662468467bfe96d887b5d9a4..eaaa02cb4ee89f456299c93c013f285f0a13d36b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,10 @@ Major new features:
   more extensive verification tests for AT_SECURE programs and not meant to
   be a security feature.
 
+* On Linux, the openat2 function has been added.  It is an extension of
+  openat and provides a superset of its functionality.  It is supported only
+  in LFS mode and as other open like it is a cancellable entrypoint.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * Architectures which use a 32-bit seconds-since-epoch field in struct
index 415aa1f14dd20ba64b237e9201c9240e3ca2b9c6..fcb9b810b58b86e8e1ab45eef4de163c827d1b62 100644 (file)
@@ -133,6 +133,7 @@ sysdep_headers += \
   bits/mman-linux.h \
   bits/mman-map-flags-generic.h \
   bits/mman-shared.h \
+  bits/openat2.h \
   bits/procfs-extra.h \
   bits/procfs-id.h \
   bits/procfs-prregset.h \
@@ -593,6 +594,7 @@ sysdep_routines += \
   open_nocancel \
   openat64_nocancel \
   openat_nocancel \
+  openat2 \
   pread64_nocancel \
   read_nocancel \
   stat_t64_cp \
@@ -607,11 +609,23 @@ sysdep_headers += \
   # sysdep_headers
 
 tests += \
+  tst-openat2 \
   tst-fallocate \
   tst-fallocate64 \
   tst-getcwd-smallbuff \
   tst-o_path-locks \
   # tests
+
+tests-special += \
+  $(objpfx)tst-openat2-consts.out \
+  # tests-special
+$(objpfx)tst-openat2-consts.out: ../sysdeps/unix/sysv/linux/tst-openat2-consts.py
+       $(sysdeps-linux-python) \
+         ../sysdeps/unix/sysv/linux/tst-openat2-consts.py \
+           $(sysdeps-linux-python-cc) \
+         < /dev/null > $@ 2>&1; $(evaluate-test)
+$(objpfx)tst-openat2-consts.out: $(sysdeps-linux-python-deps)
+
 endif
 
 ifeq ($(subdir),elf)
index 268ba1b6acffd32efa9d0af4e06dbe074e78cfe0..65da2b617a5a12b3987fd140eedaa03ee4ba21dd 100644 (file)
@@ -328,6 +328,9 @@ libc {
     posix_spawnattr_getcgroup_np;
     posix_spawnattr_setcgroup_np;
   }
+  GLIBC_2.40 {
+    openat2;
+  }
   GLIBC_PRIVATE {
     # functions used in other libraries
     __syscall_rt_sigqueueinfo;
index 68eeca1c080f0401a83bd8b7a1bf7722a006fc44..0b9bd8ae625895c3f18ac280a822f5a6dfd6bd3b 100644 (file)
@@ -2748,3 +2748,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F
index 34c187b72198b367e9c7b579c5b469ffdcdf576c..c0bd27d617504ee105b78aecef7def00e27c13d8 100644 (file)
@@ -3095,6 +3095,7 @@ GLIBC_2.4 wcstold F
 GLIBC_2.4 wcstold_l F
 GLIBC_2.4 wprintf F
 GLIBC_2.4 wscanf F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 916c18ea94add192225d7a03af1b13ec18cab6cf..965438e7a763a6e8656a6fcf24edc9ac46886880 100644 (file)
@@ -2509,3 +2509,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F
index 1cdbc983e19b7ccce0cb524cd088fe7d999a04b6..70fd4258699cb06db925e766eb55b7cdc36a1fd4 100644 (file)
@@ -2798,6 +2798,7 @@ GLIBC_2.4 xdrstdio_create F
 GLIBC_2.4 xencrypt F
 GLIBC_2.4 xprt_register F
 GLIBC_2.4 xprt_unregister F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 628612b8856b9082f202001034d267b09b2954d4..279aa2b8ebe0c1bb890b6621674457e77dc598dd 100644 (file)
@@ -451,6 +451,28 @@ extern int name_to_handle_at (int __dfd, const char *__name,
 extern int open_by_handle_at (int __mountdirfd, struct file_handle *__handle,
                              int __flags);
 
+#ifdef __has_include
+# if __has_include ("linux/openat2.h")
+#  include "linux/openat2.h"
+#  define __glibc_has_open_how 1
+# endif
+#endif
+
+#include <bits/openat2.h>
+
+/* Similar to `openat' but the arguments are packed on HOW with the size
+   USIZE.  If flags and mode from HOW are non-zero, then openat2 operates
+   like openat.
+
+   Unlike openat2, unknown or invalid flags result in an error (EINVAL),
+   rather than being ignored.  The mode must be zero unless one O_CREAT
+   or O_TMPFILE are set.
+
+   The kernel does not support legacy non-LFS interface.  */
+extern int openat2 (int __dfd, const char *__filename, struct open_how *__how,
+                   size_t __usize)
+     __nonnull ((2, 3));
+
 #endif /* use GNU */
 
 __END_DECLS
diff --git a/sysdeps/unix/sysv/linux/bits/openat2.h b/sysdeps/unix/sysv/linux/bits/openat2.h
new file mode 100644 (file)
index 0000000..a07984d
--- /dev/null
@@ -0,0 +1,61 @@
+/* openat2 definition.  Linux specific.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef        _FCNTL_H
+# error "Never use <bits/openat2.h> directly; include <fcntl.h> instead."
+#endif
+
+#ifndef __glibc_has_open_how
+/* Arguments for how openat2 should open the target path.  */
+struct open_how
+{
+  __uint64_t flags;
+  __uint64_t mode;
+  __uint64_t resolve;
+};
+#endif
+
+/* how->resolve flags for openat2. */
+#ifndef RESOLVE_NO_XDEV
+# define RESOLVE_NO_XDEV       0x01 /* Block mount-point crossings
+                                       (includes bind-mounts).  */
+#endif
+#ifndef RESOLVE_NO_MAGICLINKS
+# define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style
+                                       "magic-links".  */
+#endif
+#ifndef RESOLVE_NO_SYMLINKS
+# define RESOLVE_NO_SYMLINKS   0x04 /* Block traversal through all symlinks
+                                       (implies OEXT_NO_MAGICLINKS).  */
+#endif
+#ifndef RESOLVE_BENEATH
+# define RESOLVE_BENEATH       0x08 /* Block "lexical" trickery like
+                                       "..", symlinks, and absolute
+                                       paths which escape the dirfd.  */
+#endif
+#ifndef RESOLVE_IN_ROOT
+# define RESOLVE_IN_ROOT       0x10 /* Make all jumps to "/" and ".."
+                                       be scoped inside the dirfd
+                                       (similar to chroot).  */
+#endif
+#ifndef RESOLVE_CACHED
+# define RESOLVE_CACHED                0x20 /* Only complete if resolution can be
+                                       completed through cached lookup. May
+                                       return -EAGAIN if that's not
+                                       possible.  */
+#endif
index 96d45961e2c29ac6d6c659b8955a3e4f2994fd0d..c81ea43dc1d3412b215c9869831ea03c2bf2f031 100644 (file)
@@ -2785,3 +2785,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F
index fbcd60c2b300e3b0e14039e77f04dd28b5ee82bd..23eec25d8a4d2226153b47f684b84efdcb6eec42 100644 (file)
@@ -2821,6 +2821,7 @@ GLIBC_2.4 sys_errlist D 0x400
 GLIBC_2.4 sys_nerr D 0x4
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index c989b433c0995ed9aed405b6164de2176e1cd0d9..4ce2afb147366b9d343374d9c4d4a5def74ab282 100644 (file)
@@ -3005,6 +3005,7 @@ GLIBC_2.4 sys_errlist D 0x210
 GLIBC_2.4 sys_nerr D 0x4
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 0023ec1fa1eea9877b5610f6909a73c14f6a83ca..be76251b284e97da9bae286320865afccbae03c6 100644 (file)
@@ -2269,3 +2269,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F
index 439796d6934c87264435b88c23abdab6dc3c7be2..39645248afc29d7393114b7aaa4bc9e5d68bc518 100644 (file)
@@ -2948,6 +2948,7 @@ GLIBC_2.4 sys_errlist D 0x210
 GLIBC_2.4 sys_nerr D 0x4
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 1069d3252c111d362363caa038083c0f472ac933..2f917724de838a7d3474d8bc5815e196c306f254 100644 (file)
@@ -2834,3 +2834,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F
index 799e5089506401c8dbcd0e55d30351b76eea103b..ae5b95bc76ad2c2ed3c46b66f08c8ad85c7dc245 100644 (file)
@@ -2909,6 +2909,7 @@ GLIBC_2.4 renameat F
 GLIBC_2.4 symlinkat F
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 03d9655f26e6ca4c0af2bfb0c61a3dc12ebb5c53..5dc2996fcca175b38e292e28ce21951a1194d34e 100644 (file)
@@ -2915,6 +2915,7 @@ GLIBC_2.4 renameat F
 GLIBC_2.4 symlinkat F
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 05e402ed3070a0ae852a438f681ed5dd15090a23..865dc5e7f17ab92c54487d7c52cf8bcaaaf9b622 100644 (file)
@@ -2817,6 +2817,7 @@ GLIBC_2.4 renameat F
 GLIBC_2.4 symlinkat F
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 3aa81766aa6dc644dd235b97b5e5b0940cbda51d..12775fdad52c8dcdf899cd73b87337ea29c0af03 100644 (file)
@@ -2873,3 +2873,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F
diff --git a/sysdeps/unix/sysv/linux/openat2.c b/sysdeps/unix/sysv/linux/openat2.c
new file mode 100644 (file)
index 0000000..a2b134b
--- /dev/null
@@ -0,0 +1,29 @@
+/* Linux openat2 syscall implementation.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fcntl.h>
+#include <bits/openat2.h>
+#include <sysdep-cancel.h>
+
+int
+__openat2 (int dfd, const char *filename, struct open_how *how,
+          size_t usize)
+{
+  return SYSCALL_CANCEL (openat2, dfd, filename, how, usize);
+}
+weak_alias (__openat2, openat2)
index c40c843aaf471d84604244b8d5b2168cfdeea72f..28354360113343e7eaa1006dcba0435198ef46a3 100644 (file)
@@ -2255,3 +2255,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F
index 971430560819bbc20064f12f98a51365a790b4cf..3b70a56944f67987bb9510eba70db0f889e3a9ea 100644 (file)
@@ -3138,6 +3138,7 @@ GLIBC_2.4 wcstold F
 GLIBC_2.4 wcstold_l F
 GLIBC_2.4 wprintf F
 GLIBC_2.4 wscanf F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index cfc2ebd3eca013856132271074cfec2288ce4101..10fc3c89dc331cabb168c20077e2de4c234e2bc1 100644 (file)
@@ -2892,6 +2892,7 @@ GLIBC_2.4 wcstold F
 GLIBC_2.4 wcstold_l F
 GLIBC_2.4 wprintf F
 GLIBC_2.4 wscanf F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 8c9efc5a166399823e8be8ad013f6c61a3f68202..713fa1d1c8eb01047c7074dadb618d08a28d623b 100644 (file)
@@ -2968,3 +2968,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F
index 6397a9cb91e6e82b2af1630a5e9b5516ee649230..550ba877ef02244f9991eaf83420050506df7c74 100644 (file)
@@ -2512,3 +2512,4 @@ GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
 GLIBC_2.40 __riscv_hwprobe F
+GLIBC_2.40 openat2 F
index 71bbf94f663d4663b4071a450699811ef6e37537..8bf9f309b7f7ba02d0fc67d148256818551d36ef 100644 (file)
@@ -2712,3 +2712,4 @@ GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
 GLIBC_2.40 __riscv_hwprobe F
+GLIBC_2.40 openat2 F
index a7467e28504530bd73bf1372c63dd181a8afc26d..08bc3d6f8b8484f1a8105359dbaaeb25cfcbbfea 100644 (file)
@@ -3136,6 +3136,7 @@ GLIBC_2.4 wcstold F
 GLIBC_2.4 wcstold_l F
 GLIBC_2.4 wprintf F
 GLIBC_2.4 wscanf F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index fd1cb2972d314a9cc49b74c2a81ee4d6eb0aa820..e25afff581f5a8aeb0acbbc98c2d36539e56ed55 100644 (file)
@@ -2929,6 +2929,7 @@ GLIBC_2.4 wcstold F
 GLIBC_2.4 wcstold_l F
 GLIBC_2.4 wprintf F
 GLIBC_2.4 wscanf F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 449d92bbc55043ba946458d9eb823c95c0723db5..bdd9c600f02bdb5d251e9d972ffcddece2a2ba5a 100644 (file)
@@ -2825,6 +2825,7 @@ GLIBC_2.4 sys_errlist D 0x210
 GLIBC_2.4 sys_nerr D 0x4
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index e615be759ad292589705b4e4cfa89c0eb6a3c194..b20dd43d47f83a488aeac35f6144e511367aafbd 100644 (file)
@@ -3157,6 +3157,7 @@ GLIBC_2.4 wcstold F
 GLIBC_2.4 wcstold_l F
 GLIBC_2.4 wprintf F
 GLIBC_2.4 wscanf F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index bd36431dd740ad5cffd4a27b948a5040737b98f1..19981aa9819d1c0ec96b9ccc155e7daaa14a7572 100644 (file)
@@ -2793,6 +2793,7 @@ GLIBC_2.4 sys_errlist D 0x430
 GLIBC_2.4 sys_nerr D 0x4
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
diff --git a/sysdeps/unix/sysv/linux/tst-openat2-consts.py b/sysdeps/unix/sysv/linux/tst-openat2-consts.py
new file mode 100755 (executable)
index 0000000..1623faf
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/python3
+# Test that glibc's sys/openat2.h constants match the kernel's.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+import argparse
+import sys
+
+import glibcextract
+import glibcsyscalls
+
+
+def main():
+    """The main entry point."""
+    parser = argparse.ArgumentParser(
+        description="Test that glibc's sys/openat2.h constants "
+        "match the kernel's.")
+    parser.add_argument('--cc', metavar='CC',
+                        help='C compiler (including options) to use')
+    args = parser.parse_args()
+
+    if glibcextract.compile_c_snippet(
+            '#include <linux/openat2.h>',
+            args.cc).returncode != 0:
+        sys.exit (77)
+
+    linux_version_headers = glibcsyscalls.linux_kernel_version(args.cc)
+    # Constants in glibc were updated to match Linux v6.8.  When glibc
+    # constants are updated this value should be updated to match the
+    # released kernel version from which the constants were taken.
+    linux_version_glibc = (6, 8)
+    def check(cte, exclude=None):
+        return glibcextract.compare_macro_consts(
+                '#define _FCNTL_H\n'
+                '#include <stdint.h>\n'
+                '#include <bits/openat2.h>\n',
+                '#include <asm/fcntl.h>\n'
+                '#include <linux/openat2.h>\n',
+                args.cc,
+                cte,
+                exclude,
+                linux_version_glibc > linux_version_headers,
+                linux_version_headers > linux_version_glibc)
+
+    status = check('RESOLVE.*')
+    sys.exit(status)
+
+if __name__ == '__main__':
+    main()
diff --git a/sysdeps/unix/sysv/linux/tst-openat2.c b/sysdeps/unix/sysv/linux/tst-openat2.c
new file mode 100644 (file)
index 0000000..6936b9f
--- /dev/null
@@ -0,0 +1,259 @@
+/* Linux openat2 tests.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* openat2 is only support in LFS mode.  */
+#define _FILE_OFFSET_BITS 64
+
+#include <array_length.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+#include <support/xunistd.h>
+
+static int dir_fd;
+
+static void
+do_prepare (int argc, char *argv[])
+{
+  char *temp_dir = support_create_temp_directory ("tst-openat2");
+  dir_fd = xopen (temp_dir, O_RDONLY | O_DIRECTORY, 0);
+}
+#define PREPARE do_prepare
+
+static int
+do_test_struct (void)
+{
+  static struct struct_test
+  {
+    struct open_how_ext
+    {
+      struct open_how inner;
+      int extra1;
+      int extra2;
+      int extra3;
+    } arg;
+    size_t size;
+    int err;
+  } tests[] =
+  {
+    {
+      /* Zero size.  */
+      .arg.inner.flags = O_RDONLY,
+      .size = 0,
+      .err = EINVAL,
+    },
+    {
+      /* Normal struct.  */
+      .arg.inner.flags = O_RDONLY,
+      .size = sizeof (struct open_how),
+    },
+    {
+      /* Larger struct, zeroed out the unused values.  */
+      .arg.inner.flags = O_RDONLY,
+      .size = sizeof (struct open_how_ext),
+    },
+    {
+      /* Larger struct, non-zeroed out the unused values.  */
+      .arg.inner.flags = O_RDONLY,
+      .arg.extra1 = 0xdeadbeef,
+      .size = sizeof (struct open_how_ext),
+      .err = E2BIG,
+    },
+    {
+      /* Larger struct, non-zeroed out the unused values.  */
+      .arg.inner.flags = O_RDONLY,
+      .arg.extra2 = 0xdeadbeef,
+      .size = sizeof (struct open_how_ext),
+      .err = E2BIG,
+    },
+  };
+
+  for (struct struct_test *t = tests; t != array_end (tests); t++)
+    {
+      int fd = openat2 (AT_FDCWD, ".", (struct open_how *) &t->arg, t->size);
+      if (fd == -1 && errno == ENOSYS)
+       FAIL_UNSUPPORTED ("openat2 is not supported by the kernel");
+
+      if (t->err != 0)
+       {
+         TEST_COMPARE (fd, -1);
+         TEST_COMPARE (errno, t->err);
+       }
+      else
+       TEST_VERIFY (fd >= 0);
+    }
+
+  return 0;
+}
+
+static int
+do_test_flags (void)
+{
+  static struct flag_test
+  {
+    struct open_how how;
+    int err;
+  } tests[] =
+  {
+    /* O_TMPFILE is incompatible with O_PATH and O_CREAT.  */
+    { .how.flags = O_TMPFILE | O_PATH | O_RDWR, .err = EINVAL },
+    { .how.flags = O_TMPFILE | O_CREAT | O_RDWR, .err = EINVAL },
+
+    /* O_PATH only permits certain other flags to be set ...  */
+    { .how.flags = O_PATH | O_CLOEXEC },
+    { .how.flags = O_PATH | O_DIRECTORY },
+    { .how.flags = O_PATH | O_NOFOLLOW },
+    /* ... and others are absolutely not permitted. */
+    { .how.flags = O_PATH | O_RDWR, .err = EINVAL },
+    { .how.flags = O_PATH | O_CREAT, .err = EINVAL },
+    { .how.flags = O_PATH | O_EXCL, .err = EINVAL },
+    { .how.flags = O_PATH | O_NOCTTY, .err = EINVAL },
+    { .how.flags = O_PATH | O_DIRECT, .err = EINVAL },
+
+    /* ->mode must only be set with O_{CREAT,TMPFILE}. */
+    { .how.flags = O_RDONLY, .how.mode = 0600, .err = EINVAL },
+    { .how.flags = O_PATH,   .how.mode = 0600, .err = EINVAL },
+    { .how.flags = O_CREAT,  .how.mode = 0600 },
+    { .how.flags = O_TMPFILE | O_RDWR, .how.mode = 0600 },
+    /* ->mode must only contain 0777 bits. */
+    { .how.flags = O_CREAT, .how.mode = 0xFFFF, .err = EINVAL },
+    { .how.flags = O_CREAT, .how.mode = 0xC000000000000000ULL, .err = EINVAL },
+    { .how.flags = O_TMPFILE | O_RDWR, .how.mode = 0x1337, .err = EINVAL },
+    { .how.flags = O_TMPFILE | O_RDWR, .how.mode = 0x0000A00000000000ULL,
+      .err = EINVAL },
+
+    /* ->resolve flags must not conflict. */
+    { .how.flags = O_RDONLY,
+      .how.resolve = RESOLVE_BENEATH | RESOLVE_IN_ROOT,
+      .err = EINVAL },
+
+    /* ->resolve must only contain RESOLVE_* flags.  */
+    { .how.flags = O_RDONLY,
+      .how.resolve = 0x1337, .err = EINVAL },
+    { .how.flags = O_CREAT,
+      .how.resolve = 0x1337, .err = EINVAL },
+    { .how.flags = O_TMPFILE | O_RDWR,
+      .how.resolve = 0x1337, .err = EINVAL },
+    { .how.flags = O_PATH,
+      .how.resolve = 0x1337, .err = EINVAL },
+
+    /* currently unknown upper 32 bit rejected.  */
+    { .how.flags = O_RDONLY | (1ULL << 63),
+      .how.resolve = 0, .err = EINVAL },
+  };
+
+  for (struct flag_test *t = tests; t != array_end (tests); t++)
+    {
+      char *path;
+      if (t->how.flags & O_CREAT)
+       {
+         int temp_fd = create_temp_file ("tst-openat2.", &path);
+         TEST_VERIFY_EXIT (temp_fd != -1);
+         xunlink (path);
+       }
+      else
+       path = (char *) ".";
+
+      int fd = openat2 (AT_FDCWD, path, &t->how, sizeof (struct open_how));
+      if (fd != 0 && errno == EOPNOTSUPP)
+       {
+         /* Skip the testcase if FS does not support the operation (e.g.
+            valid O_TMPFILE on NFS).  */
+         continue;
+       }
+
+      if (t->err != 0)
+       {
+         TEST_COMPARE (fd, -1);
+         TEST_COMPARE (errno, t->err);
+       }
+      else
+       TEST_VERIFY (fd >= 0);
+    }
+
+  return 0;
+}
+
+static int
+do_test_basic (void)
+{
+  int fd;
+
+  fd = openat2 (dir_fd,
+               "some-file",
+               &(struct open_how)
+               {
+                 .flags = O_CREAT|O_RDWR|O_EXCL,
+                 .mode = 0666,
+               },
+               sizeof (struct open_how));
+  TEST_VERIFY (fd != -1);
+
+  xwrite (fd, "hello", 5);
+
+  /* Before closing the file, try using this file descriptor to open
+     another file.  This must fail.  */
+  {
+    int fd2 = openat2 (fd,
+                      "should-not-work",
+                      &(struct open_how)
+                      {
+                        .flags = O_CREAT|O_RDWR|O_EXCL,
+                        .mode = 0666,
+                      },
+                      sizeof (struct open_how));
+    TEST_COMPARE (fd2, -1);
+    TEST_COMPARE (errno, ENOTDIR);
+  }
+
+  /* Remove the created file.  */
+  int cwdfd = xopen (".", O_RDONLY | O_DIRECTORY, 0);
+  TEST_COMPARE (fchdir (dir_fd), 0);
+  xunlink ("some-file");
+  TEST_COMPARE (fchdir (cwdfd), 0);
+
+  xclose (dir_fd);
+  xclose (cwdfd);
+
+  fd = openat2 (dir_fd,
+               "some-file",
+               &(struct open_how)
+               {
+                 .flags = O_CREAT|O_RDWR|O_EXCL,
+                 .mode = 0666,
+               },
+               sizeof (struct open_how));
+  TEST_COMPARE (fd, -1);
+  TEST_COMPARE (errno, EBADF);
+
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  do_test_struct ();
+  do_test_flags ();
+  do_test_basic ();
+
+  return 0;
+}
+
+#include <support/test-driver.c>
index aea7848ed6833407d4d8bb28a856d94ff5166ea6..a7f177c8a8c3a4f18da00dfcc5be84de608b8950 100644 (file)
@@ -2744,6 +2744,7 @@ GLIBC_2.4 sys_errlist D 0x420
 GLIBC_2.4 sys_nerr D 0x4
 GLIBC_2.4 unlinkat F
 GLIBC_2.4 unshare F
+GLIBC_2.40 openat2 F
 GLIBC_2.5 __readlinkat_chk F
 GLIBC_2.5 inet6_opt_append F
 GLIBC_2.5 inet6_opt_find F
index 4ab36819146e15bd34469fa23ae00d72b2ceda01..00dfc8f1e7f546752d3d7dce43c9c6717ee74899 100644 (file)
@@ -2763,3 +2763,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
 GLIBC_2.39 stdc_trailing_zeros_ul F
 GLIBC_2.39 stdc_trailing_zeros_ull F
 GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 openat2 F