Merge "Reland: "Make native bridge libc uninstallable""
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index dd623a5..8084e73 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -149,50 +149,25 @@
   _exit(EXIT_FAILURE);
 }
 
-// Force any of the closed stdin, stdout and stderr to be associated with /dev/null.
+// Force any of the stdin/stdout/stderr file descriptors that aren't
+// open to be associated with /dev/null.
 static void __nullify_closed_stdio() {
-  int dev_null = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
-  if (dev_null == -1) {
-    // init won't have /dev/null available, but SELinux provides an equivalent.
-    dev_null = TEMP_FAILURE_RETRY(open("/sys/fs/selinux/null", O_RDWR));
-  }
-  if (dev_null == -1) {
-    __early_abort(__LINE__);
-  }
-
-  // If any of the stdio file descriptors is valid and not associated
-  // with /dev/null, dup /dev/null to it.
   for (int i = 0; i < 3; i++) {
-    // If it is /dev/null already, we are done.
-    if (i == dev_null) {
-      continue;
-    }
+    if (TEMP_FAILURE_RETRY(fcntl(i, F_GETFL)) == -1) {
+      // The only error we allow is that the file descriptor does not exist.
+      if (errno != EBADF) __early_abort(__LINE__);
 
-    // Is this fd already open?
-    int status = TEMP_FAILURE_RETRY(fcntl(i, F_GETFL));
-    if (status != -1) {
-      continue;
-    }
-
-    // The only error we allow is that the file descriptor does not
-    // exist, in which case we dup /dev/null to it.
-    if (errno == EBADF) {
-      // Try dupping /dev/null to this stdio file descriptor and
-      // repeat if there is a signal. Note that any errors in closing
-      // the stdio descriptor are lost.
-      status = TEMP_FAILURE_RETRY(dup2(dev_null, i));
-      if (status == -1) {
+      // This file descriptor wasn't open, so open /dev/null.
+      // init won't have /dev/null available, but SELinux provides an equivalent.
+      // This takes advantage of the fact that open() will take the lowest free
+      // file descriptor, and we're iterating in order from 0, but we'll
+      // double-check we got the right fd anyway...
+      int fd;
+      if (((fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR))) == -1 &&
+           (fd = TEMP_FAILURE_RETRY(open("/sys/fs/selinux/null", O_RDWR))) == -1) ||
+          fd != i) {
         __early_abort(__LINE__);
       }
-    } else {
-      __early_abort(__LINE__);
-    }
-  }
-
-  // If /dev/null is not one of the stdio file descriptors, close it.
-  if (dev_null > 2) {
-    if (close(dev_null) == -1) {
-      __early_abort(__LINE__);
     }
   }
 }
diff --git a/libc/malloc_debug/UnwindBacktrace.cpp b/libc/malloc_debug/UnwindBacktrace.cpp
index 128991b..dbaebb3 100644
--- a/libc/malloc_debug/UnwindBacktrace.cpp
+++ b/libc/malloc_debug/UnwindBacktrace.cpp
@@ -87,7 +87,7 @@
 void UnwindLog(const std::vector<unwindstack::LocalFrameData>& frame_info) {
   for (size_t i = 0; i < frame_info.size(); i++) {
     const unwindstack::LocalFrameData* info = &frame_info[i];
-    unwindstack::MapInfo* map_info = info->map_info;
+    std::shared_ptr<unwindstack::MapInfo> map_info = info->map_info;
 
     std::string line = android::base::StringPrintf("          #%0zd  pc %" PAD_PTR "  ", i, info->rel_pc);
     if (map_info->offset() != 0) {
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 1298df7..7b58f31 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -1528,19 +1528,18 @@
 TEST_F(MallocDebugTest, backtrace_full_dump_on_exit) {
   pid_t pid;
   if ((pid = fork()) == 0) {
+    std::shared_ptr<unwindstack::MapInfo> empty_map;
     Init("backtrace=4 backtrace_full backtrace_dump_on_exit");
+    BacktraceUnwindFake(std::vector<unwindstack::LocalFrameData>{
+        {empty_map, 0x1100, 0x100, "fake1", 10}, {empty_map, 0x1200, 0x200, "fake2", 20}});
+    std::shared_ptr<unwindstack::MapInfo> map_info =
+        unwindstack::MapInfo::Create(0x10000, 0x20000, 0, PROT_READ | PROT_EXEC, "/data/fake.so");
+    BacktraceUnwindFake(std::vector<unwindstack::LocalFrameData>{
+        {map_info, 0x1a000, 0xa000, "level1", 0}, {map_info, 0x1b000, 0xb000, "level2", 10}});
     BacktraceUnwindFake(
-      std::vector<unwindstack::LocalFrameData>{{nullptr, 0x1100, 0x100, "fake1", 10},
-                                               {nullptr, 0x1200, 0x200, "fake2", 20}});
-    unwindstack::MapInfo map_info{nullptr, nullptr, 0x10000, 0x20000, 0,
-                                  PROT_READ | PROT_EXEC, "/data/fake.so"};
-    BacktraceUnwindFake(
-      std::vector<unwindstack::LocalFrameData>{{&map_info, 0x1a000, 0xa000, "level1", 0},
-                                               {&map_info, 0x1b000, 0xb000, "level2", 10}});
-    BacktraceUnwindFake(
-      std::vector<unwindstack::LocalFrameData>{{nullptr, 0x1a000, 0xa000, "func1", 0},
-                                               {nullptr, 0x1b000, 0xb000, "func2", 10},
-                                               {nullptr, 0x1c000, 0xc000, "", 30}});
+        std::vector<unwindstack::LocalFrameData>{{empty_map, 0x1a000, 0xa000, "func1", 0},
+                                                 {empty_map, 0x1b000, 0xb000, "func2", 10},
+                                                 {empty_map, 0x1c000, 0xc000, "", 30}});
 
     std::vector<void*> pointers;
     pointers.push_back(debug_malloc(300));