Merge "Rename GWP-ASan android_mallopt() arguments" into main
diff --git a/docs/status.md b/docs/status.md
index 2919471..bc8ab6a 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -397,22 +397,25 @@
overrun is detected, the program is safely aborted as in this
[example](https://source.android.com/devices/tech/debug/native-crash#fortify).
-Note that in recent releases Android's FORTIFY has been extended to
-cover other issues. It can now detect, for example, passing `O_CREAT`
-to open(2) without specifying a mode. It also performs some checking
-regardless of whether the caller was built with FORTIFY enabled. In P,
-for example, calling a `pthread_mutex_` function on a destroyed mutex,
-calling a `<dirent.h>` function on a null pointer, using `%n` with the
-printf(3) family, or using the scanf(3) `m` modifier incorrectly will
-all result in FORTIFY failures even for code not built with FORTIFY.
+Note that Android's FORTIFY has been extended to cover other issues. It can
+detect, for example, passing `O_CREAT` to open(2) without specifying a mode. It
+also performs some checking regardless of whether the caller was built with
+FORTIFY enabled. From API level 28, for example, calling a `pthread_mutex_`
+function on a destroyed mutex, calling a `<dirent.h>` function on a null
+pointer, using `%n` with the printf(3) family, or using the scanf(3) `m`
+modifier incorrectly will all result in FORTIFY failures even for code not built
+with FORTIFY.
More background information is available in our
[FORTIFY in Android](https://android-developers.googleblog.com/2017/04/fortify-in-android.html)
-blog post.
+blog post, and there's more detail about the implementation in
+[The Anatomy of Clang FORTIFY](clang_fortify_anatomy.md).
-The Android platform is built with `-D_FORTIFY_SOURCE=2`, but NDK users
-need to manually enable FORTIFY by setting that themselves in whatever
-build system they're using. The exact subset of FORTIFY available to
+The Android platform is built with `-D_FORTIFY_SOURCE=2`. Users of ndk-build
+or the NDK's CMake toolchain file also get this by default with NDK r21 or
+newer. Users of other build systems
+need to manually enable FORTIFY by setting `_FORTIFY_SOURCE` themselves in
+whatever build system they're using. The exact subset of FORTIFY available to
NDK users will depend on their target ABI level, because when a FORTIFY
check can't be guaranteed at compile-time, a call to a run-time `_chk`
function is added.
diff --git a/libc/Android.bp b/libc/Android.bp
index 84fa498..2efca68 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -55,7 +55,9 @@
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 @@
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 @@
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 @@
name: "versioner-dependencies",
srcs: ["versioner-dependencies/**/*"],
}
+
+filegroup {
+ name: "linux_capability_header",
+ srcs: ["kernel/uapi/linux/capability.h"],
+}
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index 4d1981c..c8a025f 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 @@
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/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index a2bb1db..1bbdb29 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -77,9 +77,13 @@
int je_mallopt(int param, int value) {
// The only parameter we currently understand is M_DECAY_TIME.
if (param == M_DECAY_TIME) {
- // Only support setting the value to 1 or 0.
+ // Only support setting the value to -1 or 0 or 1.
ssize_t decay_time_ms;
- if (value) {
+ if (value < 0) {
+ // Given that SSIZE_MAX may not be supported in jemalloc, set this to a
+ // sufficiently large number that essentially disables the decay timer.
+ decay_time_ms = 10000000;
+ } else if (value) {
decay_time_ms = 1000;
} else {
decay_time_ms = 0;
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 1180a51..2dde2f1 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -61,7 +61,7 @@
};
void memtag_stack_dlopen_callback() {
- async_safe_format_log(ANDROID_LOG_INFO, "libc", "remapping stacks as PROT_MTE");
+ async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "remapping stacks as PROT_MTE");
__pthread_internal_remap_stack_with_mte();
}
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 9932e3e..596a1fc 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -123,7 +123,7 @@
// Track the M_DECAY_TIME mallopt calls.
if (param == M_DECAY_TIME && retval == 1) {
__libc_globals.mutate([value](libc_globals* globals) {
- if (value == 0) {
+ if (value <= 0) {
atomic_store(&globals->decay_time_enabled, false);
} else {
atomic_store(&globals->decay_time_enabled, true);
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index cd61f33..64528e1 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/malloc.h b/libc/include/malloc.h
index d22b85c..ef1e27d 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -186,7 +186,11 @@
int malloc_info(int __must_be_zero, FILE* _Nonnull __fp) __INTRODUCED_IN(23);
/**
- * mallopt() option to set the decay time. Valid values are 0 and 1.
+ * mallopt() option to set the decay time. Valid values are -1, 0 and 1.
+ * -1 : Disable the releasing of unused pages. This value is available since
+ * API level 35.
+ * 0 : Release the unused pages immediately.
+ * 1 : Release the unused pages at a device-specific interval.
*
* Available since API level 27.
*/
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 32264d6..78114c3 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -69,7 +69,7 @@
#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/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
index 9dd5e35..e0d38a8 100644
--- a/libc/system_properties/system_properties.cpp
+++ b/libc/system_properties/system_properties.cpp
@@ -120,14 +120,18 @@
return false;
}
- auto* appcompat_contexts = new (appcompat_override_contexts_data_) ContextsSerialized();
appcompat_filename_ = PropertiesFilename(properties_filename_.c_str(), "appcompat_override");
- if (!appcompat_contexts->Initialize(true, appcompat_filename_.c_str(), fsetxattr_failed,
- load_default_path)) {
- appcompat_override_contexts_ = nullptr;
- return false;
+ appcompat_override_contexts_ = nullptr;
+ if (access(appcompat_filename_.c_str(), F_OK) != -1) {
+ auto* appcompat_contexts = new (appcompat_override_contexts_data_) ContextsSerialized();
+ if (!appcompat_contexts->Initialize(true, appcompat_filename_.c_str(), fsetxattr_failed,
+ load_default_path)) {
+ // The appcompat folder exists, but initializing it failed
+ return false;
+ } else {
+ appcompat_override_contexts_ = appcompat_contexts;
+ }
}
- appcompat_override_contexts_ = appcompat_contexts;
initialized_ = true;
return true;
@@ -333,31 +337,42 @@
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/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 8e6f87d..cbc52b5 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -42,23 +42,8 @@
#define PROTO_NORMAL(x)
-/* OpenBSD's <ctype.h> uses these names, which conflicted with stlport.
- * Additionally, we changed the numeric/digit type from N to D for libcxx.
- */
-#define _U _CTYPE_U
-#define _L _CTYPE_L
-#define _N _CTYPE_D
-#define _S _CTYPE_S
-#define _P _CTYPE_P
-#define _C _CTYPE_C
-#define _X _CTYPE_X
-#define _B _CTYPE_B
-
-/* OpenBSD has this, but we can't really implement it correctly on Linux. */
-#define issetugid() 0
-
#if !defined(ANDROID_HOST_MUSL)
-#define explicit_bzero(p, s) memset(p, 0, s)
+#define explicit_bzero(p, s) memset_explicit(p, 0, s)
#endif
#if defined(ANDROID_HOST_MUSL)
diff --git a/libc/upstream-openbsd/lib/libc/crypt/arc4random.c b/libc/upstream-openbsd/lib/libc/crypt/arc4random.c
index 8a4ecc9..0737cf3 100644
--- a/libc/upstream-openbsd/lib/libc/crypt/arc4random.c
+++ b/libc/upstream-openbsd/lib/libc/crypt/arc4random.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: arc4random.c,v 1.54 2015/09/13 08:31:47 guenther Exp $ */
+/* $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
@@ -49,6 +49,8 @@
#define BLOCKSZ 64
#define RSBUFSZ (16*BLOCKSZ)
+#define REKEY_BASE (1024*1024) /* NB. should be a power of 2 */
+
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
static struct _rs {
size_t rs_have; /* valid bytes at end of rs_buf */
@@ -78,7 +80,7 @@
abort();
}
- chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
+ chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
}
@@ -86,6 +88,7 @@
_rs_stir(void)
{
u_char rnd[KEYSZ + IVSZ];
+ uint32_t rekey_fuzz = 0;
if (getentropy(rnd, sizeof rnd) == -1)
_getentropy_fail();
@@ -100,7 +103,10 @@
rs->rs_have = 0;
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
- rs->rs_count = 1600000;
+ /* rekey interval should not be predictable */
+ chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
+ (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
+ rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
}
static inline void
diff --git a/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h b/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h
index 7c3680f..b0427b6 100644
--- a/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h
+++ b/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h
@@ -4,7 +4,7 @@
Public domain.
*/
-/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
+/* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
typedef unsigned char u8;
typedef unsigned int u32;
@@ -52,7 +52,7 @@
static const char tau[16] = "expand 16-byte k";
static void
-chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
+chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
{
const char *constants;
diff --git a/libc/upstream-openbsd/lib/libc/gen/ctype_.c b/libc/upstream-openbsd/lib/libc/gen/ctype_.c
index 8972244..9742c9f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/ctype_.c
+++ b/libc/upstream-openbsd/lib/libc/gen/ctype_.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ctype_.c,v 1.12 2015/09/19 04:02:21 guenther Exp $ */
+/* $OpenBSD: ctype_.c,v 1.13 2024/02/04 13:03:18 jca Exp $ */
/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
@@ -36,6 +36,16 @@
#include <ctype.h>
#include "ctype_private.h"
+/* Shorter names for the defines provided by <ctype.h> */
+#define _U _CTYPE_U
+#define _L _CTYPE_L
+#define _N _CTYPE_N
+#define _S _CTYPE_S
+#define _P _CTYPE_P
+#define _C _CTYPE_C
+#define _X _CTYPE_X
+#define _B _CTYPE_B
+
const char _C_ctype_[1 + CTYPE_NUM_CHARS] = {
0,
_C, _C, _C, _C, _C, _C, _C, _C,
diff --git a/libc/upstream-openbsd/lib/libc/net/htonl.c b/libc/upstream-openbsd/lib/libc/net/htonl.c
index 6ee6e7e..58bfb46 100644
--- a/libc/upstream-openbsd/lib/libc/net/htonl.c
+++ b/libc/upstream-openbsd/lib/libc/net/htonl.c
@@ -1,6 +1,5 @@
-/* $OpenBSD: htonl.c,v 1.7 2014/07/21 01:51:10 guenther Exp $ */
+/* $OpenBSD: htonl.c,v 1.8 2024/04/15 14:30:48 naddy Exp $ */
/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
@@ -9,13 +8,8 @@
#undef htonl
-u_int32_t
-htonl(u_int32_t x)
+uint32_t
+htonl(uint32_t x)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
- u_char *s = (u_char *)&x;
- return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
-#else
- return x;
-#endif
+ return htobe32(x);
}
diff --git a/libc/upstream-openbsd/lib/libc/net/htons.c b/libc/upstream-openbsd/lib/libc/net/htons.c
index f48d91e..28b13ce 100644
--- a/libc/upstream-openbsd/lib/libc/net/htons.c
+++ b/libc/upstream-openbsd/lib/libc/net/htons.c
@@ -1,6 +1,5 @@
-/* $OpenBSD: htons.c,v 1.9 2014/07/21 01:51:10 guenther Exp $ */
+/* $OpenBSD: htons.c,v 1.10 2024/04/15 14:30:48 naddy Exp $ */
/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
@@ -9,13 +8,8 @@
#undef htons
-u_int16_t
-htons(u_int16_t x)
+uint16_t
+htons(uint16_t x)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
- u_char *s = (u_char *) &x;
- return (u_int16_t)(s[0] << 8 | s[1]);
-#else
- return x;
-#endif
+ return htobe16(x);
}
diff --git a/libc/upstream-openbsd/lib/libc/net/ntohl.c b/libc/upstream-openbsd/lib/libc/net/ntohl.c
index 0d05bac..7592398 100644
--- a/libc/upstream-openbsd/lib/libc/net/ntohl.c
+++ b/libc/upstream-openbsd/lib/libc/net/ntohl.c
@@ -1,6 +1,5 @@
-/* $OpenBSD: ntohl.c,v 1.7 2014/07/21 01:51:10 guenther Exp $ */
+/* $OpenBSD: ntohl.c,v 1.8 2024/04/15 14:30:48 naddy Exp $ */
/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
@@ -9,13 +8,8 @@
#undef ntohl
-u_int32_t
-ntohl(u_int32_t x)
+uint32_t
+ntohl(uint32_t x)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
- u_char *s = (u_char *)&x;
- return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
-#else
- return x;
-#endif
+ return be32toh(x);
}
diff --git a/libc/upstream-openbsd/lib/libc/net/ntohs.c b/libc/upstream-openbsd/lib/libc/net/ntohs.c
index b5ea361..ef22ea30 100644
--- a/libc/upstream-openbsd/lib/libc/net/ntohs.c
+++ b/libc/upstream-openbsd/lib/libc/net/ntohs.c
@@ -1,6 +1,5 @@
-/* $OpenBSD: ntohs.c,v 1.9 2014/07/21 01:51:10 guenther Exp $ */
+/* $OpenBSD: ntohs.c,v 1.10 2024/04/15 14:30:48 naddy Exp $ */
/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
* Public domain.
*/
@@ -9,13 +8,8 @@
#undef ntohs
-u_int16_t
-ntohs(u_int16_t x)
+uint16_t
+ntohs(uint16_t x)
{
-#if BYTE_ORDER == LITTLE_ENDIAN
- u_char *s = (u_char *) &x;
- return (u_int16_t)(s[0] << 8 | s[1]);
-#else
- return x;
-#endif
+ return be16toh(x);
}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
index d83de88..d615245 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fvwrite.c,v 1.21 2023/10/06 16:41:02 millert Exp $ */
+/* $OpenBSD: fvwrite.c,v 1.22 2024/04/28 14:28:02 millert Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,6 +31,7 @@
* SUCH DAMAGE.
*/
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -76,11 +77,12 @@
}
if (fp->_flags & __SNBF) {
/*
- * Unbuffered: write up to BUFSIZ bytes at a time.
+ * Unbuffered: write up to INT_MAX bytes at a time, to not
+ * truncate the value of len if it is greater than 2^31 bytes.
*/
do {
GETIOV(;);
- w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
+ w = (*fp->_write)(fp->_cookie, p, MIN(len, INT_MAX));
if (w <= 0)
goto err;
p += w;
@@ -90,7 +92,8 @@
/*
* Fully buffered: fill partially full buffer, if any,
* and then flush. If there is no partial buffer, write
- * one _bf._size byte chunk directly (without copying).
+ * entire payload directly (without copying) up to a
+ * multiple of the buffer size.
*
* String output is a special case: write as many bytes
* as fit, but pretend we wrote everything. This makes
@@ -134,7 +137,15 @@
if (__sflush(fp))
goto err;
} else if (len >= (w = fp->_bf._size)) {
- /* write directly */
+ /*
+ * Write directly up to INT_MAX or greatest
+ * multiple of buffer size (whichever is
+ * smaller), keeping in the memory buffer the
+ * remaining part of payload that is smaller
+ * than buffer size.
+ */
+ if (w != 0)
+ w = MIN(w * (len / w), INT_MAX);
w = (*fp->_write)(fp->_cookie, p, w);
if (w <= 0)
goto err;
diff --git a/linker/linker_crt_pad_segment_test.cpp b/linker/linker_crt_pad_segment_test.cpp
index 5a219f8..c11df50 100644
--- a/linker/linker_crt_pad_segment_test.cpp
+++ b/linker/linker_crt_pad_segment_test.cpp
@@ -72,13 +72,22 @@
}; // 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 77769f5..089eceb 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -29,6 +29,7 @@
#include "linker_main.h"
#include <link.h>
+#include <stdlib.h>
#include <sys/auxv.h>
#include "linker.h"
@@ -220,14 +221,10 @@
exe_path = arg_path;
}
- // Path might be a symlink
+ // Path might be a symlink; we need the target so that we get the right
+ // linker configuration later.
char sym_path[PATH_MAX];
- ssize_t sym_path_len = readlink(exe_path, sym_path, sizeof(sym_path));
- if (sym_path_len > 0 && sym_path_len < static_cast<ssize_t>(sizeof(sym_path))) {
- result.path = std::string(sym_path, sym_path_len);
- } else {
- result.path = std::string(exe_path, strlen(exe_path));
- }
+ result.path = std::string(realpath(exe_path, sym_path) != nullptr ? sym_path : exe_path);
result.phdr = reinterpret_cast<const ElfW(Phdr)*>(getauxval(AT_PHDR));
result.phdr_count = getauxval(AT_PHNUM);
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index ef7671c..fa712a1 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;
@@ -707,8 +709,28 @@
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 +795,16 @@
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 +918,28 @@
// 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 61242eb..aab9018 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -154,3 +154,5 @@
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 544af43..f4ef4ac 100644
--- a/tests/clang_fortify_tests.cpp
+++ b/tests/clang_fortify_tests.cpp
@@ -164,9 +164,7 @@
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 @@
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 26e869f..a5916d3 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -678,10 +678,12 @@
TEST(malloc, mallopt_decay) {
#if defined(__BIONIC__)
SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
+ ASSERT_EQ(1, mallopt(M_DECAY_TIME, -1));
ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
+ ASSERT_EQ(1, mallopt(M_DECAY_TIME, -1));
#else
GTEST_SKIP() << "bionic-only test";
#endif
@@ -1490,7 +1492,7 @@
// release secondary allocations back to the OS) was modified to 0ms/1ms by
// mallopt_decay. Ensure that we delay for at least a second before releasing
// pages to the OS in order to avoid implicit zeroing by the kernel.
- mallopt(M_DECAY_TIME, 1000);
+ mallopt(M_DECAY_TIME, 1);
TestHeapZeroing(/* num_iterations */ 32, [](int iteration) -> int {
return 1 << (19 + iteration % 4);
});
@@ -1764,6 +1766,10 @@
EXPECT_EQ(1, mallopt(M_DECAY_TIME, 1));
EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
EXPECT_TRUE(value);
+
+ EXPECT_EQ(1, mallopt(M_DECAY_TIME, -1));
+ EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
+ EXPECT_FALSE(value);
#else
GTEST_SKIP() << "bionic-only test";
#endif
diff --git a/tests/sys_hwprobe_test.cpp b/tests/sys_hwprobe_test.cpp
index 6b74e18..fd59e1d 100644
--- a/tests/sys_hwprobe_test.cpp
+++ b/tests/sys_hwprobe_test.cpp
@@ -33,6 +33,68 @@
#include <sys/syscall.h>
#endif
+
+#if defined(__riscv)
+#include <riscv_vector.h>
+
+__attribute__((noinline))
+uint64_t scalar_cast(uint8_t const* p) {
+ return *(uint64_t const*)p;
+}
+
+__attribute__((noinline))
+uint64_t scalar_memcpy(uint8_t const* p) {
+ uint64_t r;
+ __builtin_memcpy(&r, p, sizeof(r));
+ return r;
+}
+
+__attribute__((noinline))
+uint64_t vector_memcpy(uint8_t* d, uint8_t const* p) {
+ __builtin_memcpy(d, p, 16);
+ return *(uint64_t const*)d;
+}
+
+__attribute__((noinline))
+uint64_t vector_ldst(uint8_t* d, uint8_t const* p) {
+ __riscv_vse8(d, __riscv_vle8_v_u8m1(p, 16), 16);
+ return *(uint64_t const*)d;
+}
+
+__attribute__((noinline))
+uint64_t vector_ldst64(uint8_t* d, uint8_t const* p) {
+ __riscv_vse64((unsigned long *)d, __riscv_vle64_v_u64m1((const unsigned long *)p, 16), 16);
+ return *(uint64_t const*)d;
+}
+
+// For testing scalar and vector unaligned accesses.
+uint64_t tmp[3] = {1,1,1};
+uint64_t dst[3] = {1,1,1};
+#endif
+
+TEST(sys_hwprobe, __riscv_hwprobe_misaligned_scalar) {
+#if defined(__riscv)
+ uint8_t* p = (uint8_t*)tmp + 1;
+ ASSERT_NE(0U, scalar_cast(p));
+ ASSERT_NE(0U, scalar_memcpy(p));
+#else
+ GTEST_SKIP() << "__riscv_hwprobe requires riscv64";
+#endif
+}
+
+TEST(sys_hwprobe, __riscv_hwprobe_misaligned_vector) {
+#if defined(__riscv)
+ uint8_t* p = (uint8_t*)tmp + 1;
+ uint8_t* d = (uint8_t*)dst + 1;
+
+ ASSERT_NE(0U, vector_ldst(d, p));
+ ASSERT_NE(0U, vector_memcpy(d, p));
+ ASSERT_NE(0U, vector_ldst64(d, p));
+#else
+ GTEST_SKIP() << "__riscv_hwprobe requires riscv64";
+#endif
+}
+
TEST(sys_hwprobe, __riscv_hwprobe) {
#if defined(__riscv) && __has_include(<sys/hwprobe.h>)
riscv_hwprobe probes[] = {{.key = RISCV_HWPROBE_KEY_IMA_EXT_0},
@@ -82,4 +144,4 @@
#else
GTEST_SKIP() << "__riscv_hwprobe requires riscv64";
#endif
-}
+}
\ No newline at end of file
diff --git a/tests/sys_statvfs_test.cpp b/tests/sys_statvfs_test.cpp
index 73b2a96..5dd7b93 100644
--- a/tests/sys_statvfs_test.cpp
+++ b/tests/sys_statvfs_test.cpp
@@ -25,7 +25,7 @@
#include <string>
template <typename StatVfsT> void Check(StatVfsT& sb) {
- EXPECT_EQ(4096U, sb.f_bsize);
+ EXPECT_EQ(getpagesize(), static_cast<int>(sb.f_bsize));
EXPECT_EQ(0U, sb.f_bfree);
EXPECT_EQ(0U, sb.f_ffree);
EXPECT_EQ(255U, sb.f_namemax);
diff --git a/tests/sys_vfs_test.cpp b/tests/sys_vfs_test.cpp
index 96fd61a..e783190 100644
--- a/tests/sys_vfs_test.cpp
+++ b/tests/sys_vfs_test.cpp
@@ -27,7 +27,7 @@
#include "utils.h"
template <typename StatFsT> void Check(StatFsT& sb) {
- EXPECT_EQ(4096, static_cast<int>(sb.f_bsize));
+ EXPECT_EQ(getpagesize(), static_cast<int>(sb.f_bsize));
EXPECT_EQ(0U, sb.f_bfree);
EXPECT_EQ(0U, sb.f_ffree);
EXPECT_EQ(255, static_cast<int>(sb.f_namelen));