Merge "Add some MTE-related helpers."
diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp
index 61b51fa..45b953f 100644
--- a/benchmarks/stdlib_benchmark.cpp
+++ b/benchmarks/stdlib_benchmark.cpp
@@ -59,6 +59,41 @@
 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_decay1, "AT_COMMON_SIZES");
 #endif
 
+static void CallocFree(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  int pagesize = getpagesize();
+
+  for (auto _ : state) {
+    void* ptr;
+    benchmark::DoNotOptimize(ptr = calloc(1, nbytes));
+    MakeAllocationResident(ptr, nbytes, pagesize);
+    free(ptr);
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+
+static void BM_stdlib_calloc_free_default(benchmark::State& state) {
+#if defined(__BIONIC__)
+  // The default is expected to be a zero decay time.
+  mallopt(M_DECAY_TIME, 0);
+#endif
+
+  CallocFree(state);
+}
+BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_calloc_free_default, "AT_COMMON_SIZES");
+
+#if defined(__BIONIC__)
+static void BM_stdlib_calloc_free_decay1(benchmark::State& state) {
+  mallopt(M_DECAY_TIME, 1);
+
+  CallocFree(state);
+
+  mallopt(M_DECAY_TIME, 0);
+}
+BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_calloc_free_decay1, "AT_COMMON_SIZES");
+#endif
+
 static void MallocMultiple(benchmark::State& state, size_t nbytes, size_t numAllocs) {
   int pagesize = getpagesize();
   void* ptrs[numAllocs];
diff --git a/benchmarks/unistd_benchmark.cpp b/benchmarks/unistd_benchmark.cpp
index d697dfd..f0a3089 100644
--- a/benchmarks/unistd_benchmark.cpp
+++ b/benchmarks/unistd_benchmark.cpp
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
+#include <errno.h>
+#include <string.h>
 #include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
+#include <string>
+
+#include <android-base/stringprintf.h>
 #include <benchmark/benchmark.h>
 #include "util.h"
 
@@ -28,3 +35,35 @@
 BIONIC_TRIVIAL_BENCHMARK(BM_unistd_gettid, gettid());
 #endif
 BIONIC_TRIVIAL_BENCHMARK(BM_unistd_gettid_syscall, syscall(__NR_gettid));
+
+// Many native allocators have custom prefork and postfork functions.
+// Measure the fork call to make sure nothing takes too long.
+void BM_unistd_fork_call(benchmark::State& state) {
+  for (auto _ : state) {
+    pid_t pid;
+    if ((pid = fork()) == 0) {
+      // Sleep for a little while so that the parent is not interrupted
+      // right away when the process exits.
+      usleep(100);
+      _exit(1);
+    }
+    state.PauseTiming();
+    if (pid == -1) {
+      std::string err = android::base::StringPrintf("Fork failed: %s", strerror(errno));
+      state.SkipWithError(err.c_str());
+    }
+    pid_t wait_pid = waitpid(pid, 0, 0);
+    if (wait_pid != pid) {
+      if (wait_pid == -1) {
+        std::string err = android::base::StringPrintf("waitpid call failed: %s", strerror(errno));
+        state.SkipWithError(err.c_str());
+      } else {
+        std::string err = android::base::StringPrintf(
+            "waitpid return an unknown pid, expected %d, actual %d", pid, wait_pid);
+        state.SkipWithError(err.c_str());
+      }
+    }
+    state.ResumeTiming();
+  }
+}
+BIONIC_BENCHMARK(BM_unistd_fork_call);
diff --git a/libc/Android.bp b/libc/Android.bp
index 78d2e71..0f8ed3e 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1085,7 +1085,7 @@
         "bionic/clone.cpp",
         "bionic/ctype.cpp",
         "bionic/dirent.cpp",
-        "bionic/dup2.cpp",
+        "bionic/dup.cpp",
         "bionic/environ.cpp",
         "bionic/error.cpp",
         "bionic/eventfd_read.cpp",
@@ -1094,7 +1094,9 @@
         "bionic/faccessat.cpp",
         "bionic/fchmod.cpp",
         "bionic/fchmodat.cpp",
+        "bionic/fcntl.cpp",
         "bionic/fdsan.cpp",
+        "bionic/fdtrack.cpp",
         "bionic/ffs.cpp",
         "bionic/fgetxattr.cpp",
         "bionic/flistxattr.cpp",
@@ -1163,6 +1165,7 @@
         "bionic/realpath.cpp",
         "bionic/reboot.cpp",
         "bionic/recv.cpp",
+        "bionic/recvmsg.cpp",
         "bionic/rename.cpp",
         "bionic/rmdir.cpp",
         "bionic/scandir.cpp",
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 517d5f9..1343e4e 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -123,12 +123,12 @@
 ssize_t     readv(int, const struct iovec*, int)   all
 ssize_t     writev(int, const struct iovec*, int)  all
 int         __fcntl64:fcntl64(int, int, void*)  lp32
-int         fcntl(int, int, void*)  lp64
+int         __fcntl:fcntl(int, int, void*)  lp64
 int         flock(int, int)   all
 int         __fchmod:fchmod(int, mode_t)  all
-int         dup(int)  all
 int         pipe2(int*, int) all
-int         dup3(int, int, int)   all
+int         __dup:dup(int)  all
+int         __dup3:dup3(int, int, int)   all
 int         fsync(int)  all
 int         fdatasync(int) all
 int         fchown:fchown32(int, uid_t, gid_t)  arm,x86
@@ -254,9 +254,9 @@
 int           shutdown(int, int)  arm,arm64,mips,mips64,x86_64
 int           setsockopt(int, int, int, const void*, socklen_t)  arm,arm64,mips,mips64,x86_64
 int           getsockopt(int, int, int, void*, socklen_t*)    arm,arm64,mips,mips64,x86_64
-ssize_t       recvmsg(int, struct msghdr*, unsigned int)   arm,arm64,mips,mips64,x86_64
+ssize_t       __recvmsg:recvmsg(int, struct msghdr*, unsigned int)   arm,arm64,mips,mips64,x86_64
 ssize_t       __sendmsg:sendmsg(int, const struct msghdr*, unsigned int)  arm,arm64,mips,mips64,x86_64
-int           recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   arm,arm64,mips,mips64,x86_64
+int           __recvmmsg:recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   arm,arm64,mips,mips64,x86_64
 int           __sendmmsg:sendmmsg(int, struct mmsghdr*, unsigned int, int)   arm,arm64,mips,mips64,x86_64
 
 # sockets for x86. These are done as an "indexed" call to socketcall syscall.
@@ -273,9 +273,9 @@
 int           setsockopt:socketcall:14(int, int, int, const void*, socklen_t)  x86
 int           getsockopt:socketcall:15(int, int, int, void*, socklen_t*)    x86
 int           __sendmsg:socketcall:16(int, const struct msghdr*, unsigned int)  x86
-int           recvmsg:socketcall:17(int, struct msghdr*, unsigned int)   x86
+int           __recvmsg:socketcall:17(int, struct msghdr*, unsigned int)   x86
 int           __accept4:socketcall:18(int, struct sockaddr*, socklen_t*, int)  x86
-int           recvmmsg:socketcall:19(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   x86
+int           __recvmmsg:socketcall:19(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   x86
 int           __sendmmsg:socketcall:20(int, struct mmsghdr*, unsigned int, int)   x86
 
 # scheduler & real-time
diff --git a/libc/bionic/NetdClientDispatch.cpp b/libc/bionic/NetdClientDispatch.cpp
index 463ef36..e6f4a97 100644
--- a/libc/bionic/NetdClientDispatch.cpp
+++ b/libc/bionic/NetdClientDispatch.cpp
@@ -18,6 +18,8 @@
 
 #include <sys/socket.h>
 
+#include "private/bionic_fdtrack.h"
+
 #ifdef __i386__
 #define __socketcall __attribute__((__cdecl__))
 #else
@@ -53,7 +55,7 @@
 };
 
 int accept4(int fd, sockaddr* addr, socklen_t* addr_length, int flags) {
-    return __netdClientDispatch.accept4(fd, addr, addr_length, flags);
+  return FDTRACK_CREATE(__netdClientDispatch.accept4(fd, addr, addr_length, flags));
 }
 
 int connect(int fd, const sockaddr* addr, socklen_t addr_length) {
@@ -74,5 +76,5 @@
 }
 
 int socket(int domain, int type, int protocol) {
-    return __netdClientDispatch.socket(domain, type, protocol);
+  return FDTRACK_CREATE(__netdClientDispatch.socket(domain, type, protocol));
 }
diff --git a/libc/bionic/dup2.cpp b/libc/bionic/dup.cpp
similarity index 83%
rename from libc/bionic/dup2.cpp
rename to libc/bionic/dup.cpp
index 98c5646..d9e89a5 100644
--- a/libc/bionic/dup2.cpp
+++ b/libc/bionic/dup.cpp
@@ -29,6 +29,15 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include "private/bionic_fdtrack.h"
+
+extern "C" int __dup(int old_fd);
+extern "C" int __dup3(int old_fd, int new_fd, int flags);
+
+int dup(int old_fd) {
+  return FDTRACK_CREATE(__dup(old_fd));
+}
+
 int dup2(int old_fd, int new_fd) {
   // If old_fd is equal to new_fd and a valid file descriptor, dup2 returns
   // old_fd without closing it. This is not true of dup3, so we have to
@@ -40,5 +49,9 @@
     return old_fd;
   }
 
-  return dup3(old_fd, new_fd, 0);
+  return FDTRACK_CREATE(__dup3(old_fd, new_fd, 0));
+}
+
+int dup3(int old_fd, int new_fd, int flags) {
+  return FDTRACK_CREATE(__dup3(old_fd, new_fd, flags));
 }
diff --git a/libc/bionic/fcntl.cpp b/libc/bionic/fcntl.cpp
new file mode 100644
index 0000000..c508131
--- /dev/null
+++ b/libc/bionic/fcntl.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <stdarg.h>
+#include <fcntl.h>
+
+#include "private/bionic_fdtrack.h"
+
+#if defined(__LP64__)
+
+extern "C" int __fcntl(int fd, int cmd, ...);
+
+int fcntl(int fd, int cmd, ...) {
+  va_list args;
+  va_start(args, cmd);
+
+  // This is a bit sketchy, especially because arg can be an int, but all of our
+  // supported 64-bit ABIs pass arg in a register.
+  void* arg = va_arg(args, void*);
+  va_end(args);
+
+  int rc = __fcntl(fd, cmd, arg);
+  if (cmd == F_DUPFD) {
+    return FDTRACK_CREATE_NAME("F_DUPFD", rc);
+  } else if (cmd == F_DUPFD_CLOEXEC) {
+    return FDTRACK_CREATE_NAME("F_DUPFD_CLOEXEC", rc);
+  }
+  return rc;
+}
+
+#else
+
+extern "C" int __fcntl64(int, int, ...);
+
+// For fcntl we use the fcntl64 system call to signal that we're using struct flock64.
+int fcntl(int fd, int cmd, ...) {
+  va_list ap;
+
+  va_start(ap, cmd);
+  void* arg = va_arg(ap, void*);
+  va_end(ap);
+
+  if (cmd == F_DUPFD) {
+    return FDTRACK_CREATE_NAME("F_DUPFD", __fcntl64(fd, cmd, arg));
+  } else if (cmd == F_DUPFD_CLOEXEC) {
+    return FDTRACK_CREATE_NAME("F_DUPFD_CLOEXEC", __fcntl64(fd, cmd, arg));
+  }
+  return __fcntl64(fd, cmd, arg);
+}
+
+#endif
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index d4ac71c..ebc680f 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -43,6 +43,7 @@
 #include <platform/bionic/reserved_signals.h>
 #include <sys/system_properties.h>
 
+#include "private/bionic_fdtrack.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_inline_raise.h"
 #include "pthread_internal.h"
@@ -245,6 +246,7 @@
 }
 
 int android_fdsan_close_with_tag(int fd, uint64_t expected_tag) {
+  FDTRACK_CLOSE(fd);
   FdEntry* fde = GetFdEntry(fd);
   if (!fde) {
     return __close(fd);
diff --git a/libc/bionic/fdtrack.cpp b/libc/bionic/fdtrack.cpp
new file mode 100644
index 0000000..1123512
--- /dev/null
+++ b/libc/bionic/fdtrack.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <stdatomic.h>
+
+#include <platform/bionic/fdtrack.h>
+#include <platform/bionic/reserved_signals.h>
+
+#include "private/bionic_fdtrack.h"
+#include "private/bionic_tls.h"
+#include "private/bionic_globals.h"
+
+_Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
+
+bool android_fdtrack_get_enabled() {
+  return !__get_bionic_tls().fdtrack_disabled;
+}
+
+bool android_fdtrack_set_enabled(bool new_value) {
+  auto& tls = __get_bionic_tls();
+  bool prev = !tls.fdtrack_disabled;
+  tls.fdtrack_disabled = !new_value;
+  return prev;
+}
+
+bool android_fdtrack_compare_exchange_hook(android_fdtrack_hook_t* expected,
+                                           android_fdtrack_hook_t value) {
+  return atomic_compare_exchange_strong(&__android_fdtrack_hook, expected, value);
+}
+
+void __libc_init_fdtrack() {
+  // Register a no-op signal handler.
+  signal(BIONIC_SIGNAL_FDTRACK, [](int) {});
+}
diff --git a/libc/bionic/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp
index 2de1bc7..f08e582 100644
--- a/libc/bionic/legacy_32_bit_support.cpp
+++ b/libc/bionic/legacy_32_bit_support.cpp
@@ -37,27 +37,17 @@
 #include <sys/vfs.h>
 #include <unistd.h>
 
+#include "private/bionic_fdtrack.h"
+
 #if defined(__LP64__)
 #error This code is only needed on 32-bit systems!
 #endif
 
 // System calls we need.
-extern "C" int __fcntl64(int, int, void*);
 extern "C" int __llseek(int, unsigned long, unsigned long, off64_t*, int);
 extern "C" int __preadv64(int, const struct iovec*, int, long, long);
 extern "C" int __pwritev64(int, const struct iovec*, int, long, long);
 
-// For fcntl we use the fcntl64 system call to signal that we're using struct flock64.
-int fcntl(int fd, int cmd, ...) {
-  va_list ap;
-
-  va_start(ap, cmd);
-  void* arg = va_arg(ap, void*);
-  va_end(ap);
-
-  return __fcntl64(fd, cmd, arg);
-}
-
 // For lseek64 we need to use the llseek system call which splits the off64_t in two and
 // returns the off64_t result via a pointer because 32-bit kernels can't return 64-bit results.
 off64_t lseek64(int fd, off64_t off, int whence) {
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index e4106e9..12628f7 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -104,6 +104,7 @@
 
   __system_properties_init(); // Requires 'environ'.
   __libc_init_fdsan(); // Requires system properties (for debug.fdsan).
+  __libc_init_fdtrack();
 
   SetDefaultHeapTaggingLevel();
 }
diff --git a/libc/bionic/open.cpp b/libc/bionic/open.cpp
index 222e5d3..bd8685a 100644
--- a/libc/bionic/open.cpp
+++ b/libc/bionic/open.cpp
@@ -31,6 +31,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include "private/bionic_fdtrack.h"
 #include "private/bionic_fortify.h"
 
 extern "C" int __openat(int, const char*, int, int);
@@ -62,13 +63,13 @@
     va_end(args);
   }
 
-  return __openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), mode);
+  return FDTRACK_CREATE(__openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), mode));
 }
 __strong_alias(open64, open);
 
 int __open_2(const char* pathname, int flags) {
   if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
-  return __openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0);
+  return FDTRACK_CREATE_NAME("open", __openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0));
 }
 
 int openat(int fd, const char *pathname, int flags, ...) {
@@ -81,11 +82,11 @@
     va_end(args);
   }
 
-  return __openat(fd, pathname, force_O_LARGEFILE(flags), mode);
+  return FDTRACK_CREATE_NAME("openat", __openat(fd, pathname, force_O_LARGEFILE(flags), mode));
 }
 __strong_alias(openat64, openat);
 
 int __openat_2(int fd, const char* pathname, int flags) {
   if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
-  return __openat(fd, pathname, force_O_LARGEFILE(flags), 0);
+  return FDTRACK_CREATE_NAME("openat", __openat(fd, pathname, force_O_LARGEFILE(flags), 0));
 }
diff --git a/libc/bionic/recvmsg.cpp b/libc/bionic/recvmsg.cpp
new file mode 100644
index 0000000..003f43d
--- /dev/null
+++ b/libc/bionic/recvmsg.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <string.h>
+#include <sys/socket.h>
+
+#include <async_safe/log.h>
+
+#include "private/bionic_fdtrack.h"
+
+extern "C" ssize_t __recvmsg(int __fd, struct msghdr* __msg, int __flags);
+extern "C" int __recvmmsg(int __fd, struct mmsghdr* __msgs, unsigned int __msg_count, int __flags,
+                          const struct timespec* __timeout);
+
+static inline __attribute__((artificial)) __attribute__((always_inline)) void track_fds(
+    struct msghdr* msg, const char* function_name) {
+  if (!__android_fdtrack_hook) {
+    return;
+  }
+
+  for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+    if (cmsg->cmsg_type != SCM_RIGHTS) {
+      continue;
+    }
+
+    if (cmsg->cmsg_len <= sizeof(struct cmsghdr)) {
+      continue;
+    }
+
+    size_t data_length = cmsg->cmsg_len - sizeof(struct cmsghdr);
+    if (data_length % sizeof(int) != 0) {
+      async_safe_fatal("invalid cmsg length: %zu", data_length);
+    }
+
+    for (size_t offset = 0; offset < data_length; offset += sizeof(int)) {
+      int fd;
+      memcpy(&fd, CMSG_DATA(cmsg) + offset, sizeof(int));
+      FDTRACK_CREATE_NAME(function_name, fd);
+    }
+  }
+}
+
+ssize_t recvmsg(int __fd, struct msghdr* __msg, int __flags) {
+  ssize_t rc = __recvmsg(__fd, __msg, __flags);
+  if (rc == -1) {
+    return -1;
+  }
+  track_fds(__msg, "recvmsg");
+  return rc;
+}
+
+int recvmmsg(int __fd, struct mmsghdr* __msgs, unsigned int __msg_count, int __flags,
+             const struct timespec* __timeout) {
+  int rc = __recvmmsg(__fd, __msgs, __msg_count, __flags, __timeout);
+  if (rc == -1) {
+    return -1;
+  }
+  for (int i = 0; i < rc; ++i) {
+    track_fds(&__msgs[i].msg_hdr, "recvmmsg");
+  }
+  return rc;
+}
diff --git a/libc/include/.clang-format b/libc/include/.clang-format
new file mode 100644
index 0000000..e384528
--- /dev/null
+++ b/libc/include/.clang-format
@@ -0,0 +1 @@
+DisableFormat: true
diff --git a/libc/bionic/dup2.cpp b/libc/include/bits/flock.h
similarity index 67%
copy from libc/bionic/dup2.cpp
copy to libc/include/bits/flock.h
index 98c5646..7c452ad 100644
--- a/libc/bionic/dup2.cpp
+++ b/libc/include/bits/flock.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,19 +26,41 @@
  * SUCH DAMAGE.
  */
 
-#include <fcntl.h>
-#include <unistd.h>
+#pragma once
 
-int dup2(int old_fd, int new_fd) {
-  // If old_fd is equal to new_fd and a valid file descriptor, dup2 returns
-  // old_fd without closing it. This is not true of dup3, so we have to
-  // handle this case ourselves.
-  if (old_fd == new_fd) {
-    if (fcntl(old_fd, F_GETFD) == -1) {
-      return -1;
-    }
-    return old_fd;
-  }
+/**
+ * @file bits/flock.h
+ * @brief struct flock.
+ */
 
-  return dup3(old_fd, new_fd, 0);
-}
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+#define __FLOCK64_BODY \
+  short l_type; \
+  short l_whence; \
+  off64_t l_start; \
+  off64_t l_len; \
+  pid_t l_pid; \
+
+#if defined(__USE_FILE_OFFSET64) || defined(__LP64__)
+#define __FLOCK_BODY __FLOCK64_BODY
+#else
+#define __FLOCK_BODY \
+  short l_type; \
+  short l_whence; \
+  off_t l_start; \
+  off_t l_len; \
+  pid_t l_pid; \
+
+#endif
+
+struct flock { __FLOCK_BODY };
+struct flock64 { __FLOCK64_BODY };
+
+#undef __FLOCK_BODY
+#undef __FLOCK64_BODY
+
+__END_DECLS
diff --git a/libc/bionic/dup2.cpp b/libc/include/bits/flock64.h
similarity index 73%
copy from libc/bionic/dup2.cpp
copy to libc/include/bits/flock64.h
index 98c5646..95500b9 100644
--- a/libc/bionic/dup2.cpp
+++ b/libc/include/bits/flock64.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,19 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include <fcntl.h>
-#include <unistd.h>
+#pragma once
 
-int dup2(int old_fd, int new_fd) {
-  // If old_fd is equal to new_fd and a valid file descriptor, dup2 returns
-  // old_fd without closing it. This is not true of dup3, so we have to
-  // handle this case ourselves.
-  if (old_fd == new_fd) {
-    if (fcntl(old_fd, F_GETFD) == -1) {
-      return -1;
-    }
-    return old_fd;
-  }
-
-  return dup3(old_fd, new_fd, 0);
-}
+/* Empty. */
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 23a58d6..1ea94e6 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -51,14 +51,32 @@
 
 __BEGIN_DECLS
 
-#ifdef __LP64__
+#if defined(__LP64__)
+
 /* LP64 kernels don't have F_*64 defines because their flock is 64-bit. */
+
 /** Flag for flock(). */
 #define F_GETLK64  F_GETLK
 /** Flag for flock(). */
 #define F_SETLK64  F_SETLK
 /** Flag for flock(). */
 #define F_SETLKW64 F_SETLKW
+
+#elif defined(__USE_FILE_OFFSET64)
+
+/* For _FILE_OFFSET_BITS=64, redirect the constants to the off64_t variants. */
+
+#undef F_GETLK
+#undef F_SETLK
+#undef F_SETLKW
+
+/** Flag for flock(). */
+#define F_GETLK F_GETLK64
+/** Flag for flock(). */
+#define F_SETLK F_SETLK64
+/** Flag for flock(). */
+#define F_SETLKW F_SETLKW64
+
 #endif
 
 /** Flag for open(). */
diff --git a/libc/kernel/.clang-format b/libc/kernel/.clang-format
index e384528..39789c8 100644
--- a/libc/kernel/.clang-format
+++ b/libc/kernel/.clang-format
@@ -1 +1,3 @@
 DisableFormat: true
+SortIncludes: false
+SortUsingDeclarations: false
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index 967d0c7..463de12 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -90,6 +90,8 @@
 kernel_struct_replacements = set(
         [
           "epoll_event",
+          "flock",
+          "flock64",
           "in_addr",
           "ip_mreq_source",
           "ip_msfilter",
diff --git a/libc/kernel/uapi/asm-generic/fcntl.h b/libc/kernel/uapi/asm-generic/fcntl.h
index aeb1ac6..a2cb5f4 100644
--- a/libc/kernel/uapi/asm-generic/fcntl.h
+++ b/libc/kernel/uapi/asm-generic/fcntl.h
@@ -18,6 +18,8 @@
  ****************************************************************************/
 #ifndef _ASM_GENERIC_FCNTL_H
 #define _ASM_GENERIC_FCNTL_H
+#include <bits/flock64.h>
+#include <bits/flock.h>
 #include <linux/types.h>
 #define O_ACCMODE 00000003
 #define O_RDONLY 00000000
@@ -145,26 +147,10 @@
 #ifndef __ARCH_FLOCK_PAD
 #define __ARCH_FLOCK_PAD
 #endif
-struct flock {
-  short l_type;
-  short l_whence;
-  __kernel_off_t l_start;
-  __kernel_off_t l_len;
-  __kernel_pid_t l_pid;
-  __ARCH_FLOCK_PAD
-};
 #endif
 #ifndef HAVE_ARCH_STRUCT_FLOCK64
 #ifndef __ARCH_FLOCK64_PAD
 #define __ARCH_FLOCK64_PAD
 #endif
-struct flock64 {
-  short l_type;
-  short l_whence;
-  __kernel_loff_t l_start;
-  __kernel_loff_t l_len;
-  __kernel_pid_t l_pid;
-  __ARCH_FLOCK64_PAD
-};
 #endif
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/fcntl.h b/libc/kernel/uapi/asm-mips/asm/fcntl.h
index 91835f2..8aef90d 100644
--- a/libc/kernel/uapi/asm-mips/asm/fcntl.h
+++ b/libc/kernel/uapi/asm-mips/asm/fcntl.h
@@ -18,6 +18,7 @@
  ****************************************************************************/
 #ifndef _UAPI_ASM_FCNTL_H
 #define _UAPI_ASM_FCNTL_H
+#include <bits/flock.h>
 #include <asm/sgidefs.h>
 #define O_APPEND 0x0008
 #define O_DSYNC 0x0010
@@ -43,15 +44,6 @@
 #endif
 #if _MIPS_SIM != _MIPS_SIM_ABI64
 #include <linux/types.h>
-struct flock {
-  short l_type;
-  short l_whence;
-  __kernel_off_t l_start;
-  __kernel_off_t l_len;
-  long l_sysid;
-  __kernel_pid_t l_pid;
-  long pad[4];
-};
 #define HAVE_ARCH_STRUCT_FLOCK
 #endif
 #include <asm-generic/fcntl.h>
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 2710fb2..2ca4b21 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1752,6 +1752,9 @@
     __system_property_set_filename;
     __system_property_update;
     android_fdsan_get_fd_table;
+    android_fdtrack_compare_exchange_hook; # llndk
+    android_fdtrack_get_enabled; # llndk
+    android_fdtrack_set_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
new file mode 100644
index 0000000..6eb379b
--- /dev/null
+++ b/libc/platform/bionic/fdtrack.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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
+
+#include <sys/cdefs.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+// Types of an android_fdtrack_event.
+enum android_fdtrack_event_type {
+  // File descriptor creation: create is the active member of android_fdtrack_event::data.
+  ANDROID_FDTRACK_EVENT_TYPE_CREATE,
+
+  // File descriptor closed.
+  ANDROID_FDTRACK_EVENT_TYPE_CLOSE,
+};
+
+struct android_fdtrack_event {
+  // File descriptor for which this event occurred.
+  int fd;
+
+  // Type of event: this is one of the enumerators of android_fdtrack_event_type.
+  uint8_t type;
+
+  // Data for the event.
+  union {
+    struct {
+      const char* function_name;
+    } create;
+  } data;
+};
+
+// Callback invoked upon file descriptor creation/closure.
+typedef void (*android_fdtrack_hook_t)(struct android_fdtrack_event*);
+
+// Register a hook which is called to track fd lifecycle events.
+bool android_fdtrack_compare_exchange_hook(android_fdtrack_hook_t* expected, android_fdtrack_hook_t value) __INTRODUCED_IN(30);
+
+// Enable/disable fdtrack *on the current thread*.
+// This is primarily useful when performing operations which you don't want to track
+// (e.g. when emitting already-recorded information).
+bool android_fdtrack_get_enabled() __INTRODUCED_IN(30);
+bool android_fdtrack_set_enabled(bool new_value) __INTRODUCED_IN(30);
+
+__END_DECLS
diff --git a/libc/platform/bionic/reserved_signals.h b/libc/platform/bionic/reserved_signals.h
index 7634b27..4ac6455 100644
--- a/libc/platform/bionic/reserved_signals.h
+++ b/libc/platform/bionic/reserved_signals.h
@@ -42,14 +42,16 @@
 //   36 (__SIGRTMIN + 4)        platform profilers (heapprofd, traced_perf)
 //   37 (__SIGRTMIN + 5)        coverage (libprofile-extras)
 //   38 (__SIGRTMIN + 6)        heapprofd ART managed heap dumps
+//   39 (__SIGRTMIN + 7)        fdtrack
 //
 // If you change this, also change __ndk_legacy___libc_current_sigrtmin
 // in <android/legacy_signal_inlines.h> to match.
 
 #define BIONIC_SIGNAL_DEBUGGER __SIGRTMIN + 3
 #define BIONIC_SIGNAL_PROFILER __SIGRTMIN + 4
+#define BIONIC_SIGNAL_FDTRACK __SIGRTMIN + 7
 
-#define __SIGRT_RESERVED 7
+#define __SIGRT_RESERVED 8
 static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset, int how) {
   int (*block)(sigset64_t*, int);
   int (*unblock)(sigset64_t*, int);
@@ -77,5 +79,6 @@
   unblock(&sigset, __SIGRTMIN + 4);
   unblock(&sigset, __SIGRTMIN + 5);
   unblock(&sigset, __SIGRTMIN + 6);
+  unblock(&sigset, __SIGRTMIN + 7);
   return sigset;
 }
diff --git a/libc/private/bionic_fdtrack.h b/libc/private/bionic_fdtrack.h
new file mode 100644
index 0000000..174ba1d
--- /dev/null
+++ b/libc/private/bionic_fdtrack.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 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
+
+#include <sys/cdefs.h>
+#include <stdatomic.h>
+
+#include "platform/bionic/fdtrack.h"
+
+#include "bionic/pthread_internal.h"
+#include "private/bionic_tls.h"
+#include "private/ErrnoRestorer.h"
+
+extern "C" _Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
+
+// 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)) {  \
+      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;                   \
+        __android_fdtrack_hook(&event);                           \
+        tls.fdtrack_disabled = false;                             \
+      }                                                           \
+    }                                                             \
+    __fd;                                                         \
+  })
+
+// Macro to record file descriptor creation, with the current function's name.
+// e.g.:
+//   int socket(int domain, int type, int protocol) {
+//     return FDTRACK_CREATE_NAME(__socket(domain, type, protocol));
+//   }
+#define FDTRACK_CREATE(fd_value) FDTRACK_CREATE_NAME(__func__, (fd_value))
+
+// 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)) { \
+      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;           \
+        __android_fdtrack_hook(&event);                          \
+        tls.fdtrack_disabled = false;                            \
+        errno = saved_errno;                                     \
+      }                                                          \
+    }                                                            \
+    __fd;                                                        \
+  })
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 8997ceb..4cc9bbe 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -100,6 +100,7 @@
 
 __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
 __LIBC_HIDDEN__ void __libc_init_fdsan();
+__LIBC_HIDDEN__ void __libc_init_fdtrack();
 __LIBC_HIDDEN__ void __libc_init_profiling_handlers();
 
 __LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals);
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index bb5c67b..80d645a 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -128,6 +128,9 @@
   group_state_t group;
   passwd_state_t passwd;
 
+  char fdtrack_disabled;
+  char padding[3];
+
   // Initialize the main thread's final object using its bootstrap object.
   void copy_from_bootstrap(const bionic_tls* boot __attribute__((unused))) {
     // Nothing in bionic_tls needs to be preserved in the transition to the
diff --git a/libc/upstream-freebsd/.clang-format b/libc/upstream-freebsd/.clang-format
index e384528..39789c8 100644
--- a/libc/upstream-freebsd/.clang-format
+++ b/libc/upstream-freebsd/.clang-format
@@ -1 +1,3 @@
 DisableFormat: true
+SortIncludes: false
+SortUsingDeclarations: false
diff --git a/libc/upstream-netbsd/.clang-format b/libc/upstream-netbsd/.clang-format
index e384528..39789c8 100644
--- a/libc/upstream-netbsd/.clang-format
+++ b/libc/upstream-netbsd/.clang-format
@@ -1 +1,3 @@
 DisableFormat: true
+SortIncludes: false
+SortUsingDeclarations: false
diff --git a/libc/upstream-openbsd/.clang-format b/libc/upstream-openbsd/.clang-format
index e384528..39789c8 100644
--- a/libc/upstream-openbsd/.clang-format
+++ b/libc/upstream-openbsd/.clang-format
@@ -1 +1,3 @@
 DisableFormat: true
+SortIncludes: false
+SortUsingDeclarations: false
diff --git a/libfdtrack/.clang-format b/libfdtrack/.clang-format
new file mode 120000
index 0000000..fd0645f
--- /dev/null
+++ b/libfdtrack/.clang-format
@@ -0,0 +1 @@
+../.clang-format-2
\ No newline at end of file
diff --git a/libfdtrack/Android.bp b/libfdtrack/Android.bp
new file mode 100644
index 0000000..fd13512
--- /dev/null
+++ b/libfdtrack/Android.bp
@@ -0,0 +1,18 @@
+cc_library_shared {
+    name: "libfdtrack",
+    srcs: ["fdtrack.cpp"],
+    stl: "libc++_static",
+
+    header_libs: ["bionic_libc_platform_headers"],
+    static_libs: [
+        "libasync_safe",
+        "libbase",
+        "libunwindstack",
+        "liblzma",
+        "liblog",
+    ],
+    version_script: "libfdtrack.map.txt",
+
+    allow_undefined_symbols: true,
+    recovery_available: true,
+}
diff --git a/libfdtrack/fdtrack.cpp b/libfdtrack/fdtrack.cpp
new file mode 100644
index 0000000..831a50d
--- /dev/null
+++ b/libfdtrack/fdtrack.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <inttypes.h>
+
+#include <array>
+#include <mutex>
+#include <vector>
+
+#include <android/fdsan.h>
+#include <bionic/fdtrack.h>
+
+#include <android-base/no_destructor.h>
+#include <android-base/thread_annotations.h>
+#include <async_safe/log.h>
+#include <bionic/reserved_signals.h>
+#include <unwindstack/LocalUnwinder.h>
+
+struct FdEntry {
+  std::mutex mutex;
+  std::vector<unwindstack::LocalFrameData> backtrace GUARDED_BY(mutex);
+};
+
+extern "C" void fdtrack_dump();
+static void fd_hook(android_fdtrack_event* event);
+
+// Backtraces for the first 4k file descriptors ought to be enough to diagnose an fd leak.
+static constexpr size_t kFdTableSize = 4096;
+static constexpr size_t kStackDepth = 10;
+
+static bool installed = false;
+static std::array<FdEntry, kFdTableSize> stack_traces;
+static unwindstack::LocalUnwinder& Unwinder() {
+  static android::base::NoDestructor<unwindstack::LocalUnwinder> unwinder;
+  return *unwinder.get();
+}
+
+__attribute__((constructor)) static void ctor() {
+  signal(BIONIC_SIGNAL_FDTRACK, [](int) { fdtrack_dump(); });
+  if (Unwinder().Init()) {
+    android_fdtrack_hook_t expected = nullptr;
+    installed = android_fdtrack_compare_exchange_hook(&expected, &fd_hook);
+  }
+}
+
+__attribute__((destructor)) static void dtor() {
+  if (installed) {
+    android_fdtrack_hook_t expected = &fd_hook;
+    android_fdtrack_compare_exchange_hook(&expected, nullptr);
+  }
+}
+
+FdEntry* GetFdEntry(int fd) {
+  if (fd >= 0 && fd < static_cast<int>(kFdTableSize)) {
+    return &stack_traces[fd];
+  }
+  return nullptr;
+}
+
+static void fd_hook(android_fdtrack_event* event) {
+  if (event->type == ANDROID_FDTRACK_EVENT_TYPE_CREATE) {
+    if (FdEntry* entry = GetFdEntry(event->fd); entry) {
+      std::lock_guard<std::mutex> lock(entry->mutex);
+      entry->backtrace.clear();
+      Unwinder().Unwind(&entry->backtrace, kStackDepth);
+    }
+  } else if (event->type == ANDROID_FDTRACK_EVENT_TYPE_CLOSE) {
+    if (FdEntry* entry = GetFdEntry(event->fd); entry) {
+      std::lock_guard<std::mutex> lock(entry->mutex);
+      entry->backtrace.clear();
+    }
+  }
+}
+
+void fdtrack_dump() {
+  if (!installed) {
+    async_safe_format_log(ANDROID_LOG_INFO, "fdtrack", "fdtrack not installed");
+  } else {
+    async_safe_format_log(ANDROID_LOG_INFO, "fdtrack", "fdtrack dumping...");
+  }
+
+  bool prev = android_fdtrack_set_enabled(false);
+  for (int fd = 0; fd < static_cast<int>(stack_traces.size()); ++fd) {
+    FdEntry* entry = GetFdEntry(fd);
+    if (!entry) {
+      continue;
+    }
+
+    if (!entry->mutex.try_lock()) {
+      async_safe_format_log(ANDROID_LOG_WARN, "fdtrack", "fd %d locked, skipping", fd);
+      continue;
+    }
+
+    if (entry->backtrace.empty()) {
+      continue;
+    }
+
+    uint64_t fdsan_owner = android_fdsan_get_owner_tag(fd);
+
+    if (fdsan_owner != 0) {
+      async_safe_format_log(ANDROID_LOG_INFO, "fdtrack", "fd %d: (owner = %#" PRIx64 ")", fd,
+                            fdsan_owner);
+    } else {
+      async_safe_format_log(ANDROID_LOG_INFO, "fdtrack", "fd %d: (unowned)", fd);
+    }
+
+    const size_t frame_skip = 2;
+    for (size_t i = frame_skip; i < entry->backtrace.size(); ++i) {
+      auto& frame = entry->backtrace[i];
+      async_safe_format_log(ANDROID_LOG_INFO, "fdtrack", "  %zu: %s+%" PRIu64, i - frame_skip,
+                            frame.function_name.c_str(), frame.function_offset);
+    }
+
+    entry->mutex.unlock();
+  }
+  android_fdtrack_set_enabled(prev);
+}
diff --git a/libfdtrack/libfdtrack.map.txt b/libfdtrack/libfdtrack.map.txt
new file mode 100644
index 0000000..7a54c35
--- /dev/null
+++ b/libfdtrack/libfdtrack.map.txt
@@ -0,0 +1,6 @@
+LIBFDTRACK {
+  global:
+    fdtrack_dump;
+  local:
+    *;
+};
diff --git a/libm/upstream-freebsd/.clang-format b/libm/upstream-freebsd/.clang-format
index e384528..39789c8 100644
--- a/libm/upstream-freebsd/.clang-format
+++ b/libm/upstream-freebsd/.clang-format
@@ -1 +1,3 @@
 DisableFormat: true
+SortIncludes: false
+SortUsingDeclarations: false
diff --git a/libm/upstream-netbsd/.clang-format b/libm/upstream-netbsd/.clang-format
index e384528..39789c8 100644
--- a/libm/upstream-netbsd/.clang-format
+++ b/libm/upstream-netbsd/.clang-format
@@ -1 +1,3 @@
 DisableFormat: true
+SortIncludes: false
+SortUsingDeclarations: false
diff --git a/tests/Android.bp b/tests/Android.bp
index 6320eea..e530132 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -98,7 +98,9 @@
         "eventfd_test.cpp",
         "fcntl_test.cpp",
         "fdsan_test.cpp",
+        "fdtrack_test.cpp",
         "fenv_test.cpp",
+        "_FILE_OFFSET_BITS_test.cpp",
         "float_test.cpp",
         "ftw_test.cpp",
         "getauxval_test.cpp",
diff --git a/libc/bionic/dup2.cpp b/tests/_FILE_OFFSET_BITS_test.cpp
similarity index 75%
copy from libc/bionic/dup2.cpp
copy to tests/_FILE_OFFSET_BITS_test.cpp
index 98c5646..cbdb369 100644
--- a/libc/bionic/dup2.cpp
+++ b/tests/_FILE_OFFSET_BITS_test.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,19 +26,22 @@
  * SUCH DAMAGE.
  */
 
+#define _FILE_OFFSET_BITS 64
+
+#include <gtest/gtest.h>
+
 #include <fcntl.h>
-#include <unistd.h>
 
-int dup2(int old_fd, int new_fd) {
-  // If old_fd is equal to new_fd and a valid file descriptor, dup2 returns
-  // old_fd without closing it. This is not true of dup3, so we have to
-  // handle this case ourselves.
-  if (old_fd == new_fd) {
-    if (fcntl(old_fd, F_GETFD) == -1) {
-      return -1;
-    }
-    return old_fd;
-  }
+TEST(fcntl, f_getlk_FOB64) {
+  int fd = open("/proc/version", O_RDONLY);
+  ASSERT_TRUE(fd != -1);
 
-  return dup3(old_fd, new_fd, 0);
+  struct flock check_lock;
+  check_lock.l_type = F_WRLCK;
+  check_lock.l_start = 0;
+  check_lock.l_whence = SEEK_SET;
+  check_lock.l_len = 0;
+
+  ASSERT_EQ(0, fcntl(fd, F_GETLK, &check_lock));
+  close(fd);
 }
diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp
index d7dce31..a8a4cc5 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -148,6 +148,20 @@
   ASSERT_EQ(4, sb.st_size);
 }
 
+TEST(fcntl, f_getlk) {
+  int fd = open("/proc/version", O_RDONLY);
+  ASSERT_TRUE(fd != -1);
+
+  struct flock check_lock;
+  check_lock.l_type = F_WRLCK;
+  check_lock.l_start = 0;
+  check_lock.l_whence = SEEK_SET;
+  check_lock.l_len = 0;
+
+  ASSERT_EQ(0, fcntl(fd, F_GETLK, &check_lock));
+  close(fd);
+}
+
 TEST(fcntl, f_getlk64) {
   int fd = open64("/proc/version", O_RDONLY);
   ASSERT_TRUE(fd != -1);
@@ -158,9 +172,7 @@
   check_lock.l_whence = SEEK_SET;
   check_lock.l_len = 0;
 
-  int rc = fcntl(fd, F_GETLK64, &check_lock);
-  ASSERT_EQ(0, rc);
-
+  ASSERT_EQ(0, fcntl(fd, F_GETLK64, &check_lock));
   close(fd);
 }
 
diff --git a/tests/fdtrack_test.cpp b/tests/fdtrack_test.cpp
new file mode 100644
index 0000000..fca92ce
--- /dev/null
+++ b/tests/fdtrack_test.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#if defined(__BIONIC__)
+#include "platform/bionic/fdtrack.h"
+#endif
+
+#include <vector>
+
+#include <android-base/unique_fd.h>
+
+#if defined(__BIONIC__)
+std::vector<android_fdtrack_event> FdtrackRun(void (*func)()) {
+  // Each bionic test is run in separate process, so we can safely use a static here.
+  static std::vector<android_fdtrack_event> events;
+  events.clear();
+
+  android_fdtrack_hook_t previous = nullptr;
+  android_fdtrack_hook_t hook = [](android_fdtrack_event* event) {
+    events.push_back(*event);
+  };
+
+  if (!android_fdtrack_compare_exchange_hook(&previous, hook)) {
+    errx(1, "failed to exchange hook: previous hook was %p", previous);
+  }
+
+  if (previous) {
+    errx(1, "hook was already registered?");
+    abort();
+  }
+
+  func();
+
+  if (!android_fdtrack_compare_exchange_hook(&hook, nullptr)) {
+    errx(1, "failed to reset hook");
+  }
+
+  return std::move(events);
+}
+#endif
+
+TEST(fdtrack, open) {
+#if defined(__BIONIC__)
+  static int fd = -1;
+  auto events = FdtrackRun([]() { fd = open("/dev/null", O_WRONLY | O_CLOEXEC); });
+  ASSERT_NE(-1, fd);
+  ASSERT_EQ(1U, events.size());
+  ASSERT_EQ(fd, events[0].fd);
+  ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, events[0].type);
+  ASSERT_STREQ("open", events[0].data.create.function_name);
+#endif
+}
+
+TEST(fdtrack, close) {
+#if defined(__BIONIC__)
+  static int fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
+  ASSERT_NE(-1, fd);
+
+  auto events = FdtrackRun([]() { close(fd); });
+  ASSERT_EQ(1U, events.size());
+  ASSERT_EQ(fd, events[0].fd);
+  ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CLOSE, events[0].type);
+#endif
+}
+
+TEST(fdtrack, enable_disable) {
+#if defined(__BIONIC__)
+  static int fd1 = -1;
+  static int fd2 = -1;
+  static int fd3 = -1;
+
+  auto events = FdtrackRun([]() {
+    if (!android_fdtrack_get_enabled()) {
+      errx(1, "fdtrack is disabled");
+    }
+    fd1 = open("/dev/null", O_WRONLY | O_CLOEXEC);
+    android_fdtrack_set_enabled(false);
+    fd2 = open("/dev/null", O_WRONLY | O_CLOEXEC);
+    android_fdtrack_set_enabled(true);
+    fd3 = open("/dev/null", O_WRONLY | O_CLOEXEC);
+  });
+
+  if (fd1 == -1 || fd2 == -1 || fd3 == -1) {
+    errx(1, "failed to open /dev/null");
+  }
+
+  ASSERT_EQ(2U, events.size());
+
+  ASSERT_EQ(fd1, events[0].fd);
+  ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, events[0].type);
+  ASSERT_STREQ("open", events[0].data.create.function_name);
+
+  ASSERT_EQ(fd3, events[1].fd);
+  ASSERT_EQ(ANDROID_FDTRACK_EVENT_TYPE_CREATE, events[1].type);
+  ASSERT_STREQ("open", events[1].data.create.function_name);
+#endif
+}
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index ef2f895..6620cdb 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -829,6 +829,63 @@
 #endif
 }
 
+// Jemalloc doesn't pass this test right now, so leave it as disabled.
+TEST(malloc, DISABLED_alloc_after_fork) {
+  // Both of these need to be a power of 2.
+  static constexpr size_t kMinAllocationSize = 8;
+  static constexpr size_t kMaxAllocationSize = 2097152;
+
+  static constexpr size_t kNumAllocatingThreads = 5;
+  static constexpr size_t kNumForkLoops = 100;
+
+  std::atomic_bool stop;
+
+  // Create threads that simply allocate and free different sizes.
+  std::vector<std::thread*> threads;
+  for (size_t i = 0; i < kNumAllocatingThreads; i++) {
+    std::thread* t = new std::thread([&stop] {
+      while (!stop) {
+        for (size_t size = kMinAllocationSize; size <= kMaxAllocationSize; size <<= 1) {
+          void* ptr = malloc(size);
+          if (ptr == nullptr) {
+            return;
+          }
+          // Make sure this value is not optimized away.
+          asm volatile("" : : "r,m"(ptr) : "memory");
+          free(ptr);
+        }
+      }
+    });
+    threads.push_back(t);
+  }
+
+  // Create a thread to fork and allocate.
+  for (size_t i = 0; i < kNumForkLoops; i++) {
+    pid_t pid;
+    if ((pid = fork()) == 0) {
+      for (size_t size = kMinAllocationSize; size <= kMaxAllocationSize; size <<= 1) {
+        void* ptr = malloc(size);
+        ASSERT_TRUE(ptr != nullptr);
+        // Make sure this value is not optimized away.
+        asm volatile("" : : "r,m"(ptr) : "memory");
+        // Make sure we can touch all of the allocation.
+        memset(ptr, 0x1, size);
+        ASSERT_LE(size, malloc_usable_size(ptr));
+        free(ptr);
+      }
+      _exit(10);
+    }
+    ASSERT_NE(-1, pid);
+    AssertChildExited(pid, 10);
+  }
+
+  stop = true;
+  for (auto thread : threads) {
+    thread->join();
+    delete thread;
+  }
+}
+
 TEST(android_mallopt, error_on_unexpected_option) {
 #if defined(__BIONIC__)
   const int unrecognized_option = -1;