[GWP-ASan] Add TURN_ON_FOR_APP_SAMPLED_NON_CRASHING to android_mallopt

This mode allows an android_mallopt(M_INITIALIZE_GWP_ASAN, ...) to turn
on the recoverable, sampled mode. This is the intended mode for
non-system apps that don't specify the gwpAsanMode in Android U.

Bug: 247012630
Test: Patch the zygote to use this option, launch an app with
gwpAsanMode unspecified, trigger a use-after-free, assert the app uses
the recoverable mode.

Change-Id: I701e10f44b2e2694789cc5ec6f0af4bc0c55b9e4
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index fc59c88..3ccaf9b 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -236,6 +236,10 @@
   *process_sample_rate = 1;
   if (mallopt_options.desire == Action::TURN_ON_WITH_SAMPLING) {
     *process_sample_rate = kDefaultProcessSampling;
+  } else if (mallopt_options.desire == Action::TURN_ON_FOR_APP_SAMPLED_NON_CRASHING) {
+    *process_sample_rate = kDefaultProcessSampling;
+    options->Recoverable = true;
+    GwpAsanRecoverable = true;
   }
 }
 
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index ecc8743..3c290fc 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -121,15 +121,28 @@
   // apply to system apps. They use the "libc.debug.gwp_asan.*.system_default"
   // sysprops.
   enum Action {
-    // The app has opted-in to GWP-ASan, and should always have it enabled. This
-    // should only be used by apps.
+    // Enable GWP-ASan. This is used by apps that have `gwpAsanMode=always` in
+    // the manifest.
     TURN_ON_FOR_APP,
-    // System processes apps have GWP-ASan enabled by default, but use the
-    // process sampling method.
+    // Enable GWP-ASan, but only a small percentage of the time. This is used by
+    // system processes and system apps, and we use a lottery to determine which
+    // processes have GWP-ASan enabled. This allows us to mitigate system-wide
+    // memory overhead concerns, as each GWP-ASan enabled process uses ~70KiB of
+    // extra memory.
     TURN_ON_WITH_SAMPLING,
-    // Non-system apps don't have GWP-ASan by default.
+    // Don't enable GWP-ASan, unless overwritten by a system property or
+    // environment variable. This is used by apps that have `gwpAsanMode=never`
+    // in the manifest. Prior to Android 14, this also was used by non-system
+    // apps that didn't specify a `gwpAsanMode` in their manifest.
     DONT_TURN_ON_UNLESS_OVERRIDDEN,
-    // Note: GWP-ASan cannot be disabled once it's been enabled.
+    // Enable GWP-ASan, but only a small percentage of the time, and enable it
+    // in the non-crashing ("recoverable") mode. In Android 14, this is used by
+    // apps that don't specify `gwpAsanMode` (or use `gwpAsanMode=default`) in
+    // their manifest. GWP-ASan will detect heap memory safety bugs in this
+    // mode, and bug reports will be created by debuggerd, however the process
+    // will recover and continue to function as if the memory safety bug wasn't
+    // detected.
+    TURN_ON_FOR_APP_SAMPLED_NON_CRASHING,
   };
 
   Action desire = DONT_TURN_ON_UNLESS_OVERRIDDEN;