Merge "add new Linux close_range() system call to bionic"
This commit is contained in:
commit
c66cb5ba6a
6 changed files with 43 additions and 3 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue