allowlist new Linux close_range() system call, use it in posix_spawn()

Linux kernel's close_range() system call (currently) allows:
  close() unshare() fcntl(F_SETFD, FD_CLOEXEC)
to be performed on ranges of fds.

All 3 of these are already allowed by seccomp bpf:
as such this doesn't allow you to do anything you can't already do.

We can't add close_range() properly to bionic because we'd need to
fiddle about with ltp and it's too late to add new T API anyway,
so let's just make the direct syscall() call.

We'll add proper support in U.

See also:
  https://man7.org/linux/man-pages/man2/close_range.2.html

Test: TreeHugger
Bug: 229913920
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I85586d544fc23bed6aee59f00bdb79ee7a8150d1
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index 314a056..59f7631 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -30,10 +30,12 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <linux/close_range.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/resource.h>
+#include <sys/syscall.h>
 #include <unistd.h>
 
 #include <android/fdsan.h>
@@ -49,6 +51,9 @@
 
 // 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;
+
   // unfortunately getrlimit can lie:
   // - both soft and hard limits can be lowered to 0, with fds still open, so it can underestimate
   // - in practice it usually is some really large value (like 32K or more)