Add persistent GWP-ASan sysprops.

Adds persistent sysprops for test infra usage, and adds the tests for
the sysprops.

The test does some fancy flocking in order to restore any existing
GWP-ASan sysprop usage in the test cleanup.

Bug: 236738714
Test: atest bionic-unit-tests
Change-Id: I8956296d39c98ce8c7dd0a703b240530d8ad48db
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 7e19b31..fc59c88 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -41,6 +41,7 @@
 #include "gwp_asan_wrappers.h"
 #include "malloc_common.h"
 #include "platform/bionic/android_unsafe_frame_pointer_chase.h"
+#include "platform/bionic/macros.h"
 #include "platform/bionic/malloc.h"
 #include "private/bionic_arc4random.h"
 #include "private/bionic_globals.h"
@@ -221,6 +222,8 @@
 static const char* kMaxAllocsTargetedSyspropPrefix = "libc.debug.gwp_asan.max_allocs.";
 static const char* kMaxAllocsEnvVar = "GWP_ASAN_MAX_ALLOCS";
 
+static const char kPersistPrefix[] = "persist.";
+
 void SetDefaultGwpAsanOptions(Options* options, unsigned* process_sample_rate,
                               const android_mallopt_gwp_asan_options_t& mallopt_options) {
   options->Enabled = true;
@@ -244,26 +247,40 @@
   const char* basename = "";
   if (mallopt_options.program_name) basename = __gnu_basename(mallopt_options.program_name);
 
-  size_t program_specific_sysprop_size = strlen(targeted_sysprop_prefix) + strlen(basename) + 1;
-  char* program_specific_sysprop_name = static_cast<char*>(alloca(program_specific_sysprop_size));
-  async_safe_format_buffer(program_specific_sysprop_name, program_specific_sysprop_size, "%s%s",
-                           targeted_sysprop_prefix, basename);
-
-  const char* sysprop_names[2] = {nullptr, nullptr};
+  constexpr size_t kSyspropMaxLen = 512;
+  char program_specific_sysprop[kSyspropMaxLen] = {};
+  char persist_program_specific_sysprop[kSyspropMaxLen] = {};
+  char persist_default_sysprop[kSyspropMaxLen] = {};
+  const char* sysprop_names[4] = {};
   // Tests use a blank program name to specify that system properties should not
   // be used. Tests still continue to use the environment variable though.
   if (*basename != '\0') {
-    sysprop_names[0] = program_specific_sysprop_name;
+    const char* default_sysprop = system_sysprop;
     if (mallopt_options.desire == Action::TURN_ON_FOR_APP) {
-      sysprop_names[1] = app_sysprop;
-    } else {
-      sysprop_names[1] = system_sysprop;
+      default_sysprop = app_sysprop;
     }
+    async_safe_format_buffer(&program_specific_sysprop[0], kSyspropMaxLen, "%s%s",
+                             targeted_sysprop_prefix, basename);
+    async_safe_format_buffer(&persist_program_specific_sysprop[0], kSyspropMaxLen, "%s%s",
+                             kPersistPrefix, program_specific_sysprop);
+    async_safe_format_buffer(&persist_default_sysprop[0], kSyspropMaxLen, "%s%s", kPersistPrefix,
+                             default_sysprop);
+
+    // In order of precedence, always take the program-specific sysprop (e.g.
+    // '[persist.]libc.debug.gwp_asan.sample_rate.cameraserver') over the
+    // generic sysprop (e.g.
+    // '[persist.]libc.debug.gwp_asan.(system_default|app_default)'). In
+    // addition, always take the non-persistent option over the persistent
+    // option.
+    sysprop_names[0] = program_specific_sysprop;
+    sysprop_names[1] = persist_program_specific_sysprop;
+    sysprop_names[2] = default_sysprop;
+    sysprop_names[3] = persist_default_sysprop;
   }
 
   char settings_buf[PROP_VALUE_MAX];
-  if (!get_config_from_env_or_sysprops(env_var, sysprop_names,
-                                       /* sys_prop_names_size */ 2, settings_buf, PROP_VALUE_MAX)) {
+  if (!get_config_from_env_or_sysprops(env_var, sysprop_names, arraysize(sysprop_names),
+                                       settings_buf, PROP_VALUE_MAX)) {
     return false;
   }