Merge "Add tests for FNM_LEADING_DIR"
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index 5f8c113..61084a1 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -29,7 +29,6 @@
         "bionic_benchmarks.cpp",
         "atomic_benchmark.cpp",
         "ctype_benchmark.cpp",
-        "dlfcn_benchmark.cpp",
         "get_heap_size_benchmark.cpp",
         "inttypes_benchmark.cpp",
         "malloc_benchmark.cpp",
@@ -80,6 +79,9 @@
 cc_benchmark {
     name: "bionic-benchmarks",
     defaults: ["bionic-benchmarks-defaults"],
+    srcs: [
+        "dlfcn_benchmark.cpp",
+    ],
     data: ["suites/*"],
     static_libs: [
         "libsystemproperties",
@@ -88,16 +90,26 @@
     include_dirs: ["bionic/libc"],
 }
 
-// We don't build a static benchmark executable because it's not usually
-// useful. If you're trying to run the current benchmarks on an older
-// release, it's (so far at least) always because you want to measure the
-// performance of the old release's libc, and a static benchmark isn't
-// going to let you do that.
+cc_benchmark {
+    name: "bionic-benchmarks-static",
+    defaults: ["bionic-benchmarks-defaults"],
+    data: ["suites/*"],
+    static_libs: [
+        "liblog",
+        "libsystemproperties",
+        "libasync_safe",
+    ],
+    include_dirs: ["bionic/libc"],
+    static_executable: true,
+}
 
 // Build benchmarks for the host (against glibc!). Run with:
 cc_benchmark_host {
     name: "bionic-benchmarks-glibc",
     defaults: ["bionic-benchmarks-defaults"],
+    srcs: [
+        "dlfcn_benchmark.cpp",
+    ],
     target: {
         darwin: {
             // Only supported on linux systems.
diff --git a/libc/Android.bp b/libc/Android.bp
index 4d63751..cce23b3 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -506,8 +506,6 @@
         "upstream-openbsd/lib/libc/stdio/open_wmemstream.c",
         "upstream-openbsd/lib/libc/stdio/rget.c",
         "upstream-openbsd/lib/libc/stdio/setvbuf.c",
-        "upstream-openbsd/lib/libc/stdio/tempnam.c",
-        "upstream-openbsd/lib/libc/stdio/tmpnam.c",
         "upstream-openbsd/lib/libc/stdio/ungetc.c",
         "upstream-openbsd/lib/libc/stdio/ungetwc.c",
         "upstream-openbsd/lib/libc/stdio/vasprintf.c",
@@ -1011,7 +1009,9 @@
         "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/NOTICE b/libc/NOTICE
index 58d6679..f7d73d8 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -2368,38 +2368,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 1990, 1993, 1994
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Chris Torek.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University nor the names of its contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
 Copyright (c) 1991 The Regents of the University of California.
 All rights reserved.
 
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 6142baf..7cf7a2d 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -244,7 +244,7 @@
 # sockets
 int           __socket:socket(int, int, int)              arm,lp64
 int           __socketpair:socketpair(int, int, int, int*)    arm,lp64
-int           bind(int, struct sockaddr*, socklen_t)  arm,lp64
+int           __bind: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
@@ -262,7 +262,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
new file mode 100644
index 0000000..314b0a1
--- /dev/null
+++ b/libc/bionic/bind.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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_protocol, err;
+    socklen_t sock_length = sizeof(sock_protocol);
+    if ((err = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &sock_protocol, &sock_length) < 0)) {
+      async_safe_format_log(ANDROID_LOG_ERROR, "mac-restrictions",
+                            "Could not get socket protocol: %s", strerror(errno));
+    } else if (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
new file mode 100644
index 0000000..4cb4c84
--- /dev/null
+++ b/libc/bionic/bionic_appcompat.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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;
+  }
+
+  int len = read(file, buffer, bufferlen - 1);
+  if (len < 0) {
+    return -1;
+  }
+  buffer[len] = 0;
+
+  return 0;
+}
\ No newline at end of file
diff --git a/libc/bionic/bionic_appcompat.h b/libc/bionic/bionic_appcompat.h
new file mode 100644
index 0000000..1976e0b
--- /dev/null
+++ b/libc/bionic/bionic_appcompat.h
@@ -0,0 +1,44 @@
+/*
+ * 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.skype.raider",
+    nullptr,
+};
+
+static inline const char* const soft_mac_getlink_allowlist[] = {
+    nullptr,
+};
+
+int get_package_name(char* buffer, const int bufferlen);
+bool should_apply_soft_mac_bind_restrictions();
+bool should_apply_soft_mac_getlink_restrictions();
\ No newline at end of file
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index 1536333..22ecdb4 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -42,6 +42,7 @@
 
 #include "private/ErrnoRestorer.h"
 
+#include "bionic_appcompat.h"
 #include "bionic_netlink.h"
 
 // The public ifaddrs struct is full of pointers. Rather than track several
@@ -310,9 +311,12 @@
   // - System apps
   // - Apps with a target SDK version lower than R
   bool getlink_success = false;
-  if (getuid() < FIRST_APPLICATION_UID ||
-      android_get_application_target_sdk_version() < __ANDROID_API_R__) {
+  if (!should_apply_soft_mac_getlink_restrictions()) {
     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/bionic/new.cpp b/libc/bionic/new.cpp
index a0da2fb..c9ce163 100644
--- a/libc/bionic/new.cpp
+++ b/libc/bionic/new.cpp
@@ -21,7 +21,7 @@
 
 #include <async_safe/log.h>
 
-const std::nothrow_t std::nothrow = {};
+__attribute__((weak)) const std::nothrow_t std::nothrow = {};
 
 void* operator new(std::size_t size) {
     void* p = malloc(size);
diff --git a/libc/bionic/tmpfile.cpp b/libc/bionic/tmpfile.cpp
index d7ce897..3d04610 100644
--- a/libc/bionic/tmpfile.cpp
+++ b/libc/bionic/tmpfile.cpp
@@ -35,6 +35,7 @@
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -99,3 +100,48 @@
   return fp;
 }
 __strong_alias(tmpfile64, tmpfile);
+
+char* tempnam(const char* dir, const char* prefix) {
+  // This function is a terrible idea, marked deprecated in our headers,
+  // and marked obsolescent by POSIX.1-2008, but we make some effort anyway
+  // since we can't easily remove it...
+
+  // $TMPDIR overrides any directory passed in.
+  char* tmpdir = getenv("TMPDIR");
+  if (tmpdir != nullptr) dir = tmpdir;
+
+  // If we still have no directory, we'll give you a default.
+  // It's useless for apps, but good enough for the shell.
+  if (dir == nullptr) dir = "/data/local/tmp";
+
+  // Default prefix?
+  if (prefix == nullptr) prefix = "tempnam.";
+
+  // Make up a mktemp(3) template and defer to it for the real work.
+  char* path = nullptr;
+  if (asprintf(&path, "%s/%sXXXXXXXXXX", dir, prefix) == -1) return nullptr;
+  if (mktemp(path) == nullptr) {
+    free(path);
+    return nullptr;
+  }
+  return path;
+}
+
+char* tmpnam(char* s) {
+  // This function is a terrible idea, marked deprecated in our headers,
+  // and marked obsolescent by POSIX-1.2008, but we make some effort anyway
+  // since we can't easily remove it...
+
+  // Default buffer?
+  static char buf[L_tmpnam];
+  if (s == nullptr) s = buf;
+
+  // Use $TMPDIR if set, or fall back to /data/local/tmp otherwise.
+  // Useless for apps, but good enough for the shell.
+  const char* dir = getenv("TMPDIR");
+  if (dir == nullptr) dir = "/data/local/tmp";
+
+  // Make up a mktemp(3) template and defer to it for the real work.
+  snprintf(s, L_tmpnam, "%s/tmpnam.XXXXXXXXXX", dir);
+  return mktemp(s);
+}
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index a645a6b..fa81e6d 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -948,6 +948,8 @@
 			else
 				break;
 		}
+		// return size should never exceed container size
+		resplen = anssiz;
 	}
 	/*
 	 * If the calling applicating has bailed out of
@@ -960,7 +962,7 @@
 		DprintQ((statp->options & RES_DEBUG) ||
 			(statp->pfcode & RES_PRF_REPLY),
 			(stdout, ";; old answer (unexpected):\n"),
-			ans, (resplen > anssiz) ? anssiz: resplen);
+			ans, resplen);
 		goto read_len;
 	}
 
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 1bf578c..9de12a4 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -160,7 +160,7 @@
 int vsprintf(char* __s, const char* __fmt, va_list __args)
     __printflike(2, 0) __warnattr_strict("vsprintf is often misused; please use vsnprintf");
 char* tmpnam(char* __s)
-    __warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
+    __warnattr("tmpnam is unsafe, use mkstemp or tmpfile instead");
 #define P_tmpdir "/tmp/" /* deprecated */
 char* tempnam(const char* __dir, const char* __prefix)
     __warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
diff --git a/libc/upstream-openbsd/lib/libc/stdio/tempnam.c b/libc/upstream-openbsd/lib/libc/stdio/tempnam.c
deleted file mode 100644
index d2c848c..0000000
--- a/libc/upstream-openbsd/lib/libc/stdio/tempnam.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*	$OpenBSD: tempnam.c,v 1.20 2017/11/28 06:55:49 tb Exp $ */
-/*
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <errno.h>
-#include <limits.h>
-#include <paths.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-__warn_references(tempnam,
-    "tempnam() possibly used unsafely; consider using mkstemp()");
-
-char *
-tempnam(const char *dir, const char *pfx)
-{
-	int sverrno, len;
-	char *f, *name;
-
-	if (!(name = malloc(PATH_MAX)))
-		return(NULL);
-
-	if (!pfx)
-		pfx = "tmp.";
-
-	if (issetugid() == 0 && (f = getenv("TMPDIR")) && *f != '\0') {
-		len = snprintf(name, PATH_MAX, "%s%s%sXXXXXXXXXX", f,
-		    f[strlen(f) - 1] == '/' ? "" : "/", pfx);
-		if (len < 0 || len >= PATH_MAX) {
-			errno = ENAMETOOLONG;
-			goto fail;
-		}
-		if ((f = _mktemp(name)))
-			return(f);
-	}
-
-	if (dir != NULL) {
-		f = *dir ? (char *)dir : ".";
-		len = snprintf(name, PATH_MAX, "%s%s%sXXXXXXXXXX", f,
-		    f[strlen(f) - 1] == '/' ? "" : "/", pfx);
-		if (len < 0 || len >= PATH_MAX) {
-			errno = ENAMETOOLONG;
-			goto fail;
-		}
-		if ((f = _mktemp(name)))
-			return(f);
-	}
-
-	f = P_tmpdir;
-	len = snprintf(name, PATH_MAX, "%s%sXXXXXXXXX", f, pfx);
-	if (len < 0 || len >= PATH_MAX) {
-		errno = ENAMETOOLONG;
-		goto fail;
-	}
-	if ((f = _mktemp(name)))
-		return(f);
-
-	f = _PATH_TMP;
-	len = snprintf(name, PATH_MAX, "%s%sXXXXXXXXX", f, pfx);
-	if (len < 0 || len >= PATH_MAX) {
-		errno = ENAMETOOLONG;
-		goto fail;
-	}
-	if ((f = _mktemp(name)))
-		return(f);
-
-fail:
-	sverrno = errno;
-	free(name);
-	errno = sverrno;
-	return(NULL);
-}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c b/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c
deleted file mode 100644
index 52cd43d..0000000
--- a/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*	$OpenBSD: tmpnam.c,v 1.12 2017/11/28 06:55:49 tb Exp $ */
-/*-
- * Copyright (c) 1990, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <sys/types.h>
-
-#include <stdio.h>
-#include <unistd.h>
-
-__warn_references(tmpnam,
-    "tmpnam() possibly used unsafely; consider using mkstemp()");
-
-char *
-tmpnam(char *s)
-{
-	static u_long tmpcount;
-	static char buf[L_tmpnam];
-
-	if (s == NULL)
-		s = buf;
-	(void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXXXXX", P_tmpdir, tmpcount);
-	++tmpcount;
-	return (_mktemp(s));
-}
diff --git a/linker/Android.bp b/linker/Android.bp
index 8a2809a..3ebae59 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -357,12 +357,35 @@
             static_libs: [
                 "liblinker_debuggerd_stub",
             ],
-        }
+        },
+        android_arm64: {
+            pgo: {
+                profile_file: "bionic/linker_arm_arm64.profdata",
+            },
+        },
+        android_arm: {
+            pgo: {
+                profile_file: "bionic/linker_arm_arm64.profdata",
+            },
+        },
+        android_x86_64: {
+            pgo: {
+                profile_file: "bionic/linker_x86_x86_64.profdata",
+            },
+        },
+        android_x86: {
+            pgo: {
+                profile_file: "bionic/linker_x86_x86_64.profdata",
+            },
+        },
     },
 
     lto: {
         never: true,
     },
+    pgo: {
+        sampling: true,
+    },
 }
 
 // ========================================================
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index c21c3b8..5680f95 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -33,6 +33,7 @@
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/test_utils.h>
 #include <android-base/unique_fd.h>
 
 #include "BionicDeathTest.h"
@@ -2816,3 +2817,69 @@
   ASSERT_TRUE(fp == nullptr);
   ASSERT_EQ(ENOENT, errno);
 }
+
+static void tempnam_test(bool has_TMPDIR, const char* dir, const char* prefix, const char* re) {
+  if (has_TMPDIR) {
+    setenv("TMPDIR", "/my/tmp/dir", 1);
+  } else {
+    unsetenv("TMPDIR");
+  }
+  char* s1 = tempnam(dir, prefix);
+  char* s2 = tempnam(dir, prefix);
+  ASSERT_MATCH(s1, re);
+  ASSERT_MATCH(s2, re);
+  ASSERT_STRNE(s1, s2);
+  free(s1);
+  free(s2);
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_system_prefix_with_TMPDIR) {
+  tempnam_test(true, nullptr, nullptr, "^/my/tmp/dir/.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_system_prefix_without_TMPDIR) {
+  tempnam_test(false, nullptr, nullptr, "^/data/local/tmp/.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_user_prefix_with_TMPDIR) {
+  tempnam_test(true, nullptr, "prefix", "^/my/tmp/dir/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_user_prefix_without_TMPDIR) {
+  tempnam_test(false, nullptr, "prefix", "^/data/local/tmp/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_system_prefix_with_TMPDIR) {
+  tempnam_test(true, "/a/b/c", nullptr, "^/my/tmp/dir/.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_system_prefix_without_TMPDIR) {
+  tempnam_test(false, "/a/b/c", nullptr, "^/a/b/c/.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_user_prefix_with_TMPDIR) {
+  tempnam_test(true, "/a/b/c", "prefix", "^/my/tmp/dir/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_user_prefix_without_TMPDIR) {
+  tempnam_test(false, "/a/b/c", "prefix", "^/a/b/c/prefix.*");
+}
+
+static void tmpnam_test(char* s) {
+  char s1[L_tmpnam], s2[L_tmpnam];
+
+  strcpy(s1, tmpnam(s));
+  strcpy(s2, tmpnam(s));
+  ASSERT_MATCH(s1, "/tmp/.*");
+  ASSERT_MATCH(s2, "/tmp/.*");
+  ASSERT_STRNE(s1, s2);
+}
+
+TEST(STDIO_TEST, tmpnam) {
+  tmpnam_test(nullptr);
+}
+
+TEST(STDIO_TEST, tmpnam_buf) {
+  char buf[L_tmpnam];
+  tmpnam_test(buf);
+}