From: uazo Date: Fri, 12 Jan 2024 15:04:40 +0000 Subject: Enable gwp asan on Android the patch enables gwp asan in android and changes the activation conditions to 50% for all build configs. in android there is a test function accessible in the developer settings. --- android_webview/lib/aw_main_delegate.cc | 2 +- build/config/compiler/compiler.gni | 3 +- chrome/android/java/AndroidManifest.xml | 1 + .../java/res/xml/developer_preferences.xml | 3 ++ .../tracing/settings/DeveloperSettings.java | 20 +++++++++++ chrome/app/chrome_main_delegate.cc | 2 +- chrome/browser/platform_util_android.cc | 33 +++++++++++++++++++ .../chrome/browser/util/PlatformUtil.java | 10 ++++++ components/gwp_asan/client/gwp_asan.cc | 10 +++--- components/memory_system/memory_system.cc | 1 + 10 files changed, 77 insertions(+), 8 deletions(-) diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc --- a/android_webview/lib/aw_main_delegate.cc +++ b/android_webview/lib/aw_main_delegate.cc @@ -387,7 +387,7 @@ void AwMainDelegate::InitializeMemorySystem(const bool is_browser_process) { const std::string process_type = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kProcessType); - const bool gwp_asan_boost_sampling = is_canary_dev || is_browser_process; + const bool gwp_asan_boost_sampling = ((true)) || is_canary_dev || is_browser_process; // Add PoissonAllocationSampler. On Android WebView we do not have obvious // observers of PoissonAllocationSampler. Unfortunately, some potential diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni @@ -268,10 +268,11 @@ if (is_chromeos || (enable_cast_receiver && is_linux)) { enable_frame_pointers = true } } else if (is_android) { - enable_frame_pointers = + enable_frame_pointers = true || enable_profiling || # Ensure that stacks from arm64 crash dumps are usable (crbug.com/391706). current_cpu == "arm64" || + current_cpu == "x86" || # For x86 Android, unwind tables are huge without frame pointers # (crbug.com/762629). Enabling frame pointers grows the code size slightly # but overall shrinks binaries considerably by avoiding huge unwind diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml @@ -196,6 +196,7 @@ by a child template that "extends" this file. + { + Toast toast = Toast.makeText(getContext(), + "Test Gwp Asan in progress. Browser should crash.", Toast.LENGTH_LONG); + toast.show(); + + PlatformUtil.launchTestGwpAsan(); + + toast = Toast.makeText(getContext(), + "Test Gwp Asan done. Try again, it didn't work.", Toast.LENGTH_LONG); + toast.show(); + + // handle the click so the default action isn't triggered. + return true; + }); } private static boolean shouldRemoveBetaStableHint() { diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc @@ -1713,7 +1713,7 @@ void ChromeMainDelegate::InitializeMemorySystem() { const std::string process_type = command_line->GetSwitchValueASCII(switches::kProcessType); const bool is_browser_process = process_type.empty(); - const bool gwp_asan_boost_sampling = is_browser_process || IsCanaryDev(); + const bool gwp_asan_boost_sampling = ((true)) || is_browser_process || IsCanaryDev(); const memory_system::DispatcherParameters::AllocationTraceRecorderInclusion allocation_recorder_inclusion = is_browser_process ? memory_system::DispatcherParameters:: diff --git a/chrome/browser/platform_util_android.cc b/chrome/browser/platform_util_android.cc --- a/chrome/browser/platform_util_android.cc +++ b/chrome/browser/platform_util_android.cc @@ -10,6 +10,7 @@ #include "base/android/jni_string.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/logging.h" #include "base/notimplemented.h" #include "chrome/browser/platform_util_internal.h" #include "ui/android/view_android.h" @@ -85,4 +86,36 @@ bool IsVisible(gfx::NativeView view) { } // namespace platform_util +namespace { + +jstring native_get_string(JNIEnv* env) { +#pragma GCC diagnostic ignored "-Wdangling-gsl" + std::string s = "Hellooooooooooooooo "; + std::string_view sv = s + "World\n"; + + // BUG: Use-after-free. `sv` holds a dangling reference to the ephemeral + // string created by `s + "World\n"`. Accessing the data here is a + // use-after-free. + return env->NewStringUTF(sv.data()); +} + +} + +static base::android::ScopedJavaLocalRef JNI_PlatformUtil_TestGwpAsan(JNIEnv* env) { + // Repeat the buggy code a few thousand times. GWP-ASan has a small chance + // of detecting the use-after-free every time it happens. A single user who + // triggers the use-after-free thousands of times will catch the bug once. + // Alternatively, if a few thousand users each trigger the bug a single time, + // you'll also get one report (this is the assumed model). + jstring return_string; + for (unsigned i = 0; i < 0x10000; ++i) { + return_string = native_get_string(env); + LOG(INFO) << "Testing GwpAsan " << return_string; + } + + base::android::ScopedJavaGlobalRef obj; + obj.Reset(env, jni_zero::JavaRef::CreateLeaky(env, return_string)); + return ScopedJavaLocalRef(obj); +} + DEFINE_JNI(PlatformUtil) diff --git a/chrome/browser/util/android/java/src/org/chromium/chrome/browser/util/PlatformUtil.java b/chrome/browser/util/android/java/src/org/chromium/chrome/browser/util/PlatformUtil.java --- a/chrome/browser/util/android/java/src/org/chromium/chrome/browser/util/PlatformUtil.java +++ b/chrome/browser/util/android/java/src/org/chromium/chrome/browser/util/PlatformUtil.java @@ -11,6 +11,7 @@ import android.net.Uri; import org.jni_zero.CalledByNative; import org.jni_zero.JniType; +import org.jni_zero.NativeMethods; import org.chromium.base.ContextUtils; import org.chromium.base.Log; @@ -47,4 +48,13 @@ public class PlatformUtil { Log.e(TAG, "cannot find activity to launch %s", url, e); } } + + public static String launchTestGwpAsan() { + return PlatformUtilJni.get().testGwpAsan(); + } + + @NativeMethods + interface Natives { + String testGwpAsan(); + } } diff --git a/components/gwp_asan/client/gwp_asan.cc b/components/gwp_asan/client/gwp_asan.cc --- a/components/gwp_asan/client/gwp_asan.cc +++ b/components/gwp_asan/client/gwp_asan.cc @@ -87,21 +87,21 @@ constexpr int kDefaultMaxMetadata = 210; constexpr int kDefaultTotalPages = kCpuIs64Bit ? 2048 : kDefaultMaxMetadata * 2; constexpr int kDefaultAllocationSamplingMultiplier = 1500; constexpr int kDefaultAllocationSamplingRange = 16; -constexpr double kDefaultProcessSamplingProbability = 0.01; +constexpr double kDefaultProcessSamplingProbability = 0.5; #elif BUILDFLAG(IS_ANDROID) constexpr int kDefaultMaxAllocations = 70; constexpr int kDefaultMaxMetadata = 255; constexpr int kDefaultTotalPages = 512; constexpr int kDefaultAllocationSamplingMultiplier = 2000; constexpr int kDefaultAllocationSamplingRange = 20; -constexpr double kDefaultProcessSamplingProbability = 0.015; +constexpr double kDefaultProcessSamplingProbability = 0.5; #else constexpr int kDefaultMaxAllocations = 70; constexpr int kDefaultMaxMetadata = 255; constexpr int kDefaultTotalPages = kCpuIs64Bit ? 2048 : kDefaultMaxMetadata * 2; constexpr int kDefaultAllocationSamplingMultiplier = 1000; constexpr int kDefaultAllocationSamplingRange = 16; -constexpr double kDefaultProcessSamplingProbability = 0.015; +constexpr double kDefaultProcessSamplingProbability = 0.5; #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || // BUILDFLAG(IS_FUCHSIA) constexpr int kDefaultProcessSamplingBoost2 = 10; @@ -534,7 +534,7 @@ void EnableForMalloc(bool boost_sampling, std::string_view process_type) { std::ignore = init_once; #else std::ignore = internal::kGwpAsanMalloc; - DLOG(WARNING) << "base::allocator shims are unavailable for GWP-ASan."; + LOG(WARNING) << "MemorySystem: base::allocator shims are unavailable for GWP-ASan."; #endif // PA_BUILDFLAG(USE_ALLOCATOR_SHIM) } @@ -558,7 +558,7 @@ void EnableForPartitionAlloc(bool boost_sampling, std::ignore = init_once; #else std::ignore = internal::kGwpAsanPartitionAlloc; - DLOG(WARNING) << "PartitionAlloc hooks are unavailable for GWP-ASan."; + LOG(WARNING) << "MemorySystem: PartitionAlloc hooks are unavailable for GWP-ASan."; #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC) } diff --git a/components/memory_system/memory_system.cc b/components/memory_system/memory_system.cc --- a/components/memory_system/memory_system.cc +++ b/components/memory_system/memory_system.cc @@ -197,6 +197,7 @@ void MemorySystem::Impl::Initialize( if (gwp_asan_parameters) { InitializeGwpASan(*gwp_asan_parameters, initialization_data); + DLOG(INFO) << "MemorySystem: Gwp Asan Initialized."; } if (profiling_client_parameters) { --