Merge "Improve diagnostics from the assembler __memcpy_chk routines."
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index 1fb16d4..408949c 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -68,24 +68,52 @@
   }
 
   void SetAddress(int family, const void* data, size_t byteCount) {
+    // The kernel currently uses the order IFA_ADDRESS, IFA_LOCAL, IFA_BROADCAST
+    // in inet_fill_ifaddr, but let's not assume that will always be true...
+    if (ifa.ifa_addr == nullptr) {
+      // This is an IFA_ADDRESS and haven't seen an IFA_LOCAL yet, so assume this is the
+      // local address. SetLocalAddress will fix things if we later see an IFA_LOCAL.
       ifa.ifa_addr = CopyAddress(family, data, byteCount, &addr);
+    } else {
+      // We already saw an IFA_LOCAL, which implies this is a destination address.
+      ifa.ifa_dstaddr = CopyAddress(family, data, byteCount, &ifa_ifu);
+    }
   }
 
   void SetBroadcastAddress(int family, const void* data, size_t byteCount) {
-      ifa.ifa_dstaddr = CopyAddress(family, data, byteCount, &ifa_ifu);
+    // ifa_broadaddr and ifa_dstaddr overlap in a union. Unfortunately, it's possible
+    // to have an interface with both. Keeping the last thing the kernel gives us seems
+    // to be glibc 2.19's behavior too, so our choice is being source compatible with
+    // badly-written code that assumes ifa_broadaddr and ifa_dstaddr are interchangeable
+    // or supporting interfaces with both addresses configured. My assumption is that
+    // bad code is more common than weird network interfaces...
+    ifa.ifa_broadaddr = CopyAddress(family, data, byteCount, &ifa_ifu);
+  }
+
+  void SetLocalAddress(int family, const void* data, size_t byteCount) {
+    // The kernel source says "for point-to-point IFA_ADDRESS is DESTINATION address,
+    // local address is supplied in IFA_LOCAL attribute".
+    //   -- http://lxr.free-electrons.com/source/include/uapi/linux/if_addr.h#L17
+
+    // So copy any existing IFA_ADDRESS into ifa_dstaddr...
+    if (ifa.ifa_addr != nullptr) {
+      ifa.ifa_dstaddr = reinterpret_cast<sockaddr*>(memcpy(&ifa_ifu, &addr, sizeof(addr)));
+    }
+    // ...and then put this IFA_LOCAL into ifa_addr.
+    ifa.ifa_addr = CopyAddress(family, data, byteCount, &addr);
   }
 
   // Netlink gives us the prefix length as a bit count. We need to turn
   // that into a BSD-compatible netmask represented by a sockaddr*.
   void SetNetmask(int family, size_t prefix_length) {
-      // ...and work out the netmask from the prefix length.
-      netmask.ss_family = family;
-      uint8_t* dst = SockaddrBytes(family, &netmask);
-      memset(dst, 0xff, prefix_length / 8);
-      if ((prefix_length % 8) != 0) {
-        dst[prefix_length/8] = (0xff << (8 - (prefix_length % 8)));
-      }
-      ifa.ifa_netmask = reinterpret_cast<sockaddr*>(&netmask);
+    // ...and work out the netmask from the prefix length.
+    netmask.ss_family = family;
+    uint8_t* dst = SockaddrBytes(family, &netmask);
+    memset(dst, 0xff, prefix_length / 8);
+    if ((prefix_length % 8) != 0) {
+      dst[prefix_length/8] = (0xff << (8 - (prefix_length % 8)));
+    }
+    ifa.ifa_netmask = reinterpret_cast<sockaddr*>(&netmask);
   }
 
   void SetPacketAttributes(int ifindex, unsigned short hatype, unsigned char halen) {
@@ -97,19 +125,19 @@
 
  private:
   sockaddr* CopyAddress(int family, const void* data, size_t byteCount, sockaddr_storage* ss) {
-      // Netlink gives us the address family in the header, and the
-      // sockaddr_in or sockaddr_in6 bytes as the payload. We need to
-      // stitch the two bits together into the sockaddr that's part of
-      // our portable interface.
-      ss->ss_family = family;
-      memcpy(SockaddrBytes(family, ss), data, byteCount);
+    // Netlink gives us the address family in the header, and the
+    // sockaddr_in or sockaddr_in6 bytes as the payload. We need to
+    // stitch the two bits together into the sockaddr that's part of
+    // our portable interface.
+    ss->ss_family = family;
+    memcpy(SockaddrBytes(family, ss), data, byteCount);
 
-      // For IPv6 we might also have to set the scope id.
-      if (family == AF_INET6 && (IN6_IS_ADDR_LINKLOCAL(data) || IN6_IS_ADDR_MC_LINKLOCAL(data))) {
-          reinterpret_cast<sockaddr_in6*>(ss)->sin6_scope_id = interface_index;
-      }
+    // For IPv6 we might also have to set the scope id.
+    if (family == AF_INET6 && (IN6_IS_ADDR_LINKLOCAL(data) || IN6_IS_ADDR_MC_LINKLOCAL(data))) {
+      reinterpret_cast<sockaddr_in6*>(ss)->sin6_scope_id = interface_index;
+    }
 
-      return reinterpret_cast<sockaddr*>(ss);
+    return reinterpret_cast<sockaddr*>(ss);
   }
 
   // Returns a pointer to the first byte in the address data (which is
@@ -192,9 +220,13 @@
           new_addr->SetNetmask(msg->ifa_family, msg->ifa_prefixlen);
         }
       } else if (rta->rta_type == IFA_BROADCAST) {
-        if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
+        if (msg->ifa_family == AF_INET) {
           new_addr->SetBroadcastAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
         }
+      } else if (rta->rta_type == IFA_LOCAL) {
+        if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
+          new_addr->SetLocalAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
+        }
       }
       rta = RTA_NEXT(rta, rta_len);
     }
diff --git a/linker/linker.cpp b/linker/linker.cpp
index b5b76b6..a43630b 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -93,6 +93,9 @@
     default_library_paths_ = library_paths;
   }
 
+  const std::vector<std::string>& get_permitted_paths() const {
+    return permitted_paths_;
+  }
   void set_permitted_paths(std::vector<std::string>&& permitted_paths) {
     permitted_paths_ = permitted_paths;
   }
@@ -1651,8 +1654,23 @@
 
   if (!ns->is_accessible(realpath)) {
     // do not load libraries if they are not accessible for the specified namespace.
-    DL_ERR("library \"%s\" is not accessible for the namespace \"%s\"",
-           name, ns->get_name());
+    const char* needed_or_dlopened_by = task->get_needed_by() == nullptr ?
+                                        "(unknown)" :
+                                        task->get_needed_by()->get_realpath();
+
+    DL_ERR("library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"",
+           name, needed_or_dlopened_by, ns->get_name());
+
+    PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
+          " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
+          " permitted_paths=\"%s\"]",
+          name, realpath.c_str(),
+          needed_or_dlopened_by,
+          ns->get_name(),
+          android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
+          android::base::Join(ns->get_default_library_paths(), ':').c_str(),
+          android::base::Join(ns->get_permitted_paths(), ':').c_str());
+
     return false;
   }
 
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index c64ec15..66d8859 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -799,7 +799,9 @@
   // Check dlopen by absolute path
   handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
   ASSERT_TRUE(handle2 == nullptr);
-  ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" is not accessible for the namespace \"private_isolated1\"", dlerror());
+  ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
+            " or dlopened by \"" + get_executable_name() +  "\" is not accessible"
+            " for the namespace \"private_isolated1\"", dlerror());
 
   extinfo.library_namespace = ns_isolated2;
 
@@ -899,7 +901,9 @@
   // Check dlopen by absolute path
   handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo);
   ASSERT_TRUE(handle2 == nullptr);
-  ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" is not accessible for the namespace \"private_isolated_shared\"", dlerror());
+  ASSERT_EQ("dlopen failed: library \"" + lib_private_external_path + "\" needed"
+            " or dlopened by \"" + get_executable_name() + "\" is not accessible"
+            " for the namespace \"private_isolated_shared\"", dlerror());
 
   // load libnstest_root.so to shared namespace in order to check that everything is different
   // except shared libnstest_dlopened.so
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 7360f12..ad23aa8 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -46,6 +46,12 @@
 
 #endif
 
+static std::string g_executable_name;
+
+const std::string& get_executable_name() {
+  return g_executable_name;
+}
+
 namespace testing {
 namespace internal {
 
@@ -1113,6 +1119,7 @@
 }
 
 int main(int argc, char** argv) {
+  g_executable_name = argv[0];
   std::vector<char*> arg_list;
   for (int i = 0; i < argc; ++i) {
     arg_list.push_back(argv[i]);
diff --git a/tests/utils.h b/tests/utils.h
index 828c8d0..a335c66 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -119,4 +119,6 @@
   ASSERT_EQ(expected_exit_status, WEXITSTATUS(status));
 }
 
+const std::string& get_executable_name();
+
 #endif