mirror of
https://sourceware.org/git/glibc.git
synced 2024-09-19 16:10:01 +00:00
linux: Add openat2 (BZ 31664)
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.
This commit is contained in:
parent
f4724843ad
commit
921efb18ef
4
NEWS
4
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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
61
sysdeps/unix/sysv/linux/bits/openat2.h
Normal file
61
sysdeps/unix/sysv/linux/bits/openat2.h
Normal file
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
29
sysdeps/unix/sysv/linux/openat2.c
Normal file
29
sysdeps/unix/sysv/linux/openat2.c
Normal file
@ -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)
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
63
sysdeps/unix/sysv/linux/tst-openat2-consts.py
Executable file
63
sysdeps/unix/sysv/linux/tst-openat2-consts.py
Executable file
@ -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()
|
259
sysdeps/unix/sysv/linux/tst-openat2.c
Normal file
259
sysdeps/unix/sysv/linux/tst-openat2.c
Normal file
@ -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>
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user