Merge "Implement <spawn.h>."
diff --git a/libc/bionic/android_set_abort_message.cpp b/libc/bionic/android_set_abort_message.cpp
index 2a11613..8c80c5a 100644
--- a/libc/bionic/android_set_abort_message.cpp
+++ b/libc/bionic/android_set_abort_message.cpp
@@ -29,6 +29,7 @@
 #include <android/set_abort_message.h>
 
 #include <pthread.h>
+#include <string.h>
 #include <sys/mman.h>
 
 #include "private/ScopedPthreadMutexLocker.h"
diff --git a/libc/bionic/bionic_arc4random.cpp b/libc/bionic/bionic_arc4random.cpp
index a339900..391eb0c 100644
--- a/libc/bionic/bionic_arc4random.cpp
+++ b/libc/bionic/bionic_arc4random.cpp
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <stdatomic.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/auxv.h>
 #include <unistd.h>
 
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index 2823662..50fcbce 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -580,7 +580,7 @@
   ErrnoRestorer errno_restorer;
   *result = NULL;
   char* p = reinterpret_cast<char*>(
-      BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
+      __BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
   if (p + sizeof(group_state_t) > buf + buflen) {
     return ERANGE;
   }
diff --git a/libc/bionic/iconv.cpp b/libc/bionic/iconv.cpp
index b0372a1..015d70f 100644
--- a/libc/bionic/iconv.cpp
+++ b/libc/bionic/iconv.cpp
@@ -32,6 +32,7 @@
 #include <endian.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 #include <uchar.h>
 
 #include "private/bionic_mbstate.h"
diff --git a/libc/bionic/icu.cpp b/libc/bionic/icu.cpp
index 944a3f8..78e551b 100644
--- a/libc/bionic/icu.cpp
+++ b/libc/bionic/icu.cpp
@@ -32,6 +32,7 @@
 #include <dlfcn.h>
 #include <pthread.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <async_safe/log.h>
 
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 266b966..19081a4 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -23,7 +23,7 @@
 
 void* je_pvalloc(size_t bytes) {
   size_t pagesize = getpagesize();
-  size_t size = BIONIC_ALIGN(bytes, pagesize);
+  size_t size = __BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) {
     return NULL;
   }
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
index 57a8cdf..3503319 100644
--- a/libc/bionic/mmap.cpp
+++ b/libc/bionic/mmap.cpp
@@ -48,7 +48,7 @@
   }
 
   // prevent allocations large enough for `end - start` to overflow
-  size_t rounded = BIONIC_ALIGN(size, PAGE_SIZE);
+  size_t rounded = __BIONIC_ALIGN(size, PAGE_SIZE);
   if (rounded < size || rounded > PTRDIFF_MAX) {
     errno = ENOMEM;
     return MAP_FAILED;
diff --git a/libc/bionic/mremap.cpp b/libc/bionic/mremap.cpp
index 6653d43..896ccef 100644
--- a/libc/bionic/mremap.cpp
+++ b/libc/bionic/mremap.cpp
@@ -38,7 +38,7 @@
 
 void* mremap(void* old_address, size_t old_size, size_t new_size, int flags, ...) {
   // prevent allocations large enough for `end - start` to overflow
-  size_t rounded = BIONIC_ALIGN(new_size, PAGE_SIZE);
+  size_t rounded = __BIONIC_ALIGN(new_size, PAGE_SIZE);
   if (rounded < new_size || rounded > PTRDIFF_MAX) {
     errno = ENOMEM;
     return MAP_FAILED;
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 65ab92c..be0fd1b 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -172,8 +172,8 @@
     // Make sure the stack size and guard size are multiples of PAGE_SIZE.
     if (__builtin_add_overflow(attr->stack_size, attr->guard_size, &mmap_size)) return EAGAIN;
     if (__builtin_add_overflow(mmap_size, sizeof(pthread_internal_t), &mmap_size)) return EAGAIN;
-    mmap_size = BIONIC_ALIGN(mmap_size, PAGE_SIZE);
-    attr->guard_size = BIONIC_ALIGN(attr->guard_size, PAGE_SIZE);
+    mmap_size = __BIONIC_ALIGN(mmap_size, PAGE_SIZE);
+    attr->guard_size = __BIONIC_ALIGN(attr->guard_size, PAGE_SIZE);
     attr->stack_base = __create_thread_mapped_space(mmap_size, attr->guard_size);
     if (attr->stack_base == NULL) {
       return EAGAIN;
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index c57cd9c..b87d7e8 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -71,9 +71,27 @@
 #define SERIAL_DIRTY(serial) ((serial)&1)
 #define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
 
+constexpr static const char kLongLegacyError[] = "Must use __system_property_read_callback() to read";
+
+// The error message fits in part of a union with the previous 92 char property value so there must
+// be room left over after the error message for the offset to the new longer property value and
+// future expansion fields if needed.
+// Note that this value cannot ever increase.  The offset to the new longer property value appears
+// immediately after it, so an increase of this size will break compatibility.
+constexpr size_t kLongLegacyErrorBufferSize = 56;
+static_assert(sizeof(kLongLegacyError) < kLongLegacyErrorBufferSize,
+              "Error message for long properties read by legacy libc must fit within 56 chars");
+
 static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
 static const char* kServiceVersionPropertyName = "ro.property_service.version";
 
+// The C11 standard doesn't allow atomic loads from const fields,
+// though C++11 does.  Fudge it until standards get straightened out.
+static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, memory_order mo) {
+  atomic_uint_least32_t* non_const_s = const_cast<atomic_uint_least32_t*>(s);
+  return atomic_load_explicit(non_const_s, mo);
+}
+
 /*
  * Properties are stored in a hybrid trie/binary tree structure.
  * Each property's name is delimited at '.' characters, and the tokens are put
@@ -182,12 +200,34 @@
 };
 
 struct prop_info {
+  // Read only properties will not set anything but the bottom most bit of serial and the top byte.
+  // We borrow the 2nd from the top byte for extra flags, and use the bottom most bit of that for
+  // our first user, kLongFlag.
+  constexpr static uint32_t kLongFlag = 1 << 16;
   atomic_uint_least32_t serial;
   // we need to keep this buffer around because the property
   // value can be modified whereas name is constant.
-  char value[PROP_VALUE_MAX];
+  union {
+    char value[PROP_VALUE_MAX];
+    struct {
+      char error_message[kLongLegacyErrorBufferSize];
+      uint32_t offset;
+    } long_property;
+  };
   char name[0];
 
+  bool is_long() const {
+    return (load_const_atomic(&serial, memory_order_relaxed) & kLongFlag) != 0;
+  }
+
+  const char* long_value() const {
+    // We can't store pointers here since this is shared memory that will have different absolute
+    // pointers in different processes.  We don't have data_ from prop_area, but since we know
+    // `this` is data_ + some offset and long_value is data_ + some other offset, we calculate the
+    // offset from `this` to long_value and store it as long_property.offset.
+    return reinterpret_cast<const char*>(this) + long_property.offset;
+  }
+
   prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen) {
     memcpy(this->name, name, namelen);
     this->name[namelen] = '\0';
@@ -196,10 +236,23 @@
     this->value[valuelen] = '\0';
   }
 
+  prop_info(const char* name, uint32_t namelen, uint32_t long_offset) {
+    memcpy(this->name, name, namelen);
+    this->name[namelen] = '\0';
+
+    auto error_value_len = sizeof(kLongLegacyError) - 1;
+    atomic_init(&this->serial, error_value_len << 24 | kLongFlag);
+    memcpy(this->long_property.error_message, kLongLegacyError, sizeof(kLongLegacyError));
+
+    this->long_property.offset = long_offset;
+  }
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
 };
 
+static_assert(sizeof(prop_info) == 96, "size of struct prop_info must be 96 bytes");
+
 // This is public because it was exposed in the NDK. As of 2017-01, ~60 apps reference this symbol.
 prop_area* __system_property_area__ = nullptr;
 
@@ -304,7 +357,7 @@
 }
 
 void* prop_area::allocate_obj(const size_t size, uint_least32_t* const off) {
-  const size_t aligned = BIONIC_ALIGN(size, sizeof(uint_least32_t));
+  const size_t aligned = __BIONIC_ALIGN(size, sizeof(uint_least32_t));
   if (bytes_used_ + aligned > pa_data_size) {
     return nullptr;
   }
@@ -330,13 +383,28 @@
                                     uint32_t valuelen, uint_least32_t* const off) {
   uint_least32_t new_offset;
   void* const p = allocate_obj(sizeof(prop_info) + namelen + 1, &new_offset);
-  if (p != nullptr) {
-    prop_info* info = new (p) prop_info(name, namelen, value, valuelen);
-    *off = new_offset;
-    return info;
-  }
+  if (p == nullptr) return nullptr;
 
-  return nullptr;
+  prop_info* info;
+  if (valuelen >= PROP_VALUE_MAX) {
+    uint32_t long_value_offset = 0;
+    char* long_location = reinterpret_cast<char*>(allocate_obj(valuelen + 1, &long_value_offset));
+    if (!long_location) return nullptr;
+
+    memcpy(long_location, value, valuelen);
+    long_location[valuelen] = '\0';
+
+    // Both new_offset and long_value_offset are offsets based off of data_, however prop_info
+    // does not know what data_ is, so we change this offset to be an offset from the prop_info
+    // pointer that contains it.
+    long_value_offset -= new_offset;
+
+    info = new (p) prop_info(name, namelen, long_value_offset);
+  } else {
+    info = new (p) prop_info(name, namelen, value, valuelen);
+  }
+  *off = new_offset;
+  return info;
 }
 
 void* prop_area::to_prop_obj(uint_least32_t off) {
@@ -1161,11 +1229,8 @@
   return pa->find(name);
 }
 
-// The C11 standard doesn't allow atomic loads from const fields,
-// though C++11 does.  Fudge it until standards get straightened out.
-static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, memory_order mo) {
-  atomic_uint_least32_t* non_const_s = const_cast<atomic_uint_least32_t*>(s);
-  return atomic_load_explicit(non_const_s, mo);
+static bool is_read_only(const char* name) {
+  return strncmp(name, "ro.", 3) == 0;
 }
 
 int __system_property_read(const prop_info* pi, char* name, char* value) {
@@ -1193,6 +1258,13 @@
                                 pi->name, PROP_NAME_MAX - 1, name);
         }
       }
+      if (is_read_only(pi->name) && pi->is_long()) {
+        async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                              "The property \"%s\" has a value with length %zu that is too large for"
+                              " __system_property_get()/__system_property_read(); use"
+                              " __system_property_read_callback() instead.",
+                              pi->name, strlen(pi->long_value()));
+      }
       return len;
     }
   }
@@ -1204,6 +1276,18 @@
                                                       const char* value,
                                                       uint32_t serial),
                                      void* cookie) {
+  // Read only properties don't need to copy the value to a temporary buffer, since it can never
+  // change.
+  if (is_read_only(pi->name)) {
+    uint32_t serial = __system_property_serial(pi);
+    if (pi->is_long()) {
+      callback(cookie, pi->name, pi->long_value(), serial);
+    } else {
+      callback(cookie, pi->name, pi->value, serial);
+    }
+    return;
+  }
+
   while (true) {
     uint32_t serial = __system_property_serial(pi);  // acquire semantics
     size_t len = SERIAL_VALUE_LEN(serial);
@@ -1260,15 +1344,15 @@
 int __system_property_set(const char* key, const char* value) {
   if (key == nullptr) return -1;
   if (value == nullptr) value = "";
-  if (strlen(value) >= PROP_VALUE_MAX) return -1;
 
   if (g_propservice_protocol_version == 0) {
     detect_protocol_version();
   }
 
   if (g_propservice_protocol_version == kProtocolVersion1) {
-    // Old protocol does not support long names
+    // Old protocol does not support long names or values
     if (strlen(key) >= PROP_NAME_MAX) return -1;
+    if (strlen(value) >= PROP_VALUE_MAX) return -1;
 
     prop_msg msg;
     memset(&msg, 0, sizeof msg);
@@ -1278,6 +1362,8 @@
 
     return send_prop_msg(&msg);
   } else {
+    // New protocol only allows long values for ro. properties only.
+    if (strlen(value) >= PROP_VALUE_MAX && !is_read_only(key)) return -1;
     // Use proper protocol
     PropertyServiceConnection connection;
     if (!connection.IsValid()) {
@@ -1364,7 +1450,7 @@
 
 int __system_property_add(const char* name, unsigned int namelen, const char* value,
                           unsigned int valuelen) {
-  if (valuelen >= PROP_VALUE_MAX) {
+  if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) {
     return -1;
   }
 
diff --git a/libc/bionic/wcstod.cpp b/libc/bionic/wcstod.cpp
index 41df854..41a94fb 100644
--- a/libc/bionic/wcstod.cpp
+++ b/libc/bionic/wcstod.cpp
@@ -31,6 +31,7 @@
 #include <wchar.h>
 
 #include <stdlib.h>
+#include <string.h>
 
 #include "local.h"
 
diff --git a/libc/include/android/legacy_sys_mman_inlines.h b/libc/include/android/legacy_sys_mman_inlines.h
new file mode 100644
index 0000000..7eb537e
--- /dev/null
+++ b/libc/include/android/legacy_sys_mman_inlines.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 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
+
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#if __ANDROID_API__ < __ANDROID_API_L__
+
+__BEGIN_DECLS
+
+/*
+ * While this was never an inline, this function alone has caused most of the
+ * bug reports related to _FILE_OFFSET_BITS=64. Providing an inline for it
+ * should allow a lot more code to build with _FILE_OFFSET_BITS=64 when
+ * targeting pre-L.
+ */
+static __inline void* mmap64(void* __addr, size_t __size, int __prot, int __flags, int __fd,
+                             off64_t __offset) __RENAME(mmap64);
+static __inline void* mmap64(void* __addr, size_t __size, int __prot, int __flags, int __fd,
+                             off64_t __offset) {
+  const int __mmap2_shift = 12; // 2**12 == 4096
+  if (__offset < 0 || (__offset & ((1UL << __mmap2_shift) - 1)) != 0) {
+    errno = EINVAL;
+    return MAP_FAILED;
+  }
+
+  // prevent allocations large enough for `end - start` to overflow
+  size_t __rounded = __BIONIC_ALIGN(__size, PAGE_SIZE);
+  if (__rounded < __size || __rounded > PTRDIFF_MAX) {
+    errno = ENOMEM;
+    return MAP_FAILED;
+  }
+
+  extern void* __mmap2(void* __addr, size_t __size, int __prot, int __flags, int __fd,
+                       size_t __offset);
+  return __mmap2(__addr, __size, __prot, __flags, __fd, __offset >> __mmap2_shift);
+}
+
+__END_DECLS
+
+#endif  /* __ANDROID_API__ < __ANDROID_API_L__ */
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 063b51d..3656733 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -79,6 +79,8 @@
 #define __BIONIC_CAST(_k,_t,_v) ((_t) (_v))
 #endif
 
+#define __BIONIC_ALIGN(__value, __alignment) (((__value) + (__alignment)-1) & ~((__alignment)-1))
+
 /*
  * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
  * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 1e752c4..028b024 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -45,12 +45,30 @@
 #define MREMAP_FIXED    2
 
 #if defined(__USE_FILE_OFFSET64)
-void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset) __RENAME(mmap64) __INTRODUCED_IN(21);
+/*
+ * mmap64 wasn't really around until L, but we added an inline for it since it
+ * allows a lot more code to compile with _FILE_OFFSET_BITS=64.
+ *
+ * GCC removes the static inline unless it is explicitly used. We can get around
+ * this with __attribute__((used)), but that needlessly adds a definition of
+ * mmap64 to every translation unit that includes this header. Instead, just
+ * preserve the old behavior for GCC and emit a useful diagnostic.
+ */
+void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset)
+#if !defined(__clang__) && __ANDROID_API__ < __ANDROID_API_L__
+    __attribute__((error("mmap is not available with _FILE_OFFSET_BITS=64 when using GCC until "
+                         "android-21. Either raise your minSdkVersion, disable "
+                         "_FILE_OFFSET_BITS=64, or switch to Clang.")));
+#else
+    __RENAME(mmap64);
+#endif  /* defined(__clang__) */
 #else
 void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset);
-#endif
+#endif  /* defined(__USE_FILE_OFFSET64) */
 
+#if __ANDROID_API__ >= __ANDROID_API_L__
 void* mmap64(void* __addr, size_t __size, int __prot, int __flags, int __fd, off64_t __offset) __INTRODUCED_IN(21);
+#endif
 
 int munmap(void* __addr, size_t __size);
 int msync(void* __addr, size_t __size, int __flags);
@@ -86,4 +104,6 @@
 
 __END_DECLS
 
+#include <android/legacy_sys_mman_inlines.h>
+
 #endif
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index 65ae6fa..d597280 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -53,7 +53,7 @@
     : OptionData(debug_data) {
   size_t hdr_len = sizeof(BacktraceHeader) + sizeof(uintptr_t) * config.backtrace_frames();
   alloc_offset_ = *offset;
-  *offset += BIONIC_ALIGN(hdr_len, MINIMUM_ALIGNMENT_BYTES);
+  *offset += __BIONIC_ALIGN(hdr_len, MINIMUM_ALIGNMENT_BYTES);
 }
 
 bool BacktraceData::Initialize(const Config& config) {
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index e3798ab..3cecf9b 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -191,7 +191,7 @@
 
   // It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
   // make sure that the header is aligned properly.
-  front_guard_bytes_ = BIONIC_ALIGN(rear_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
+  front_guard_bytes_ = __BIONIC_ALIGN(rear_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
   return true;
 }
 
@@ -201,7 +201,7 @@
   }
   // It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
   // make sure that the header is aligned properly.
-  front_guard_bytes_ = BIONIC_ALIGN(front_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
+  front_guard_bytes_ = __BIONIC_ALIGN(front_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
   return true;
 }
 
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp
index e9974d7..d6ca998 100644
--- a/libc/malloc_debug/DebugData.cpp
+++ b/libc/malloc_debug/DebugData.cpp
@@ -47,7 +47,7 @@
     need_header_ = true;
 
     // Initialize all of the static header offsets.
-    pointer_offset_ = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
+    pointer_offset_ = __BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
 
     if (config_.options() & BACKTRACE) {
       backtrace.reset(new BacktraceData(this, config_, &pointer_offset_));
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index d890a1c..a2ada2f 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -767,7 +767,7 @@
   }
 
   size_t pagesize = getpagesize();
-  size_t size = BIONIC_ALIGN(bytes, pagesize);
+  size_t size = __BIONIC_ALIGN(bytes, pagesize);
   if (size < bytes) {
     // Overflow
     errno = ENOMEM;
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 37d8057..d7ba379 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -74,9 +74,10 @@
 constexpr uint32_t BACKTRACE_HEADER = 0x1;
 
 static size_t get_tag_offset(uint32_t flags = 0, size_t backtrace_frames = 0) {
-  size_t offset = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
+  size_t offset = __BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
   if (flags & BACKTRACE_HEADER) {
-    offset += BIONIC_ALIGN(sizeof(BacktraceHeader) + sizeof(uintptr_t) * backtrace_frames, MINIMUM_ALIGNMENT_BYTES);
+    offset += __BIONIC_ALIGN(sizeof(BacktraceHeader) + sizeof(uintptr_t) * backtrace_frames,
+                             MINIMUM_ALIGNMENT_BYTES);
   }
   return offset;
 }
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index b1dfc7f..c0df917 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -40,9 +40,6 @@
   TypeName() = delete;                           \
   DISALLOW_COPY_AND_ASSIGN(TypeName)
 
-#define BIONIC_ALIGN(value, alignment) \
-  (((value) + (alignment) - 1) & ~((alignment) - 1))
-
 #define BIONIC_ROUND_UP_POWER_OF_2(value) \
   ((sizeof(value) == 8) \
     ? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 852b9ae..de086f2 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -102,7 +102,7 @@
   passwd_state_t passwd;
 };
 
-#define BIONIC_TLS_SIZE (BIONIC_ALIGN(sizeof(bionic_tls), PAGE_SIZE))
+#define BIONIC_TLS_SIZE (__BIONIC_ALIGN(sizeof(bionic_tls), PAGE_SIZE))
 
 /*
  * Bionic uses some pthread keys internally. All pthread keys used internally
diff --git a/libc/tzcode/bionic.cpp b/libc/tzcode/bionic.cpp
index b486174..9b59183 100644
--- a/libc/tzcode/bionic.cpp
+++ b/libc/tzcode/bionic.cpp
@@ -27,6 +27,7 @@
  */
 
 #include <arpa/inet.h> // For ntohl(3).
+#include <errno.h>
 #include <fcntl.h>
 #include <stdint.h>
 #include <stdlib.h>
diff --git a/libc/upstream-openbsd/android/include/arc4random.h b/libc/upstream-openbsd/android/include/arc4random.h
index 4c4be0e..afa8d14 100644
--- a/libc/upstream-openbsd/android/include/arc4random.h
+++ b/libc/upstream-openbsd/android/include/arc4random.h
@@ -22,10 +22,10 @@
  * Stub functions for portability.
  */
 
-#include <sys/mman.h>
-
+#include <errno.h>
 #include <pthread.h>
 #include <signal.h>
+#include <sys/mman.h>
 
 #include <async_safe/log.h>
 
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index 9c16828..7fc6cbf 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -29,6 +29,7 @@
 #ifndef __LINKER_ALLOCATOR_H
 #define __LINKER_ALLOCATOR_H
 
+#include <errno.h>
 #include <stdlib.h>
 #include <sys/cdefs.h>
 #include <sys/mman.h>
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 0dc54d0..7028ca7 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -1635,6 +1635,7 @@
 
   uintptr_t addr_start = 0;
   uintptr_t addr_end = 0;
+  bool has_executable_segment = false;
   std::vector<map_record> maps_to_copy;
 
   for (const auto& rec : maps) {
@@ -1643,6 +1644,7 @@
         addr_start = rec.addr_start;
       }
       addr_end = rec.addr_end;
+      has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
 
       maps_to_copy.push_back(rec);
     }
@@ -1655,6 +1657,16 @@
   ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
   ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
 
+  if (!has_executable_segment) {
+    // For some natively bridged environments this code might be missing
+    // the executable flag. This is because the guest code is not supposed
+    // to be executed directly and making it non-executable is more secure.
+    // If this is the case we assume that the first segment is the one that
+    // has this flag.
+    ASSERT_TRUE((maps_to_copy[0].perms & PROT_WRITE) == 0);
+    maps_to_copy[0].perms |= PROT_EXEC;
+  }
+
   // copy
   uintptr_t reserved_addr = reinterpret_cast<uintptr_t>(mmap(nullptr, addr_end - addr_start,
                                                              PROT_NONE, MAP_ANON | MAP_PRIVATE,
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 66ea0f9..adc5ee4 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -21,6 +21,9 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>
+#if __has_include(<sys/auxv.h>)
+#include <sys/auxv.h>
+#endif
 
 #include <string>
 #include <thread>
@@ -246,6 +249,12 @@
 }
 
 TEST(dlfcn, dlopen_vdso) {
+#if __has_include(<sys/auxv.h>)
+  if (getauxval(AT_SYSINFO_EHDR) == 0) {
+    GTEST_LOG_(INFO) << "getauxval(AT_SYSINFO_EHDR) == 0, skipping this test.";
+    return;
+  }
+#endif
   void* handle = dlopen("linux-vdso.so.1", RTLD_NOW);
   ASSERT_TRUE(handle != nullptr) << dlerror();
   dlclose(handle);
diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp
index 7e78830..cb00c3a 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -207,7 +207,7 @@
 }
 
 TEST(fcntl, tee) {
-  char expected[256];
+  char expected[BUFSIZ];
   FILE* expected_fp = fopen("/proc/version", "r");
   ASSERT_TRUE(expected_fp != NULL);
   ASSERT_TRUE(fgets(expected, sizeof(expected), expected_fp) != NULL);
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index 7415b3c..69647bf 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -24,6 +24,8 @@
 #include <string>
 #include <thread>
 
+using namespace std::literals;
+
 #if defined(__BIONIC__)
 
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
@@ -452,3 +454,89 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
+
+TEST(properties, __system_property_extra_long_read_only) {
+#if defined(__BIONIC__)
+  LocalPropertyTestState pa;
+  ASSERT_TRUE(pa.valid);
+
+  std::vector<std::pair<std::string, std::string>> short_properties = {
+    { "ro.0char", std::string() },
+    { "ro.50char", std::string(50, 'x') },
+    { "ro.91char", std::string(91, 'x') },
+  };
+
+  std::vector<std::pair<std::string, std::string>> long_properties = {
+    { "ro.92char", std::string(92, 'x') },
+    { "ro.93char", std::string(93, 'x') },
+    { "ro.1000char", std::string(1000, 'x') },
+  };
+
+  for (const auto& property : short_properties) {
+    const std::string& name = property.first;
+    const std::string& value = property.second;
+    ASSERT_EQ(0, __system_property_add(name.c_str(), name.size(), value.c_str(), value.size()));
+  }
+
+  for (const auto& property : long_properties) {
+    const std::string& name = property.first;
+    const std::string& value = property.second;
+    ASSERT_EQ(0, __system_property_add(name.c_str(), name.size(), value.c_str(), value.size()));
+  }
+
+  auto check_with_legacy_read = [](const std::string& name, const std::string& expected_value) {
+    char value[PROP_VALUE_MAX];
+    EXPECT_EQ(static_cast<int>(expected_value.size()), __system_property_get(name.c_str(), value))
+        << name;
+    EXPECT_EQ(expected_value, value) << name;
+  };
+
+  auto check_with_read_callback = [](const std::string& name, const std::string& expected_value) {
+    const prop_info* pi = __system_property_find(name.c_str());
+    ASSERT_NE(nullptr, pi);
+    std::string value;
+    __system_property_read_callback(pi,
+                                    [](void* cookie, const char*, const char* value, uint32_t) {
+                                      std::string* out_value =
+                                          reinterpret_cast<std::string*>(cookie);
+                                      *out_value = value;
+                                    },
+                                    &value);
+    EXPECT_EQ(expected_value, value) << name;
+  };
+
+  for (const auto& property : short_properties) {
+    const std::string& name = property.first;
+    const std::string& value = property.second;
+    check_with_legacy_read(name, value);
+    check_with_read_callback(name, value);
+  }
+
+  constexpr static const char* kExtraLongLegacyError =
+      "Must use __system_property_read_callback() to read";
+  for (const auto& property : long_properties) {
+    const std::string& name = property.first;
+    const std::string& value = property.second;
+    check_with_legacy_read(name, kExtraLongLegacyError);
+    check_with_read_callback(name, value);
+  }
+
+#else   // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif  // __BIONIC__
+}
+
+// pa_size is 128 * 1024 currently, if a property is longer then we expect it to fail gracefully.
+TEST(properties, __system_property_extra_long_read_only_too_long) {
+#if defined(__BIONIC__)
+  LocalPropertyTestState pa;
+  ASSERT_TRUE(pa.valid);
+
+  auto name = "ro.super_long_property"s;
+  auto value = std::string(128 * 1024 + 1, 'x');
+  ASSERT_NE(0, __system_property_add(name.c_str(), name.size(), value.c_str(), value.size()));
+
+#else   // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif  // __BIONIC__
+}