1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-01 10:06:57 +03:00

linux: Add close_range

It was added on Linux 5.9 (278a5fbaed89) with CLOSE_RANGE_CLOEXEC
added on 5.11 (582f1fb6b721f).  Although FreeBSD has added the same
syscall, this only adds the symbol on Linux ports.  This syscall is
required to provided a fail-safe way to implement the closefrom
symbol (BZ #10353).

Checked on x86_64-linux-gnu and i686-linux-gnu on kernel 5.11 and 4.15.
This commit is contained in:
Adhemerval Zanella
2021-03-10 12:26:31 -03:00
parent ae8c243d24
commit 286286283e
40 changed files with 422 additions and 1 deletions

3
NEWS
View File

@ -60,6 +60,9 @@ Major new features:
to call async-signal-safe functions (such as raise or execve). This function to call async-signal-safe functions (such as raise or execve). This function
is currently a GNU extension. is currently a GNU extension.
* On Linux, the close_range function has been added. It allows efficiently
closing a range of file descriptors on recent kernels (version 5.9).
Deprecated and removed features, and other changes affecting compatibility: Deprecated and removed features, and other changes affecting compatibility:
* The function pthread_mutex_consistent_np has been deprecated; programs * The function pthread_mutex_consistent_np has been deprecated; programs

View File

@ -0,0 +1,6 @@
#include_next <bits/unistd_ext.h>
#ifndef _ISOMAC
extern int __close_range (unsigned int lowfd, unsigned int highfd, int flags);
libc_hidden_proto (__close_range);
#endif

View File

@ -284,6 +284,57 @@ of trying to close its underlying file descriptor with @code{close}.
This flushes any buffered output and updates the stream object to This flushes any buffered output and updates the stream object to
indicate that it is closed. indicate that it is closed.
@deftypefun int close_range (unsigned int @var{lowfd}, unsigned int @var{maxfd}, int @var{flags})
@standards{Linux, unistd.h}
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}}
@c This is a syscall for Linux v5.9. There is no fallback emulation for
@c older kernels.
The function @code{close_range} closes the file descriptor from @var{lowfd}
to @var{maxfd} (inclusive). This function is similar to call @code{close} in
specified file descriptor range depending on the @var{flags}.
This is function is only supported on recent Linux versions and @theglibc{}
does not provide any fallback (the application will need to handle possible
@code{ENOSYS}).
The @var{flags} add options on how the files are closes. Linux currently
supports:
@vtable @code
@item CLOSE_RANGE_UNSHARE
Unshare the file descriptor table before closing file descriptors.
@item CLOSE_RANGE_CLOEXEC
Set the @code{FD_CLOEXEC} bit instead of closing the file descriptor.
@end vtable
The normal return value from @code{close_range} is @math{0}; a value
of @math{-1} is returned in case of failure. The following @code{errno} error
conditions are defined for this function:
@table @code
@item EINVAL
The @var{lowfd} value is larger than @var{maxfd} or an unsupported @var{flags}
is used.
@item ENOMEM
Either there is not enough memory for the operation, or the process is
out of address space. It can only happnes when @code{CLOSE_RANGE_UNSHARED}
flag is used.
@item EMFILE
The process has too many files open and it can only happens when
@code{CLOSE_RANGE_UNSHARED} flag is used.
The maximum number of file descriptors is controlled by the
@code{RLIMIT_NOFILE} resource limit; @pxref{Limits on Resources}.
@item ENOSYS
The kernel does not implement the required functionality.
@end table
@end deftypefun
@node I/O Primitives @node I/O Primitives
@section Input and Output Primitives @section Input and Output Primitives

View File

@ -116,7 +116,8 @@ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux \ tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux \
tst-timerfd tst-ppoll \ tst-timerfd tst-ppoll \
tst-clock_adjtime tst-adjtimex tst-ntp_adjtime tst-ntp_gettime \ tst-clock_adjtime tst-adjtimex tst-ntp_adjtime tst-ntp_gettime \
tst-ntp_gettimex tst-sigtimedwait tst-misalign-clone tst-ntp_gettimex tst-sigtimedwait tst-misalign-clone \
tst-close_range
# Test for the symbol version of fcntl that was replaced in glibc 2.28. # Test for the symbol version of fcntl that was replaced in glibc 2.28.
ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes) ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes)

View File

@ -283,6 +283,7 @@ libc {
__wait3_time64; __wait3_time64;
__wait4_time64; __wait4_time64;
%endif %endif
close_range;
} }
GLIBC_PRIVATE { GLIBC_PRIVATE {
# functions used in other libraries # functions used in other libraries

View File

@ -2407,6 +2407,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2506,6 +2506,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2166,6 +2166,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -300,6 +300,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -297,6 +297,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -33,4 +33,27 @@
not detached and has not been joined. */ not detached and has not been joined. */
extern __pid_t gettid (void) __THROW; extern __pid_t gettid (void) __THROW;
#ifdef __has_include
# if __has_include ("linux/close_range.h")
# include "linux/close_range.h"
# endif
#endif #endif
/* Unshare the file descriptor table before closing file descriptors. */
#ifndef CLOSE_RANGE_UNSHARE
# define CLOSE_RANGE_UNSHARE (1U << 1)
#endif
/* Set the FD_CLOEXEC bit instead of closing the file descriptor. */
#ifndef CLOSE_RANGE_CLOEXEC
# define CLOSE_RANGE_CLOEXEC (1U << 2)
#endif
/* Close all file descriptors in the range FD up to MAX_FD. The flag FLAGS
are define by the CLOSE_RANGE prefix. This function behaves like close
on the range, but in a fail-safe where it will either fail and not close
any file descriptor or close all of them. Gaps where the file descriptor
is invalid are ignored. Returns 0 on successor or -1 for failure (and
sets errno accordingly). */
extern int close_range (unsigned int __fd, unsigned int __max_fd,
int __flags) __THROW;
#endif /* __USE_GNU */

View File

@ -2432,6 +2432,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2385,6 +2385,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2569,6 +2569,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2344,6 +2344,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -301,6 +301,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2512,6 +2512,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2483,6 +2483,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2480,6 +2480,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2477,6 +2477,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2475,6 +2475,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2483,6 +2483,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2395,6 +2395,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2522,6 +2522,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2539,6 +2539,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2572,6 +2572,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2308,6 +2308,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2603,6 +2603,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2168,6 +2168,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2368,6 +2368,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2537,6 +2537,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2345,6 +2345,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2392,6 +2392,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2389,6 +2389,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2532,6 +2532,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2367,6 +2367,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -99,3 +99,4 @@ pkey_alloc EXTRA pkey_alloc i:ii pkey_alloc
pkey_free EXTRA pkey_free i:i pkey_free pkey_free EXTRA pkey_free i:i pkey_free
gettid EXTRA gettid Ei: __gettid gettid gettid EXTRA gettid Ei: __gettid gettid
tgkill EXTRA tgkill i:iii __tgkill tgkill tgkill EXTRA tgkill i:iii __tgkill tgkill
close_range EXTRA close_range i:iii __close_range close_range

View File

@ -0,0 +1,303 @@
/* Test for the close_range system call.
Copyright (C) 2021 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 <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <getopt.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <array_length.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
#include <support/descriptors.h>
#include <support/support.h>
#include <support/xsched.h>
#include <support/xunistd.h>
#define NFDS 100
static int
open_multiple_temp_files (void)
{
/* Check if the temporary file descriptor has no no gaps. */
int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
for (int i = 1; i <= NFDS; i++)
TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600),
lowfd + i);
return lowfd;
}
static void
close_range_test_max_upper_limit (void)
{
struct support_descriptors *descrs = support_descriptors_list ();
int lowfd = open_multiple_temp_files ();
{
int r = close_range (lowfd, ~0U, 0);
if (r == -1 && errno == ENOSYS)
FAIL_UNSUPPORTED ("close_range not supported");
TEST_COMPARE (r, 0);
}
support_descriptors_check (descrs);
support_descriptors_free (descrs);
}
static void
close_range_test_common (int lowfd, unsigned int flags)
{
const int maximum_fd = lowfd + NFDS;
const int half_fd = lowfd + NFDS / 2;
const int gap_1 = maximum_fd - 8;
/* Close half of the descriptors and check result. */
TEST_COMPARE (close_range (lowfd, half_fd, flags), 0);
for (int i = lowfd; i <= half_fd; i++)
{
TEST_COMPARE (fcntl (i, F_GETFL), -1);
TEST_COMPARE (errno, EBADF);
}
for (int i = half_fd + 1; i < maximum_fd; i++)
TEST_VERIFY (fcntl (i, F_GETFL) > -1);
/* Create some gaps, close up to a threshold, and check result. */
xclose (lowfd + 57);
xclose (lowfd + 78);
xclose (lowfd + 81);
xclose (lowfd + 82);
xclose (lowfd + 84);
xclose (lowfd + 90);
TEST_COMPARE (close_range (half_fd + 1, gap_1, flags), 0);
for (int i = half_fd + 1; i < gap_1; i++)
{
TEST_COMPARE (fcntl (i, F_GETFL), -1);
TEST_COMPARE (errno, EBADF);
}
for (int i = gap_1 + 1; i < maximum_fd; i++)
TEST_VERIFY (fcntl (i, F_GETFL) > -1);
/* Close the remaining but the last one. */
TEST_COMPARE (close_range (gap_1 + 1, maximum_fd - 1, flags), 0);
for (int i = gap_1 + 1; i < maximum_fd - 1; i++)
{
TEST_COMPARE (fcntl (i, F_GETFL), -1);
TEST_COMPARE (errno, EBADF);
}
TEST_VERIFY (fcntl (maximum_fd, F_GETFL) > -1);
/* Close the last one. */
TEST_COMPARE (close_range (maximum_fd, maximum_fd, flags), 0);
TEST_COMPARE (fcntl (maximum_fd, F_GETFL), -1);
TEST_COMPARE (errno, EBADF);
}
/* Basic tests: check if the syscall close ranges with and without gaps. */
static void
close_range_test (void)
{
struct support_descriptors *descrs = support_descriptors_list ();
/* Check if the temporary file descriptor has no no gaps. */
int lowfd = open_multiple_temp_files ();
close_range_test_common (lowfd, 0);
/* Double check by check the /proc. */
support_descriptors_check (descrs);
support_descriptors_free (descrs);
}
_Noreturn static int
close_range_test_fn (void *arg)
{
int lowfd = (int) ((uintptr_t) arg);
close_range_test_common (lowfd, 0);
exit (EXIT_SUCCESS);
}
/* Check if a clone_range on a subprocess created with CLONE_FILES close
the shared file descriptor table entries in the parent. */
static void
close_range_test_subprocess (void)
{
struct support_descriptors *descrs = support_descriptors_list ();
/* Check if the temporary file descriptor has no no gaps. */
int lowfd = open_multiple_temp_files ();
struct support_stack stack = support_stack_alloc (4096);
pid_t pid = xclone (close_range_test_fn, (void*) (uintptr_t) lowfd,
stack.stack, stack.size, CLONE_FILES | SIGCHLD);
TEST_VERIFY_EXIT (pid > 0);
int status;
xwaitpid (pid, &status, 0);
TEST_VERIFY (WIFEXITED (status));
TEST_COMPARE (WEXITSTATUS (status), 0);
support_stack_free (&stack);
for (int i = lowfd; i < NFDS; i++)
TEST_VERIFY (fcntl (i, F_GETFL) < 0);
support_descriptors_check (descrs);
support_descriptors_free (descrs);
}
_Noreturn static int
close_range_unshare_test_fn (void *arg)
{
int lowfd = (int) ((uintptr_t) arg);
close_range_test_common (lowfd, CLOSE_RANGE_UNSHARE);
exit (EXIT_SUCCESS);
}
/* Check if a close_range with CLOSE_RANGE_UNSHARE issued from a subprocess
created with CLONE_FILES does not close the parent file descriptor list. */
static void
close_range_unshare_test (void)
{
struct support_descriptors *descrs1 = support_descriptors_list ();
/* Check if the temporary file descriptor has no no gaps. */
int lowfd = open_multiple_temp_files ();
struct support_descriptors *descrs2 = support_descriptors_list ();
struct support_stack stack = support_stack_alloc (4096);
pid_t pid = xclone (close_range_unshare_test_fn, (void*) (uintptr_t) lowfd,
stack.stack, stack.size, CLONE_FILES | SIGCHLD);
TEST_VERIFY_EXIT (pid > 0);
int status;
xwaitpid (pid, &status, 0);
TEST_VERIFY (WIFEXITED (status));
TEST_COMPARE (WEXITSTATUS (status), 0);
support_stack_free (&stack);
for (int i = 0; i < NFDS; i++)
TEST_VERIFY (fcntl (i, F_GETFL) > -1);
support_descriptors_check (descrs2);
support_descriptors_free (descrs2);
TEST_COMPARE (close_range (lowfd, lowfd + NFDS, 0), 0);
support_descriptors_check (descrs1);
support_descriptors_free (descrs1);
}
static bool
is_in_array (int *arr, size_t len, int fd)
{
bool r = false;
for (int i = 0; i < len; i++)
if (arr[i] == fd)
return true;
return r;
}
static void
close_range_cloexec_test (void)
{
/* Check if the temporary file descriptor has no no gaps. */
const int lowfd = open_multiple_temp_files ();
const int maximum_fd = lowfd + NFDS;
const int half_fd = lowfd + NFDS / 2;
const int gap_1 = maximum_fd - 8;
/* Close half of the descriptors and check result. */
int r = close_range (lowfd, half_fd, CLOSE_RANGE_CLOEXEC);
if (r == -1 && errno == EINVAL)
{
printf ("%s: CLOSE_RANGE_CLOEXEC not supported\n", __func__);
return;
}
for (int i = lowfd; i <= half_fd; i++)
{
int flags = fcntl (i, F_GETFD);
TEST_VERIFY (flags > -1);
TEST_COMPARE (flags & FD_CLOEXEC, FD_CLOEXEC);
}
for (int i = half_fd + 1; i < maximum_fd; i++)
TEST_VERIFY (fcntl (i, F_GETFL) > -1);
/* Create some gaps, close up to a threshold, and check result. */
static int gap_close[] = { 57, 78, 81, 82, 84, 90 };
for (int i = 0; i < array_length (gap_close); i++)
xclose (gap_close[i]);
TEST_COMPARE (close_range (half_fd + 1, gap_1, CLOSE_RANGE_CLOEXEC), 0);
for (int i = half_fd + 1; i < gap_1; i++)
{
int flags = fcntl (i, F_GETFD);
if (is_in_array (gap_close, array_length (gap_close), i))
TEST_COMPARE (flags, -1);
else
{
TEST_VERIFY (flags > -1);
TEST_COMPARE (flags & FD_CLOEXEC, FD_CLOEXEC);
}
}
for (int i = gap_1 + 1; i < maximum_fd; i++)
TEST_VERIFY (fcntl (i, F_GETFL) > -1);
/* Close the remaining but the last one. */
TEST_COMPARE (close_range (gap_1 + 1, maximum_fd - 1, CLOSE_RANGE_CLOEXEC),
0);
for (int i = gap_1 + 1; i < maximum_fd - 1; i++)
{
int flags = fcntl (i, F_GETFD);
TEST_VERIFY (flags > -1);
TEST_COMPARE (flags & FD_CLOEXEC, FD_CLOEXEC);
}
TEST_VERIFY (fcntl (maximum_fd, F_GETFL) > -1);
/* Close the last one. */
TEST_COMPARE (close_range (maximum_fd, maximum_fd, CLOSE_RANGE_CLOEXEC), 0);
{
int flags = fcntl (maximum_fd, F_GETFD);
TEST_VERIFY (flags > -1);
TEST_COMPARE (flags & FD_CLOEXEC, FD_CLOEXEC);
}
}
static int
do_test (void)
{
close_range_test_max_upper_limit ();
close_range_test ();
close_range_test_subprocess ();
close_range_unshare_test ();
close_range_cloexec_test ();
return 0;
}
#include <support/test-driver.c>

View File

@ -2323,6 +2323,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F

View File

@ -2422,6 +2422,7 @@ GLIBC_2.34 aio_suspend64 F
GLIBC_2.34 aio_write F GLIBC_2.34 aio_write F
GLIBC_2.34 aio_write64 F GLIBC_2.34 aio_write64 F
GLIBC_2.34 call_once F GLIBC_2.34 call_once F
GLIBC_2.34 close_range F
GLIBC_2.34 cnd_broadcast F GLIBC_2.34 cnd_broadcast F
GLIBC_2.34 cnd_destroy F GLIBC_2.34 cnd_destroy F
GLIBC_2.34 cnd_init F GLIBC_2.34 cnd_init F