#505 Enable Gwp Asan in Android

This commit is contained in:
Carmelo Messina
2024-01-12 17:23:18 +01:00
parent 453cbc569b
commit cd7ca5e627
2 changed files with 282 additions and 0 deletions
+1
View File
@@ -278,6 +278,7 @@ Timezone-customization.patch
00Disable-Android-AppRestrictions.patch
00Customize-selection-popup.patch
00Enables-deactivation-of-the-js-debugger-statement.patch
00Enable-gwp-asan-on-Android.patch
00Temp-PerformanceNavigationTiming-privacy-fix.patch
00Temp-disable-predictive-back-gesture.patch
@@ -0,0 +1,281 @@
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 | 32 +++++++++++++++++++
.../chrome/browser/util/PlatformUtil.java | 10 ++++++
components/gwp_asan/client/gwp_asan.cc | 18 ++++++++---
.../gwp_asan/client/gwp_asan_features.cc | 3 +-
components/memory_system/memory_system.cc | 1 +
11 files changed, 86 insertions(+), 9 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
@@ -464,7 +464,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
@@ -191,10 +191,11 @@ if (is_chromeos) {
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
@@ -169,6 +169,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
@@ -5,13 +5,16 @@
package org.chromium.chrome.browser.tracing.settings;
import android.os.Bundle;
+import android.widget.Toast;
+import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import org.chromium.base.ResettersForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
+import org.chromium.chrome.browser.util.PlatformUtil;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import org.chromium.components.version_info.Channel;
import org.chromium.components.version_info.VersionConstants;
@@ -22,6 +25,7 @@ import org.chromium.components.version_info.VersionInfo;
*/
public class DeveloperSettings extends PreferenceFragmentCompat {
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";
@@ -56,5 +60,21 @@ public class DeveloperSettings extends PreferenceFragmentCompat {
if (VersionInfo.isBetaBuild() || VersionInfo.isStableBuild()) {
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;
+ });
}
}
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
@@ -1940,7 +1940,7 @@ void ChromeMainDelegate::InitializeMemorySystem() {
const version_info::Channel channel = chrome::GetChannel();
const bool is_canary_dev = (channel == version_info::Channel::CANARY ||
channel == version_info::Channel::DEV);
- 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;
memory_system::Initializer()
.SetGwpAsanParameters(gwp_asan_boost_sampling, process_type)
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
@@ -62,3 +62,35 @@ 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, return_string);
+ return ScopedJavaLocalRef<jstring>(obj);
+}
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
@@ -10,6 +10,7 @@ import android.content.Intent;
import android.net.Uri;
import org.jni_zero.CalledByNative;
+import org.jni_zero.NativeMethods;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
@@ -32,4 +33,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
@@ -38,7 +38,7 @@ namespace gwp_asan {
namespace internal {
namespace {
-constexpr bool kCpuIs64Bit =
+[[maybe_unused]] constexpr bool kCpuIs64Bit =
#if defined(ARCH_CPU_64_BITS)
true;
#else
@@ -72,7 +72,15 @@ 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;
+constexpr int kDefaultProcessSamplingBoost2 = 10;
+#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.5;
constexpr int kDefaultProcessSamplingBoost2 = 10;
#else // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
constexpr int kDefaultMaxAllocations = 70;
@@ -80,7 +88,7 @@ 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;
constexpr int kDefaultProcessSamplingBoost2 = 10;
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
// BUILDFLAG(IS_FUCHSIA)
@@ -288,7 +296,7 @@ void EnableForMalloc(bool boost_sampling, const char* 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 // BUILDFLAG(USE_ALLOCATOR_SHIM)
}
@@ -308,7 +316,7 @@ void EnableForPartitionAlloc(bool boost_sampling, const char* process_type) {
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 // BUILDFLAG(USE_PARTITION_ALLOC)
}
diff --git a/components/gwp_asan/client/gwp_asan_features.cc b/components/gwp_asan/client/gwp_asan_features.cc
--- a/components/gwp_asan/client/gwp_asan_features.cc
+++ b/components/gwp_asan/client/gwp_asan_features.cc
@@ -9,7 +9,8 @@
namespace gwp_asan::internal {
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \
- BUILDFLAG(IS_CHROMEOS)
+ BUILDFLAG(IS_CHROMEOS) || \
+ (BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_64_BITS))
constexpr base::FeatureState kDefaultEnabled = base::FEATURE_ENABLED_BY_DEFAULT;
#else
constexpr base::FeatureState kDefaultEnabled =
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
@@ -169,6 +169,7 @@ void MemorySystem::Impl::Initialize(
if (gwp_asan_parameters) {
InitializeGwpASan(*gwp_asan_parameters, initialization_data);
+ LOG(INFO) << "MemorySystem: Gwp Asan Initialized.";
}
if (profiling_client_parameters) {
--
2.25.1