diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2022-05-06 22:25:26 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-05-06 22:25:26 +0000 |
commit | c66cb5ba6a352e2b7dee39f9696358150abc0039 (patch) | |
tree | ae0ed5da2faca808ab63e5c1493e247cf55a5e1c | |
parent | de9fe1e2de37e35081b331455b557915b07e6df7 (diff) | |
parent | b65e1050476ec37330129a7de480dc4fb662a05c (diff) | |
download | bionic-c66cb5ba6a352e2b7dee39f9696358150abc0039.tar.gz |
Merge "add new Linux close_range() system call to bionic"
-rw-r--r-- | libc/SECCOMP_ALLOWLIST_COMMON.TXT | 2 | ||||
-rw-r--r-- | libc/SYSCALLS.TXT | 1 | ||||
-rw-r--r-- | libc/bionic/spawn.cpp | 2 | ||||
-rw-r--r-- | libc/include/unistd.h | 16 | ||||
-rw-r--r-- | libc/libc.map.txt | 5 | ||||
-rw-r--r-- | tests/unistd_test.cpp | 20 |
6 files changed, 43 insertions, 3 deletions
diff --git a/libc/SECCOMP_ALLOWLIST_COMMON.TXT b/libc/SECCOMP_ALLOWLIST_COMMON.TXT index 0366fdf0f..a4218ee17 100644 --- a/libc/SECCOMP_ALLOWLIST_COMMON.TXT +++ b/libc/SECCOMP_ALLOWLIST_COMMON.TXT @@ -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 diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index a09c614e6..1435e79f6 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -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 diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp index 59f763138..7e80ef6c4 100644 --- a/libc/bionic/spawn.cpp +++ b/libc/bionic/spawn.cpp @@ -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 diff --git a/libc/include/unistd.h b/libc/include/unistd.h index e36042187..f142525ba 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -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> diff --git a/libc/libc.map.txt b/libc/libc.map.txt index 7397b687c..e64fe00bd 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -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 diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp index 6d7e6878f..293b45ae5 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -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__ +} |