Files
cromite/build/patches/Enable-gwp-asan-on-Android.patch
2026-05-19 10:48:25 +02:00

266 lines
12 KiB
Diff

From: uazo <uazo@users.noreply.github.com>
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.
<!-- Set android:largeHeap to "true" to allow more than the default
Java heap limit (32Mb on Nexus S, 48Mb on Xoom). -->
<application android:name="{% block application_name %}org.chromium.chrome.browser.base.SplitChromeApplication{% endblock %}"
+ android:gwpAsanMode="always"
android:icon="@drawable/ic_launcher"
android:roundIcon="@drawable/ic_launcher_round"
android:label="Cromite"
diff --git a/chrome/android/java/res/xml/developer_preferences.xml b/chrome/android/java/res/xml/developer_preferences.xml
--- a/chrome/android/java/res/xml/developer_preferences.xml
+++ b/chrome/android/java/res/xml/developer_preferences.xml
@@ -12,6 +12,9 @@ found in the LICENSE file.
android:fragment="org.chromium.chrome.browser.tracing.settings.TracingSettings"
android:key="tracing"
android:title="Tracing" />
+ <Preference
+ android:key="test_gwp_asan"
+ android:title="Test Gwp Asan"/>
<org.chromium.components.browser_ui.settings.TextMessagePreference
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
@@ -6,7 +6,9 @@ package org.chromium.chrome.browser.tracing.settings;
import android.content.Context;
import android.os.Bundle;
+import android.widget.Toast;
+import androidx.preference.Preference;
import org.chromium.base.ResettersForTesting;
import org.chromium.base.supplier.MonotonicObservableSupplier;
import org.chromium.base.supplier.NonNullObservableSupplier;
@@ -24,11 +26,13 @@ import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider
import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import org.chromium.components.browser_ui.settings.search.SettingsIndexData;
+import org.chromium.chrome.browser.util.PlatformUtil;
/** Settings fragment containing preferences aimed at Chrome and web developers. */
@NullMarked
public class DeveloperSettings extends ChromeBaseSettingsFragment implements EmbeddableSettingsPage {
private static final String UI_PREF_BETA_STABLE_HINT = "beta_stable_hint";
+ private static final String TEST_GWP_ASAN_KEY = "test_gwp_asan";
// Non-translated strings:
private static final String MSG_DEVELOPER_OPTIONS_TITLE = "Developer options";
@@ -64,6 +68,22 @@ public class DeveloperSettings extends ChromeBaseSettingsFragment implements Emb
if (shouldRemoveBetaStableHint()) {
getPreferenceScreen().removePreference(findPreference(UI_PREF_BETA_STABLE_HINT));
}
+
+ Preference mStartUpdate = findPreference(TEST_GWP_ASAN_KEY);
+ mStartUpdate.setOnPreferenceClickListener(preference -> {
+ 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<jstring> 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<jstring> obj;
+ obj.Reset(env, jni_zero::JavaRef<jstring>::CreateLeaky(env, return_string));
+ return ScopedJavaLocalRef<jstring>(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) {
--