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);
}