Merge "Add record_allocs_on_exit option." into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index de503e0..60a4f61 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -51,6 +51,9 @@
"name": "bionic-unit-tests"
},
{
+ "name": "bionic-unit-tests-static"
+ },
+ {
"name": "linker-unit-tests"
},
{
diff --git a/libc/Android.bp b/libc/Android.bp
index 943d41f..018b7c0 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1,5 +1,3 @@
-// Define the common source files for all the libc instances
-// =========================================================
package {
default_applicable_licenses: ["bionic_libc_license"],
}
@@ -114,6 +112,26 @@
tidy_disabled_srcs: ["upstream-*/**/*.c"],
}
+// Workaround for b/24465209.
+// We're unlikely to be able to remove this before we just
+// remove ILP32 support completely.
+// Note that we also still have `pack_relocations: false`
+// for both libc and libm, even on LP64.
+// ========================================================
+cc_defaults {
+ name: "bug_24465209_workaround",
+ target: {
+ android_arm: {
+ pack_relocations: false,
+ ldflags: ["-Wl,--hash-style=both"],
+ },
+ android_x86: {
+ pack_relocations: false,
+ ldflags: ["-Wl,--hash-style=both"],
+ }
+ },
+}
+
// Defaults for native allocator libs/includes to make it
// easier to change.
// ========================================================
@@ -1529,6 +1547,7 @@
defaults: [
"libc_defaults",
"libc_native_allocator_defaults",
+ "bug_24465209_workaround",
],
name: "libc_library_defaults",
product_variables: {
@@ -1586,10 +1605,7 @@
arch: {
arm: {
- // TODO: This is to work around b/24465209. Remove after root cause is fixed.
- pack_relocations: false,
ldflags: [
- "-Wl,--hash-style=both",
// Since we are preserving the debug_frame, do not compress
// in this case to make unwinds as fast as possible.
"-Wl,--compress-debug-sections=none",
@@ -1633,10 +1649,6 @@
},
},
x86: {
- // TODO: This is to work around b/24465209. Remove after root cause is fixed.
- pack_relocations: false,
- ldflags: ["-Wl,--hash-style=both"],
-
version_script: ":libc.x86.map",
no_libcrt: true,
@@ -1916,7 +1928,10 @@
// ========================================================
cc_library {
- defaults: ["libc_defaults"],
+ defaults: [
+ "libc_defaults",
+ "bug_24465209_workaround",
+ ],
include_dirs: ["bionic/libstdc++/include"],
srcs: [
"bionic/__cxa_guard.cpp",
@@ -1941,12 +1956,8 @@
},
},
- //TODO (dimitry): This is to work around b/24465209. Remove after root cause is fixed
arch: {
arm: {
- // TODO: This is to work around b/24465209. Remove after root cause is fixed.
- pack_relocations: false,
- ldflags: ["-Wl,--hash-style=both"],
version_script: ":libstdc++.arm.map",
},
arm64: {
@@ -1956,8 +1967,6 @@
version_script: ":libstdc++.riscv64.map",
},
x86: {
- pack_relocations: false,
- ldflags: ["-Wl,--hash-style=both"],
version_script: ":libstdc++.x86.map",
},
x86_64: {
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index cadab3c..066ec32 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -53,6 +53,8 @@
heap_tagging_level = __libc_shared_globals()->initial_heap_tagging_level;
#endif
+ __libc_memtag_stack_abi = __libc_shared_globals()->initial_memtag_stack_abi;
+
__libc_globals.mutate([](libc_globals* globals) {
switch (heap_tagging_level) {
case M_HEAP_TAGGING_LEVEL_TBI:
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index c82c52e..939e4e1 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -58,6 +58,7 @@
__LIBC_HIDDEN__ constinit WriteProtected<libc_globals> __libc_globals;
__LIBC_HIDDEN__ constinit _Atomic(bool) __libc_memtag_stack;
+__LIBC_HIDDEN__ constinit bool __libc_memtag_stack_abi;
// Not public, but well-known in the BSDs.
__BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 3da0a92..ac97376 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -289,11 +289,7 @@
// We can't short-circuit the environment override, as `stack` is still inherited from the
// binary's settings.
- if (get_environment_memtag_setting(&level)) {
- if (level == M_HEAP_TAGGING_LEVEL_NONE || level == M_HEAP_TAGGING_LEVEL_TBI) {
- *stack = false;
- }
- }
+ get_environment_memtag_setting(&level);
return level;
}
@@ -329,13 +325,14 @@
bool memtag_stack = false;
HeapTaggingLevel level =
__get_tagging_level(memtag_dynamic_entries, phdr_start, phdr_ct, load_bias, &memtag_stack);
- // This is used by the linker (in linker.cpp) to communicate than any library linked by this
- // executable enables memtag-stack.
- if (__libc_shared_globals()->initial_memtag_stack) {
- if (!memtag_stack) {
- async_safe_format_log(ANDROID_LOG_INFO, "libc", "enabling PROT_MTE as requested by linker");
- }
+ // initial_memtag_stack is used by the linker (in linker.cpp) to communicate than any library
+ // linked by this executable enables memtag-stack.
+ // memtag_stack is also set for static executables if they request memtag stack via the note,
+ // in which case it will differ from initial_memtag_stack.
+ if (__libc_shared_globals()->initial_memtag_stack || memtag_stack) {
memtag_stack = true;
+ __libc_shared_globals()->initial_memtag_stack_abi = true;
+ __get_bionic_tcb()->tls_slot(TLS_SLOT_STACK_MTE) = __allocate_stack_mte_ringbuffer(0, nullptr);
}
if (int64_t timed_upgrade = __get_memtag_upgrade_secs()) {
if (level == M_HEAP_TAGGING_LEVEL_ASYNC) {
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 5bd4f16..a8d09eb 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -65,6 +65,7 @@
}
void __init_bionic_tls_ptrs(bionic_tcb* tcb, bionic_tls* tls) {
+ tcb->thread()->bionic_tcb = tcb;
tcb->thread()->bionic_tls = tls;
tcb->tls_slot(TLS_SLOT_BIONIC_TLS) = tls;
}
@@ -443,6 +444,14 @@
ScopedReadLock locker(&g_thread_creation_lock);
+// This has to be done under g_thread_creation_lock or g_thread_list_lock to avoid racing with
+// __pthread_internal_remap_stack_with_mte.
+#ifdef __aarch64__
+ if (__libc_memtag_stack_abi) {
+ tcb->tls_slot(TLS_SLOT_STACK_MTE) = __allocate_stack_mte_ringbuffer(0, thread);
+ }
+#endif
+
sigset64_t block_all_mask;
sigfillset64(&block_all_mask);
__rt_sigprocmask(SIG_SETMASK, &block_all_mask, &thread->start_mask, sizeof(thread->start_mask));
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index 2342aff..3c8f9d5 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -33,10 +33,12 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/prctl.h>
#include <async_safe/log.h>
#include <bionic/reserved_signals.h>
+#include "bionic/tls_defines.h"
#include "private/ErrnoRestorer.h"
#include "private/ScopedRWLock.h"
#include "private/bionic_futex.h"
@@ -71,8 +73,21 @@
g_thread_list = thread->next;
}
}
+// N.B. that this is NOT the pagesize, but 4096. This is hardcoded in the codegen.
+// See
+// https://github.com/search?q=repo%3Allvm/llvm-project%20AArch64StackTagging%3A%3AinsertBaseTaggedPointer&type=code
+constexpr size_t kStackMteRingbufferSizeMultiplier = 4096;
static void __pthread_internal_free(pthread_internal_t* thread) {
+#ifdef __aarch64__
+ if (void* stack_mte_tls = thread->bionic_tcb->tls_slot(TLS_SLOT_STACK_MTE)) {
+ size_t size =
+ kStackMteRingbufferSizeMultiplier * (reinterpret_cast<uintptr_t>(stack_mte_tls) >> 56ULL);
+ void* ptr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(stack_mte_tls) &
+ ((1ULL << 56ULL) - 1ULL));
+ munmap(ptr, size);
+ }
+#endif
if (thread->mmap_size != 0) {
// Free mapped space, including thread stack and pthread_internal_t.
munmap(thread->mmap_base, thread->mmap_size);
@@ -176,12 +191,70 @@
async_safe_fatal("stack not found in /proc/self/maps");
}
+__LIBC_HIDDEN__ void* __allocate_stack_mte_ringbuffer(size_t n, pthread_internal_t* thread) {
+ if (n > 7) async_safe_fatal("error: invalid mte stack ring buffer size");
+ // Allocation needs to be aligned to 2*size to make the fancy code-gen work.
+ // So we allocate 3*size - pagesz bytes, which will always contain size bytes
+ // aligned to 2*size, and unmap the unneeded part.
+ // See
+ // https://github.com/search?q=repo%3Allvm/llvm-project%20AArch64StackTagging%3A%3AinsertBaseTaggedPointer&type=code
+ //
+ // In the worst case, we get an allocation that is one page past the properly
+ // aligned address, in which case we have to unmap the previous
+ // 2*size - pagesz bytes. In that case, we still have size properly aligned
+ // bytes left.
+ size_t size = (1 << n) * kStackMteRingbufferSizeMultiplier;
+ size_t pgsize = page_size();
+
+ size_t alloc_size = __BIONIC_ALIGN(3 * size - pgsize, pgsize);
+ void* allocation_ptr =
+ mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (allocation_ptr == MAP_FAILED)
+ async_safe_fatal("error: failed to allocate stack mte ring buffer");
+ uintptr_t allocation = reinterpret_cast<uintptr_t>(allocation_ptr);
+
+ size_t alignment = 2 * size;
+ uintptr_t aligned_allocation = __BIONIC_ALIGN(allocation, alignment);
+ if (allocation != aligned_allocation) {
+ munmap(reinterpret_cast<void*>(allocation), aligned_allocation - allocation);
+ }
+ if (aligned_allocation + size != allocation + alloc_size) {
+ munmap(reinterpret_cast<void*>(aligned_allocation + size),
+ (allocation + alloc_size) - (aligned_allocation + size));
+ }
+
+ const char* name;
+ if (thread == nullptr) {
+ name = "stack_mte_ring:main";
+ } else {
+ // The kernel doesn't copy the name string, but this variable will last at least as long as the
+ // mapped area. We unmap the ring buffer before unmapping the rest of the thread storage.
+ auto& name_buffer = thread->stack_mte_ringbuffer_vma_name_buffer;
+ static_assert(arraysize(name_buffer) >= arraysize("stack_mte_ring:") + 11 + 1);
+ async_safe_format_buffer(name_buffer, arraysize(name_buffer), "stack_mte_ring:%d", thread->tid);
+ name = name_buffer;
+ }
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, reinterpret_cast<void*>(aligned_allocation), size, name);
+
+ // We store the size in the top byte of the pointer (which is ignored)
+ return reinterpret_cast<void*>(aligned_allocation | ((1ULL << n) << 56ULL));
+}
+
void __pthread_internal_remap_stack_with_mte() {
#if defined(__aarch64__)
- // If process doesn't have MTE enabled, we don't need to do anything.
+ ScopedWriteLock creation_locker(&g_thread_creation_lock);
+ ScopedReadLock list_locker(&g_thread_list_lock);
+ // If process already uses memtag-stack ABI, we don't need to do anything.
+ if (__libc_memtag_stack_abi) return;
+ __libc_memtag_stack_abi = true;
+
+ for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) {
+ if (t->terminating) continue;
+ t->bionic_tcb->tls_slot(TLS_SLOT_STACK_MTE) =
+ __allocate_stack_mte_ringbuffer(0, t->is_main() ? nullptr : t);
+ }
if (!atomic_load(&__libc_globals->memtag)) return;
- bool prev = atomic_exchange(&__libc_memtag_stack, true);
- if (prev) return;
+ if (atomic_exchange(&__libc_memtag_stack, true)) return;
uintptr_t lo, hi;
__find_main_stack_limits(&lo, &hi);
@@ -189,8 +262,6 @@
PROT_READ | PROT_WRITE | PROT_MTE | PROT_GROWSDOWN)) {
async_safe_fatal("error: failed to set PROT_MTE on main thread");
}
- ScopedWriteLock creation_locker(&g_thread_creation_lock);
- ScopedReadLock list_locker(&g_thread_list_lock);
for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) {
if (t->terminating || t->is_main()) continue;
if (mprotect(t->mmap_base_unguarded, t->mmap_size_unguarded,
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index c2abdea..765fd8b 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -178,6 +178,10 @@
bionic_tls* bionic_tls;
int errno_value;
+
+ bionic_tcb* bionic_tcb;
+ char stack_mte_ringbuffer_vma_name_buffer[32];
+
bool is_main() { return start_routine == nullptr; }
};
@@ -209,6 +213,7 @@
__LIBC_HIDDEN__ void __pthread_internal_remove(pthread_internal_t* thread);
__LIBC_HIDDEN__ void __pthread_internal_remove_and_free(pthread_internal_t* thread);
__LIBC_HIDDEN__ void __find_main_stack_limits(uintptr_t* low, uintptr_t* high);
+__LIBC_HIDDEN__ void* __allocate_stack_mte_ringbuffer(size_t n, pthread_internal_t* thread);
static inline __always_inline bionic_tcb* __get_bionic_tcb() {
return reinterpret_cast<bionic_tcb*>(&__get_tls()[MIN_TLS_SLOT]);
diff --git a/libc/include/netinet/igmp.h b/libc/include/netinet/igmp.h
new file mode 100644
index 0000000..497d02d
--- /dev/null
+++ b/libc/include/netinet/igmp.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 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
+
+/**
+ * @file netinet/igmp.h
+ * @brief Internet Group Management Protocol (IGMP).
+ */
+
+#include <sys/cdefs.h>
+#include <netinet/in.h>
+
+#include <linux/igmp.h>
+
+/**
+ * The uapi type is called `igmphdr`,
+ * doesn't have the `igmp_` prefix on each field,
+ * and uses a `__be32` for the group address.
+ *
+ * This is the type that BSDs and musl/glibc expose to userspace.
+ */
+struct igmp {
+ uint8_t igmp_type;
+ uint8_t igmp_code;
+ uint16_t igmp_cksum;
+ struct in_addr igmp_group;
+};
+
+/** Commonly-used BSD synonym for the Linux constant. */
+#define IGMP_MEMBERSHIP_QUERY IGMP_HOST_MEMBERSHIP_QUERY
diff --git a/libc/include/sys/io.h b/libc/include/sys/io.h
new file mode 100644
index 0000000..d187b78
--- /dev/null
+++ b/libc/include/sys/io.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 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
+
+/**
+ * @file sys/io.h
+ * @brief The x86/x86-64 I/O port functions iopl() and ioperm().
+ */
+
+#include <sys/cdefs.h>
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+__BEGIN_DECLS
+
+/**
+ * [iopl(2)](http://man7.org/linux/man-pages/man2/iopl.2.html) changes the I/O
+ * privilege level for all x86/x8-64 I/O ports, for the calling thread.
+ *
+ * New callers should use ioperm() instead.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ *
+ * Only available for x86/x86-64.
+ */
+#if defined(__NR_iopl)
+__attribute__((__deprecated__("use ioperm() instead"))) static __inline int iopl(int __level) {
+ return syscall(__NR_iopl, __level);
+}
+#endif
+
+/**
+ * [ioperm(2)](http://man7.org/linux/man-pages/man2/ioperm.2.html) sets the I/O
+ * permissions for the given number of x86/x86-64 I/O ports, starting at the
+ * given port.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ *
+ * Only available for x86/x86-64.
+ */
+#if defined(__NR_iopl)
+static __inline int ioperm(unsigned long __from, unsigned long __n, int __enabled) {
+ return syscall(__NR_ioperm, __from, __n, __enabled);
+}
+#endif
+
+__END_DECLS
diff --git a/libc/platform/bionic/tls_defines.h b/libc/platform/bionic/tls_defines.h
index 8fe8701..06c6617 100644
--- a/libc/platform/bionic/tls_defines.h
+++ b/libc/platform/bionic/tls_defines.h
@@ -85,7 +85,8 @@
// [1] "Addenda to, and Errata in, the ABI for the ARM Architecture". Section 3.
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045e/IHI0045E_ABI_addenda.pdf
-#define MIN_TLS_SLOT (-2) // update this value when reserving a slot
+#define MIN_TLS_SLOT (-3) // update this value when reserving a slot
+#define TLS_SLOT_STACK_MTE (-3)
#define TLS_SLOT_NATIVE_BRIDGE_GUEST_STATE (-2)
#define TLS_SLOT_BIONIC_TLS (-1)
#define TLS_SLOT_DTV 0
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 0949056..a1bebda 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -76,10 +76,23 @@
};
__LIBC_HIDDEN__ extern WriteProtected<libc_globals> __libc_globals;
-// This cannot be in __libc_globals, because we cannot access the
+// These cannot be in __libc_globals, because we cannot access the
// WriteProtected in a thread-safe way.
// See b/328256432.
+//
+// __libc_memtag_stack says whether stack MTE is enabled on the process, i.e.
+// whether the stack pages are mapped with PROT_MTE. This is always false if
+// MTE is disabled for the process (i.e. libc_globals.memtag is false).
__LIBC_HIDDEN__ extern _Atomic(bool) __libc_memtag_stack;
+// __libc_memtag_stack_abi says whether the process contains any code that was
+// compiled with memtag-stack. This is true even if the process does not have
+// MTE enabled (e.g. because it was overridden using MEMTAG_OPTIONS, or because
+// MTE is disabled for the device).
+// Code compiled with memtag-stack needs a stack history buffer in
+// TLS_SLOT_STACK_MTE, because the codegen will emit an unconditional
+// (to keep the code branchless) write to it.
+// Protected by g_heap_creation_lock.
+__LIBC_HIDDEN__ extern bool __libc_memtag_stack_abi;
struct abort_msg_t;
struct crash_detail_page_t;
@@ -133,7 +146,9 @@
size_t scudo_stack_depot_size = 0;
HeapTaggingLevel initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
+ // See comments for __libc_memtag_stack / __libc_memtag_stack_abi above.
bool initial_memtag_stack = false;
+ bool initial_memtag_stack_abi = false;
int64_t heap_tagging_upgrade_timer_sec = 0;
void (*memtag_stack_dlopen_callback)() = nullptr;
diff --git a/libc/system_properties/Android.bp b/libc/system_properties/Android.bp
index d45a2e3..16ea73f 100644
--- a/libc/system_properties/Android.bp
+++ b/libc/system_properties/Android.bp
@@ -11,7 +11,10 @@
cc_library_static {
name: "libsystemproperties",
- defaults: ["libc_defaults"],
+ defaults: [
+ "libc_defaults",
+ "large_system_property_node_defaults",
+ ],
native_bridge_supported: true,
srcs: [
"context_node.cpp",
@@ -54,3 +57,28 @@
"libasync_safe",
],
}
+
+soong_config_module_type {
+ name: "large_system_property_node_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "bionic",
+ bool_variables: [
+ "large_system_property_node",
+ ],
+ properties: [
+ "cflags",
+ ],
+}
+
+soong_config_bool_variable {
+ name: "large_system_property_node",
+}
+
+large_system_property_node_cc_defaults {
+ name: "large_system_property_node_defaults",
+ soong_config_variables: {
+ large_system_property_node: {
+ cflags: ["-DLARGE_SYSTEM_PROPERTY_NODE=1"]
+ }
+ }
+}
diff --git a/libc/system_properties/prop_area.cpp b/libc/system_properties/prop_area.cpp
index 4668eed..a816a38 100644
--- a/libc/system_properties/prop_area.cpp
+++ b/libc/system_properties/prop_area.cpp
@@ -41,7 +41,11 @@
#include <async_safe/log.h>
+#ifdef LARGE_SYSTEM_PROPERTY_NODE
+constexpr size_t PA_SIZE = 1024 * 1024;
+#else
constexpr size_t PA_SIZE = 128 * 1024;
+#endif
constexpr uint32_t PROP_AREA_MAGIC = 0x504f5250;
constexpr uint32_t PROP_AREA_VERSION = 0xfc6ed0ab;
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 95b412b..f53d2d1 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -60,7 +60,10 @@
native_bridge_supported: true,
static_ndk_lib: true,
- defaults: ["linux_bionic_supported"],
+ defaults: [
+ "linux_bionic_supported",
+ "bug_24465209_workaround",
+ ],
// NOTE: --exclude-libs=libgcc.a makes sure that any symbols libdl.so pulls from
// libgcc.a are made static to libdl.so. This in turn ensures that libraries that
@@ -70,7 +73,6 @@
// libgcc.a it uses.
//
// DO NOT REMOVE --exclude-libs!
-
ldflags: [
"-Wl,--exclude-libs=libgcc.a",
"-Wl,--exclude-libs=libgcc_stripped.a",
@@ -81,12 +83,9 @@
"-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
],
- // for x86, exclude libgcc_eh.a for the same reasons as above
arch: {
arm: {
version_script: ":libdl.arm.map",
- pack_relocations: false,
- ldflags: ["-Wl,--hash-style=both"],
},
arm64: {
version_script: ":libdl.arm64.map",
@@ -95,14 +94,12 @@
version_script: ":libdl.riscv64.map",
},
x86: {
- pack_relocations: false,
- ldflags: [
- "-Wl,--exclude-libs=libgcc_eh.a",
- "-Wl,--hash-style=both",
- ],
+ // Exclude libgcc_eh.a for the same reasons as above
+ ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
version_script: ":libdl.x86.map",
},
x86_64: {
+ // Exclude libgcc_eh.a for the same reasons as above
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
version_script: ":libdl.x86_64.map",
},
diff --git a/libm/Android.bp b/libm/Android.bp
index cc37fb7..09d8535 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -21,7 +21,10 @@
cc_library {
name: "libm",
- defaults: ["linux_bionic_supported"],
+ defaults: [
+ "linux_bionic_supported",
+ "bug_24465209_workaround",
+ ],
ramdisk_available: true,
vendor_ramdisk_available: true,
recovery_available: true,
@@ -282,8 +285,6 @@
"upstream-freebsd/lib/msun/src/s_ceilf.c",
],
instruction_set: "arm",
- pack_relocations: false,
- ldflags: ["-Wl,--hash-style=both"],
version_script: ":libm.arm.map",
no_libcrt: true,
shared: {
@@ -368,11 +369,9 @@
"upstream-freebsd/lib/msun/src/s_truncf.c",
],
local_include_dirs: ["i387"],
- pack_relocations: false,
// The x86 ABI doesn't include this, which is needed for the
// roundss/roundsd instructions that we've used since Android M.
cflags: ["-msse4.1"],
- ldflags: ["-Wl,--hash-style=both"],
version_script: ":libm.x86.map",
},
diff --git a/linker/Android.bp b/linker/Android.bp
index 78109e8..ce5eff9 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -362,6 +362,7 @@
sanitize: {
hwaddress: false,
+ memtag_stack: false,
},
static_libs: [
diff --git a/tests/Android.bp b/tests/Android.bp
index 9aca488..9f64393 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -369,7 +369,10 @@
cc_test_library {
name: "libBionicStandardTests",
- defaults: ["bionic_tests_defaults"],
+ defaults: [
+ "bionic_tests_defaults",
+ "large_system_property_node_defaults",
+ ],
tidy_disabled_srcs: [
"malloc_test.cpp", // timed out with clang-tidy, and too many warnings
],
@@ -430,6 +433,7 @@
"netdb_test.cpp",
"net_if_test.cpp",
"netinet_ether_test.cpp",
+ "netinet_igmp_test.cpp",
"netinet_in_test.cpp",
"netinet_ip_icmp_test.cpp",
"netinet_udp_test.cpp",
@@ -474,6 +478,7 @@
"sys_cachectl_test.cpp",
"sys_epoll_test.cpp",
"sys_hwprobe_test.cpp",
+ "sys_io_test.cpp",
"sys_mman_test.cpp",
"sys_msg_test.cpp",
"sys_param_test.cpp",
diff --git a/tests/libs/testbinary_is_stack_mte.cpp b/tests/libs/testbinary_is_stack_mte.cpp
index d8074d5..0cdc466 100644
--- a/tests/libs/testbinary_is_stack_mte.cpp
+++ b/tests/libs/testbinary_is_stack_mte.cpp
@@ -36,7 +36,9 @@
#if defined(__BIONIC__) && defined(__aarch64__)
extern "C" int main(int, char**) {
- int ret = is_stack_mte_on() ? 0 : 1;
+ void* mte_tls_ptr = mte_tls();
+ *reinterpret_cast<uintptr_t*>(mte_tls_ptr) = 1;
+ int ret = is_stack_mte_on() && mte_tls_ptr != nullptr ? 0 : 1;
printf("RAN\n");
return ret;
}
diff --git a/tests/libs/testbinary_is_stack_mte_after_dlopen.cpp b/tests/libs/testbinary_is_stack_mte_after_dlopen.cpp
index 937ac4c..35af8f4 100644
--- a/tests/libs/testbinary_is_stack_mte_after_dlopen.cpp
+++ b/tests/libs/testbinary_is_stack_mte_after_dlopen.cpp
@@ -96,6 +96,7 @@
State state = kInit;
bool is_early_thread_mte_on = false;
+ void* early_thread_mte_tls = nullptr;
std::thread early_th([&] {
{
std::lock_guard lk(m);
@@ -107,6 +108,8 @@
cv.wait(lk, [&] { return state == kStackRemapped; });
}
is_early_thread_mte_on = is_stack_mte_on();
+ early_thread_mte_tls = mte_tls();
+ *reinterpret_cast<uintptr_t*>(early_thread_mte_tls) = 1;
});
{
std::unique_lock lk(m);
@@ -120,6 +123,7 @@
cv.notify_one();
CHECK(handle != nullptr);
CHECK(is_stack_mte_on());
+ CHECK(mte_tls() != nullptr);
bool new_stack_page_mte_on = false;
uintptr_t low;
@@ -129,11 +133,18 @@
CHECK(new_stack_page_mte_on);
bool is_late_thread_mte_on = false;
- std::thread late_th([&] { is_late_thread_mte_on = is_stack_mte_on(); });
+ void* late_thread_mte_tls = nullptr;
+ std::thread late_th([&] {
+ is_late_thread_mte_on = is_stack_mte_on();
+ late_thread_mte_tls = mte_tls();
+ *reinterpret_cast<uintptr_t*>(late_thread_mte_tls) = 1;
+ });
late_th.join();
early_th.join();
CHECK(is_late_thread_mte_on);
CHECK(is_early_thread_mte_on);
+ CHECK(late_thread_mte_tls != nullptr);
+ CHECK(early_thread_mte_tls != nullptr);
printf("RAN\n");
return 0;
}
diff --git a/tests/mte_utils.h b/tests/mte_utils.h
index 6e8385c..020faec 100644
--- a/tests/mte_utils.h
+++ b/tests/mte_utils.h
@@ -40,4 +40,10 @@
return p == p_cpy;
}
+static void* mte_tls() {
+ void** dst;
+ __asm__("mrs %0, TPIDR_EL0" : "=r"(dst) :);
+ return dst[-3];
+}
+
#endif
diff --git a/tests/netinet_igmp_test.cpp b/tests/netinet_igmp_test.cpp
new file mode 100644
index 0000000..4cf7876
--- /dev/null
+++ b/tests/netinet_igmp_test.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <netinet/igmp.h>
+
+TEST(netinet_igmp, smoke) {
+ // Just check that the fields exist, so code is likely to compile.
+ struct igmp i;
+ i.igmp_type = IGMP_MEMBERSHIP_QUERY;
+ i.igmp_code = 0;
+ i.igmp_cksum = 0;
+ i.igmp_group.s_addr = htonl(INADDR_ANY);
+}
diff --git a/tests/struct_layout_test.cpp b/tests/struct_layout_test.cpp
index 0123ed9..1f04344 100644
--- a/tests/struct_layout_test.cpp
+++ b/tests/struct_layout_test.cpp
@@ -30,7 +30,7 @@
#define CHECK_OFFSET(name, field, offset) \
check_offset(#name, #field, offsetof(name, field), offset);
#ifdef __LP64__
- CHECK_SIZE(pthread_internal_t, 776);
+ CHECK_SIZE(pthread_internal_t, 816);
CHECK_OFFSET(pthread_internal_t, next, 0);
CHECK_OFFSET(pthread_internal_t, prev, 8);
CHECK_OFFSET(pthread_internal_t, tid, 16);
@@ -55,6 +55,8 @@
CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 248);
CHECK_OFFSET(pthread_internal_t, bionic_tls, 760);
CHECK_OFFSET(pthread_internal_t, errno_value, 768);
+ CHECK_OFFSET(pthread_internal_t, bionic_tcb, 776);
+ CHECK_OFFSET(pthread_internal_t, stack_mte_ringbuffer_vma_name_buffer, 784);
CHECK_SIZE(bionic_tls, 12200);
CHECK_OFFSET(bionic_tls, key_data, 0);
CHECK_OFFSET(bionic_tls, locale, 2080);
@@ -72,7 +74,7 @@
CHECK_OFFSET(bionic_tls, bionic_systrace_disabled, 12193);
CHECK_OFFSET(bionic_tls, padding, 12194);
#else
- CHECK_SIZE(pthread_internal_t, 668);
+ CHECK_SIZE(pthread_internal_t, 704);
CHECK_OFFSET(pthread_internal_t, next, 0);
CHECK_OFFSET(pthread_internal_t, prev, 4);
CHECK_OFFSET(pthread_internal_t, tid, 8);
@@ -97,6 +99,8 @@
CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 148);
CHECK_OFFSET(pthread_internal_t, bionic_tls, 660);
CHECK_OFFSET(pthread_internal_t, errno_value, 664);
+ CHECK_OFFSET(pthread_internal_t, bionic_tcb, 668);
+ CHECK_OFFSET(pthread_internal_t, stack_mte_ringbuffer_vma_name_buffer, 672);
CHECK_SIZE(bionic_tls, 11080);
CHECK_OFFSET(bionic_tls, key_data, 0);
CHECK_OFFSET(bionic_tls, locale, 1040);
diff --git a/tests/sys_io_test.cpp b/tests/sys_io_test.cpp
new file mode 100644
index 0000000..293ceb2
--- /dev/null
+++ b/tests/sys_io_test.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <sys/io.h>
+
+#include "utils.h"
+
+TEST(sys_io, iopl) {
+#if defined(__i386__) || defined(__x86_64__)
+ errno = 0;
+ ASSERT_EQ(-1, iopl(4));
+ ASSERT_ERRNO(EINVAL);
+#else
+ GTEST_SKIP() << "iopl requires x86/x86-64";
+#endif
+}
+
+TEST(sys_io, ioperm) {
+#if defined(__i386__) || defined(__x86_64__)
+ errno = 0;
+ ASSERT_EQ(-1, ioperm(65535, 4, 0));
+ ASSERT_ERRNO(EINVAL);
+#else
+ GTEST_SKIP() << "ioperm requires x86/x86-64";
+#endif
+}
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index 0b7f5ae..f11f509 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -593,7 +593,13 @@
ASSERT_TRUE(system_properties.valid());
auto name = "ro.super_long_property"s;
+
+#ifdef LARGE_SYSTEM_PROPERTY_NODE
+ auto value = std::string(1024 * 1024 + 1, 'x');
+#else
auto value = std::string(128 * 1024 + 1, 'x');
+#endif
+
ASSERT_NE(0, system_properties.Add(name.c_str(), name.size(), value.c_str(), value.size()));
#else // __BIONIC__