aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/Android.bp46
-rw-r--r--libc/bionic/gwp_asan_wrappers.cpp12
-rw-r--r--libc/bionic/heap_tagging.cpp9
-rw-r--r--libc/bionic/libc_init_static.cpp50
-rw-r--r--libc/bionic/sys_statvfs.cpp2
-rw-r--r--libc/dns/resolv/res_cache.c22
-rw-r--r--libc/include/android/api-level.h7
-rw-r--r--libc/include/android/dlext.h11
-rw-r--r--libc/include/android/legacy_stdlib_inlines.h6
-rw-r--r--libc/include/android/legacy_termios_inlines.h4
-rw-r--r--libc/include/android/legacy_threads_inlines.h2
-rw-r--r--libc/include/android/legacy_unistd_inlines.h2
-rw-r--r--libc/include/android/versioning.h14
-rw-r--r--libc/include/bits/stdatomic.h12
-rw-r--r--libc/include/bits/swab.h2
-rw-r--r--libc/include/bits/termios_inlines.h4
-rw-r--r--libc/include/bits/termios_winsize_inlines.h2
-rw-r--r--libc/include/bits/threads_inlines.h2
-rw-r--r--libc/include/ctype.h2
-rw-r--r--libc/include/link.h67
-rw-r--r--libc/include/stdio.h2
-rw-r--r--libc/include/strings.h6
-rw-r--r--libc/include/sys/cdefs.h4
-rw-r--r--libc/include/sys/system_properties.h56
-rwxr-xr-xlibc/kernel/tools/cpp.py4
-rw-r--r--libc/platform/bionic/malloc.h73
-rw-r--r--libc/system_properties/system_properties.cpp21
-rw-r--r--linker/linker_crt_pad_segment_test.cpp9
-rw-r--r--linker/linker_main.cpp17
-rw-r--r--linker/linker_phdr.cpp62
-rw-r--r--linker/linker_phdr.h2
-rw-r--r--tests/clang_fortify_tests.cpp8
-rw-r--r--tests/malloc_test.cpp6
-rw-r--r--tests/setjmp_test.cpp26
-rw-r--r--tests/stack_protector_test.cpp2
35 files changed, 363 insertions, 213 deletions
diff --git a/libc/Android.bp b/libc/Android.bp
index 84fa498d3..2efca6855 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -55,7 +55,9 @@ libc_common_flags = [
cc_defaults {
name: "libc_defaults",
defaults: ["linux_bionic_supported"],
- cflags: libc_common_flags,
+ cflags: libc_common_flags + [
+ "-DUSE_SCUDO",
+ ],
asflags: libc_common_flags,
conlyflags: ["-std=gnu99"],
cppflags: [],
@@ -98,8 +100,8 @@ cc_defaults {
malloc_pattern_fill_contents: {
cflags: ["-DSCUDO_PATTERN_FILL_CONTENTS"],
},
- malloc_not_svelte: {
- cflags: ["-DUSE_SCUDO"],
+ malloc_low_memory: {
+ cflags: ["-UUSE_SCUDO"],
},
},
@@ -112,32 +114,31 @@ cc_defaults {
tidy_disabled_srcs: ["upstream-*/**/*.c"],
}
-libc_scudo_product_variables = {
- malloc_not_svelte: {
- cflags: ["-DUSE_SCUDO"],
- whole_static_libs: ["libscudo"],
- exclude_static_libs: [
- "libjemalloc5",
- "libc_jemalloc_wrapper",
- ],
- },
-}
-
// Defaults for native allocator libs/includes to make it
// easier to change.
-// To disable scudo for the non-svelte config remove the line:
-// product_variables: libc_scudo_product_variables,
-// in the cc_defaults below.
// ========================================================
cc_defaults {
name: "libc_native_allocator_defaults",
whole_static_libs: [
- "libjemalloc5",
- "libc_jemalloc_wrapper",
+ "libscudo",
+ ],
+ cflags: [
+ "-DUSE_SCUDO",
],
header_libs: ["gwp_asan_headers"],
- product_variables: libc_scudo_product_variables,
+ product_variables: {
+ malloc_low_memory: {
+ cflags: ["-UUSE_SCUDO"],
+ whole_static_libs: [
+ "libjemalloc5",
+ "libc_jemalloc_wrapper",
+ ],
+ exclude_static_libs: [
+ "libscudo",
+ ],
+ },
+ },
}
// Functions not implemented by jemalloc directly, or that need to
@@ -2990,3 +2991,8 @@ filegroup {
name: "versioner-dependencies",
srcs: ["versioner-dependencies/**/*"],
}
+
+filegroup {
+ name: "linux_capability_header",
+ srcs: ["kernel/uapi/linux/capability.h"],
+}
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 11f7cedd2..2124f515d 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -57,7 +57,7 @@
static gwp_asan::GuardedPoolAllocator GuardedAlloc;
static const MallocDispatch* prev_dispatch;
-using Action = android_mallopt_gwp_asan_options_t::Action;
+using Mode = android_mallopt_gwp_asan_options_t::Mode;
using Options = gwp_asan::options::Options;
// basename() is a mess, see the manpage. Let's be explicit what handling we
@@ -261,8 +261,8 @@ void SetDefaultGwpAsanOptions(Options* options, unsigned* process_sample_rate,
options->Recoverable = true;
GwpAsanRecoverable = true;
- if (mallopt_options.desire == Action::TURN_ON_WITH_SAMPLING ||
- mallopt_options.desire == Action::TURN_ON_FOR_APP_SAMPLED_NON_CRASHING) {
+ if (mallopt_options.mode == Mode::SYSTEM_PROCESS_OR_SYSTEM_APP ||
+ mallopt_options.mode == Mode::APP_MANIFEST_DEFAULT) {
*process_sample_rate = kDefaultProcessSampling;
} else {
*process_sample_rate = 1;
@@ -285,7 +285,7 @@ bool GetGwpAsanOptionImpl(char* value_out,
// be used. Tests still continue to use the environment variable though.
if (*basename != '\0') {
const char* default_sysprop = system_sysprop;
- if (mallopt_options.desire == Action::TURN_ON_FOR_APP) {
+ if (mallopt_options.mode == Mode::APP_MANIFEST_ALWAYS) {
default_sysprop = app_sysprop;
}
async_safe_format_buffer(&program_specific_sysprop[0], kSyspropMaxLen, "%s%s",
@@ -425,7 +425,7 @@ bool MaybeInitGwpAsan(libc_globals* globals,
Options options;
unsigned process_sample_rate = kDefaultProcessSampling;
if (!GetGwpAsanOptions(&options, &process_sample_rate, mallopt_options) &&
- mallopt_options.desire == Action::DONT_TURN_ON_UNLESS_OVERRIDDEN) {
+ mallopt_options.mode == Mode::APP_MANIFEST_NEVER) {
return false;
}
@@ -492,7 +492,7 @@ bool MaybeInitGwpAsanFromLibc(libc_globals* globals) {
android_mallopt_gwp_asan_options_t mallopt_options;
mallopt_options.program_name = progname;
- mallopt_options.desire = Action::TURN_ON_WITH_SAMPLING;
+ mallopt_options.mode = Mode::SYSTEM_PROCESS_OR_SYSTEM_APP;
return MaybeInitGwpAsan(globals, mallopt_options);
}
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index 4d1981c30..c8a025f57 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -38,6 +38,11 @@
extern "C" void scudo_malloc_disable_memory_tagging();
extern "C" void scudo_malloc_set_track_allocation_stacks(int);
+extern "C" const char* __scudo_get_stack_depot_addr();
+extern "C" const char* __scudo_get_ring_buffer_addr();
+extern "C" size_t __scudo_get_ring_buffer_size();
+extern "C" size_t __scudo_get_stack_depot_size();
+
// Protected by `g_heap_tagging_lock`.
static HeapTaggingLevel heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
@@ -158,6 +163,10 @@ bool SetHeapTaggingLevel(HeapTaggingLevel tag_level) {
set_tcf_on_all_threads(PR_MTE_TCF_SYNC);
#if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
scudo_malloc_set_track_allocation_stacks(1);
+ __libc_shared_globals()->scudo_ring_buffer = __scudo_get_ring_buffer_addr();
+ __libc_shared_globals()->scudo_ring_buffer_size = __scudo_get_ring_buffer_size();
+ __libc_shared_globals()->scudo_stack_depot = __scudo_get_stack_depot_addr();
+ __libc_shared_globals()->scudo_stack_depot_size = __scudo_get_stack_depot_size();
#endif
}
break;
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index d86df3093..3da0a92d3 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -297,6 +297,30 @@ static HeapTaggingLevel __get_tagging_level(const memtag_dynamic_entries_t* memt
return level;
}
+static int64_t __get_memtag_upgrade_secs() {
+ char* env = getenv("BIONIC_MEMTAG_UPGRADE_SECS");
+ if (!env) return 0;
+ int64_t timed_upgrade = 0;
+ static const char kAppProcessName[] = "app_process64";
+ const char* progname = __libc_shared_globals()->init_progname;
+ progname = progname ? __gnu_basename(progname) : nullptr;
+ // disable timed upgrade for zygote, as the thread spawned will violate the requirement
+ // that it be single-threaded.
+ if (!progname || strncmp(progname, kAppProcessName, sizeof(kAppProcessName)) != 0) {
+ char* endptr;
+ timed_upgrade = strtoll(env, &endptr, 10);
+ if (*endptr != '\0' || timed_upgrade < 0) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "Invalid value for BIONIC_MEMTAG_UPGRADE_SECS: %s", env);
+ timed_upgrade = 0;
+ }
+ }
+ // Make sure that this does not get passed to potential processes inheriting
+ // this environment.
+ unsetenv("BIONIC_MEMTAG_UPGRADE_SECS");
+ return timed_upgrade;
+}
+
// Figure out the desired memory tagging mode (sync/async, heap/globals/stack) for this executable.
// This function is called from the linker before the main executable is relocated.
__attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(
@@ -313,31 +337,7 @@ __attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(
}
memtag_stack = true;
}
- char* env = getenv("BIONIC_MEMTAG_UPGRADE_SECS");
- static const char kAppProcessName[] = "app_process64";
- const char* progname = __libc_shared_globals()->init_progname;
- progname = progname ? __gnu_basename(progname) : nullptr;
- if (progname &&
- strncmp(progname, kAppProcessName, sizeof(kAppProcessName)) == 0) {
- // disable timed upgrade for zygote, as the thread spawned will violate the requirement
- // that it be single-threaded.
- env = nullptr;
- }
- int64_t timed_upgrade = 0;
- if (env) {
- char* endptr;
- timed_upgrade = strtoll(env, &endptr, 10);
- if (*endptr != '\0' || timed_upgrade < 0) {
- async_safe_format_log(ANDROID_LOG_ERROR, "libc",
- "Invalid value for BIONIC_MEMTAG_UPGRADE_SECS: %s",
- env);
- timed_upgrade = 0;
- }
- // Make sure that this does not get passed to potential processes inheriting
- // this environment.
- unsetenv("BIONIC_MEMTAG_UPGRADE_SECS");
- }
- if (timed_upgrade) {
+ if (int64_t timed_upgrade = __get_memtag_upgrade_secs()) {
if (level == M_HEAP_TAGGING_LEVEL_ASYNC) {
async_safe_format_log(ANDROID_LOG_INFO, "libc",
"Attempting timed MTE upgrade from async to sync.");
diff --git a/libc/bionic/sys_statvfs.cpp b/libc/bionic/sys_statvfs.cpp
index 3a05c3fa6..b3a0aca0c 100644
--- a/libc/bionic/sys_statvfs.cpp
+++ b/libc/bionic/sys_statvfs.cpp
@@ -17,7 +17,7 @@
#include <sys/statfs.h>
#include <sys/statvfs.h>
-static inline void __bionic_statfs_to_statvfs(const struct statfs* src, struct statvfs* dst) {
+static __inline void __bionic_statfs_to_statvfs(const struct statfs* src, struct statvfs* dst) {
dst->f_bsize = src->f_bsize;
dst->f_frsize = src->f_frsize;
dst->f_blocks = src->f_blocks;
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index d6416e5c5..38de84b5f 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -1166,23 +1166,19 @@ entry_free( Entry* e )
}
}
-static inline void
-entry_mru_remove( Entry* e )
-{
- e->mru_prev->mru_next = e->mru_next;
- e->mru_next->mru_prev = e->mru_prev;
+static __inline__ void entry_mru_remove(Entry* e) {
+ e->mru_prev->mru_next = e->mru_next;
+ e->mru_next->mru_prev = e->mru_prev;
}
-static inline void
-entry_mru_add( Entry* e, Entry* list )
-{
- Entry* first = list->mru_next;
+static __inline__ void entry_mru_add(Entry* e, Entry* list) {
+ Entry* first = list->mru_next;
- e->mru_next = first;
- e->mru_prev = list;
+ e->mru_next = first;
+ e->mru_prev = list;
- list->mru_next = e;
- first->mru_prev = e;
+ list->mru_next = e;
+ first->mru_prev = e;
}
/* compute the hash of a given entry, this is a hash of most
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 113897c97..1bde3a598 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -168,7 +168,10 @@ __BEGIN_DECLS
*/
#define __ANDROID_API_U__ 34
-/** Names the "V" API level (35), for comparison against `__ANDROID_API__`. */
+/**
+ * Names the Android 15 (aka "V" or "VanillaIceCream") API level (35),
+ * for comparison against `__ANDROID_API__`.
+ */
#define __ANDROID_API_V__ 35
/* This file is included in <features.h>, and might be used from .S files. */
@@ -191,7 +194,7 @@ int android_get_application_target_sdk_version() __INTRODUCED_IN(24);
#if __ANDROID_API__ < 29
/* android_get_device_api_level is a static inline before API level 29. */
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static inline
+#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
#include <bits/get_device_api_level_inlines.h>
#undef __BIONIC_GET_DEVICE_API_LEVEL_INLINE
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index a5061c741..b42e5b22f 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef __ANDROID_DLEXT_H__
-#define __ANDROID_DLEXT_H__
+#pragma once
#include <stdbool.h>
#include <stddef.h>
@@ -101,7 +100,7 @@ enum {
ANDROID_DLEXT_FORCE_LOAD = 0x40,
// Historically we had two other options for ART.
- // They were last available in Android P.
+ // They were last available in API level 28.
// Reuse these bits last!
// ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80
// ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100
@@ -115,7 +114,7 @@ enum {
ANDROID_DLEXT_USE_NAMESPACE = 0x200,
/**
- * Instructs dlopen to apply `ANDROID_DLEXT_RESERVED_ADDRESS`,
+ * Instructs dlopen() to apply `ANDROID_DLEXT_RESERVED_ADDRESS`,
* `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`, `ANDROID_DLEXT_WRITE_RELRO` and
* `ANDROID_DLEXT_USE_RELRO` to any libraries loaded as dependencies of the
* main library as well.
@@ -151,7 +150,7 @@ enum {
struct android_namespace_t;
-/** Used to pass Android-specific arguments to `android_dlopen_ext`. */
+/** Used to pass Android-specific arguments to android_dlopen_ext(). */
typedef struct {
/** A bitmask of `ANDROID_DLEXT_` enum values. */
uint64_t flags;
@@ -183,5 +182,3 @@ void* _Nullable android_dlopen_ext(const char* _Nullable __filename, int __flags
__END_DECLS
/** @} */
-
-#endif
diff --git a/libc/include/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index 0ca1022e8..f0985fe61 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -38,15 +38,15 @@
__BEGIN_DECLS
-static inline double strtod_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
+static __inline double strtod_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
return strtod(__s, __end_ptr);
}
-static inline float strtof_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
+static __inline float strtof_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
return strtof(__s, __end_ptr);
}
-static inline long strtol_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) {
+static __inline long strtol_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) {
return strtol(__s, __end_ptr, __base);
}
diff --git a/libc/include/android/legacy_termios_inlines.h b/libc/include/android/legacy_termios_inlines.h
index e557525ab..a816b4048 100644
--- a/libc/include/android/legacy_termios_inlines.h
+++ b/libc/include/android/legacy_termios_inlines.h
@@ -39,14 +39,14 @@
#include <sys/ioctl.h>
#include <sys/types.h>
-#define __BIONIC_TERMIOS_INLINE static inline
+#define __BIONIC_TERMIOS_INLINE static __inline
#include <bits/termios_inlines.h>
#endif
#if __ANDROID_API__ < 35
-#define __BIONIC_TERMIOS_WINSIZE_INLINE static inline
+#define __BIONIC_TERMIOS_WINSIZE_INLINE static __inline
#include <bits/termios_winsize_inlines.h>
#endif
diff --git a/libc/include/android/legacy_threads_inlines.h b/libc/include/android/legacy_threads_inlines.h
index 06e743813..c614cd01a 100644
--- a/libc/include/android/legacy_threads_inlines.h
+++ b/libc/include/android/legacy_threads_inlines.h
@@ -32,7 +32,7 @@
#if __ANDROID_API__ < 30
-#define __BIONIC_THREADS_INLINE static inline
+#define __BIONIC_THREADS_INLINE static __inline
#include <bits/threads_inlines.h>
#endif
diff --git a/libc/include/android/legacy_unistd_inlines.h b/libc/include/android/legacy_unistd_inlines.h
index ac9f3b354..4a5206b88 100644
--- a/libc/include/android/legacy_unistd_inlines.h
+++ b/libc/include/android/legacy_unistd_inlines.h
@@ -32,7 +32,7 @@
#if __ANDROID_API__ < 28
-#define __BIONIC_SWAB_INLINE static inline
+#define __BIONIC_SWAB_INLINE static __inline
#include <bits/swab.h>
#endif
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index cd61f3393..64528e1b5 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -22,8 +22,8 @@
#define __INTRODUCED_IN(api_level) __attribute__((__annotate__("introduced_in=" #api_level)))
#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level) __attribute__((__annotate__("introduced_in=" #api_level))) __VERSIONER_NO_GUARD
-#define __DEPRECATED_IN(api_level) __attribute__((__annotate__("deprecated_in=" #api_level)))
-#define __REMOVED_IN(api_level) __attribute__((__annotate__("obsoleted_in=" #api_level)))
+#define __DEPRECATED_IN(api_level, ...) __attribute__((__annotate__("deprecated_in=" #api_level)))
+#define __REMOVED_IN(api_level, ...) __attribute__((__annotate__("obsoleted_in=" #api_level)))
#define __INTRODUCED_IN_32(api_level) __attribute__((__annotate__("introduced_in_32=" #api_level)))
#define __INTRODUCED_IN_64(api_level) __attribute__((__annotate__("introduced_in_64=" #api_level)))
@@ -47,16 +47,16 @@
// libc++ doesn't currently guard these calls. There's no risk to the apps though because using
// those APIs will still cause a link error.
#if defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__)
-#define __BIONIC_AVAILABILITY(__what) __attribute__((__availability__(android,__what)))
+#define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,__what __VA_OPT__(,) __VA_ARGS__)))
#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level) __INTRODUCED_IN(api_level)
#else
-#define __BIONIC_AVAILABILITY(__what) __attribute__((__availability__(android,strict,__what)))
+#define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,strict,__what __VA_OPT__(,) __VA_ARGS__)))
#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level)
#endif
#define __INTRODUCED_IN(api_level) __BIONIC_AVAILABILITY(introduced=api_level)
-#define __DEPRECATED_IN(api_level) __BIONIC_AVAILABILITY(deprecated=api_level)
-#define __REMOVED_IN(api_level) __BIONIC_AVAILABILITY(obsoleted=api_level)
+#define __DEPRECATED_IN(api_level, ...) __BIONIC_AVAILABILITY(deprecated=api_level __VA_OPT__(,message=) __VA_ARGS__)
+#define __REMOVED_IN(api_level, ...) __BIONIC_AVAILABILITY(obsoleted=api_level __VA_OPT__(,message=) __VA_ARGS__)
// The same availability attribute can't be annotated multiple times. Therefore, the macros are
// defined for the configuration that it is valid for so that declarations like the below doesn't
@@ -80,5 +80,5 @@
// Vendor modules do not follow SDK versioning. Ignore NDK guards for vendor modules.
#if defined(__ANDROID_VENDOR__)
#undef __BIONIC_AVAILABILITY
-#define __BIONIC_AVAILABILITY(x)
+#define __BIONIC_AVAILABILITY(api_level, ...)
#endif // defined(__ANDROID_VENDOR__)
diff --git a/libc/include/bits/stdatomic.h b/libc/include/bits/stdatomic.h
index 8df86e2ad..c74eafdec 100644
--- a/libc/include/bits/stdatomic.h
+++ b/libc/include/bits/stdatomic.h
@@ -138,11 +138,11 @@ typedef enum {
* 7.17.4 Fences.
*/
-static inline void atomic_thread_fence(memory_order __order __attribute__((__unused__))) {
+static __inline void atomic_thread_fence(memory_order __order __attribute__((__unused__))) {
__c11_atomic_thread_fence(__order);
}
-static inline void atomic_signal_fence(memory_order __order __attribute__((__unused__))) {
+static __inline void atomic_signal_fence(memory_order __order __attribute__((__unused__))) {
__c11_atomic_signal_fence(__order);
}
@@ -269,18 +269,18 @@ typedef struct {
#define ATOMIC_FLAG_INIT { ATOMIC_VAR_INIT(false) }
-static inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
+static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
return (atomic_exchange_explicit(&__object->__flag, 1, __order));
}
-static inline void atomic_flag_clear_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
+static __inline void atomic_flag_clear_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
atomic_store_explicit(&__object->__flag, 0, __order);
}
-static inline bool atomic_flag_test_and_set(volatile atomic_flag * _Nonnull __object) {
+static __inline bool atomic_flag_test_and_set(volatile atomic_flag * _Nonnull __object) {
return (atomic_flag_test_and_set_explicit(__object, memory_order_seq_cst));
}
-static inline void atomic_flag_clear(volatile atomic_flag * _Nonnull __object) {
+static __inline void atomic_flag_clear(volatile atomic_flag * _Nonnull __object) {
atomic_flag_clear_explicit(__object, memory_order_seq_cst);
}
diff --git a/libc/include/bits/swab.h b/libc/include/bits/swab.h
index ebb7c7406..9591c2ede 100644
--- a/libc/include/bits/swab.h
+++ b/libc/include/bits/swab.h
@@ -33,7 +33,7 @@
#include <sys/types.h>
#if !defined(__BIONIC_SWAB_INLINE)
-#define __BIONIC_SWAB_INLINE static inline
+#define __BIONIC_SWAB_INLINE static __inline
#endif
__BEGIN_DECLS
diff --git a/libc/include/bits/termios_inlines.h b/libc/include/bits/termios_inlines.h
index 702f43346..a884b595f 100644
--- a/libc/include/bits/termios_inlines.h
+++ b/libc/include/bits/termios_inlines.h
@@ -37,7 +37,7 @@
#include <linux/termios.h>
#if !defined(__BIONIC_TERMIOS_INLINE)
-#define __BIONIC_TERMIOS_INLINE static inline
+#define __BIONIC_TERMIOS_INLINE static __inline
#endif
__BEGIN_DECLS
@@ -45,7 +45,7 @@ __BEGIN_DECLS
// Supporting separate input and output speeds would require an ABI
// change for `struct termios`.
-static inline speed_t cfgetspeed(const struct termios* _Nonnull s) {
+static __inline speed_t cfgetspeed(const struct termios* _Nonnull s) {
return __BIONIC_CAST(static_cast, speed_t, s->c_cflag & CBAUD);
}
diff --git a/libc/include/bits/termios_winsize_inlines.h b/libc/include/bits/termios_winsize_inlines.h
index 0d188e75e..ae246e401 100644
--- a/libc/include/bits/termios_winsize_inlines.h
+++ b/libc/include/bits/termios_winsize_inlines.h
@@ -36,7 +36,7 @@
#include <linux/termios.h>
#if !defined(__BIONIC_TERMIOS_WINSIZE_INLINE)
-#define __BIONIC_TERMIOS_WINSIZE_INLINE static inline
+#define __BIONIC_TERMIOS_WINSIZE_INLINE static __inline
#endif
__BEGIN_DECLS
diff --git a/libc/include/bits/threads_inlines.h b/libc/include/bits/threads_inlines.h
index 074e1ca98..5878e0acc 100644
--- a/libc/include/bits/threads_inlines.h
+++ b/libc/include/bits/threads_inlines.h
@@ -38,7 +38,7 @@
__BEGIN_DECLS
-static inline int __bionic_thrd_error(int __pthread_code) {
+static __inline int __bionic_thrd_error(int __pthread_code) {
switch (__pthread_code) {
case 0: return 0;
case ENOMEM: return thrd_nomem;
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index 5cad412d6..c15ee5618 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -42,7 +42,7 @@
* also provide actual symbols for any caller that needs them.
*/
#if !defined(__BIONIC_CTYPE_INLINE)
-#define __BIONIC_CTYPE_INLINE static inline
+#define __BIONIC_CTYPE_INLINE static __inline
#endif
/** Internal implementation detail. Do not use. */
diff --git a/libc/include/link.h b/libc/include/link.h
index 33fea49fc..ee1fc42ea 100644
--- a/libc/include/link.h
+++ b/libc/include/link.h
@@ -25,8 +25,13 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifndef _LINK_H_
-#define _LINK_H_
+
+#pragma once
+
+/**
+ * @file link.h
+ * @brief Extra dynamic linker functionality (see also <dlfcn.h>).
+ */
#include <stdint.h>
#include <sys/cdefs.h>
@@ -37,32 +42,80 @@
__BEGIN_DECLS
#if defined(__LP64__)
+/** Convenience macro to get the appropriate 32-bit or 64-bit <elf.h> type for the caller's bitness. */
#define ElfW(type) Elf64_ ## type
#else
+/** Convenience macro to get the appropriate 32-bit or 64-bit <elf.h> type for the caller's bitness. */
#define ElfW(type) Elf32_ ## type
#endif
+/**
+ * Information passed by dl_iterate_phdr() to the callback.
+ */
struct dl_phdr_info {
+ /** The address of the shared object. */
ElfW(Addr) dlpi_addr;
+ /** The name of the shared object. */
const char* _Nullable dlpi_name;
+ /** Pointer to the shared object's program headers. */
const ElfW(Phdr)* _Nullable dlpi_phdr;
+ /** Number of program headers pointed to by `dlpi_phdr`. */
ElfW(Half) dlpi_phnum;
- // These fields were added in Android R.
+ /**
+ * The total number of library load events at the time dl_iterate_phdr() was
+ * called.
+ *
+ * This field is only available since API level 30; you can use the size
+ * passed to the callback to determine whether you have the full struct,
+ * or just the fields up to and including `dlpi_phnum`.
+ */
unsigned long long dlpi_adds;
+ /**
+ * The total number of library unload events at the time dl_iterate_phdr() was
+ * called.
+ *
+ * This field is only available since API level 30; you can use the size
+ * passed to the callback to determine whether you have the full struct,
+ * or just the fields up to and including `dlpi_phnum`.
+ */
unsigned long long dlpi_subs;
+ /**
+ * The module ID for TLS relocations in this shared object.
+ *
+ * This field is only available since API level 30; you can use the size
+ * passed to the callback to determine whether you have the full struct,
+ * or just the fields up to and including `dlpi_phnum`.
+ */
size_t dlpi_tls_modid;
+ /**
+ * The caller's TLS data for this shared object.
+ *
+ * This field is only available since API level 30; you can use the size
+ * passed to the callback to determine whether you have the full struct,
+ * or just the fields up to and including `dlpi_phnum`.
+ */
void* _Nullable dlpi_tls_data;
};
-int dl_iterate_phdr(int (* _Nonnull __callback)(struct dl_phdr_info* _Nonnull, size_t, void* _Nullable), void* _Nullable __data);
+/**
+ * [dl_iterate_phdr(3)](http://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html)
+ * calls the given callback once for every loaded shared object. The size
+ * argument to the callback lets you determine whether you have a smaller
+ * `dl_phdr_info` from before API level 30, or the newer full one.
+ * The data argument to the callback is whatever you pass as the data argument
+ * to dl_iterate_phdr().
+ *
+ * Returns the value returned by the final call to the callback.
+ */
+int dl_iterate_phdr(int (* _Nonnull __callback)(struct dl_phdr_info* _Nonnull __info, size_t __size, void* _Nullable __data), void* _Nullable __data);
#ifdef __arm__
typedef uintptr_t _Unwind_Ptr;
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr, int* _Nonnull);
#endif
-/* Used by the dynamic linker to communicate with the debugger. */
+/** Used by the dynamic linker to communicate with the debugger. */
struct link_map {
ElfW(Addr) l_addr;
char* _Nullable l_name;
@@ -71,7 +124,7 @@ struct link_map {
struct link_map* _Nullable l_prev;
};
-/* Used by the dynamic linker to communicate with the debugger. */
+/** Used by the dynamic linker to communicate with the debugger. */
struct r_debug {
int32_t r_version;
struct link_map* _Nullable r_map;
@@ -85,5 +138,3 @@ struct r_debug {
};
__END_DECLS
-
-#endif
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 32264d6d9..78114c38c 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -69,7 +69,7 @@ extern FILE* _Nonnull stderr __INTRODUCED_IN(23);
#define stderr stderr
#else
/* Before M the actual symbols for stdin and friends had different names. */
-extern FILE __sF[] __REMOVED_IN(23);
+extern FILE __sF[] __REMOVED_IN(23, "Use stdin/stdout/stderr");
#define stdin (&__sF[0])
#define stdout (&__sF[1])
diff --git a/libc/include/strings.h b/libc/include/strings.h
index 6ec3bdf58..2f4f7641a 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -50,7 +50,7 @@
#include <bits/strcasecmp.h>
#if !defined(__BIONIC_STRINGS_INLINE)
-#define __BIONIC_STRINGS_INLINE static inline
+#define __BIONIC_STRINGS_INLINE static __inline
#endif
#undef ffs
@@ -61,13 +61,13 @@ __BEGIN_DECLS
/** Deprecated. Use memmove() instead. */
#define bcopy(b1, b2, len) __bionic_bcopy((b1), (b2), (len))
-static inline __always_inline void __bionic_bcopy(const void* _Nonnull b1, void* _Nonnull b2, size_t len) {
+static __inline__ __always_inline void __bionic_bcopy(const void* _Nonnull b1, void* _Nonnull b2, size_t len) {
__builtin_memmove(b2, b1, len);
}
/** Deprecated. Use memset() instead. */
#define bzero(b, len) __bionic_bzero((b), (len))
-static inline __always_inline void __bionic_bzero(void* _Nonnull b, size_t len) {
+static __inline__ __always_inline void __bionic_bzero(void* _Nonnull b, size_t len) {
__builtin_memset(b, 0, len);
}
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 3218d1554..7625d3886 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -260,7 +260,7 @@
* them available externally. FORTIFY'ed functions try to be as close to possible as 'invisible';
* having stack protectors detracts from that (b/182948263).
*/
-# define __BIONIC_FORTIFY_INLINE static inline __attribute__((__no_stack_protector__)) \
+# define __BIONIC_FORTIFY_INLINE static __inline__ __attribute__((__no_stack_protector__)) \
__always_inline __VERSIONER_FORTIFY_INLINE
/*
* We should use __BIONIC_FORTIFY_VARIADIC instead of __BIONIC_FORTIFY_INLINE
@@ -268,7 +268,7 @@
* The __always_inline attribute is useless, misleading, and could trigger
* clang compiler bug to incorrectly inline variadic functions.
*/
-# define __BIONIC_FORTIFY_VARIADIC static inline
+# define __BIONIC_FORTIFY_VARIADIC static __inline__
/* Error functions don't have bodies, so they can just be static. */
# define __BIONIC_ERROR_FUNCTION_VISIBILITY static __attribute__((__unused__))
#else
diff --git a/libc/include/sys/system_properties.h b/libc/include/sys/system_properties.h
index dc869da62..ae94db56c 100644
--- a/libc/include/sys/system_properties.h
+++ b/libc/include/sys/system_properties.h
@@ -26,8 +26,12 @@
* SUCH DAMAGE.
*/
-#ifndef _INCLUDE_SYS_SYSTEM_PROPERTIES_H
-#define _INCLUDE_SYS_SYSTEM_PROPERTIES_H
+#pragma once
+
+/**
+ * @file system_properties.h
+ * @brief System properties.
+ */
#include <sys/cdefs.h>
#include <stdbool.h>
@@ -36,39 +40,53 @@
__BEGIN_DECLS
+/** An opaque structure representing a system property. */
typedef struct prop_info prop_info;
+/**
+ * The limit on the length of a property value.
+ * (See PROP_NAME_MAX for property names.)
+ */
#define PROP_VALUE_MAX 92
-/*
+/**
* Sets system property `name` to `value`, creating the system property if it doesn't already exist.
+ *
+ * Returns 0 on success, or -1 on failure.
*/
int __system_property_set(const char* _Nonnull __name, const char* _Nonnull __value);
-/*
+/**
* Returns a `prop_info` corresponding system property `name`, or nullptr if it doesn't exist.
- * Use __system_property_read_callback to query the current value.
+ * Use __system_property_read_callback() to query the current value.
*
- * Property lookup is expensive, so it can be useful to cache the result of this function.
+ * Property lookup is expensive, so it can be useful to cache the result of this
+ * function rather than using __system_property_get().
*/
const prop_info* _Nullable __system_property_find(const char* _Nonnull __name);
-/*
- * Calls `callback` with a consistent trio of name, value, and serial number for property `pi`.
+/**
+ * Calls `callback` with a consistent trio of name, value, and serial number
+ * for property `pi`.
+ *
+ * Available since API level 26.
*/
void __system_property_read_callback(const prop_info* _Nonnull __pi,
void (* _Nonnull __callback)(void* _Nullable __cookie, const char* _Nonnull __name, const char* _Nonnull __value, uint32_t __serial),
void* _Nullable __cookie) __INTRODUCED_IN(26);
-/*
+/**
* Passes a `prop_info` for each system property to the provided
- * callback. Use __system_property_read_callback() to read the value.
+ * callback. Use __system_property_read_callback() to read the value of
+ * any of the properties.
*
* This method is for inspecting and debugging the property system, and not generally useful.
+ *
+ * Returns 0 on success, or -1 on failure.
*/
int __system_property_foreach(void (* _Nonnull __callback)(const prop_info* _Nonnull __pi, void* _Nullable __cookie), void* _Nullable __cookie);
-/*
+/**
* Waits for the specific system property identified by `pi` to be updated
* past `old_serial`. Waits no longer than `relative_timeout`, or forever
* if `relative_timeout` is null.
@@ -79,20 +97,24 @@ int __system_property_foreach(void (* _Nonnull __callback)(const prop_info* _Non
*
* Returns true and updates `*new_serial_ptr` on success, or false if the call
* timed out.
+ *
+ * Available since API level 26.
*/
struct timespec;
bool __system_property_wait(const prop_info* _Nullable __pi, uint32_t __old_serial, uint32_t* _Nonnull __new_serial_ptr, const struct timespec* _Nullable __relative_timeout)
__INTRODUCED_IN(26);
-/* Deprecated. In Android O and above, there's no limit on property name length. */
+/**
+ * Deprecated: there's no limit on the length of a property name since
+ * API level 26, though the limit on property values (PROP_VALUE_MAX) remains.
+ */
#define PROP_NAME_MAX 32
-/* Deprecated. Use __system_property_read_callback instead. */
+
+/** Deprecated. Use __system_property_read_callback() instead. */
int __system_property_read(const prop_info* _Nonnull __pi, char* _Nullable __name, char* _Nonnull __value);
-/* Deprecated. Use __system_property_read_callback instead. */
+/** Deprecated. Use __system_property_read_callback() instead. */
int __system_property_get(const char* _Nonnull __name, char* _Nonnull __value);
-/* Deprecated. Use __system_property_foreach instead. */
+/** Deprecated. Use __system_property_foreach() instead. */
const prop_info* _Nullable __system_property_find_nth(unsigned __n);
__END_DECLS
-
-#endif
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index 0fd6e46f9..08b786ac5 100755
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -2345,11 +2345,11 @@ struct something_s {
def test_function_keep_attribute_structs(self):
text = """\
-static inline struct some_struct1 * function(struct some_struct2 * e) {
+static __inline__ struct some_struct1 * function(struct some_struct2 * e) {
}
"""
expected = """\
-static inline struct some_struct1 * function(struct some_struct2 * e) {
+static __inline__ struct some_struct1 * function(struct some_struct2 * e) {
}
"""
self.assertEqual(self.parse(text, set(["function"])), expected)
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index ffc6d4a43..da85cf526 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -130,36 +130,55 @@ typedef struct {
// Worth noting, the "libc.debug.gwp_asan.*.app_default" sysprops *do not*
// apply to system apps. They use the "libc.debug.gwp_asan.*.system_default"
// sysprops.
- enum Action {
- // Enable GWP-ASan. This is used by apps that have `gwpAsanMode=always` in
- // the manifest.
- TURN_ON_FOR_APP,
- // Enable GWP-ASan, but only a small percentage of the time. This is used by
- // system processes and system apps, and we use a lottery to determine which
- // processes have GWP-ASan enabled. This allows us to mitigate system-wide
- // memory overhead concerns, as each GWP-ASan enabled process uses ~70KiB of
- // extra memory.
- TURN_ON_WITH_SAMPLING,
- // Don't enable GWP-ASan, unless overwritten by a system property or
- // environment variable. This is used by apps that have `gwpAsanMode=never`
- // in the manifest. Prior to Android 14, this also was used by non-system
- // apps that didn't specify a `gwpAsanMode` in their manifest.
- DONT_TURN_ON_UNLESS_OVERRIDDEN,
- // Enable GWP-ASan, but only a small percentage of the time, and enable it
- // in the non-crashing ("recoverable") mode. In Android 14, this is used by
- // apps that don't specify `gwpAsanMode` (or use `gwpAsanMode=default`) in
- // their manifest. GWP-ASan will detect heap memory safety bugs in this
- // mode, and bug reports will be created by debuggerd, however the process
- // will recover and continue to function as if the memory safety bug wasn't
- // detected.
+ //
+ // In recoverable mode, GWP-ASan will detect heap memory safety bugs, and bug
+ // reports will be created by debuggerd, however the process will recover and
+ // continue to function as if the memory safety bug wasn't detected. This
+ // prevents any user-visible impact as apps and processes don't crash, and
+ // probably saves us some CPU time in restarting the process.
+ //
+ // Process sampling enables GWP-ASan, but only a small percentage of the time
+ // (~1%). This helps mitigate any recurring high-frequency problems in certain
+ // processes, as it's highly likely the next restart of said process won't
+ // have GWP-ASan. In addition, for system processes and system apps, this
+ // allows us to mitigate system-wide memory overhead concerns, as each
+ // GWP-ASan enabled process uses ~70KiB of extra memory.
+ enum Mode {
+ // Used by default for apps, or by those that have an explicit
+ // `gwpAsanMode=default` in the manifest.
+ //
+ // Result:
+ // - Android 13 and before: GWP-ASan is not enabled.
+ // - Android 14 and after: Enables GWP-ASan with process sampling in
+ // recoverable mode.
+ APP_MANIFEST_DEFAULT = 3,
+ // This is used by apps that have `gwpAsanMode=always` in the manifest.
+ //
+ // Result:
+ // - Android 14 and before: Enables GWP-ASan in non-recoverable mode,
+ // without process sampling.
+ // - Android 15 and after: Enables GWP-ASan in recoverable mode, without
+ // process sampling.
+ APP_MANIFEST_ALWAYS = 0,
+ // This is used by apps that have `gwpAsanMode=never` in the manifest.
+ //
+ // Result:
+ // - GWP-ASan is not enabled, unless it's force-enabled by a system
+ // property or environment variable.
+ APP_MANIFEST_NEVER = 2,
+ // Used by system processes and system apps.
//
- // In Android 15, this is the same as TURN_ON_WITH_SAMPLING, as GWP-ASan is
- // only ever used in non-crashing mode (even for platform executables and
- // system apps).
- TURN_ON_FOR_APP_SAMPLED_NON_CRASHING,
+ // Result:
+ // - Android 14 and before: Enables GWP-ASan with process sampling in
+ // non-recoverable mode.
+ // - Android 15 and after: Enables GWP-ASan with process sampling in
+ // recoverable mode.
+ SYSTEM_PROCESS_OR_SYSTEM_APP = 1,
+ // Next enum value = 4. Numbered non-sequentially above to preserve ABI
+ // stability, but now ordered more logically.
};
- Action desire = DONT_TURN_ON_UNLESS_OVERRIDDEN;
+ Mode mode = APP_MANIFEST_NEVER;
} android_mallopt_gwp_asan_options_t;
#pragma clang diagnostic pop
// Manipulates bionic-specific handling of memory allocation APIs such as
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
index 1dedb61e7..e0d38a822 100644
--- a/libc/system_properties/system_properties.cpp
+++ b/libc/system_properties/system_properties.cpp
@@ -337,31 +337,42 @@ int SystemProperties::Update(prop_info* pi, const char* value, unsigned int len)
int SystemProperties::Add(const char* name, unsigned int namelen, const char* value,
unsigned int valuelen) {
- if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) {
+ if (namelen < 1) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "__system_property_add failed: name length 0");
return -1;
}
- if (namelen < 1) {
+ if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "__system_property_add failed: \"%s\" value too long: %d >= PROP_VALUE_MAX",
+ name, valuelen);
return -1;
}
if (!initialized_) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "__system_property_add failed: properties not initialized");
return -1;
}
prop_area* serial_pa = contexts_->GetSerialPropArea();
if (serial_pa == nullptr) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "__system_property_add failed: property area not found");
return -1;
}
prop_area* pa = contexts_->GetPropAreaForName(name);
if (!pa) {
- async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "__system_property_add failed: access denied for \"%s\"", name);
return -1;
}
- bool ret = pa->add(name, namelen, value, valuelen);
- if (!ret) {
+ if (!pa->add(name, namelen, value, valuelen)) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "__system_property_add failed: add failed for \"%s\"", name);
return -1;
}
diff --git a/linker/linker_crt_pad_segment_test.cpp b/linker/linker_crt_pad_segment_test.cpp
index 5a219f8ee..c11df50fe 100644
--- a/linker/linker_crt_pad_segment_test.cpp
+++ b/linker/linker_crt_pad_segment_test.cpp
@@ -72,13 +72,22 @@ bool GetPadSegment(const std::string& elf_path) {
}; // anonymous namespace
TEST(crt_pad_segment, note_absent) {
+ if (!page_size_migration_supported()) {
+ GTEST_SKIP() << "Kernel does not support page size migration";
+ }
ASSERT_FALSE(GetPadSegment("no_crt_pad_segment.so"));
}
TEST(crt_pad_segment, note_present_and_enabled) {
+ if (!page_size_migration_supported()) {
+ GTEST_SKIP() << "Kernel does not support page size migration";
+ }
ASSERT_TRUE(GetPadSegment("crt_pad_segment_enabled.so"));
}
TEST(crt_pad_segment, note_present_and_disabled) {
+ if (!page_size_migration_supported()) {
+ GTEST_SKIP() << "Kernel does not support page size migration";
+ }
ASSERT_FALSE(GetPadSegment("crt_pad_segment_disabled.so"));
}
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 089ecebf9..e27fd9175 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -422,20 +422,11 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
- // We haven't supported non-PIE since Lollipop for security reasons.
+ // For security reasons we dropped non-PIE support in API level 21,
+ // and the NDK no longer supports earlier API levels.
if (elf_hdr->e_type != ET_DYN) {
- // We don't use async_safe_fatal here because we don't want a tombstone:
- // even after several years we still find ourselves on app compatibility
- // investigations because some app's trying to launch an executable that
- // hasn't worked in at least three years, and we've "helpfully" dropped a
- // tombstone for them. The tombstone never provided any detail relevant to
- // fixing the problem anyway, and the utility of drawing extra attention
- // to the problem is non-existent at this late date.
- async_safe_format_fd(STDERR_FILENO,
- "\"%s\": error: Android 5.0 and later only support "
- "position-independent executables (-fPIE).\n",
- g_argv[0]);
- _exit(EXIT_FAILURE);
+ __linker_error("error: %s: Android only supports position-independent "
+ "executables (-fPIE)\n", exe_info.path.c_str());
}
// Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index ef7671cee..b9229caef 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -46,6 +46,8 @@
#include "private/CFIShadow.h" // For kLibraryAlignment
#include "private/elf_note.h"
+#include <android-base/file.h>
+
static int GetTargetElfMachine() {
#if defined(__arm__)
return EM_ARM;
@@ -296,7 +298,6 @@ bool ElfReader::VerifyElfHeader() {
}
if (header_.e_shentsize != sizeof(ElfW(Shdr))) {
- // Fail if app is targeting Android O or above
if (get_application_target_sdk_version() >= 26) {
DL_ERR_AND_LOG("\"%s\" has unsupported e_shentsize: 0x%x (expected 0x%zx)",
name_.c_str(), header_.e_shentsize, sizeof(ElfW(Shdr)));
@@ -310,12 +311,10 @@ bool ElfReader::VerifyElfHeader() {
}
if (header_.e_shstrndx == 0) {
- // Fail if app is targeting Android O or above
if (get_application_target_sdk_version() >= 26) {
DL_ERR_AND_LOG("\"%s\" has invalid e_shstrndx", name_.c_str());
return false;
}
-
DL_WARN_documented_change(26,
"invalid-elf-header_section-headers-enforced-for-api-level-26",
"\"%s\" has invalid e_shstrndx", name_.c_str());
@@ -707,8 +706,28 @@ bool ElfReader::ReserveAddressSpace(address_space_params* address_space) {
return true;
}
+/*
+ * Returns true if the kernel supports page size migration, else false.
+ */
+bool page_size_migration_supported() {
+ static bool pgsize_migration_enabled = []() {
+ std::string enabled;
+ if (!android::base::ReadFileToString("/sys/kernel/mm/pgsize_migration/enabled", &enabled)) {
+ return false;
+ }
+ return enabled.find("1") != std::string::npos;
+ }();
+ return pgsize_migration_enabled;
+}
+
// Find the ELF note of type NT_ANDROID_TYPE_PAD_SEGMENT and check that the desc value is 1.
bool ElfReader::ReadPadSegmentNote() {
+ if (!page_size_migration_supported()) {
+ // Don't attempt to read the note, since segment extension isn't
+ // supported; but return true so that loading can continue normally.
+ return true;
+ }
+
// The ELF can have multiple PT_NOTE's, check them all
for (size_t i = 0; i < phdr_num_; ++i) {
const ElfW(Phdr)* phdr = &phdr_table_[i];
@@ -773,7 +792,16 @@ static inline void _extend_load_segment_vma(const ElfW(Phdr)* phdr_table, size_t
const ElfW(Phdr)* next = nullptr;
size_t next_idx = phdr_idx + 1;
- if (phdr->p_align == kPageSize || !should_pad_segments) {
+ // Don't do segment extension for p_align > 64KiB, such ELFs already existed in the
+ // field e.g. 2MiB p_align for THPs and are relatively small in number.
+ //
+ // The kernel can only represent padding for p_align up to 64KiB. This is because
+ // the kernel uses 4 available bits in the vm_area_struct to represent padding
+ // extent; and so cannot enable mitigations to avoid breaking app compatibility for
+ // p_aligns > 64KiB.
+ //
+ // Don't perform segment extension on these to avoid app compatibility issues.
+ if (phdr->p_align <= kPageSize || phdr->p_align > 64*1024 || !should_pad_segments) {
return;
}
@@ -887,10 +915,28 @@ bool ElfReader::LoadSegments() {
// 2) Break the COW backing, faulting in new anon pages for a region
// that will not be used.
- // _seg_file_end = unextended seg_file_end
- uint64_t _seg_file_end = seg_start + phdr->p_filesz;
- if ((phdr->p_flags & PF_W) != 0 && page_offset(_seg_file_end) > 0) {
- memset(reinterpret_cast<void*>(_seg_file_end), 0, kPageSize - page_offset(_seg_file_end));
+ uint64_t unextended_seg_file_end = seg_start + phdr->p_filesz;
+ if ((phdr->p_flags & PF_W) != 0 && page_offset(unextended_seg_file_end) > 0) {
+ memset(reinterpret_cast<void*>(unextended_seg_file_end), 0,
+ kPageSize - page_offset(unextended_seg_file_end));
+ }
+
+ // Pages may be brought in due to readahead.
+ // Drop the padding (zero) pages, to avoid reclaim work later.
+ //
+ // NOTE: The madvise() here is special, as it also serves to hint to the
+ // kernel the portion of the LOAD segment that is padding.
+ //
+ // See: [1] https://android-review.googlesource.com/c/kernel/common/+/3032411
+ // [2] https://android-review.googlesource.com/c/kernel/common/+/3048835
+ uint64_t pad_start = page_end(unextended_seg_file_end);
+ uint64_t pad_end = page_end(seg_file_end);
+ CHECK(pad_start <= pad_end);
+ uint64_t pad_len = pad_end - pad_start;
+ if (page_size_migration_supported() && pad_len > 0 &&
+ madvise(reinterpret_cast<void*>(pad_start), pad_len, MADV_DONTNEED)) {
+ DL_WARN("\"%s\": madvise(0x%" PRIx64 ", 0x%" PRIx64 ", MADV_DONTNEED) failed: %m",
+ name_.c_str(), pad_start, pad_len);
}
seg_file_end = page_end(seg_file_end);
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 61242eb4c..aab9018b4 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -154,3 +154,5 @@ void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_co
const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count,
ElfW(Addr) load_bias);
+
+bool page_size_migration_supported();
diff --git a/tests/clang_fortify_tests.cpp b/tests/clang_fortify_tests.cpp
index 544af4308..f4ef4ac4a 100644
--- a/tests/clang_fortify_tests.cpp
+++ b/tests/clang_fortify_tests.cpp
@@ -164,9 +164,7 @@ FORTIFY_TEST(string) {
const char large_string[] = "Hello!!!";
static_assert(sizeof(large_string) > sizeof(small_buffer), "");
-#if __clang_major__ > 13
- // expected-error@+3{{will always overflow}}
-#endif
+ // expected-error@+2{{will always overflow}}
// expected-error@+1{{string bigger than buffer}}
EXPECT_FORTIFY_DEATH(strcpy(small_buffer, large_string));
// expected-error@+1{{string bigger than buffer}}
@@ -204,9 +202,7 @@ FORTIFY_TEST(string) {
static_assert(sizeof(small_string) > sizeof(split.tiny_buffer), "");
#if _FORTIFY_SOURCE > 1
-#if __clang_major__ > 13
- // expected-error@+4{{will always overflow}}
-#endif
+ // expected-error@+3{{will always overflow}}
// expected-error@+2{{string bigger than buffer}}
#endif
EXPECT_FORTIFY_DEATH_STRUCT(strcpy(split.tiny_buffer, small_string));
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index bd17b82fa..a5916d318 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -1412,15 +1412,15 @@ TEST(android_mallopt, set_allocation_limit_multiple_threads) {
}
#if defined(__BIONIC__)
-using Action = android_mallopt_gwp_asan_options_t::Action;
+using Mode = android_mallopt_gwp_asan_options_t::Mode;
TEST(android_mallopt, DISABLED_multiple_enable_gwp_asan) {
android_mallopt_gwp_asan_options_t options;
options.program_name = ""; // Don't infer GWP-ASan options from sysprops.
- options.desire = Action::DONT_TURN_ON_UNLESS_OVERRIDDEN;
+ options.mode = Mode::APP_MANIFEST_NEVER;
// GWP-ASan should already be enabled. Trying to enable or disable it should
// always pass.
ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &options, sizeof(options)));
- options.desire = Action::TURN_ON_WITH_SAMPLING;
+ options.mode = Mode::APP_MANIFEST_DEFAULT;
ASSERT_TRUE(android_mallopt(M_INITIALIZE_GWP_ASAN, &options, sizeof(options)));
}
#endif // defined(__BIONIC__)
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index 6ae8bfd3f..0de0a01ba 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -174,31 +174,23 @@ TEST(setjmp, sigsetjmp_1_signal_mask) {
}
}
-#if defined(__aarch64__)
+#if defined(__arm__)
+#define SET_FREG(n, v) asm volatile("vmov.f64 d"#n ", #"#v : : : "d"#n)
+#define GET_FREG(n) ({ double _r; asm volatile("fcpyd %P0, d"#n : "=w"(_r) : :); _r;})
+#define CLEAR_FREG(n) asm volatile("vmov.i64 d"#n ", #0x0" : : : "d"#n)
+#elif defined(__aarch64__)
#define SET_FREG(n, v) asm volatile("fmov d"#n ", "#v : : : "d"#n)
+#define GET_FREG(n) ({ double _r; asm volatile("fmov %0, d"#n : "=r"(_r) : :); _r; })
#define CLEAR_FREG(n) asm volatile("fmov d"#n ", xzr" : : : "d"#n)
+#endif
+
+#if defined(__arm__) || defined(__aarch64__)
#define SET_FREGS \
SET_FREG(8, 8.0); SET_FREG(9, 9.0); SET_FREG(10, 10.0); SET_FREG(11, 11.0); \
SET_FREG(12, 12.0); SET_FREG(13, 13.0); SET_FREG(14, 14.0); SET_FREG(15, 15.0);
#define CLEAR_FREGS \
CLEAR_FREG(8); CLEAR_FREG(9); CLEAR_FREG(10); CLEAR_FREG(11); \
CLEAR_FREG(12); CLEAR_FREG(13); CLEAR_FREG(14); CLEAR_FREG(15);
-#define GET_FREG(n) ({ double _r; asm volatile("fmov %0, d"#n : "=r"(_r) : :); _r; })
-#define CHECK_FREGS \
- EXPECT_EQ(8.0, GET_FREG(8)); EXPECT_EQ(9.0, GET_FREG(9)); \
- EXPECT_EQ(10.0, GET_FREG(10)); EXPECT_EQ(11.0, GET_FREG(11)); \
- EXPECT_EQ(12.0, GET_FREG(12)); EXPECT_EQ(13.0, GET_FREG(13)); \
- EXPECT_EQ(14.0, GET_FREG(14)); EXPECT_EQ(15.0, GET_FREG(15));
-#elif defined(__arm__)
-#define SET_FREG(n, v) \
- ({ const double _v{v}; asm volatile("fcpyd d"#n ", %P0" : : "w"(_v) : "d"#n); })
-#define SET_FREGS \
- SET_FREG(8, 8); SET_FREG(9, 9); SET_FREG(10, 10); SET_FREG(11, 11); \
- SET_FREG(12, 12); SET_FREG(13, 13); SET_FREG(14, 14); SET_FREG(15, 15);
-#define CLEAR_FREGS \
- SET_FREG(8, 0); SET_FREG(9, 0); SET_FREG(10, 0); SET_FREG(11, 0); \
- SET_FREG(12, 0); SET_FREG(13, 0); SET_FREG(14, 0); SET_FREG(15, 0);
-#define GET_FREG(n) ({ double _r; asm volatile("fcpyd %P0, d"#n : "=w"(_r) : :); _r;})
#define CHECK_FREGS \
EXPECT_EQ(8.0, GET_FREG(8)); EXPECT_EQ(9.0, GET_FREG(9)); \
EXPECT_EQ(10.0, GET_FREG(10)); EXPECT_EQ(11.0, GET_FREG(11)); \
diff --git a/tests/stack_protector_test.cpp b/tests/stack_protector_test.cpp
index c4be78c72..aea791c81 100644
--- a/tests/stack_protector_test.cpp
+++ b/tests/stack_protector_test.cpp
@@ -136,7 +136,7 @@ TEST_F(stack_protector_DeathTest, modify_stack_protector) {
if (stack_mte_enabled()) {
GTEST_SKIP() << "Stack MTE is enabled, stack protector is not available";
} else if (hwasan_enabled()) {
- ASSERT_EXIT(modify_stack_protector_test(), testing::KilledBySignal(SIGABRT), "tag-mismatch");
+ GTEST_SKIP() << "HWASan is enabled, stack protector is not testable";
} else {
ASSERT_EXIT(modify_stack_protector_test(), testing::KilledBySignal(SIGABRT),
"stack corruption detected");