Merge "libdl: Rename LIBC_PRIVATE to LIBC_PLATFORM"
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy_common.S b/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
index 955ffb8..4d1167f 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
@@ -60,10 +60,14 @@
         .fpu    neon
 
 ENTRY(__memcpy_chk)
-        cmp     r2, r3
-        bhi     .L_memcpy_chk_fail
+        cmp r2, r3
+        bls memcpy
 
-        // Fall through to memcpy...
+        // Preserve lr for backtrace.
+        push        {lr}
+        .cfi_def_cfa_offset 4
+        .cfi_rel_offset lr, 0
+        bl          __memcpy_chk_fail
 END(__memcpy_chk)
 
 // Prototype: void *memcpy (void *dst, const void *src, size_t count).
@@ -75,25 +79,4 @@
         .cfi_rel_offset lr, 4
 
 #include MEMCPY_BASE
-
-        // Undo the cfi instructions from above.
-        .cfi_def_cfa_offset 0
-        .cfi_restore r0
-        .cfi_restore lr
-.L_memcpy_chk_fail:
-        // Preserve lr for backtrace.
-        push    {lr}
-        .cfi_adjust_cfa_offset 4
-        .cfi_rel_offset lr, 0
-
-        ldr     r0, error_message
-1:
-        add     r0, pc
-        bl      __fortify_fatal
-error_message:
-        .word   error_string-(1b+8)
 END(memcpy)
-
-        .data
-error_string:
-        .string "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a9/bionic/memcpy.S b/libc/arch-arm/cortex-a9/bionic/memcpy.S
index fc0bba1..93a8629 100644
--- a/libc/arch-arm/cortex-a9/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a9/bionic/memcpy.S
@@ -41,9 +41,14 @@
 
 ENTRY(__memcpy_chk)
         cmp         r2, r3
-        bhi         __memcpy_chk_fail
+        bls         memcpy
 
-        // Fall through to memcpy...
+        // Preserve lr for backtrace.
+        push        {lr}
+        .cfi_def_cfa_offset 4
+        .cfi_rel_offset lr, 0
+
+        bl          __memcpy_chk_fail
 END(__memcpy_chk)
 
 ENTRY(memcpy)
@@ -58,21 +63,3 @@
 #define MEMCPY_BASE         __memcpy_base
 #define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
 #include "memcpy_base.S"
-
-ENTRY_PRIVATE(__memcpy_chk_fail)
-        // Preserve lr for backtrace.
-        push    {lr}
-        .cfi_def_cfa_offset 4
-        .cfi_rel_offset lr, 0
-
-        ldr     r0, error_message
-1:
-        add     r0, pc
-        bl      __fortify_fatal
-error_message:
-        .word   error_string-(1b+4)
-END(__memcpy_chk_fail)
-
-        .data
-error_string:
-        .string     "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/denver/bionic/memcpy.S b/libc/arch-arm/denver/bionic/memcpy.S
index c1db06c..d4e0fb4 100644
--- a/libc/arch-arm/denver/bionic/memcpy.S
+++ b/libc/arch-arm/denver/bionic/memcpy.S
@@ -63,9 +63,14 @@
 
 ENTRY(__memcpy_chk)
         cmp     r2, r3
-        bhi     __memcpy_chk_fail
+        bls     memcpy
 
-        // Fall through to memcpy...
+        // Preserve lr for backtrace.
+        push    {lr}
+        .cfi_def_cfa_offset 4
+        .cfi_rel_offset lr, 0
+
+        bl      __memcpy_chk_fail
 END(__memcpy_chk)
 
 ENTRY(memcpy)
@@ -79,21 +84,3 @@
 #define MEMCPY_BASE         __memcpy_base
 #define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
 #include "memcpy_base.S"
-
-ENTRY_PRIVATE(__memcpy_chk_fail)
-        // Preserve lr for backtrace.
-        push    {lr}
-        .cfi_def_cfa_offset 4
-        .cfi_rel_offset lr, 0
-
-        ldr     r0, error_message
-1:
-        add     r0, pc
-        bl      __fortify_fatal
-error_message:
-        .word   error_string-(1b+8)
-END(__memcpy_chk_fail)
-
-        .data
-error_string:
-        .string "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/generic/bionic/memcpy.S b/libc/arch-arm/generic/bionic/memcpy.S
index 54c3060..f5e97f2 100644
--- a/libc/arch-arm/generic/bionic/memcpy.S
+++ b/libc/arch-arm/generic/bionic/memcpy.S
@@ -40,9 +40,14 @@
 
 ENTRY(__memcpy_chk)
         cmp         r2, r3
-        bhi         __memcpy_chk_fail
+        bls         memcpy
 
-        // Fall through to memcpy...
+        // Preserve lr for backtrace.
+        push        {lr}
+        .cfi_def_cfa_offset 4
+        .cfi_rel_offset lr, 0
+
+        bl          __memcpy_chk_fail
 END(__memcpy_chk)
 
 ENTRY(memcpy)
@@ -385,22 +390,3 @@
         add         sp,  sp, #28
         ldmfd       sp!, {r0, r4, pc}
 END(memcpy)
-
-        // Only reached when the __memcpy_chk check fails.
-ENTRY_PRIVATE(__memcpy_chk_fail)
-        // Preserve lr for backtrace.
-        push    {lr}
-        .cfi_def_cfa_offset 4
-        .cfi_rel_offset lr, 0
-
-        ldr     r0, error_message
-1:
-        add     r0, pc
-        bl      __fortify_fatal
-error_message:
-        .word   error_string-(1b+8)
-END(__memcpy_chk_fail)
-
-        .data
-error_string:
-        .string     "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/krait/bionic/memcpy.S b/libc/arch-arm/krait/bionic/memcpy.S
index 189a097..de6f432 100644
--- a/libc/arch-arm/krait/bionic/memcpy.S
+++ b/libc/arch-arm/krait/bionic/memcpy.S
@@ -44,9 +44,14 @@
 
 ENTRY(__memcpy_chk)
         cmp         r2, r3
-        bhi         .L_memcpy_chk_fail
+        bls         memcpy
 
-        // Fall through to memcpy...
+        // Preserve lr for backtrace.
+        push        {lr}
+        .cfi_def_cfa_offset 4
+        .cfi_rel_offset lr, 0
+
+        bl          __memcpy_chk_fail
 END(__memcpy_chk)
 
 ENTRY(memcpy)
@@ -57,25 +62,4 @@
         .cfi_rel_offset lr, 4
 
 #include "memcpy_base.S"
-
-        // Undo the cfi directives from above.
-        .cfi_adjust_cfa_offset -8
-        .cfi_restore r0
-        .cfi_restore lr
-.L_memcpy_chk_fail:
-        // Preserve lr for backtrace.
-        push    {lr}
-        .cfi_adjust_cfa_offset 4
-        .cfi_rel_offset lr, 0
-
-        ldr     r0, error_message
-1:
-        add     r0, pc
-        bl      __fortify_fatal
-error_message:
-        .word   error_string-(1b+4)
 END(memcpy)
-
-        .data
-error_string:
-        .string     "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm64/denver64/bionic/memcpy.S b/libc/arch-arm64/denver64/bionic/memcpy.S
index 83ab5d1..0be2aac 100644
--- a/libc/arch-arm64/denver64/bionic/memcpy.S
+++ b/libc/arch-arm64/denver64/bionic/memcpy.S
@@ -31,29 +31,18 @@
 #include <private/bionic_asm.h>
 
 ENTRY(__memcpy_chk)
-  cmp   x2, x3
-  b.hi  __memcpy_chk_fail
+  cmp x2, x3
+  bls memcpy
 
-  // Fall through to memcpy...
+  // Preserve for accurate backtrace.
+  stp x29, x30, [sp, -16]!
+  .cfi_def_cfa_offset 16
+  .cfi_rel_offset x29, 0
+  .cfi_rel_offset x30, 8
+
+  bl __memcpy_chk_fail
 END(__memcpy_chk)
 
 ENTRY(memcpy)
   #include "memcpy_base.S"
 END(memcpy)
-
-ENTRY_PRIVATE(__memcpy_chk_fail)
-  // Preserve for accurate backtrace.
-  stp  x29, x30, [sp, -16]!
-  .cfi_def_cfa_offset 16
-  .cfi_rel_offset x29, 0
-  .cfi_rel_offset x30, 8
-
-  adrp  x0, error_string
-  add   x0, x0, :lo12:error_string
-  bl    __fortify_fatal
-END(__memcpy_chk_fail)
-
-  .data
-  .align 2
-error_string:
-  .string "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm64/generic/bionic/memcpy.S b/libc/arch-arm64/generic/bionic/memcpy.S
index 83ab5d1..0be2aac 100644
--- a/libc/arch-arm64/generic/bionic/memcpy.S
+++ b/libc/arch-arm64/generic/bionic/memcpy.S
@@ -31,29 +31,18 @@
 #include <private/bionic_asm.h>
 
 ENTRY(__memcpy_chk)
-  cmp   x2, x3
-  b.hi  __memcpy_chk_fail
+  cmp x2, x3
+  bls memcpy
 
-  // Fall through to memcpy...
+  // Preserve for accurate backtrace.
+  stp x29, x30, [sp, -16]!
+  .cfi_def_cfa_offset 16
+  .cfi_rel_offset x29, 0
+  .cfi_rel_offset x30, 8
+
+  bl __memcpy_chk_fail
 END(__memcpy_chk)
 
 ENTRY(memcpy)
   #include "memcpy_base.S"
 END(memcpy)
-
-ENTRY_PRIVATE(__memcpy_chk_fail)
-  // Preserve for accurate backtrace.
-  stp  x29, x30, [sp, -16]!
-  .cfi_def_cfa_offset 16
-  .cfi_rel_offset x29, 0
-  .cfi_rel_offset x30, 8
-
-  adrp  x0, error_string
-  add   x0, x0, :lo12:error_string
-  bl    __fortify_fatal
-END(__memcpy_chk_fail)
-
-  .data
-  .align 2
-error_string:
-  .string "memcpy: prevented write past end of buffer"
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index 1b9f951..ad7aa04 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -140,6 +140,14 @@
   return memmove(dst, src, len);
 }
 
+// memcpy is performance-critical enough that we have assembler __memcpy_chk implementations.
+// This function is used to give better diagnostics than we can easily do from assembler.
+extern "C" void* __memcpy_chk_fail(void* /*dst*/, const void* /*src*/, size_t count, size_t dst_len) {
+  __check_count("memcpy", "count", count);
+  __check_buffer_access("memcpy", "write into", count, dst_len);
+  abort(); // One of the above is supposed to have failed, otherwise we shouldn't have been called.
+}
+
 void* __memrchr_chk(const void* s, int c, size_t n, size_t actual_size) {
   __check_buffer_access("memrchr", "read from", n, actual_size);
   return memrchr(s, c, n);
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);
     }