Merge "add new Linux close_range() system call to bionic"

This commit is contained in:
Treehugger Robot 2022-05-06 22:25:26 +00:00 committed by Gerrit Code Review
commit c66cb5ba6a
6 changed files with 43 additions and 3 deletions

View file

@ -76,5 +76,3 @@ int futex_time64(int*, int, int, const timespec64*, int*, int) lp32
int sched_rr_get_interval_time64(pid_t, timespec64*) lp32
# Since Linux 5.4, not in glibc. Probed for and conditionally used by ART.
int userfaultfd(int) all
# Since Linux 5.9, used by POSIX_SPAWN_CLOEXEC_DEFAULT
int close_range(unsigned int, unsigned int, int) all

View file

@ -107,6 +107,7 @@ ssize_t __preadv64v2:preadv2(int, const struct iovec*, int, long, long, int)
ssize_t __pwritev64v2:pwritev2(int, const struct iovec*, int, long, long, int) all
int __close:close(int) all
int close_range(unsigned int, unsigned int, int) all
pid_t __getpid:getpid() all
int memfd_create(const char*, unsigned) all
int munmap(void*, size_t) all

View file

@ -52,7 +52,7 @@ static int set_cloexec(int i) {
// mark all open fds except stdin/out/err as close-on-exec
static int cloexec_except_stdioe() {
// requires 5.11+ or ACK 5.10-T kernel, otherwise returns ENOSYS or EINVAL
if (!syscall(SYS_close_range, 3, ~0U, CLOSE_RANGE_CLOEXEC)) return 0;
if (!close_range(3, ~0U, CLOSE_RANGE_CLOEXEC)) return 0;
// unfortunately getrlimit can lie:
// - both soft and hard limits can be lowered to 0, with fds still open, so it can underestimate

View file

@ -317,6 +317,22 @@ int setdomainname(const char* __name, size_t __n) __INTRODUCED_IN(26);
void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN(28);
#endif
/**
* [close_range(2)](https://man7.org/linux/man-pages/man2/close_range.2.html)
* performs an action (which depends on value of flags) on an inclusive range
* of file descriptors.
*
* Available since API level 34.
*
* Note: there is no emulation on too old kernels, hence this will fail with
* -1/ENOSYS on pre-5.9 kernels, -1/EINVAL for unsupported flags. In particular
* CLOSE_RANGE_CLOEXEC requires 5.11, though support was backported to Android
* Common Kernel 5.10-T.
*
* Returns 0 on success, and returns -1 and sets `errno` on failure.
*/
int close_range(unsigned int __min_fd, unsigned int __max_fd, int __flags) __INTRODUCED_IN(34);
#if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
#define _UNISTD_H_
#include <bits/fortify/unistd.h>

View file

@ -1576,6 +1576,11 @@ LIBC_T { # introduced=Tiramisu
pwritev64v2;
} LIBC_S;
LIBC_U { # introduced=UpsideDownCake
global:
close_range;
} LIBC_T;
LIBC_PRIVATE {
global:
__accept4; # arm x86

View file

@ -1648,3 +1648,23 @@ TEST(UNISTD_TEST, sleep) {
auto t1 = std::chrono::steady_clock::now();
ASSERT_GE(t1-t0, 1s);
}
TEST(UNISTD_TEST, close_range) {
#if defined(__GLIBC__)
GTEST_SKIP() << "glibc too old";
#else // __GLIBC__
int fd = open("/proc/version", O_RDONLY);
ASSERT_GE(fd, 0);
// Try to close the file descriptor (this requires a 5.9+ kernel)
if (close_range(fd, fd, 0) == 0) {
// we can't close it *again*
ASSERT_EQ(close(fd), -1);
ASSERT_EQ(errno, EBADF);
} else {
ASSERT_EQ(errno, ENOSYS);
// since close_range() failed, we can close it normally
ASSERT_EQ(close(fd), 0);
}
#endif // __GLIBC__
}