summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/Android.bp47
-rw-r--r--libc/NOTICE28
-rw-r--r--libc/arch-arm/bionic/kuser_helper_on.S4
-rw-r--r--libc/arch-arm64/bionic/note_memtag_heap_async.S46
-rw-r--r--libc/arch-arm64/bionic/note_memtag_heap_sync.S46
-rw-r--r--libc/arch-arm64/dynamic_function_dispatch.cpp28
-rw-r--r--libc/arch-common/bionic/crtbrand.S4
-rw-r--r--libc/bionic/bionic_appcompat.cpp2
-rw-r--r--libc/bionic/bionic_appcompat.h2
-rw-r--r--libc/bionic/fts.c130
-rw-r--r--libc/bionic/heap_tagging.cpp76
-rw-r--r--libc/bionic/heap_tagging.h2
-rw-r--r--libc/bionic/libc_init_common.cpp6
-rw-r--r--libc/bionic/libc_init_common.h3
-rw-r--r--libc/bionic/libc_init_dynamic.cpp1
-rw-r--r--libc/bionic/libc_init_static.cpp176
-rw-r--r--libc/bionic/malloc_common.cpp16
-rw-r--r--libc/bionic/malloc_common_dynamic.cpp7
-rw-r--r--libc/bionic/malloc_tagged_pointers.h7
-rw-r--r--libc/bionic/memory_mitigation_state.cpp6
-rw-r--r--libc/bionic/memory_mitigation_state.h2
-rw-r--r--libc/bionic/recvmsg.cpp2
-rw-r--r--libc/dns/net/gethnamaddr.c3
-rw-r--r--libc/dns/net/sethostent.c3
-rw-r--r--libc/include/android/api-level.h7
-rw-r--r--libc/include/android/legacy_signal_inlines.h8
-rw-r--r--libc/include/android/versioning.h57
-rw-r--r--libc/include/malloc.h54
-rw-r--r--libc/platform/bionic/malloc.h29
-rw-r--r--libc/platform/bionic/mte.h10
-rw-r--r--libc/private/bionic_asm.h8
-rw-r--r--libc/private/bionic_asm_arm64.h8
-rw-r--r--libc/private/bionic_asm_note.h (renamed from libc/platform/bionic/mte_kernel.h)34
-rw-r--r--libc/private/bionic_fdtrack.h4
-rw-r--r--libc/private/bionic_globals.h4
-rw-r--r--libc/private/bsd_sys_param.h21
-rw-r--r--libc/stdio/stdio.cpp3
-rw-r--r--libc/system_properties/context_lookup_benchmark_data.h1
-rw-r--r--libc/upstream-openbsd/android/include/openbsd-compat.h6
39 files changed, 645 insertions, 256 deletions
diff --git a/libc/Android.bp b/libc/Android.bp
index 6bb197446..5340c6f8a 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -93,9 +93,6 @@ cc_defaults {
ldflags: ["-Wl,-z,muldefs"],
product_variables: {
- experimental_mte: {
- cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
- },
malloc_zero_contents: {
cflags: ["-DSCUDO_ZERO_CONTENTS"],
},
@@ -269,6 +266,7 @@ cc_library_static {
"-Wno-unused-parameter",
"-include netbsd-compat.h",
"-Wframe-larger-than=66000",
+ "-include private/bsd_sys_param.h",
],
local_include_dirs: [
@@ -579,6 +577,7 @@ cc_library_static {
],
local_include_dirs: [
+ "private",
"upstream-openbsd/android/include/",
"upstream-openbsd/lib/libc/include/",
"upstream-openbsd/lib/libc/gdtoa/",
@@ -1653,6 +1652,7 @@ cc_library {
"gwp_asan",
"libc_init_dynamic",
"libc_common_shared",
+ "libunwind-exported",
],
},
@@ -1694,8 +1694,6 @@ cc_library {
srcs: [":libc_sources_shared_arm"],
// special for arm
cflags: ["-DCRT_LEGACY_WORKAROUND"],
-
- whole_static_libs: [ "libunwind_llvm" ],
},
// Arm 32 bit does not produce complete exidx unwind information
@@ -1714,10 +1712,6 @@ cc_library {
strip: {
keep_symbols: true,
},
-
- shared: {
- whole_static_libs: [ "libgcc_stripped" ],
- },
},
x86: {
// TODO: This is to work around b/24465209. Remove after root cause is fixed.
@@ -1731,10 +1725,6 @@ cc_library {
strip: {
keep_symbols: true,
},
-
- shared: {
- whole_static_libs: [ "libgcc_stripped" ],
- },
},
x86_64: {
version_script: ":libc.x86_64.map",
@@ -1744,10 +1734,6 @@ cc_library {
strip: {
keep_symbols: true,
},
-
- shared: {
- whole_static_libs: [ "libgcc_stripped" ],
- },
},
},
@@ -2122,6 +2108,8 @@ cc_object {
local_include_dirs: ["include"],
srcs: ["arch-common/bionic/crtbegin.c"],
defaults: ["crt_defaults"],
+ // When using libc.a, we're using the latest library regardless of target API level.
+ min_sdk_version: "current",
}
cc_object {
@@ -2132,6 +2120,8 @@ cc_object {
"crtbrand",
],
defaults: ["crt_defaults"],
+ // When using libc.a, we're using the latest library regardless of target API level.
+ min_sdk_version: "current",
}
cc_object {
@@ -2169,6 +2159,28 @@ cc_object {
defaults: ["crt_defaults"],
}
+cc_library_static {
+ name: "note_memtag_heap_async",
+ arch: {
+ arm64: {
+ srcs: ["arch-arm64/bionic/note_memtag_heap_async.S"],
+ }
+ },
+
+ defaults: ["crt_defaults"],
+}
+
+cc_library_static {
+ name: "note_memtag_heap_sync",
+ arch: {
+ arm64: {
+ srcs: ["arch-arm64/bionic/note_memtag_heap_sync.S"],
+ }
+ },
+
+ defaults: ["crt_defaults"],
+}
+
// ========================================================
// NDK headers.
// ========================================================
@@ -2249,7 +2261,6 @@ ndk_headers {
ndk_library {
name: "libc",
- native_bridge_supported: true,
symbol_file: "libc.map.txt",
first_version: "9",
}
diff --git a/libc/NOTICE b/libc/NOTICE
index f7d73d8f8..7041e5c3c 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -1083,6 +1083,34 @@ SUCH DAMAGE.
-------------------------------------------------------------------
+Copyright (C) 2021 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.
+
+-------------------------------------------------------------------
+
Copyright (c) 1980, 1983, 1988, 1993
The Regents of the University of California. All rights reserved.
diff --git a/libc/arch-arm/bionic/kuser_helper_on.S b/libc/arch-arm/bionic/kuser_helper_on.S
index cff2073b7..2a1d86dde 100644
--- a/libc/arch-arm/bionic/kuser_helper_on.S
+++ b/libc/arch-arm/bionic/kuser_helper_on.S
@@ -26,13 +26,15 @@
* SUCH DAMAGE.
*/
+#include <private/bionic_asm_note.h>
+
.section .note.android.kuser_helper_on,"a",%note
.balign 4
.type kuser_helper_on, %object
kuser_helper_on:
.long 2f-1f // int32_t namesz
.long 3f-2f // int32_t descsz
- .long 3 // int32_t type
+ .long NT_TYPE_KUSER // int32_t type
1:.ascii "Android\0" // char name[]
2:.long 1 // int32_t on
3:
diff --git a/libc/arch-arm64/bionic/note_memtag_heap_async.S b/libc/arch-arm64/bionic/note_memtag_heap_async.S
new file mode 100644
index 000000000..208115c13
--- /dev/null
+++ b/libc/arch-arm64/bionic/note_memtag_heap_async.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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 <private/bionic_asm.h>
+#include <private/bionic_asm_note.h>
+
+__bionic_asm_custom_note_gnu_section()
+
+ .section ".note.android.memtag", "a", %note
+ .p2align 2
+ .long 1f - 0f // int32_t namesz
+ .long 3f - 2f // int32_t descsz
+ .long NT_TYPE_MEMTAG // int32_t type
+0:
+ .asciz "Android" // char name[]
+1:
+ .p2align 2
+2:
+ .long (NT_MEMTAG_LEVEL_ASYNC | NT_MEMTAG_HEAP) // value
+3:
+ .p2align 2
diff --git a/libc/arch-arm64/bionic/note_memtag_heap_sync.S b/libc/arch-arm64/bionic/note_memtag_heap_sync.S
new file mode 100644
index 000000000..d71ad020e
--- /dev/null
+++ b/libc/arch-arm64/bionic/note_memtag_heap_sync.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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 <private/bionic_asm.h>
+#include <private/bionic_asm_note.h>
+
+__bionic_asm_custom_note_gnu_section()
+
+ .section ".note.android.memtag", "a", %note
+ .p2align 2
+ .long 1f - 0f // int32_t namesz
+ .long 3f - 2f // int32_t descsz
+ .long NT_TYPE_MEMTAG // int32_t type
+0:
+ .asciz "Android" // char name[]
+1:
+ .p2align 2
+2:
+ .long (NT_MEMTAG_LEVEL_SYNC | NT_MEMTAG_HEAP) // value
+3:
+ .p2align 2
diff --git a/libc/arch-arm64/dynamic_function_dispatch.cpp b/libc/arch-arm64/dynamic_function_dispatch.cpp
index 0fd331f79..83e5ca4da 100644
--- a/libc/arch-arm64/dynamic_function_dispatch.cpp
+++ b/libc/arch-arm64/dynamic_function_dispatch.cpp
@@ -26,25 +26,15 @@
* SUCH DAMAGE.
*/
-#include <platform/bionic/mte_kernel.h>
#include <private/bionic_ifuncs.h>
#include <stddef.h>
#include <sys/auxv.h>
extern "C" {
-static bool supports_mte(unsigned long hwcap2) {
-#ifdef ANDROID_EXPERIMENTAL_MTE
- return hwcap2 & HWCAP2_MTE;
-#else
- (void)hwcap2;
- return false;
-#endif
-}
-
typedef void* memchr_func(const void*, int, size_t);
DEFINE_IFUNC_FOR(memchr) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(memchr_func, __memchr_aarch64_mte);
} else {
RETURN_FUNC(memchr_func, __memchr_aarch64);
@@ -53,7 +43,7 @@ DEFINE_IFUNC_FOR(memchr) {
typedef int stpcpy_func(char*, const char*);
DEFINE_IFUNC_FOR(stpcpy) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(stpcpy_func, __stpcpy_aarch64_mte);
} else {
RETURN_FUNC(stpcpy_func, __stpcpy_aarch64);
@@ -62,7 +52,7 @@ DEFINE_IFUNC_FOR(stpcpy) {
typedef char* strchr_func(const char*, int);
DEFINE_IFUNC_FOR(strchr) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(strchr_func, __strchr_aarch64_mte);
} else {
RETURN_FUNC(strchr_func, __strchr_aarch64);
@@ -71,7 +61,7 @@ DEFINE_IFUNC_FOR(strchr) {
typedef char* strchrnul_func(const char*, int);
DEFINE_IFUNC_FOR(strchrnul) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(strchrnul_func, __strchrnul_aarch64_mte);
} else {
RETURN_FUNC(strchrnul_func, __strchrnul_aarch64);
@@ -80,7 +70,7 @@ DEFINE_IFUNC_FOR(strchrnul) {
typedef int strcmp_func(const char*, const char*);
DEFINE_IFUNC_FOR(strcmp) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(strcmp_func, __strcmp_aarch64_mte);
} else {
RETURN_FUNC(strcmp_func, __strcmp_aarch64);
@@ -89,7 +79,7 @@ DEFINE_IFUNC_FOR(strcmp) {
typedef int strcpy_func(char*, const char*);
DEFINE_IFUNC_FOR(strcpy) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(strcpy_func, __strcpy_aarch64_mte);
} else {
RETURN_FUNC(strcpy_func, __strcpy_aarch64);
@@ -98,7 +88,7 @@ DEFINE_IFUNC_FOR(strcpy) {
typedef size_t strlen_func(const char*);
DEFINE_IFUNC_FOR(strlen) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(strlen_func, __strlen_aarch64_mte);
} else {
RETURN_FUNC(strlen_func, __strlen_aarch64);
@@ -107,7 +97,7 @@ DEFINE_IFUNC_FOR(strlen) {
typedef int strncmp_func(const char*, const char*, int);
DEFINE_IFUNC_FOR(strncmp) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(strncmp_func, __strncmp_aarch64_mte);
} else {
RETURN_FUNC(strncmp_func, __strncmp_aarch64);
@@ -116,7 +106,7 @@ DEFINE_IFUNC_FOR(strncmp) {
typedef char* strrchr_func(const char*, int);
DEFINE_IFUNC_FOR(strrchr) {
- if (supports_mte(arg->_hwcap2)) {
+ if (arg->_hwcap2 & HWCAP2_MTE) {
RETURN_FUNC(strrchr_func, __strrchr_aarch64_mte);
} else {
RETURN_FUNC(strrchr_func, __strrchr_aarch64);
diff --git a/libc/arch-common/bionic/crtbrand.S b/libc/arch-common/bionic/crtbrand.S
index 3d80d7353..307ef2e34 100644
--- a/libc/arch-common/bionic/crtbrand.S
+++ b/libc/arch-common/bionic/crtbrand.S
@@ -32,13 +32,15 @@
__bionic_asm_custom_note_gnu_section()
#endif
+#include <private/bionic_asm_note.h>
+
.section .note.android.ident,"a",%note
.balign 4
.type abitag, %object
abitag:
.long 2f-1f // int32_t namesz
.long 3f-2f // int32_t descsz
- .long 1 // int32_t type
+ .long NT_TYPE_IDENT // int32_t type
#ifdef __ANDROID__
1:.ascii "Android\0" // char name[]
2:.long PLATFORM_SDK_VERSION // int32_t android_api
diff --git a/libc/bionic/bionic_appcompat.cpp b/libc/bionic/bionic_appcompat.cpp
index 5b31c299d..dcca0dad5 100644
--- a/libc/bionic/bionic_appcompat.cpp
+++ b/libc/bionic/bionic_appcompat.cpp
@@ -88,4 +88,4 @@ int get_package_name(char* buffer, const int bufferlen) {
close(file);
return 0;
-} \ No newline at end of file
+}
diff --git a/libc/bionic/bionic_appcompat.h b/libc/bionic/bionic_appcompat.h
index 1976e0b70..fd3703588 100644
--- a/libc/bionic/bionic_appcompat.h
+++ b/libc/bionic/bionic_appcompat.h
@@ -41,4 +41,4 @@ static inline const char* const soft_mac_getlink_allowlist[] = {
int get_package_name(char* buffer, const int bufferlen);
bool should_apply_soft_mac_bind_restrictions();
-bool should_apply_soft_mac_getlink_restrictions(); \ No newline at end of file
+bool should_apply_soft_mac_getlink_restrictions();
diff --git a/libc/bionic/fts.c b/libc/bionic/fts.c
index 8888ab18a..77b411762 100644
--- a/libc/bionic/fts.c
+++ b/libc/bionic/fts.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fts.c,v 1.48 2014/11/20 04:14:15 guenther Exp $ */
+/* $OpenBSD: fts.c,v 1.60 2021/01/08 16:06:30 tb Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -29,10 +29,9 @@
* SUCH DAMAGE.
*/
-#include <sys/param.h>
+#include <sys/param.h> /* ALIGN */
#include <sys/stat.h>
-#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -42,7 +41,9 @@
#include <string.h>
#include <unistd.h>
-static FTSENT *fts_alloc(FTS *, char *, size_t);
+#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
+
+static FTSENT *fts_alloc(FTS *, const char *, size_t);
static FTSENT *fts_build(FTS *, int);
static void fts_lfree(FTSENT *);
static void fts_load(FTS *, FTSENT *);
@@ -51,11 +52,12 @@ static void fts_padjust(FTS *, FTSENT *);
static int fts_palloc(FTS *, size_t);
static FTSENT *fts_sort(FTS *, FTSENT *, int);
static u_short fts_stat(FTS *, FTSENT *, int, int);
-static int fts_safe_changedir(FTS *, FTSENT *, int, char *);
+static int fts_safe_changedir(FTS *, FTSENT *, int, const char *);
-#define ALIGNBYTES (sizeof(uintptr_t) - 1)
-#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
-void* reallocarray(void*, size_t, size_t);
+/* Android: OpenBSD source compatibility workarounds. */
+#include "private/bsd_sys_param.h"
+#define DEF_WEAK(s) /* nothing */
+void* recallocarray(void*, size_t, size_t, size_t);
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
@@ -70,12 +72,22 @@ void* reallocarray(void*, size_t, size_t);
#define BNAMES 2 /* fts_children, names only */
#define BREAD 3 /* fts_read */
-FTS* __fts_open(char* const* argv, int options, int (*compar)(const FTSENT**, const FTSENT**)) {
+FTS *
+__fts_open(char * const *argv, int options,
+ int (*compar)(const FTSENT **, const FTSENT **))
+{
FTS *sp;
FTSENT *p, *root;
int nitems;
- FTSENT *parent, *tmp;
- size_t len;
+ FTSENT *parent, *prev;
+
+ /* Android: options check moved to __fts_open() for ftw(). */
+
+ /* At least one path must be specified. */
+ if (*argv == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
/* Allocate/initialize the stream */
if ((sp = calloc(1, sizeof(FTS))) == NULL)
@@ -91,7 +103,7 @@ FTS* __fts_open(char* const* argv, int options, int (*compar)(const FTSENT**, co
* Start out with 1K of path space, and enough, in any case,
* to hold the user's paths.
*/
- if (fts_palloc(sp, MAX(fts_maxarglen(argv), PATH_MAX)))
+ if (fts_palloc(sp, MAXIMUM(fts_maxarglen(argv), PATH_MAX)))
goto mem1;
/* Allocate/initialize root's parent. */
@@ -100,21 +112,15 @@ FTS* __fts_open(char* const* argv, int options, int (*compar)(const FTSENT**, co
parent->fts_level = FTS_ROOTPARENTLEVEL;
/* Allocate/initialize root(s). */
- for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
- /* Don't allow zero-length paths. */
- if ((len = strlen(*argv)) == 0) {
- errno = ENOENT;
- goto mem3;
- }
-
- if ((p = fts_alloc(sp, *argv, len)) == NULL)
+ for (root = prev = NULL, nitems = 0; *argv; ++argv, ++nitems) {
+ if ((p = fts_alloc(sp, *argv, strlen(*argv))) == NULL)
goto mem3;
p->fts_level = FTS_ROOTLEVEL;
p->fts_parent = parent;
p->fts_accpath = p->fts_name;
p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), -1);
- // For ftw/nftw we need to fail early: http://b/31152735
+ // Android: for ftw/nftw we need to fail early: http://b/31152735
if ((options & FTS_FOR_FTW) != 0 && p->fts_info == FTS_NS) goto mem3;
/* Command-line "." and ".." are real directories. */
@@ -131,11 +137,10 @@ FTS* __fts_open(char* const* argv, int options, int (*compar)(const FTSENT**, co
} else {
p->fts_link = NULL;
if (root == NULL)
- tmp = root = p;
- else {
- tmp->fts_link = p;
- tmp = p;
- }
+ root = p;
+ else
+ prev->fts_link = p;
+ prev = p;
}
}
if (compar && nitems > 1)
@@ -158,7 +163,8 @@ FTS* __fts_open(char* const* argv, int options, int (*compar)(const FTSENT**, co
* and ".." are all fairly nasty problems. Note, if we can't get the
* descriptor we run anyway, just more slowly.
*/
- if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY|O_CLOEXEC, 0)) < 0)
+ if (!ISSET(FTS_NOCHDIR) &&
+ (sp->fts_rfd = open(".", O_RDONLY | O_CLOEXEC)) == -1)
SET(FTS_NOCHDIR);
if (nitems == 0)
@@ -172,6 +178,7 @@ mem2: free(sp->fts_path);
mem1: free(sp);
return (NULL);
}
+DEF_WEAK(fts_open);
static void
fts_load(FTS *sp, FTSENT *p)
@@ -221,7 +228,8 @@ fts_close(FTS *sp)
rfd = ISSET(FTS_NOCHDIR) ? -1 : sp->fts_rfd;
/* Free up child linked list, sort array, path buffer, stream ptr.*/
- fts_lfree(sp->fts_child);
+ if (sp->fts_child)
+ fts_lfree(sp->fts_child);
free(sp->fts_array);
free(sp->fts_path);
free(sp);
@@ -237,6 +245,7 @@ fts_close(FTS *sp)
return (error);
}
+DEF_WEAK(fts_close);
/*
* Special case of "/" at the end of the path so that slashes aren't
@@ -281,7 +290,8 @@ fts_read(FTS *sp)
(p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
p->fts_info = fts_stat(sp, p, 1, -1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
- if ((p->fts_symfd = open(".", O_RDONLY|O_CLOEXEC, 0)) < 0) {
+ if ((p->fts_symfd =
+ open(".", O_RDONLY | O_CLOEXEC)) == -1) {
p->fts_errno = errno;
p->fts_info = FTS_ERR;
} else
@@ -370,7 +380,8 @@ next: tmp = p;
if (p->fts_instr == FTS_FOLLOW) {
p->fts_info = fts_stat(sp, p, 1, -1);
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
- if ((p->fts_symfd = open(".", O_RDONLY|O_CLOEXEC, 0)) < 0) {
+ if ((p->fts_symfd =
+ open(".", O_RDONLY | O_CLOEXEC)) == -1) {
p->fts_errno = errno;
p->fts_info = FTS_ERR;
} else
@@ -432,6 +443,7 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
return (sp->fts_cur = p);
}
+DEF_WEAK(fts_read);
/*
* Fts_set takes the stream as an argument although it's not used in this
@@ -439,7 +451,6 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
* semantics to fts using fts_set. An error return is allowed for similar
* reasons.
*/
-/* ARGSUSED */
int
fts_set(FTS *sp __unused, FTSENT *p, int instr)
{
@@ -451,6 +462,7 @@ fts_set(FTS *sp __unused, FTSENT *p, int instr)
p->fts_instr = instr;
return (0);
}
+DEF_WEAK(fts_set);
FTSENT *
fts_children(FTS *sp, int instr)
@@ -489,7 +501,8 @@ fts_children(FTS *sp, int instr)
return (NULL);
/* Free up any previous child list. */
- fts_lfree(sp->fts_child);
+ if (sp->fts_child)
+ fts_lfree(sp->fts_child);
if (instr == FTS_NAMEONLY) {
SET(FTS_NAMEONLY);
@@ -508,7 +521,7 @@ fts_children(FTS *sp, int instr)
ISSET(FTS_NOCHDIR))
return (sp->fts_child = fts_build(sp, instr));
- if ((fd = open(".", O_RDONLY|O_CLOEXEC, 0)) < 0)
+ if ((fd = open(".", O_RDONLY | O_CLOEXEC)) == -1)
return (NULL);
sp->fts_child = fts_build(sp, instr);
if (fchdir(fd)) {
@@ -518,6 +531,7 @@ fts_children(FTS *sp, int instr)
(void)close(fd);
return (sp->fts_child);
}
+DEF_WEAK(fts_children);
/*
* This is the tricky part -- do not casually change *anything* in here. The
@@ -542,9 +556,9 @@ fts_build(FTS *sp, int type)
DIR *dirp;
void *oldaddr;
size_t len, maxlen;
- int nitems, cderrno, descend, level, nlinks, nostat = 0, doadjust;
+ int nitems, cderrno, descend, level, nlinks, nostat, doadjust;
int saved_errno;
- char *cp = NULL;
+ char *cp;
/* Set current node pointer. */
cur = sp->fts_cur;
@@ -709,8 +723,7 @@ mem1: saved_errno = errno;
/* Build a file name for fts_stat to stat. */
if (ISSET(FTS_NOCHDIR)) {
p->fts_accpath = p->fts_path;
- assert(cp && "cp should be non-null if FTS_NOCHDIR is set");
- memmove(cp, p->fts_name, p->fts_namelen + 1); // NOLINT
+ memmove(cp, p->fts_name, p->fts_namelen + 1);
p->fts_info = fts_stat(sp, p, 0, dirfd(dirp));
} else {
p->fts_accpath = p->fts_name;
@@ -806,9 +819,9 @@ fts_stat(FTS *sp, FTSENT *p, int follow, int dfd)
* fail, set the errno from the stat call.
*/
if (ISSET(FTS_LOGICAL) || follow) {
- if (fstatat(dfd, path, sbp, 0) == -1) {
+ if (fstatat(dfd, path, sbp, 0)) {
saved_errno = errno;
- if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW) == 0) {
+ if (!fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) {
errno = 0;
return (FTS_SLNONE);
}
@@ -872,19 +885,19 @@ fts_sort(FTS *sp, FTSENT *head, int nitems)
if (nitems > sp->fts_nitems) {
struct _ftsent **a;
- sp->fts_nitems = nitems + 40;
if ((a = reallocarray(sp->fts_array,
- sp->fts_nitems, sizeof(FTSENT *))) == NULL) {
+ nitems + 40, sizeof(FTSENT *))) == NULL) {
free(sp->fts_array);
sp->fts_array = NULL;
sp->fts_nitems = 0;
return (head);
}
+ sp->fts_nitems = nitems + 40;
sp->fts_array = a;
}
for (ap = sp->fts_array, p = head; p; p = p->fts_link)
*ap++ = p;
- qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
+ qsort(sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
for (head = *(ap = sp->fts_array); --nitems; ++ap)
ap[0]->fts_link = ap[1];
ap[0]->fts_link = NULL;
@@ -892,7 +905,7 @@ fts_sort(FTS *sp, FTSENT *head, int nitems)
}
static FTSENT *
-fts_alloc(FTS *sp, char *name, size_t namelen)
+fts_alloc(FTS *sp, const char *name, size_t namelen)
{
FTSENT *p;
size_t len;
@@ -954,13 +967,14 @@ fts_palloc(FTS *sp, size_t more)
errno = ENAMETOOLONG;
return (1);
}
- sp->fts_pathlen += more;
- p = realloc(sp->fts_path, sp->fts_pathlen);
+ p = recallocarray(sp->fts_path, sp->fts_pathlen,
+ sp->fts_pathlen + more, 1);
if (p == NULL) {
free(sp->fts_path);
sp->fts_path = NULL;
return (1);
}
+ sp->fts_pathlen += more;
sp->fts_path = p;
return (0);
}
@@ -1010,7 +1024,7 @@ fts_maxarglen(char * const *argv)
* Assumes p->fts_dev and p->fts_ino are filled in.
*/
static int
-fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
+fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const char *path)
{
int ret, oerrno, newfd;
struct stat sb;
@@ -1018,9 +1032,9 @@ fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
newfd = fd;
if (ISSET(FTS_NOCHDIR))
return (0);
- if (fd < 0 && (newfd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0)) < 0)
+ if (fd == -1 && (newfd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC)) == -1)
return (-1);
- if (fstat(newfd, &sb)) {
+ if (fstat(newfd, &sb) == -1) {
ret = -1;
goto bail;
}
@@ -1032,17 +1046,21 @@ fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
ret = fchdir(newfd);
bail:
oerrno = errno;
- if (fd < 0)
+ if (fd == -1)
(void)close(newfd);
errno = oerrno;
return (ret);
}
-FTS* fts_open(char* const* argv, int options, int (*compar)(const FTSENT**, const FTSENT**)) {
- // Options check.
- if ((options & ~FTS_OPTIONMASK) != 0) {
- errno = EINVAL;
- return NULL;
- }
- return __fts_open(argv, options, compar);
+FTS *
+fts_open(char * const *argv, int options,
+ int (*compar)(const FTSENT **, const FTSENT **))
+{
+ // Android needs to an __fts_open() that doesn't make this check
+ // so that FTS_FOR_FTW works.
+ if (options & ~FTS_OPTIONMASK) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ return __fts_open(argv, options, compar);
}
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index 2c5d4d8cb..ffbabb9a0 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -32,7 +32,6 @@
#include <bionic/pthread_internal.h>
#include <platform/bionic/malloc.h>
-#include <platform/bionic/mte_kernel.h>
extern "C" void scudo_malloc_disable_memory_tagging();
extern "C" void scudo_malloc_set_track_allocation_stacks(int);
@@ -42,35 +41,36 @@ static HeapTaggingLevel heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
void SetDefaultHeapTaggingLevel() {
#if defined(__aarch64__)
-#ifdef ANDROID_EXPERIMENTAL_MTE
- // First, try enabling MTE in asynchronous mode, with tag 0 excluded. This will fail if the kernel
- // or hardware doesn't support MTE, and we will fall back to just enabling tagged pointers in
- // syscall arguments.
- if (prctl(PR_SET_TAGGED_ADDR_CTRL,
- PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_ASYNC | (0xfffe << PR_MTE_TAG_SHIFT), 0, 0,
- 0) == 0) {
- heap_tagging_level = M_HEAP_TAGGING_LEVEL_ASYNC;
- return;
- }
-#endif // ANDROID_EXPERIMENTAL_MTE
-
- // Allow the kernel to accept tagged pointers in syscall arguments. This is a no-op (kernel
- // returns -EINVAL) if the kernel doesn't understand the prctl.
- if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) {
#if !__has_feature(hwaddress_sanitizer)
- heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
- __libc_globals.mutate([](libc_globals* globals) {
- // Arrange for us to set pointer tags to POINTER_TAG, check tags on
- // deallocation and untag when passing pointers to the allocator.
- globals->heap_pointer_tag = (reinterpret_cast<uintptr_t>(POINTER_TAG) << TAG_SHIFT) |
- (0xffull << CHECK_SHIFT) | (0xffull << UNTAG_SHIFT);
- });
-#endif // hwaddress_sanitizer
+ heap_tagging_level = __libc_shared_globals()->initial_heap_tagging_level;
+#endif
+ switch (heap_tagging_level) {
+ case M_HEAP_TAGGING_LEVEL_TBI:
+ __libc_globals.mutate([](libc_globals* globals) {
+ // Arrange for us to set pointer tags to POINTER_TAG, check tags on
+ // deallocation and untag when passing pointers to the allocator.
+ globals->heap_pointer_tag = (reinterpret_cast<uintptr_t>(POINTER_TAG) << TAG_SHIFT) |
+ (0xffull << CHECK_SHIFT) | (0xffull << UNTAG_SHIFT);
+ });
+#if defined(USE_SCUDO)
+ scudo_malloc_disable_memory_tagging();
+#endif // USE_SCUDO
+ break;
+#if defined(USE_SCUDO)
+ case M_HEAP_TAGGING_LEVEL_SYNC:
+ scudo_malloc_set_track_allocation_stacks(1);
+ break;
+
+ case M_HEAP_TAGGING_LEVEL_NONE:
+ scudo_malloc_disable_memory_tagging();
+ break;
+#endif // USE_SCUDO
+ default:
+ break;
}
#endif // aarch64
}
-#ifdef ANDROID_EXPERIMENTAL_MTE
static bool set_tcf_on_all_threads(int tcf) {
static int g_tcf;
g_tcf = tcf;
@@ -90,7 +90,6 @@ static bool set_tcf_on_all_threads(int tcf) {
},
nullptr);
}
-#endif
pthread_mutex_t g_heap_tagging_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -100,12 +99,7 @@ HeapTaggingLevel GetHeapTaggingLevel() {
}
// Requires `g_heap_tagging_lock` to be held.
-bool SetHeapTaggingLevel(void* arg, size_t arg_size) {
- if (arg_size != sizeof(HeapTaggingLevel)) {
- return false;
- }
-
- auto tag_level = *reinterpret_cast<HeapTaggingLevel*>(arg);
+bool SetHeapTaggingLevel(HeapTaggingLevel tag_level) {
if (tag_level == heap_tagging_level) {
return true;
}
@@ -119,13 +113,9 @@ bool SetHeapTaggingLevel(void* arg, size_t arg_size) {
// tagged and checks no longer happen.
globals->heap_pointer_tag = static_cast<uintptr_t>(0xffull << UNTAG_SHIFT);
});
- } else {
-#if defined(ANDROID_EXPERIMENTAL_MTE)
- if (!set_tcf_on_all_threads(PR_MTE_TCF_NONE)) {
- error_log("SetHeapTaggingLevel: set_tcf_on_all_threads failed");
- return false;
- }
-#endif
+ } else if (!set_tcf_on_all_threads(PR_MTE_TCF_NONE)) {
+ error_log("SetHeapTaggingLevel: set_tcf_on_all_threads failed");
+ return false;
}
#if defined(USE_SCUDO)
scudo_malloc_disable_memory_tagging();
@@ -135,8 +125,12 @@ bool SetHeapTaggingLevel(void* arg, size_t arg_size) {
case M_HEAP_TAGGING_LEVEL_ASYNC:
case M_HEAP_TAGGING_LEVEL_SYNC:
if (heap_tagging_level == M_HEAP_TAGGING_LEVEL_NONE) {
+#if !__has_feature(hwaddress_sanitizer)
+ // Suppress the error message in HWASan builds. Apps can try to enable TBI (or even MTE
+ // modes) being unaware of HWASan, fail them silently.
error_log(
"SetHeapTaggingLevel: re-enabling tagging after it was disabled is not supported");
+#endif
return false;
} else if (tag_level == M_HEAP_TAGGING_LEVEL_TBI ||
heap_tagging_level == M_HEAP_TAGGING_LEVEL_TBI) {
@@ -145,16 +139,12 @@ bool SetHeapTaggingLevel(void* arg, size_t arg_size) {
}
if (tag_level == M_HEAP_TAGGING_LEVEL_ASYNC) {
-#if defined(ANDROID_EXPERIMENTAL_MTE)
set_tcf_on_all_threads(PR_MTE_TCF_ASYNC);
-#endif
#if defined(USE_SCUDO)
scudo_malloc_set_track_allocation_stacks(0);
#endif
} else if (tag_level == M_HEAP_TAGGING_LEVEL_SYNC) {
-#if defined(ANDROID_EXPERIMENTAL_MTE)
set_tcf_on_all_threads(PR_MTE_TCF_SYNC);
-#endif
#if defined(USE_SCUDO)
scudo_malloc_set_track_allocation_stacks(1);
#endif
diff --git a/libc/bionic/heap_tagging.h b/libc/bionic/heap_tagging.h
index db45fc100..110b6ed7a 100644
--- a/libc/bionic/heap_tagging.h
+++ b/libc/bionic/heap_tagging.h
@@ -42,5 +42,5 @@ extern pthread_mutex_t g_heap_tagging_lock;
// These functions can be called in a multithreaded context, and thus should
// only be called when holding the `g_heap_tagging_lock`.
-bool SetHeapTaggingLevel(void* arg, size_t arg_size);
+bool SetHeapTaggingLevel(HeapTaggingLevel level);
HeapTaggingLevel GetHeapTaggingLevel();
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 80adbbe8e..f2c3f1c68 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -86,7 +86,7 @@ static void arc4random_fork_handler() {
_thread_arc4_lock();
}
-static void __libc_init_malloc_fill_contents() {
+void __libc_init_scudo() {
// TODO(b/158870657) make this unconditional when all devices support SCUDO.
#if defined(USE_SCUDO)
#if defined(SCUDO_PATTERN_FILL_CONTENTS)
@@ -95,6 +95,7 @@ static void __libc_init_malloc_fill_contents() {
scudo_malloc_set_zero_contents(1);
#endif
#endif
+ SetDefaultHeapTaggingLevel();
}
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
@@ -119,9 +120,6 @@ void __libc_init_common() {
__system_properties_init(); // Requires 'environ'.
__libc_init_fdsan(); // Requires system properties (for debug.fdsan).
__libc_init_fdtrack();
-
- __libc_init_malloc_fill_contents();
- SetDefaultHeapTaggingLevel();
}
void __libc_init_fork_handler() {
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index be7526f5f..a89908916 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -28,6 +28,7 @@
#pragma once
+#include <stdint.h>
#include <sys/cdefs.h>
typedef void init_func_t(int, char*[], char*[]);
@@ -57,6 +58,8 @@ __LIBC_HIDDEN__ void __libc_init_globals();
__LIBC_HIDDEN__ void __libc_init_common();
+__LIBC_HIDDEN__ void __libc_init_scudo();
+
__LIBC_HIDDEN__ void __libc_init_AT_SECURE(char** envp);
// The fork handler must be initialised after __libc_init_malloc, as
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index c9da02eab..175fa3ee9 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -90,6 +90,7 @@ static void __libc_preinit_impl() {
__libc_init_globals();
__libc_init_common();
+ __libc_init_scudo();
// Hooks for various libraries to let them know that we're starting up.
__libc_globals.mutate(__libc_init_malloc);
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 4a73918f2..2e4ee11a9 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -39,13 +39,17 @@
#include "libc_init_common.h"
#include "pthread_internal.h"
+#include "platform/bionic/macros.h"
+#include "platform/bionic/mte.h"
#include "platform/bionic/page.h"
+#include "private/KernelArgumentBlock.h"
+#include "private/bionic_asm.h"
+#include "private/bionic_asm_note.h"
#include "private/bionic_call_ifunc_resolver.h"
#include "private/bionic_elf_tls.h"
#include "private/bionic_globals.h"
-#include "platform/bionic/macros.h"
#include "private/bionic_tls.h"
-#include "private/KernelArgumentBlock.h"
+#include "sys/system_properties.h"
#if __has_feature(hwaddress_sanitizer)
#include <sanitizer/hwasan_interface.h>
@@ -59,6 +63,7 @@ __LIBC_HIDDEN__ void* __libc_sysinfo;
#endif
extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
+extern "C" const char* __gnu_basename(const char* path);
static void call_array(init_func_t** list, int argc, char* argv[], char* envp[]) {
// First element is -1, list is null-terminated
@@ -158,6 +163,170 @@ static void layout_static_tls(KernelArgumentBlock& args) {
layout.finish_layout();
}
+// Get the presiding config string, in the following order of priority:
+// 1. Environment variables.
+// 2. System properties, in the order they're specified in sys_prop_names.
+// If neither of these options are specified, this function returns false.
+// Otherwise, it returns true, and the presiding options string is written to
+// the `options` buffer of size `size`. If this function returns true, `options`
+// is guaranteed to be null-terminated. `options_size` should be at least
+// PROP_VALUE_MAX.
+bool get_config_from_env_or_sysprops(const char* env_var_name, const char* const* sys_prop_names,
+ size_t sys_prop_names_size, char* options,
+ size_t options_size) {
+ const char* env = getenv(env_var_name);
+ if (env && *env != '\0') {
+ strncpy(options, env, options_size);
+ options[options_size - 1] = '\0'; // Ensure null-termination.
+ return true;
+ }
+
+ for (size_t i = 0; i < sys_prop_names_size; ++i) {
+ if (__system_property_get(sys_prop_names[i], options) && *options != '\0') return true;
+ }
+ return false;
+}
+
+#ifdef __aarch64__
+static bool __read_memtag_note(const ElfW(Nhdr)* note, const char* name, const char* desc,
+ unsigned* result) {
+ if (note->n_namesz != 8 || strncmp(name, "Android", 8) != 0) {
+ return false;
+ }
+ if (note->n_type != NT_TYPE_MEMTAG) {
+ return false;
+ }
+ if (note->n_descsz != 4) {
+ async_safe_fatal("unrecognized android.memtag note: n_descsz = %d, expected 4", note->n_descsz);
+ }
+ *result = *reinterpret_cast<const ElfW(Word)*>(desc);
+ return true;
+}
+
+static unsigned __get_memtag_note(const ElfW(Phdr)* phdr_start, size_t phdr_ct,
+ const ElfW(Addr) load_bias) {
+ for (size_t i = 0; i < phdr_ct; ++i) {
+ const ElfW(Phdr)* phdr = &phdr_start[i];
+ if (phdr->p_type != PT_NOTE) {
+ continue;
+ }
+ ElfW(Addr) p = load_bias + phdr->p_vaddr;
+ ElfW(Addr) note_end = load_bias + phdr->p_vaddr + phdr->p_memsz;
+ while (p + sizeof(ElfW(Nhdr)) <= note_end) {
+ const ElfW(Nhdr)* note = reinterpret_cast<const ElfW(Nhdr)*>(p);
+ p += sizeof(ElfW(Nhdr));
+ const char* name = reinterpret_cast<const char*>(p);
+ p += align_up(note->n_namesz, 4);
+ const char* desc = reinterpret_cast<const char*>(p);
+ p += align_up(note->n_descsz, 4);
+ if (p > note_end) {
+ break;
+ }
+ unsigned ret;
+ if (__read_memtag_note(note, name, desc, &ret)) {
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+// Returns true if there's an environment setting (either sysprop or env var)
+// that should overwrite the ELF note, and places the equivalent heap tagging
+// level into *level.
+static bool get_environment_memtag_setting(HeapTaggingLevel* level) {
+ static const char kMemtagPrognameSyspropPrefix[] = "arm64.memtag.process.";
+
+ const char* progname = __libc_shared_globals()->init_progname;
+ if (progname == nullptr) return false;
+
+ const char* basename = __gnu_basename(progname);
+
+ static constexpr size_t kOptionsSize = PROP_VALUE_MAX;
+ char options_str[kOptionsSize];
+ size_t sysprop_size = strlen(basename) + strlen(kMemtagPrognameSyspropPrefix) + 1;
+ char* sysprop_name = static_cast<char*>(alloca(sysprop_size));
+
+ async_safe_format_buffer(sysprop_name, sysprop_size, "%s%s", kMemtagPrognameSyspropPrefix,
+ basename);
+
+ if (!get_config_from_env_or_sysprops("MEMTAG_OPTIONS", &sysprop_name,
+ /* sys_prop_names_size */ 1, options_str, kOptionsSize)) {
+ return false;
+ }
+
+ if (strcmp("sync", options_str) == 0) {
+ *level = M_HEAP_TAGGING_LEVEL_SYNC;
+ } else if (strcmp("async", options_str) == 0) {
+ *level = M_HEAP_TAGGING_LEVEL_ASYNC;
+ } else if (strcmp("off", options_str) == 0) {
+ *level = M_HEAP_TAGGING_LEVEL_TBI;
+ } else {
+ async_safe_format_log(
+ ANDROID_LOG_ERROR, "libc",
+ "unrecognized memtag level: \"%s\" (options are \"sync\", \"async\", or \"off\").",
+ options_str);
+ return false;
+ }
+
+ return true;
+}
+
+// Returns the initial heap tagging level. Note: This function will never return
+// M_HEAP_TAGGING_LEVEL_NONE, if MTE isn't enabled for this process we enable
+// M_HEAP_TAGGING_LEVEL_TBI.
+static HeapTaggingLevel __get_heap_tagging_level(const void* phdr_start, size_t phdr_ct,
+ uintptr_t load_bias) {
+ HeapTaggingLevel level;
+ if (get_environment_memtag_setting(&level)) return level;
+
+ unsigned note_val =
+ __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
+ if (note_val & ~(NT_MEMTAG_LEVEL_MASK | NT_MEMTAG_HEAP)) {
+ async_safe_fatal("unrecognized android.memtag note: desc = %d", note_val);
+ }
+
+ if (!(note_val & NT_MEMTAG_HEAP)) return M_HEAP_TAGGING_LEVEL_TBI;
+
+ unsigned memtag_level = note_val & NT_MEMTAG_LEVEL_MASK;
+ switch (memtag_level) {
+ case NT_MEMTAG_LEVEL_ASYNC:
+ return M_HEAP_TAGGING_LEVEL_ASYNC;
+ case NT_MEMTAG_LEVEL_DEFAULT:
+ case NT_MEMTAG_LEVEL_SYNC:
+ return M_HEAP_TAGGING_LEVEL_SYNC;
+ default:
+ async_safe_fatal("unrecognized android.memtag note: level = %d", memtag_level);
+ }
+}
+
+// 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(const void* phdr_start,
+ size_t phdr_ct,
+ uintptr_t load_bias) {
+ HeapTaggingLevel level = __get_heap_tagging_level(phdr_start, phdr_ct, load_bias);
+
+ if (level == M_HEAP_TAGGING_LEVEL_SYNC || level == M_HEAP_TAGGING_LEVEL_ASYNC) {
+ unsigned long prctl_arg = PR_TAGGED_ADDR_ENABLE | PR_MTE_TAG_SET_NONZERO;
+ prctl_arg |= (level == M_HEAP_TAGGING_LEVEL_SYNC) ? PR_MTE_TCF_SYNC : PR_MTE_TCF_ASYNC;
+
+ if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg, 0, 0, 0) == 0) {
+ __libc_shared_globals()->initial_heap_tagging_level = level;
+ return;
+ }
+ }
+
+ // MTE was either not enabled, or wasn't supported on this device. Try and use
+ // TBI.
+ if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) {
+ __libc_shared_globals()->initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
+ }
+}
+#else // __aarch64__
+void __libc_init_mte(const void*, size_t, uintptr_t) {}
+#endif // __aarch64__
+
__noreturn static void __real_libc_init(void *raw_args,
void (*onexit)(void) __unused,
int (*slingshot)(int, char**, char**),
@@ -175,6 +344,9 @@ __noreturn static void __real_libc_init(void *raw_args,
layout_static_tls(args);
__libc_init_main_thread_final();
__libc_init_common();
+ __libc_init_mte(reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)), getauxval(AT_PHNUM),
+ /*load_bias = */ 0);
+ __libc_init_scudo();
__libc_init_fork_handler();
call_ifunc_resolvers();
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 0ee12a7fd..863103deb 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -102,6 +102,15 @@ extern "C" int malloc_info(int options, FILE* fp) {
}
extern "C" int mallopt(int param, int value) {
+ // Some are handled by libc directly rather than by the allocator.
+ if (param == M_BIONIC_SET_HEAP_TAGGING_LEVEL) {
+ ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
+ return SetHeapTaggingLevel(static_cast<HeapTaggingLevel>(value));
+ }
+ if (param == M_BIONIC_DISABLE_MEMORY_MITIGATIONS) {
+ return DisableMemoryMitigations(value);
+ }
+ // The rest we pass on...
auto dispatch_table = GetDispatchTable();
if (__predict_false(dispatch_table != nullptr)) {
return dispatch_table->mallopt(param, value);
@@ -316,10 +325,6 @@ extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
return LimitEnable(arg, arg_size);
}
- if (opcode == M_SET_HEAP_TAGGING_LEVEL) {
- ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
- return SetHeapTaggingLevel(arg, arg_size);
- }
if (opcode == M_INITIALIZE_GWP_ASAN) {
if (arg == nullptr || arg_size != sizeof(bool)) {
errno = EINVAL;
@@ -329,9 +334,6 @@ extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
});
}
- if (opcode == M_DISABLE_MEMORY_MITIGATIONS) {
- return DisableMemoryMitigations(arg, arg_size);
- }
errno = ENOTSUP;
return false;
}
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 2d6a1bbcb..7a221d891 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -523,10 +523,6 @@ extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
}
return FreeMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
}
- if (opcode == M_SET_HEAP_TAGGING_LEVEL) {
- ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
- return SetHeapTaggingLevel(arg, arg_size);
- }
if (opcode == M_INITIALIZE_GWP_ASAN) {
if (arg == nullptr || arg_size != sizeof(bool)) {
errno = EINVAL;
@@ -536,9 +532,6 @@ extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
});
}
- if (opcode == M_DISABLE_MEMORY_MITIGATIONS) {
- return DisableMemoryMitigations(arg, arg_size);
- }
// Try heapprofd's mallopt, as it handles options not covered here.
return HeapprofdMallopt(opcode, arg, arg_size);
}
diff --git a/libc/bionic/malloc_tagged_pointers.h b/libc/bionic/malloc_tagged_pointers.h
index de3cc2ed9..484a0802e 100644
--- a/libc/bionic/malloc_tagged_pointers.h
+++ b/libc/bionic/malloc_tagged_pointers.h
@@ -99,9 +99,10 @@ static inline void* MaybeUntagAndCheckPointer(const volatile void* ptr) {
// check below allows us to turn *off* pointer tagging (by setting PointerCheckMask() and
// FixedPointerTag() to zero) and still allow tagged heap allocations to be freed.
if ((ptr_int & PointerCheckMask()) != FixedPointerTag()) {
- // TODO(b/145604058) - Upstream tagged pointers documentation and provide
- // a link to it in the abort message here.
- async_safe_fatal("Pointer tag for %p was truncated.", ptr);
+ async_safe_fatal(
+ "Pointer tag for %p was truncated, see "
+ "'https://source.android.com/devices/tech/debug/tagged-pointers'.",
+ ptr);
}
return reinterpret_cast<void*>(ptr_int & PointerUntagMask());
}
diff --git a/libc/bionic/memory_mitigation_state.cpp b/libc/bionic/memory_mitigation_state.cpp
index 4761d8862..b262f8616 100644
--- a/libc/bionic/memory_mitigation_state.cpp
+++ b/libc/bionic/memory_mitigation_state.cpp
@@ -47,8 +47,8 @@
extern "C" void scudo_malloc_set_zero_contents(int zero_contents);
-bool DisableMemoryMitigations(void* arg, size_t arg_size) {
- if (arg || arg_size) {
+bool DisableMemoryMitigations(int arg) {
+ if (arg != 0) {
return false;
}
@@ -61,7 +61,7 @@ bool DisableMemoryMitigations(void* arg, size_t arg_size) {
HeapTaggingLevel current_level = GetHeapTaggingLevel();
if (current_level != M_HEAP_TAGGING_LEVEL_NONE && current_level != M_HEAP_TAGGING_LEVEL_TBI) {
HeapTaggingLevel level = M_HEAP_TAGGING_LEVEL_NONE;
- SetHeapTaggingLevel(reinterpret_cast<void*>(&level), sizeof(level));
+ SetHeapTaggingLevel(level);
}
return true;
diff --git a/libc/bionic/memory_mitigation_state.h b/libc/bionic/memory_mitigation_state.h
index ffa19121d..047b6ad3a 100644
--- a/libc/bionic/memory_mitigation_state.h
+++ b/libc/bionic/memory_mitigation_state.h
@@ -30,4 +30,4 @@
#include <stddef.h>
-bool DisableMemoryMitigations(void* arg, size_t arg_size);
+bool DisableMemoryMitigations(int arg);
diff --git a/libc/bionic/recvmsg.cpp b/libc/bionic/recvmsg.cpp
index 003f43d8a..4d3f98939 100644
--- a/libc/bionic/recvmsg.cpp
+++ b/libc/bionic/recvmsg.cpp
@@ -39,7 +39,7 @@ extern "C" int __recvmmsg(int __fd, struct mmsghdr* __msgs, unsigned int __msg_c
static inline __attribute__((artificial)) __attribute__((always_inline)) void track_fds(
struct msghdr* msg, const char* function_name) {
- if (!__android_fdtrack_hook) {
+ if (!atomic_load(&__android_fdtrack_hook)) {
return;
}
diff --git a/libc/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c
index 84942f876..f8212a295 100644
--- a/libc/dns/net/gethnamaddr.c
+++ b/libc/dns/net/gethnamaddr.c
@@ -75,9 +75,6 @@
#include <syslog.h>
#include <unistd.h>
-#define ALIGNBYTES (sizeof(uintptr_t) - 1)
-#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
-
#ifndef LOG_AUTH
# define LOG_AUTH 0
#endif
diff --git a/libc/dns/net/sethostent.c b/libc/dns/net/sethostent.c
index a743a543e..b2b0132c5 100644
--- a/libc/dns/net/sethostent.c
+++ b/libc/dns/net/sethostent.c
@@ -55,9 +55,6 @@ __RCSID("$NetBSD: sethostent.c,v 1.20 2014/03/17 13:24:23 christos Exp $");
#include "hostent.h"
#include "resolv_private.h"
-#define ALIGNBYTES (sizeof(uintptr_t) - 1)
-#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
-
#ifndef _REENTRANT
void res_close(void);
#endif
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index bcddddd59..40846fb8b 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -151,6 +151,9 @@ __BEGIN_DECLS
/** Names the "S" API level (31), for comparison against `__ANDROID_API__`. */
#define __ANDROID_API_S__ 31
+/* This file is included in <features.h>, and might be used from .S files. */
+#if !defined(__ASSEMBLY__)
+
/**
* Returns the `targetSdkVersion` of the caller, or `__ANDROID_API_FUTURE__` if
* there is no known target SDK version (for code not running in the context of
@@ -167,7 +170,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.
+/* android_get_device_api_level is a static inline before API level 29. */
#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
#include <bits/get_device_api_level_inlines.h>
#undef __BIONIC_GET_DEVICE_API_LEVEL_INLINE
@@ -185,6 +188,8 @@ int android_get_device_api_level() __INTRODUCED_IN(29);
#endif
+#endif /* defined(__ASSEMBLY__) */
+
__END_DECLS
/** @} */
diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h
index 90eda7dc1..a6734464c 100644
--- a/libc/include/android/legacy_signal_inlines.h
+++ b/libc/include/android/legacy_signal_inlines.h
@@ -45,12 +45,16 @@ int __libc_current_sigrtmax() __attribute__((__weak__)) __VERSIONER_NO_GUARD;
int __libc_current_sigrtmin() __attribute__((__weak__)) __VERSIONER_NO_GUARD;
static __inline int __ndk_legacy___libc_current_sigrtmax() {
- if (__libc_current_sigrtmax) return __libc_current_sigrtmax();
+ if (__builtin_available(android 21, *)) {
+ return __libc_current_sigrtmax();
+ }
return __SIGRTMAX; /* Should match __libc_current_sigrtmax. */
}
static __inline int __ndk_legacy___libc_current_sigrtmin() {
- if (__libc_current_sigrtmin) return __libc_current_sigrtmin();
+ if (__builtin_available(android 21, *)) {
+ return __libc_current_sigrtmin();
+ }
return __SIGRTMIN + 7; /* Should match __libc_current_sigrtmin. */
}
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index 3ea414a45..2b9a0272b 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -33,13 +33,62 @@
#else
-#define __INTRODUCED_IN(api_level)
-#define __DEPRECATED_IN(api_level)
-#define __REMOVED_IN(api_level)
-#define __INTRODUCED_IN_32(api_level)
+// When headers are not processed by the versioner (i.e. compiled into object files),
+// the availability attributed is emitted instead. The clang compiler will make the symbol weak
+// when targeting old api_level and enforce the reference to the symbol to be guarded with
+// __builtin_available(android api_level, *).
+
+// The 'strict' flag is required for NDK clients where the use of "-Wunguarded-availability" cannot
+// be enforced. In the case, the absence of 'strict' makes it possible to call an unavailable API
+// without the __builtin_available check, which will cause a link error at runtime.
+// Android platform build system defines this macro along with -Wunguarded-availability
+#if defined(__ANDROID_UNGUARDED_AVAILABILITY__)
+#define __MAYBE_STRICT
+#else
+#define __MAYBE_STRICT ,strict
+#endif
+
+#define __INTRODUCED_IN(api_level) \
+ __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
+#define __DEPRECATED_IN(api_level) \
+ __attribute__((availability(android __MAYBE_STRICT,deprecated=api_level)))
+#define __REMOVED_IN(api_level) \
+ __attribute__((availability(android __MAYBE_STRICT,obsoleted=api_level)))
+
+// 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
+// cause inconsistent availability values which is an error with -Wavailability:
+//
+// void foo() __INTRODUCED_IN_32(30) __INTRODUCED_IN_64(31);
+//
+// This also takes the advantage of the fact that we never use bitness-specific macro with
+// arch-specific macro. In other words,
+//
+// void foo() __INTRODUCED_IN_ARM(30) __INTRODUCED_IN_64(31);
+//
+// hasn't been supported and won't be.
+#if !defined(__LP64__)
+#define __INTRODUCED_IN_32(api_level) \
+ __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
#define __INTRODUCED_IN_64(api_level)
+#else
+#define __INTRODUCED_IN_32(api_level)
+#define __INTRODUCED_IN_64(api_level) \
+ __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
+#endif
+
+#if defined(__arm__) || defined(__aarch64__)
+#define __INTRODUCED_IN_ARM(api_level) \
+ __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
+#define __INTRODUCED_IN_X86(api_level)
+#elif defined(__i386__) || defined(__x86_64__)
+#define __INTRODUCED_IN_ARM(api_level)
+#define __INTRODUCED_IN_X86(api_level) \
+ __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
+#else
#define __INTRODUCED_IN_ARM(api_level)
#define __INTRODUCED_IN_X86(api_level)
+#endif
#define __VERSIONER_NO_GUARD
#define __VERSIONER_FORTIFY_INLINE
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index a237254b7..598a50bc5 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -204,6 +204,60 @@ int malloc_info(int __must_be_zero, FILE* __fp) __INTRODUCED_IN(23);
#define M_TSDS_COUNT_MAX (-202)
/**
+ * mallopt() option to disable heap initialization across the whole process.
+ * If the hardware supports memory tagging, this also disables memory tagging.
+ * May be called at any time, including when multiple threads are running. The
+ * value is unused but must be set to 0.
+ *
+ * Note that these memory mitigations are only implemented in scudo and
+ * therefore this will have no effect when using another allocator (such as
+ * jemalloc on Android Go devices).
+ *
+ * Available since API level 31.
+ */
+#define M_BIONIC_DISABLE_MEMORY_MITIGATIONS (-203)
+
+/**
+ * mallopt() option to change the heap tagging state. May be called at any
+ * time, including when multiple threads are running.
+ * The value must be one of the M_HEAP_TAGGING_LEVEL_ constants.
+ *
+ * Available since API level 31.
+ */
+#define M_BIONIC_SET_HEAP_TAGGING_LEVEL (-204)
+
+/**
+ * Constants for use with the M_BIONIC_SET_HEAP_TAGGING_LEVEL mallopt() option.
+ */
+enum HeapTaggingLevel {
+ /**
+ * Disable heap tagging and memory tag checks (if supported).
+ * Heap tagging may not be re-enabled after being disabled.
+ */
+ M_HEAP_TAGGING_LEVEL_NONE = 0,
+#define M_HEAP_TAGGING_LEVEL_NONE M_HEAP_TAGGING_LEVEL_NONE
+ /**
+ * Address-only tagging. Heap pointers have a non-zero tag in the
+ * most significant ("top") byte which is checked in free(). Memory
+ * accesses ignore the tag using arm64's Top Byte Ignore (TBI) feature.
+ */
+ M_HEAP_TAGGING_LEVEL_TBI = 1,
+#define M_HEAP_TAGGING_LEVEL_TBI M_HEAP_TAGGING_LEVEL_TBI
+ /**
+ * Enable heap tagging and asynchronous memory tag checks (if supported).
+ * Disable stack trace collection.
+ */
+ M_HEAP_TAGGING_LEVEL_ASYNC = 2,
+#define M_HEAP_TAGGING_LEVEL_ASYNC M_HEAP_TAGGING_LEVEL_ASYNC
+ /**
+ * Enable heap tagging and synchronous memory tag checks (if supported).
+ * Enable stack trace collection.
+ */
+ M_HEAP_TAGGING_LEVEL_SYNC = 3,
+#define M_HEAP_TAGGING_LEVEL_SYNC M_HEAP_TAGGING_LEVEL_SYNC
+};
+
+/**
* [mallopt(3)](http://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
* heap behavior. Values of `__option` are the `M_` constants from this header.
*
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index 56badf0fd..b56ca746a 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -28,6 +28,7 @@
#pragma once
+#include <malloc.h>
#include <stdbool.h>
#include <stdint.h>
@@ -85,12 +86,6 @@ enum {
// arg_size = sizeof(android_mallopt_leak_info_t)
M_FREE_MALLOC_LEAK_INFO = 7,
#define M_FREE_MALLOC_LEAK_INFO M_FREE_MALLOC_LEAK_INFO
- // Change the heap tagging state. May be called at any time including when
- // multiple threads are running.
- // arg = HeapTaggingLevel*
- // arg_size = sizeof(HeapTaggingLevel)
- M_SET_HEAP_TAGGING_LEVEL = 8,
-#define M_SET_HEAP_TAGGING_LEVEL M_SET_HEAP_TAGGING_LEVEL
// Query whether the current process is considered to be profileable by the
// Android platform. Result is assigned to the arg pointer's destination.
// arg = bool*
@@ -105,28 +100,6 @@ enum {
// arg_size = sizeof(bool)
M_INITIALIZE_GWP_ASAN = 10,
#define M_INITIALIZE_GWP_ASAN M_INITIALIZE_GWP_ASAN
- // Disable heap initialization across the whole process. If the hardware supports memory
- // tagging, it also disables memory tagging. May be called at any time including
- // when multiple threads are running. arg and arg_size are unused and must be set to 0.
- // Note that the memory mitigations are only implemented in scudo and therefore this API call will
- // have no effect when using another allocator.
- M_DISABLE_MEMORY_MITIGATIONS = 11,
-#define M_DISABLE_MEMORY_MITIGATIONS M_DISABLE_MEMORY_MITIGATIONS
-};
-
-enum HeapTaggingLevel {
- // Disable heap tagging and memory tag checks if supported. Heap tagging may not be re-enabled
- // after being disabled.
- M_HEAP_TAGGING_LEVEL_NONE = 0,
- // Address-only tagging. Heap pointers have a non-zero tag in the most significant byte which is
- // checked in free(). Memory accesses ignore the tag.
- M_HEAP_TAGGING_LEVEL_TBI = 1,
- // Enable heap tagging and asynchronous memory tag checks if supported. Disable stack trace
- // collection.
- M_HEAP_TAGGING_LEVEL_ASYNC = 2,
- // Enable heap tagging and synchronous memory tag checks if supported. Enable stack trace
- // collection.
- M_HEAP_TAGGING_LEVEL_SYNC = 3,
};
// Manipulates bionic-specific handling of memory allocation APIs such as
diff --git a/libc/platform/bionic/mte.h b/libc/platform/bionic/mte.h
index 1e393eb0c..73cd821b6 100644
--- a/libc/platform/bionic/mte.h
+++ b/libc/platform/bionic/mte.h
@@ -29,10 +29,16 @@
#pragma once
#include <sys/auxv.h>
-#include <bionic/mte_kernel.h>
+#include <sys/prctl.h>
+
+// Note: Most PR_MTE_* constants come from the upstream kernel. This tag mask
+// allows for the hardware to provision any nonzero tag. Zero tags are reserved
+// for scudo to use for the chunk headers in order to prevent linear heap
+// overflow/underflow.
+#define PR_MTE_TAG_SET_NONZERO (0xfffeUL << PR_MTE_TAG_SHIFT)
inline bool mte_supported() {
-#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+#if defined(__aarch64__)
static bool supported = getauxval(AT_HWCAP2) & HWCAP2_MTE;
#else
static bool supported = false;
diff --git a/libc/private/bionic_asm.h b/libc/private/bionic_asm.h
index 6d4f7d52c..d68a2d604 100644
--- a/libc/private/bionic_asm.h
+++ b/libc/private/bionic_asm.h
@@ -26,8 +26,10 @@
* SUCH DAMAGE.
*/
-#ifndef _PRIVATE_BIONIC_ASM_H_
-#define _PRIVATE_BIONIC_ASM_H_
+#pragma once
+
+/* https://github.com/android/ndk/issues/1422 */
+#include <features.h>
#include <asm/unistd.h> /* For system call numbers. */
#define MAX_ERRNO 4095 /* For recognizing system call error returns. */
@@ -86,5 +88,3 @@
#define NOTE_GNU_PROPERTY() \
__bionic_asm_custom_note_gnu_section()
-
-#endif
diff --git a/libc/private/bionic_asm_arm64.h b/libc/private/bionic_asm_arm64.h
index c11732ae8..e73f25d36 100644
--- a/libc/private/bionic_asm_arm64.h
+++ b/libc/private/bionic_asm_arm64.h
@@ -69,4 +69,10 @@
.long (__bionic_asm_aarch64_feature_pac | \
__bionic_asm_aarch64_feature_bti); \
.long 0; \
- .popsection; \
+ .popsection;
+
+#define NT_MEMTAG_LEVEL_MASK 3
+#define NT_MEMTAG_LEVEL_DEFAULT 0
+#define NT_MEMTAG_LEVEL_ASYNC 1
+#define NT_MEMTAG_LEVEL_SYNC 2
+#define NT_MEMTAG_HEAP 4
diff --git a/libc/platform/bionic/mte_kernel.h b/libc/private/bionic_asm_note.h
index d81480aa7..80b8f011c 100644
--- a/libc/platform/bionic/mte_kernel.h
+++ b/libc/private/bionic_asm_note.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,32 +28,6 @@
#pragma once
-// Defines constants used as part of the interface in an experimental MTE branch
-// of the Linux kernel, which may be found at:
-//
-// https://github.com/pcc/linux/tree/android-experimental-mte
-//
-// This interface should not be considered to be stable.
-
-#ifdef ANDROID_EXPERIMENTAL_MTE
-
-#define HWCAP2_MTE (1 << 18)
-#define PROT_MTE 0x20
-
-#define PR_MTE_TCF_SHIFT 1
-#define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
-#define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
-#define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
-#define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
-#define PR_MTE_TAG_SHIFT 3
-#define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
-
-#define SEGV_MTEAERR 8
-#define SEGV_MTESERR 9
-
-#define PTRACE_PEEKMTETAGS 33
-#define PTRACE_POKEMTETAGS 34
-
-#define NT_ARM_TAGGED_ADDR_CTRL 0x409
-
-#endif
+#define NT_TYPE_IDENT 1
+#define NT_TYPE_KUSER 3
+#define NT_TYPE_MEMTAG 4
diff --git a/libc/private/bionic_fdtrack.h b/libc/private/bionic_fdtrack.h
index 752dd8dc5..259897c22 100644
--- a/libc/private/bionic_fdtrack.h
+++ b/libc/private/bionic_fdtrack.h
@@ -58,7 +58,7 @@ extern "C" _Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
event.fd = __fd; \
event.type = ANDROID_FDTRACK_EVENT_TYPE_CREATE; \
event.data.create.function_name = name; \
- __android_fdtrack_hook(&event); \
+ atomic_load(&__android_fdtrack_hook)(&event); \
tls.fdtrack_disabled = false; \
} \
} \
@@ -86,7 +86,7 @@ extern "C" _Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
android_fdtrack_event event; \
event.fd = __fd; \
event.type = ANDROID_FDTRACK_EVENT_TYPE_CLOSE; \
- __android_fdtrack_hook(&event); \
+ atomic_load(&__android_fdtrack_hook)(&event); \
tls.fdtrack_disabled = false; \
errno = saved_errno; \
} \
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 5c9b726d2..813226172 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -41,6 +41,8 @@
#include "private/bionic_vdso.h"
#include "private/WriteProtected.h"
+#include <platform/bionic/malloc.h>
+
struct libc_globals {
vdso_entry vdso[VDSO_END];
long setjmp_cookie;
@@ -106,6 +108,8 @@ struct libc_shared_globals {
const char* scudo_stack_depot = nullptr;
const char* scudo_region_info = nullptr;
+
+ HeapTaggingLevel initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
};
__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
diff --git a/libc/private/bsd_sys_param.h b/libc/private/bsd_sys_param.h
new file mode 100644
index 000000000..8c936c459
--- /dev/null
+++ b/libc/private/bsd_sys_param.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/* OpenBSD has these in <sys/param.h>, but "ALIGN" isn't something we want to reserve. */
+#define ALIGNBYTES (sizeof(uintptr_t) - 1)
+#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index b8aced83b..c7b1ba459 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -57,8 +57,7 @@
#include "private/ErrnoRestorer.h"
#include "private/thread_private.h"
-#define ALIGNBYTES (sizeof(uintptr_t) - 1)
-#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+#include "private/bsd_sys_param.h" // For ALIGN/ALIGNBYTES.
#define NDYNAMIC 10 /* add ten more whenever necessary */
diff --git a/libc/system_properties/context_lookup_benchmark_data.h b/libc/system_properties/context_lookup_benchmark_data.h
index 3cc325724..b928875dd 100644
--- a/libc/system_properties/context_lookup_benchmark_data.h
+++ b/libc/system_properties/context_lookup_benchmark_data.h
@@ -885,7 +885,6 @@ ro.hwui.use_vulkan u:object_r:exported_default_prop:s0 exact bool
ro.kernel.qemu u:object_r:exported_default_prop:s0 exact bool
ro.kernel.qemu. u:object_r:exported_default_prop:s0
ro.kernel.android.bootanim u:object_r:exported_default_prop:s0 exact int
-ro.kernel.ebpf.supported u:object_r:exported_default_prop:s0 exact bool
ro.oem.key1 u:object_r:exported_default_prop:s0 exact string
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 2fc5046ad..6c21c5b49 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -25,6 +25,8 @@
#include <sys/random.h> // For getentropy.
+#include "private/bsd_sys_param.h"
+
#define __BEGIN_HIDDEN_DECLS _Pragma("GCC visibility push(hidden)")
#define __END_HIDDEN_DECLS _Pragma("GCC visibility pop")
@@ -57,10 +59,6 @@ extern const char* __progname;
#define explicit_bzero(p, s) memset(p, 0, s)
-/* OpenBSD has these in <sys/param.h>, but "ALIGN" isn't something we want to reserve. */
-#define ALIGNBYTES (sizeof(uintptr_t) - 1)
-#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
-
/* OpenBSD has this in paths.h. But this directory doesn't normally exist.
* Even when it does exist, only the 'shell' user has permissions.
*/