Merge "Add tests for the untested <wchar.h> functions."
diff --git a/libc/Android.bp b/libc/Android.bp
index 4084b96..ba51b0e 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1028,9 +1028,7 @@
         "bionic/arpa_inet.cpp",
         "bionic/assert.cpp",
         "bionic/atof.cpp",
-        "bionic/bind.cpp",
         "bionic/bionic_allocator.cpp",
-        "bionic/bionic_appcompat.cpp",
         "bionic/bionic_arc4random.cpp",
         "bionic/bionic_futex.cpp",
         "bionic/bionic_netlink.cpp",
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index ec34828..391e7af 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -245,7 +245,7 @@
 # sockets
 int           __socket:socket(int, int, int)              arm,lp64
 int           __socketpair:socketpair(int, int, int, int*)    arm,lp64
-int           __bind:bind(int, struct sockaddr*, socklen_t)  arm,lp64
+int           bind(int, struct sockaddr*, socklen_t)  arm,lp64
 int           __connect:connect(int, struct sockaddr*, socklen_t)   arm,lp64
 int           listen(int, int)                   arm,lp64
 int           __accept4:accept4(int, struct sockaddr*, socklen_t*, int)  arm,lp64
@@ -263,7 +263,7 @@
 
 # sockets for x86. These are done as an "indexed" call to socketcall syscall.
 int           __socket:socketcall:1(int, int, int) x86
-int           __bind:socketcall:2(int, struct sockaddr*, int)  x86
+int           bind:socketcall:2(int, struct sockaddr*, int)  x86
 int           __connect:socketcall:3(int, struct sockaddr*, socklen_t)   x86
 int           listen:socketcall:4(int, int)                   x86
 int           getsockname:socketcall:6(int, struct sockaddr*, socklen_t*)  x86
diff --git a/libc/bionic/bind.cpp b/libc/bionic/bind.cpp
deleted file mode 100644
index 79e8020..0000000
--- a/libc/bionic/bind.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-// b/170214442: Intercept bind calls on NETLINK_ROUTE sockets.
-// This entire file will be reverted before release.
-
-#include <async_safe/log.h>
-#include <errno.h>
-#include <linux/rtnetlink.h>
-#include <string.h>
-#include <sys/socket.h>
-
-#include "bionic_appcompat.h"
-
-extern "C" int __bind(int fd, const struct sockaddr* addr, socklen_t addr_length);
-
-int bind(int fd, const struct sockaddr* addr, socklen_t addr_length) {
-  if (should_apply_soft_mac_bind_restrictions()) {
-    int sock_domain, sock_protocol;
-    socklen_t sock_domain_length = sizeof(sock_domain);
-    socklen_t sock_protocol_length = sizeof(sock_protocol);
-    if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &sock_domain, &sock_domain_length) < 0 ||
-        getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &sock_protocol, &sock_protocol_length) < 0) {
-      async_safe_format_log(ANDROID_LOG_ERROR, "mac-restrictions",
-                            "Could not get socket type/protocol: %s", strerror(errno));
-    } else if (AF_NETLINK == sock_domain && NETLINK_ROUTE == sock_protocol) {
-      char package_name[MAX_PACKAGE_NAME_LENGTH + 1];
-      get_package_name(package_name, sizeof(package_name));
-      async_safe_format_log(
-          ANDROID_LOG_ERROR, "mac-restrictions",
-          "%s tried to call bind() on a NETLINK_ROUTE socket, which is not allowed. Please follow "
-          "instructions at go/netlink-bug if this app behaves incorrectly.",
-          package_name);
-      errno = EACCES;
-      return -1;
-    }
-  }
-
-  return __bind(fd, addr, addr_length);
-}
diff --git a/libc/bionic/bionic_appcompat.cpp b/libc/bionic/bionic_appcompat.cpp
deleted file mode 100644
index dcca0da..0000000
--- a/libc/bionic/bionic_appcompat.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-// b/170214442: Intercept bind calls on NETLINK_ROUTE sockets and getifaddrs() calls.
-// This entire file will be reverted before release.
-
-#include <async_safe/log.h>
-#include <cutils/misc.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "bionic_appcompat.h"
-
-bool should_apply_soft_mac_restrictions(const char* const allowlist[]) {
-  if (getuid() < FIRST_APPLICATION_UID) {
-    // System app. No restrictions should be applied.
-    return false;
-  }
-  if (android_get_application_target_sdk_version() >= __ANDROID_API_R__) {
-    // Restrictions already applied by SELinux. Behave as normally.
-    return false;
-  }
-
-  char package_name[MAX_PACKAGE_NAME_LENGTH + 1];
-  if (get_package_name(package_name, sizeof(package_name)) < 0) {
-    // Error in getting own package name. Apply restrictions by default.
-    async_safe_format_log(ANDROID_LOG_ERROR, "mac-restrictions",
-                          "Could not determine own package name for uid %d", getuid());
-    return true;
-  }
-  for (int i = 0; allowlist[i] != nullptr; i++) {
-    if (strcmp(package_name, allowlist[i]) == 0) {
-      async_safe_format_log(ANDROID_LOG_WARN, "mac-restrictions",
-                            "Temporarily allowing %s to bypass MAC address restrictions.",
-                            package_name);
-      return false;
-    }
-  }
-  return true;
-}
-
-bool should_apply_soft_mac_bind_restrictions() {
-  return should_apply_soft_mac_restrictions(soft_mac_bind_allowlist);
-}
-
-bool should_apply_soft_mac_getlink_restrictions() {
-  return should_apply_soft_mac_restrictions(soft_mac_getlink_allowlist);
-}
-
-int get_package_name(char* buffer, const int bufferlen) {
-  int file = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC);
-  if (file < 0) {
-    return file;
-  }
-
-  ssize_t len = read(file, buffer, bufferlen - 1);
-  if (len < 0) {
-    close(file);
-    return -1;
-  }
-  buffer[len] = 0;
-
-  close(file);
-  return 0;
-}
diff --git a/libc/bionic/bionic_appcompat.h b/libc/bionic/bionic_appcompat.h
deleted file mode 100644
index e67e50c..0000000
--- a/libc/bionic/bionic_appcompat.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#pragma once
-
-constexpr int MAX_PACKAGE_NAME_LENGTH = 230;
-
-static inline const char* const soft_mac_bind_allowlist[] = {
-    "com.cisco.anyconnect.vpn.android.avf:nchs",
-    "com.skype.raider",
-    nullptr,
-};
-
-static inline const char* const soft_mac_getlink_allowlist[] = {
-    "com.cisco.anyconnect.vpn.android.avf:nchs",
-    nullptr,
-};
-
-int get_package_name(char* buffer, const int bufferlen);
-bool should_apply_soft_mac_bind_restrictions();
-bool should_apply_soft_mac_getlink_restrictions();
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 043510c..48e8674 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -137,14 +137,6 @@
     return;
   }
 
-  // Lots of code will (sensibly) fork, call close on all of their fds,
-  // and then exec. Compare our cached pid value against the real one to detect
-  // this scenario and permit it.
-  pid_t cached_pid = __get_cached_pid();
-  if (cached_pid == 0 || cached_pid != syscall(__NR_getpid)) {
-    return;
-  }
-
   struct {
     size_t size;
     char buf[512];
diff --git a/libc/bionic/fdtrack.cpp b/libc/bionic/fdtrack.cpp
index 1123512..89a208f 100644
--- a/libc/bionic/fdtrack.cpp
+++ b/libc/bionic/fdtrack.cpp
@@ -37,8 +37,14 @@
 
 _Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
 
+bool __android_fdtrack_globally_disabled = false;
+
+void android_fdtrack_set_globally_enabled(bool new_value) {
+  __android_fdtrack_globally_disabled = !new_value;
+}
+
 bool android_fdtrack_get_enabled() {
-  return !__get_bionic_tls().fdtrack_disabled;
+  return !__get_bionic_tls().fdtrack_disabled && !__android_fdtrack_globally_disabled;
 }
 
 bool android_fdtrack_set_enabled(bool new_value) {
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index 8c5cf2b..d432c6d 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -31,6 +31,7 @@
 #include <android/fdsan.h>
 
 #include "private/bionic_defs.h"
+#include "private/bionic_fdtrack.h"
 #include "pthread_internal.h"
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE_INLINE
@@ -55,9 +56,10 @@
   int result = __clone_for_fork();
 
   if (result == 0) {
-    // Disable fdsan post-fork, so we don't falsely trigger on processes that
+    // Disable fdsan and fdtrack post-fork, so we don't falsely trigger on processes that
     // fork, close all of their fds, and then exec.
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
+    android_fdtrack_set_globally_enabled(false);
 
     // Reset the stack_and_tls VMA name so it doesn't end with a tid from the
     // parent process.
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index 22ecdb4..1536333 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -42,7 +42,6 @@
 
 #include "private/ErrnoRestorer.h"
 
-#include "bionic_appcompat.h"
 #include "bionic_netlink.h"
 
 // The public ifaddrs struct is full of pointers. Rather than track several
@@ -311,12 +310,9 @@
   // - System apps
   // - Apps with a target SDK version lower than R
   bool getlink_success = false;
-  if (!should_apply_soft_mac_getlink_restrictions()) {
+  if (getuid() < FIRST_APPLICATION_UID ||
+      android_get_application_target_sdk_version() < __ANDROID_API_R__) {
     getlink_success = nc.SendRequest(RTM_GETLINK) && nc.ReadResponses(__getifaddrs_callback, out);
-  } else if (android_get_application_target_sdk_version() < __ANDROID_API_R__) {
-    async_safe_format_log(ANDROID_LOG_WARN, "mac-restrictions",
-                          "ifaddr no longer returns link info. Please follow instructions at "
-                          "go/netlink-bug if this app behaves incorrectly.");
   }
   bool getaddr_success =
     nc.SendRequest(RTM_GETADDR) && nc.ReadResponses(__getifaddrs_callback, out);
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 51a1076..c31e306 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1772,6 +1772,7 @@
     android_fdtrack_compare_exchange_hook; # llndk
     android_fdtrack_get_enabled; # llndk
     android_fdtrack_set_enabled; # llndk
+    android_fdtrack_set_globally_enabled; # llndk
     android_net_res_stats_get_info_for_net;
     android_net_res_stats_aggregate;
     android_net_res_stats_get_usable_servers;
diff --git a/libc/platform/bionic/fdtrack.h b/libc/platform/bionic/fdtrack.h
index 6eb379b..fe6ca84 100644
--- a/libc/platform/bionic/fdtrack.h
+++ b/libc/platform/bionic/fdtrack.h
@@ -70,4 +70,8 @@
 bool android_fdtrack_get_enabled() __INTRODUCED_IN(30);
 bool android_fdtrack_set_enabled(bool new_value) __INTRODUCED_IN(30);
 
+// Globally enable/disable fdtrack.
+// This is primaryily useful to reenable fdtrack after it's been automatically disabled post-fork.
+void android_fdtrack_set_globally_enabled(bool new_value) __INTRODUCED_IN(31);
+
 __END_DECLS
diff --git a/libc/private/bionic_fdtrack.h b/libc/private/bionic_fdtrack.h
index 259897c..c05b32b 100644
--- a/libc/private/bionic_fdtrack.h
+++ b/libc/private/bionic_fdtrack.h
@@ -28,41 +28,43 @@
 
 #pragma once
 
-#include <sys/cdefs.h>
 #include <stdatomic.h>
+#include <sys/cdefs.h>
 
 #include "platform/bionic/fdtrack.h"
 
 #include "bionic/pthread_internal.h"
-#include "private/bionic_tls.h"
 #include "private/ErrnoRestorer.h"
+#include "private/bionic_tls.h"
 
 extern "C" _Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
+extern "C" bool __android_fdtrack_globally_disabled;
 
 // Macro to record file descriptor creation.
 // e.g.:
 //   int socket(int domain, int type, int protocol) {
 //     return FDTRACK_CREATE_NAME("socket", __socket(domain, type, protocol));
 //   }
-#define FDTRACK_CREATE_NAME(name, fd_value)                       \
-  ({                                                              \
-    int __fd = (fd_value);                                        \
-    if (__fd != -1 && __predict_false(__android_fdtrack_hook) &&  \
-        !__predict_false(__get_thread()->is_vforked())) {         \
-      bionic_tls& tls = __get_bionic_tls();                       \
-      /* fdtrack_disabled is only true during reentrant calls. */ \
-      if (!__predict_false(tls.fdtrack_disabled)) {               \
-        ErrnoRestorer r;                                          \
-        tls.fdtrack_disabled = true;                              \
-        android_fdtrack_event event;                              \
-        event.fd = __fd;                                          \
-        event.type = ANDROID_FDTRACK_EVENT_TYPE_CREATE;           \
-        event.data.create.function_name = name;                   \
-        atomic_load(&__android_fdtrack_hook)(&event);             \
-        tls.fdtrack_disabled = false;                             \
-      }                                                           \
-    }                                                             \
-    __fd;                                                         \
+#define FDTRACK_CREATE_NAME(name, fd_value)                        \
+  ({                                                               \
+    int __fd = (fd_value);                                         \
+    if (__fd != -1 && __predict_false(__android_fdtrack_hook) &&   \
+        !__predict_false(__get_thread()->is_vforked())) {          \
+      bionic_tls& tls = __get_bionic_tls();                        \
+      /* fdtrack_disabled is only true during reentrant calls. */  \
+      if (!__predict_false(tls.fdtrack_disabled) &&                \
+          !__predict_false(__android_fdtrack_globally_disabled)) { \
+        ErrnoRestorer r;                                           \
+        tls.fdtrack_disabled = true;                               \
+        android_fdtrack_event event;                               \
+        event.fd = __fd;                                           \
+        event.type = ANDROID_FDTRACK_EVENT_TYPE_CREATE;            \
+        event.data.create.function_name = name;                    \
+        atomic_load (&__android_fdtrack_hook)(&event);             \
+        tls.fdtrack_disabled = false;                              \
+      }                                                            \
+    }                                                              \
+    __fd;                                                          \
   })
 
 // Macro to record file descriptor creation, with the current function's name.
@@ -74,22 +76,23 @@
 
 // Macro to record file descriptor closure.
 // Note that this does not actually close the file descriptor.
-#define FDTRACK_CLOSE(fd_value)                                  \
-  ({                                                             \
-    int __fd = (fd_value);                                       \
-    if (__fd != -1 && __predict_false(__android_fdtrack_hook) && \
-        !__predict_false(__get_thread()->is_vforked())) {        \
-      bionic_tls& tls = __get_bionic_tls();                      \
-      if (!__predict_false(tls.fdtrack_disabled)) {              \
-        int saved_errno = errno;                                 \
-        tls.fdtrack_disabled = true;                             \
-        android_fdtrack_event event;                             \
-        event.fd = __fd;                                         \
-        event.type = ANDROID_FDTRACK_EVENT_TYPE_CLOSE;           \
-        atomic_load(&__android_fdtrack_hook)(&event);            \
-        tls.fdtrack_disabled = false;                            \
-        errno = saved_errno;                                     \
-      }                                                          \
-    }                                                            \
-    __fd;                                                        \
+#define FDTRACK_CLOSE(fd_value)                                    \
+  ({                                                               \
+    int __fd = (fd_value);                                         \
+    if (__fd != -1 && __predict_false(__android_fdtrack_hook) &&   \
+        !__predict_false(__get_thread()->is_vforked())) {          \
+      bionic_tls& tls = __get_bionic_tls();                        \
+      if (!__predict_false(tls.fdtrack_disabled) &&                \
+          !__predict_false(__android_fdtrack_globally_disabled)) { \
+        int saved_errno = errno;                                   \
+        tls.fdtrack_disabled = true;                               \
+        android_fdtrack_event event;                               \
+        event.fd = __fd;                                           \
+        event.type = ANDROID_FDTRACK_EVENT_TYPE_CLOSE;             \
+        atomic_load (&__android_fdtrack_hook)(&event);             \
+        tls.fdtrack_disabled = false;                              \
+        errno = saved_errno;                                       \
+      }                                                            \
+    }                                                              \
+    __fd;                                                          \
   })
diff --git a/libfdtrack/fdtrack.cpp b/libfdtrack/fdtrack.cpp
index fd56274..2e9cfbc 100644
--- a/libfdtrack/fdtrack.cpp
+++ b/libfdtrack/fdtrack.cpp
@@ -93,6 +93,8 @@
     android_fdtrack_hook_t expected = nullptr;
     installed = android_fdtrack_compare_exchange_hook(&expected, &fd_hook);
   }
+
+  android_fdtrack_set_globally_enabled(true);
 }
 
 __attribute__((destructor)) static void dtor() {
diff --git a/tests/fdtrack_test.cpp b/tests/fdtrack_test.cpp
index 13f1b2e..9fcb402 100644
--- a/tests/fdtrack_test.cpp
+++ b/tests/fdtrack_test.cpp
@@ -57,8 +57,13 @@
   }
 }
 
-std::vector<android_fdtrack_event> FdtrackRun(void (*func)()) {
+std::vector<android_fdtrack_event> FdtrackRun(void (*func)(), bool reenable = true) {
   // Each bionic test is run in separate process, so we can safely use a static here.
+  // However, since they're all forked, we need to reenable fdtrack.
+  if (reenable) {
+    android_fdtrack_set_globally_enabled(true);
+  }
+
   static std::vector<android_fdtrack_event> events;
   events.clear();
 
@@ -129,6 +134,21 @@
 #endif
 }
 
+TEST(fdtrack, fork) {
+#if defined(__BIONIC__)
+  ASSERT_EXIT(
+      []() {
+        static int fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
+        ASSERT_NE(-1, fd);
+
+        auto events = FdtrackRun([]() { close(fd); }, false);
+        ASSERT_EQ(0U, events.size());
+        exit(0);
+      }(),
+      testing::ExitedWithCode(0), "");
+#endif
+}
+
 TEST(fdtrack, enable_disable) {
 #if defined(__BIONIC__)
   static int fd1 = -1;
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 1dd45b4..9f7e65b 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -1473,16 +1473,40 @@
   ASSERT_EQ(-1, sign);
 }
 
+TEST(MATH_TEST, tgamma_NaN) {
+  ASSERT_TRUE(isnan(tgamma(nan(""))));
+  ASSERT_TRUE(isnanf(tgammaf(nanf(""))));
+  ASSERT_TRUE(isnanl(tgammal(nanl(""))));
+}
+
+TEST(MATH_TEST, tgamma_inf) {
+  ASSERT_TRUE(isinf(tgamma(HUGE_VAL)));
+  ASSERT_TRUE(isinff(tgammaf(HUGE_VALF)));
+  ASSERT_TRUE(isinfl(tgammal(HUGE_VALL)));
+}
+
+TEST(MATH_TEST, tgamma_negative) {
+  ASSERT_TRUE(isnan(tgamma(-1.0)));
+  ASSERT_TRUE(isnanf(tgammaf(-1.0f)));
+  ASSERT_TRUE(isnanl(tgammal(-1.0L)));
+}
+
 TEST(MATH_TEST, tgamma) {
   ASSERT_DOUBLE_EQ(24.0, tgamma(5.0));
+  ASSERT_DOUBLE_EQ(120.0, tgamma(6.0));
+  ASSERT_TRUE(isinf(tgamma(172.0)));
 }
 
 TEST(MATH_TEST, tgammaf) {
   ASSERT_FLOAT_EQ(24.0f, tgammaf(5.0f));
+  ASSERT_FLOAT_EQ(120.0f, tgammaf(6.0f));
+  ASSERT_TRUE(isinff(tgammaf(172.0f)));
 }
 
 TEST(MATH_TEST, tgammal) {
   ASSERT_DOUBLE_EQ(24.0L, tgammal(5.0L));
+  ASSERT_DOUBLE_EQ(120.0L, tgammal(6.0L));
+  ASSERT_TRUE(isinf(tgammal(172.0L)));
 }
 
 TEST(MATH_TEST, j0) {
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index 4b1482a..ec1badc 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -321,6 +321,6 @@
   ASSERT_EQ(0, pthread_create(&t, nullptr, interrupter, tids));
   pthread_join(t, nullptr);
 #else
-  GTEST_LOG_(INFO) << "tests uses functions not in glibc";
+  GTEST_SKIP() << "tests uses functions not in glibc";
 #endif
 }
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 16299cc..b16fe16 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -31,8 +31,6 @@
 #include "SignalUtils.h"
 #include "utils.h"
 
-#include "private/bionic_constants.h"
-
 using namespace std::chrono_literals;
 
 TEST(time, time) {
@@ -760,22 +758,22 @@
 
 TEST(time, clock_gettime) {
   // Try to ensure that our vdso clock_gettime is working.
+  timespec ts0;
   timespec ts1;
-  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts1));
   timespec ts2;
-  ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts2));
+  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts0));
+  ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts1));
+  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts2));
 
-  // What's the difference between the two?
-  ts2.tv_sec -= ts1.tv_sec;
-  ts2.tv_nsec -= ts1.tv_nsec;
-  if (ts2.tv_nsec < 0) {
-    --ts2.tv_sec;
-    ts2.tv_nsec += NS_PER_S;
+  // Check we have a nice monotonic timestamp sandwich.
+  ASSERT_LE(ts0.tv_sec, ts1.tv_sec);
+  if (ts0.tv_sec == ts1.tv_sec) {
+    ASSERT_LE(ts0.tv_nsec, ts1.tv_nsec);
   }
-
-  // To try to avoid flakiness we'll accept answers within 10,000,000ns (0.01s).
-  ASSERT_EQ(0, ts2.tv_sec);
-  ASSERT_LT(ts2.tv_nsec, 10'000'000);
+  ASSERT_LE(ts1.tv_sec, ts2.tv_sec);
+  if (ts1.tv_sec == ts2.tv_sec) {
+    ASSERT_LE(ts1.tv_nsec, ts2.tv_nsec);
+  }
 }
 
 TEST(time, clock_gettime_CLOCK_REALTIME) {