Fortify ppoll64.

I've deliberately not bothered with the GCC implementation because we'll
have removed GCC from the NDK before anyone gets to use this.

Bug: http://b/72493232
Test: ran tests
Change-Id: Icfc2a3b214739ab53aa41bacacc11b5c67498fb4
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index 985d47f..944cfca 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -169,6 +169,12 @@
   return ppoll(fds, fd_count, timeout, mask);
 }
 
+int __ppoll64_chk(pollfd* fds, nfds_t fd_count, const timespec* timeout,
+                  const sigset64_t* mask, size_t fds_size) {
+  __check_pollfd_array("ppoll64", fds_size, fd_count);
+  return ppoll64(fds, fd_count, timeout, mask);
+}
+
 ssize_t __pread64_chk(int fd, void* buf, size_t count, off64_t offset, size_t buf_size) {
   __check_count("pread64", "count", count);
   __check_buffer_access("pread64", "write into", count, buf_size);
diff --git a/libc/include/bits/fortify/poll.h b/libc/include/bits/fortify/poll.h
index 8363e35..c3ae31d 100644
--- a/libc/include/bits/fortify/poll.h
+++ b/libc/include/bits/fortify/poll.h
@@ -31,8 +31,8 @@
 #endif
 
 int __poll_chk(struct pollfd*, nfds_t, int, size_t) __INTRODUCED_IN(23);
-int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t)
-  __INTRODUCED_IN(23);
+int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t) __INTRODUCED_IN(23);
+int __ppoll64_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset64_t*, size_t) __INTRODUCED_IN(28);
 
 #if defined(__BIONIC_FORTIFY)
 #if __ANDROID_API__ >= __ANDROID_API_M__
@@ -64,7 +64,24 @@
   }
   return __ppoll_chk(fds, fd_count, timeout, mask, bos_fds);
 }
-#else /* defined(__clang__) */
+
+#if __ANDROID_API__ >= __ANDROID_API_P__
+__BIONIC_FORTIFY_INLINE
+int ppoll64(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const struct timespec* timeout, const sigset64_t* mask)
+    __overloadable
+    __clang_error_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                       __bos(fds) < sizeof(*fds) * fd_count,
+                     "in call to 'ppoll64', fd_count is larger than the given buffer") {
+  size_t bos_fds = __bos(fds);
+
+  if (bos_fds == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+    return __call_bypassing_fortify(ppoll64)(fds, fd_count, timeout, mask);
+  }
+  return __ppoll64_chk(fds, fd_count, timeout, mask, bos_fds);
+}
+#endif
+
+#else /* !defined(__clang__) */
 int __poll_real(struct pollfd*, nfds_t, int) __RENAME(poll);
 __errordecl(__poll_too_small_error, "poll: pollfd array smaller than fd count");
 
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index b0f96a9..56e4189 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -115,6 +115,7 @@
     __poll_chk; # introduced=23
     __ppoll; # arm x86 mips introduced=21
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 6b0e415..880ed80 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -74,6 +74,7 @@
     __p_type_syms; # var
     __poll_chk; # introduced=23
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 85c9a58..b787ea5 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -115,6 +115,7 @@
     __poll_chk; # introduced=23
     __ppoll; # arm x86 mips introduced=21
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 9e760c2..ec3fe3a 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -112,6 +112,7 @@
     __poll_chk; # introduced=23
     __ppoll; # arm x86 mips introduced=21
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 6b0e415..880ed80 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -74,6 +74,7 @@
     __p_type_syms; # var
     __poll_chk; # introduced=23
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 2855f9e..9407b58 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -112,6 +112,7 @@
     __poll_chk; # introduced=23
     __ppoll; # arm x86 mips introduced=21
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 6b0e415..880ed80 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -74,6 +74,7 @@
     __p_type_syms; # var
     __poll_chk; # introduced=23
     __ppoll_chk; # introduced=23
+    __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
diff --git a/tests/fortify_filecheck_diagnostics_test.cpp b/tests/fortify_filecheck_diagnostics_test.cpp
index c6198c6..375a156 100644
--- a/tests/fortify_filecheck_diagnostics_test.cpp
+++ b/tests/fortify_filecheck_diagnostics_test.cpp
@@ -278,7 +278,15 @@
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__ppoll_too_small_error' declared with attribute error: ppoll: pollfd array smaller than fd count
   // CLANG: error: in call to 'ppoll', fd_count is larger than the given buffer
-  ppoll(fds, 2, &timeout, NULL);
+  ppoll(fds, 2, &timeout, nullptr);
+}
+
+void test_ppoll64() {
+  pollfd fds[1];
+  timespec timeout;
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // CLANG: error: in call to 'ppoll64', fd_count is larger than the given buffer
+  ppoll64(fds, 2, &timeout, nullptr);
 }
 
 void test_fread_overflow() {
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 67c124d..b5b858f 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -995,7 +995,18 @@
   // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
   timespec timeout;
   timeout.tv_sec = timeout.tv_nsec = 0;
-  ASSERT_FORTIFY(ppoll(buf, fd_count, &timeout, NULL));
+  ASSERT_FORTIFY(ppoll(buf, fd_count, &timeout, nullptr));
+}
+
+TEST_F(DEATHTEST, ppoll64_fortified) {
+#if __BIONIC__ // glibc doesn't have ppoll64.
+  nfds_t fd_count = atoi("2"); // suppress compiler optimizations
+  pollfd buf[1] = {{0, POLLIN, 0}};
+  // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
+  timespec timeout;
+  timeout.tv_sec = timeout.tv_nsec = 0;
+  ASSERT_FORTIFY(ppoll64(buf, fd_count, &timeout, nullptr));
+#endif
 }
 
 TEST_F(DEATHTEST, open_O_CREAT_without_mode_fortified) {