Merge "Add Display P3 color mode"
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index ec9b1c3..c3f1fe0 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -388,7 +388,13 @@
 
 static void adb_auth_inotify_init(const std::set<std::string>& paths) {
     LOG(INFO) << "adb_auth_inotify_init...";
+
     int infd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
+    if (infd < 0) {
+        PLOG(ERROR) << "failed to create inotify fd";
+        return;
+    }
+
     for (const std::string& path : paths) {
         int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
         if (wd < 0) {
diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp
index 78be944..f902af3 100644
--- a/bootstat/boot_event_record_store.cpp
+++ b/bootstat/boot_event_record_store.cpp
@@ -46,24 +46,6 @@
 
   *uptime = file_stat.st_mtime;
 
-  // The following code (till function exit) is a debug test to ensure the
-  // validity of the file mtime value, i.e., to check that the record file
-  // mtime values are not changed once set.
-  // TODO(jhawkins): Remove this code.
-  std::string content;
-  if (!android::base::ReadFileToString(path, &content)) {
-    PLOG(ERROR) << "Failed to read " << path;
-    return false;
-  }
-
-  // Ignore existing bootstat records (which do not contain file content).
-  if (!content.empty()) {
-    int32_t value;
-    if (android::base::ParseInt(content, &value)) {
-      bootstat::LogHistogram("bootstat_mtime_matches_content", value == *uptime);
-    }
-  }
-
   return true;
 }
 
@@ -89,16 +71,6 @@
     return;
   }
 
-  // Writing the value as content in the record file is a debug measure to
-  // ensure the validity of the file mtime value, i.e., to check that the record
-  // file mtime values are not changed once set.
-  // TODO(jhawkins): Remove this block.
-  if (!android::base::WriteStringToFd(std::to_string(value), record_fd)) {
-    PLOG(ERROR) << "Failed to write value to " << record_path;
-    close(record_fd);
-    return;
-  }
-
   // Fill out the stat structure for |record_path| in order to get the atime to
   // set in the utime() call.
   struct stat file_stat;
diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp
index 01c2cc1..90f6513 100644
--- a/bootstat/boot_event_record_store_test.cpp
+++ b/bootstat/boot_event_record_store_test.cpp
@@ -45,14 +45,6 @@
     return false;
   }
 
-  // Writing the value as content in the record file is a debug measure to
-  // ensure the validity of the file mtime value, i.e., to check that the record
-  // file mtime values are not changed once set.
-  // TODO(jhawkins): Remove this block.
-  if (!android::base::WriteStringToFd(std::to_string(value), record_fd)) {
-    return false;
-  }
-
   // Set the |mtime| of the file to store the value of the boot event while
   // preserving the |atime|.
   struct timeval atime = {/* tv_sec */ 0, /* tv_usec */ 0};
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index b9dfedb..831150b 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -57,8 +57,9 @@
 }
 
 // Attach to a thread, and verify that it's still a member of the given process
-static bool ptrace_attach_thread(pid_t pid, pid_t tid) {
+static bool ptrace_attach_thread(pid_t pid, pid_t tid, std::string* error) {
   if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) {
+    *error = StringPrintf("failed to attach to thread %d: %s", tid, strerror(errno));
     return false;
   }
 
@@ -67,7 +68,7 @@
     if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
       PLOG(FATAL) << "failed to detach from thread " << tid;
     }
-    errno = ECHILD;
+    *error = StringPrintf("thread %d is not in process %d", tid, pid);
     return false;
   }
   return true;
@@ -244,9 +245,9 @@
 
   check_process(target_proc_fd, target);
 
-  int attach_error = 0;
-  if (!ptrace_attach_thread(target, main_tid)) {
-    PLOG(FATAL) << "failed to attach to thread " << main_tid << " in process " << target;
+  std::string attach_error;
+  if (!ptrace_attach_thread(target, main_tid, &attach_error)) {
+    LOG(FATAL) << attach_error;
   }
 
   check_process(target_proc_fd, target);
@@ -268,10 +269,6 @@
     TEMP_FAILURE_RETRY(dup2(devnull.get(), STDOUT_FILENO));
   }
 
-  if (attach_error != 0) {
-    PLOG(FATAL) << "failed to attach to thread " << main_tid << " in process " << target;
-  }
-
   LOG(INFO) << "performing dump of process " << target << " (target tid = " << main_tid << ")";
 
   // At this point, the thread that made the request has been PTRACE_ATTACHed
@@ -307,6 +304,7 @@
   bool fatal_signal = signo != DEBUGGER_SIGNAL;
   int resume_signal = fatal_signal ? signo : 0;
   std::set<pid_t> siblings;
+  std::set<pid_t> attached_siblings;
   if (resume_signal == 0) {
     if (!android::procinfo::GetProcessTids(target, &siblings)) {
       PLOG(FATAL) << "failed to get process siblings";
@@ -314,8 +312,10 @@
     siblings.erase(main_tid);
 
     for (pid_t sibling_tid : siblings) {
-      if (!ptrace_attach_thread(target, sibling_tid)) {
-        PLOG(FATAL) << "failed to attach to thread " << main_tid << " in process " << target;
+      if (!ptrace_attach_thread(target, sibling_tid, &attach_error)) {
+        LOG(WARNING) << attach_error;
+      } else {
+        attached_siblings.insert(sibling_tid);
       }
     }
   }
@@ -328,14 +328,14 @@
   std::string amfd_data;
 
   if (backtrace) {
-    dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, siblings, 0);
+    dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, attached_siblings, 0);
   } else {
     // Collect the list of open files.
     OpenFilesList open_files;
     populate_open_files_list(target, &open_files);
 
-    engrave_tombstone(output_fd.get(), backtrace_map.get(), open_files, target, main_tid, siblings,
-                      abort_address, fatal_signal ? &amfd_data : nullptr);
+    engrave_tombstone(output_fd.get(), backtrace_map.get(), open_files, target, main_tid,
+                      attached_siblings, abort_address, fatal_signal ? &amfd_data : nullptr);
   }
 
   bool wait_for_gdb = android::base::GetBoolProperty("debug.debuggerd.wait_for_gdb", false);
@@ -357,7 +357,7 @@
     }
   }
 
-  for (pid_t tid : siblings) {
+  for (pid_t tid : attached_siblings) {
     // Don't send the signal to sibling threads.
     if (ptrace(PTRACE_DETACH, tid, 0, wait_for_gdb ? SIGSTOP : 0) != 0) {
       PLOG(ERROR) << "ptrace detach from " << tid << " failed";
diff --git a/debuggerd/tombstoned/tombstoned.rc b/debuggerd/tombstoned/tombstoned.rc
index 3aacf33..eaae9c4 100644
--- a/debuggerd/tombstoned/tombstoned.rc
+++ b/debuggerd/tombstoned/tombstoned.rc
@@ -1,6 +1,4 @@
 service tombstoned /system/bin/tombstoned
-    class core
-
     user tombstoned
     group system
 
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 4d72a1a..86b6287 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -304,9 +304,9 @@
             sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
             sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
             if (service != NULL) {
-                status_t ret = service->addAuthToken(*auth_token, *auth_token_length);
-                if (ret != ResponseCode::NO_ERROR) {
-                    ALOGE("Falure sending auth token to KeyStore: %d", ret);
+                auto ret = service->addAuthToken(*auth_token, *auth_token_length);
+                if (!ret.isOk()) {
+                    ALOGE("Failure sending auth token to KeyStore: %" PRId32, int32_t(ret));
                 }
             } else {
                 ALOGE("Unable to communicate with KeyStore");
diff --git a/init/init.cpp b/init/init.cpp
index 75d8bc7..ddc707f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -263,26 +263,18 @@
     panic();
 }
 
-#define MMAP_RND_PATH "/proc/sys/vm/mmap_rnd_bits"
-#define MMAP_RND_COMPAT_PATH "/proc/sys/vm/mmap_rnd_compat_bits"
-
-/* __attribute__((unused)) due to lack of mips support: see mips block
- * in set_mmap_rnd_bits_action */
-static bool __attribute__((unused)) set_mmap_rnd_bits_min(int start, int min, bool compat) {
-    std::string path;
-    if (compat) {
-        path = MMAP_RND_COMPAT_PATH;
-    } else {
-        path = MMAP_RND_PATH;
-    }
+static bool set_highest_available_option_value(std::string path, int min, int max)
+{
     std::ifstream inf(path, std::fstream::in);
     if (!inf) {
         LOG(ERROR) << "Cannot open for reading: " << path;
         return false;
     }
-    while (start >= min) {
+
+    int current = max;
+    while (current >= min) {
         // try to write out new value
-        std::string str_val = std::to_string(start);
+        std::string str_val = std::to_string(current);
         std::ofstream of(path, std::fstream::out);
         if (!of) {
             LOG(ERROR) << "Cannot open for writing: " << path;
@@ -298,16 +290,33 @@
         if (str_val.compare(str_rec) == 0) {
             break;
         }
-        start--;
+        current--;
     }
     inf.close();
-    if (start < min) {
-        LOG(ERROR) << "Unable to set minimum required entropy " << min << " in " << path;
+
+    if (current < min) {
+        LOG(ERROR) << "Unable to set minimum option value " << min << " in " << path;
         return false;
     }
     return true;
 }
 
+#define MMAP_RND_PATH "/proc/sys/vm/mmap_rnd_bits"
+#define MMAP_RND_COMPAT_PATH "/proc/sys/vm/mmap_rnd_compat_bits"
+
+/* __attribute__((unused)) due to lack of mips support: see mips block
+ * in set_mmap_rnd_bits_action */
+static bool __attribute__((unused)) set_mmap_rnd_bits_min(int start, int min, bool compat) {
+    std::string path;
+    if (compat) {
+        path = MMAP_RND_COMPAT_PATH;
+    } else {
+        path = MMAP_RND_PATH;
+    }
+
+    return set_highest_available_option_value(path, min, start);
+}
+
 /*
  * Set /proc/sys/vm/mmap_rnd_bits and potentially
  * /proc/sys/vm/mmap_rnd_compat_bits to the maximum supported values.
@@ -360,6 +369,25 @@
     return ret;
 }
 
+#define KPTR_RESTRICT_PATH "/proc/sys/kernel/kptr_restrict"
+#define KPTR_RESTRICT_MINVALUE 2
+#define KPTR_RESTRICT_MAXVALUE 4
+
+/* Set kptr_restrict to the highest available level.
+ *
+ * Aborts if unable to set this to an acceptable value.
+ */
+static int set_kptr_restrict_action(const std::vector<std::string>& args)
+{
+    std::string path = KPTR_RESTRICT_PATH;
+
+    if (!set_highest_available_option_value(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) {
+        LOG(ERROR) << "Unable to set adequate kptr_restrict value!";
+        security_failure();
+    }
+    return 0;
+}
+
 static int keychord_init_action(const std::vector<std::string>& args)
 {
     keychord_init();
@@ -818,6 +846,7 @@
     // ... so that we can start queuing up actions that require stuff from /dev.
     am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
     am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
+    am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");
     am.QueueBuiltinAction(keychord_init_action, "keychord_init");
     am.QueueBuiltinAction(console_init_action, "console_init");
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 498a5a1..72fcb5b 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -439,6 +439,8 @@
 
 void property_load_boot_defaults() {
     load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT, NULL);
+    load_properties_from_file(PROP_PATH_ODM_DEFAULT, NULL);
+    load_properties_from_file(PROP_PATH_VENDOR_DEFAULT, NULL);
 }
 
 static void load_override_properties() {
@@ -501,6 +503,7 @@
 
 void load_system_props() {
     load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL);
+    load_properties_from_file(PROP_PATH_ODM_BUILD, NULL);
     load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL);
     load_properties_from_file(PROP_PATH_FACTORY, "ro.*");
     load_recovery_id_prop();
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 18c0020..a7c2dce 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -202,7 +202,10 @@
     { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "system/build.prop" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/build.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/build.prop" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "default.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/default.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/default.prop" },
     { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
 };
 
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index f19c3ab..1a2d506 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -262,6 +262,8 @@
     }
 
 #if defined(__ANDROID__)
+    clock_gettime(android_log_clockid(), &ts);
+
     if (log_id == LOG_ID_SECURITY) {
         if (vec[0].iov_len < 4) {
             return -EINVAL;
@@ -351,8 +353,6 @@
             return -EPERM;
         }
     }
-
-    clock_gettime(android_log_clockid(), &ts);
 #else
     /* simulate clock_gettime(CLOCK_REALTIME, &ts); */
     {
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index c204a16..d9935c3 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -581,24 +581,36 @@
 
 } /* namespace android */
 
+void reportErrorName(const char **current,
+                     const char* name,
+                     bool blockSecurity) {
+    if (*current) {
+       return;
+    }
+    if (blockSecurity && (android_name_to_log_id(name) == LOG_ID_SECURITY)) {
+       return;
+    }
+    *current = name;
+}
 
 int main(int argc, char **argv)
 {
     using namespace android;
     int err;
     int hasSetLogFormat = 0;
-    int clearLog = 0;
-    int getLogSize = 0;
+    bool clearLog = false;
+    bool allSelected = false;
+    bool getLogSize = false;
+    bool getPruneList = false;
+    bool printStatistics = false;
+    bool printDividers = false;
     unsigned long setLogSize = 0;
-    int getPruneList = 0;
     char *setPruneList = NULL;
     char *setId = NULL;
-    int printStatistics = 0;
     int mode = ANDROID_LOG_RDONLY;
     const char *forceFilters = NULL;
     log_device_t* devices = NULL;
     log_device_t* dev;
-    bool printDividers = false;
     struct logger_list *logger_list;
     size_t tail_lines = 0;
     log_time tail_time(log_time::EPOCH);
@@ -710,7 +722,7 @@
             break;
 
             case 'c':
-                clearLog = 1;
+                clearLog = true;
                 mode |= ANDROID_LOG_WRONLY;
             break;
 
@@ -771,7 +783,7 @@
 
             case 'g':
                 if (!optarg) {
-                    getLogSize = 1;
+                    getLogSize = true;
                     break;
                 }
                 // FALLTHRU
@@ -813,7 +825,7 @@
 
             case 'p':
                 if (!optarg) {
-                    getPruneList = 1;
+                    getPruneList = true;
                     break;
                 }
                 // FALLTHRU
@@ -830,6 +842,7 @@
                                   (1 << LOG_ID_SYSTEM) |
                                   (1 << LOG_ID_CRASH);
                     } else if (strcmp(optarg, "all") == 0) {
+                        allSelected = true;
                         idMask = (unsigned)-1;
                     } else {
                         log_id_t log_id = android_name_to_log_id(optarg);
@@ -839,6 +852,7 @@
                             logcat_panic(HELP_TRUE,
                                          "unknown buffer %s\n", optarg);
                         }
+                        if (log_id == LOG_ID_SECURITY) allSelected = false;
                         idMask |= (1 << log_id);
                     }
                     optarg = NULL;
@@ -992,7 +1006,7 @@
                 break;
 
             case 'S':
-                printStatistics = 1;
+                printStatistics = true;
                 break;
 
             case ':':
@@ -1114,7 +1128,7 @@
         dev->logger = android_logger_open(logger_list,
                                           android_name_to_log_id(dev->device));
         if (!dev->logger) {
-            openDeviceFail = openDeviceFail ?: dev->device;
+            reportErrorName(&openDeviceFail, dev->device, allSelected);
             dev = dev->next;
             continue;
         }
@@ -1136,7 +1150,7 @@
 
                     if (file.length() == 0) {
                         perror("while clearing log files");
-                        clearFail = clearFail ?: dev->device;
+                        reportErrorName(&clearFail, dev->device, allSelected);
                         break;
                     }
 
@@ -1144,17 +1158,17 @@
 
                     if (err < 0 && errno != ENOENT && clearFail == NULL) {
                         perror("while clearing log files");
-                        clearFail = dev->device;
+                        reportErrorName(&clearFail, dev->device, allSelected);
                     }
                 }
             } else if (android_logger_clear(dev->logger)) {
-                clearFail = clearFail ?: dev->device;
+                reportErrorName(&clearFail, dev->device, allSelected);
             }
         }
 
         if (setLogSize) {
             if (android_logger_set_log_size(dev->logger, setLogSize)) {
-                setSizeFail = setSizeFail ?: dev->device;
+                reportErrorName(&setSizeFail, dev->device, allSelected);
             }
         }
 
@@ -1163,7 +1177,7 @@
             long readable = android_logger_get_log_readable_size(dev->logger);
 
             if ((size < 0) || (readable < 0)) {
-                getSizeFail = getSizeFail ?: dev->device;
+                reportErrorName(&getSizeFail, dev->device, allSelected);
             } else {
                 printf("%s: ring buffer is %ld%sb (%ld%sb consumed), "
                        "max entry is %db, max payload is %db\n", dev->device,
diff --git a/logcat/tests/Android.mk b/logcat/tests/Android.mk
index 99c2e0a..cb8b061 100644
--- a/logcat/tests/Android.mk
+++ b/logcat/tests/Android.mk
@@ -55,6 +55,6 @@
 LOCAL_MODULE := $(test_module_prefix)unit-tests
 LOCAL_MODULE_TAGS := $(test_tags)
 LOCAL_CFLAGS += $(test_c_flags)
-LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SHARED_LIBRARIES := liblog libbase
 LOCAL_SRC_FILES := $(test_src_files)
 include $(BUILD_NATIVE_TEST)
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 725d76e..8a390f6 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -27,6 +27,7 @@
 #include <memory>
 #include <string>
 
+#include <android-base/file.h>
 #include <gtest/gtest.h>
 #include <log/log.h>
 #include <log/log_event_list.h>
@@ -1412,3 +1413,22 @@
         EXPECT_TRUE(End_to_End(sync.tagStr, ""));
     }
 }
+
+static bool reportedSecurity(const char* command) {
+    FILE* fp = popen(command, "r");
+    if (!fp) return true;
+
+    std::string ret;
+    bool val = android::base::ReadFdToString(fileno(fp), &ret);
+    pclose(fp);
+
+    if (!val) return true;
+    return std::string::npos != ret.find("'security'");
+}
+
+TEST(logcat, security) {
+    EXPECT_FALSE(reportedSecurity("logcat -b all -g 2>&1"));
+    EXPECT_TRUE(reportedSecurity("logcat -b security -g 2>&1"));
+    EXPECT_TRUE(reportedSecurity("logcat -b security -c 2>&1"));
+    EXPECT_TRUE(reportedSecurity("logcat -b security -G 256K 2>&1"));
+}
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 703c0fb..13a7922 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -196,7 +196,9 @@
     EXPECT_TRUE(NULL != main_logs);
 
     char *radio_logs = strstr(cp, "\nChattiest UIDs in radio ");
-    EXPECT_TRUE(NULL != radio_logs);
+    if (!radio_logs) GTEST_LOG_(INFO) << "Value of: NULL != radio_logs\n"
+                                         "Actual: false\n"
+                                         "Expected: false\n";
 
     char *system_logs = strstr(cp, "\nChattiest UIDs in system ");
     EXPECT_TRUE(NULL != system_logs);
@@ -942,8 +944,16 @@
         return 0;
     }
 
-    // Requests dac_read_search, falls back to request dac_override
-    rate /= 2;
+    // The key here is we are root, but we are in u:r:shell:s0,
+    // and the directory does not provide us DAC access
+    // (eg: 0700 system system) so we trigger the pair dac_override
+    // and dac_read_search on every try to get past the message
+    // de-duper.  We will also rotate the file name in the directory
+    // as another measure.
+    static const char file[] = "/data/backup/cannot_access_directory_%u";
+    static const unsigned avc_requests_per_access = 2;
+
+    rate /= avc_requests_per_access;
     useconds_t usec;
     if (rate == 0) {
         rate = 1;
@@ -951,15 +961,12 @@
     } else {
         usec = (1000000 + (rate / 2)) / rate;
     }
-    num = (num + 1) / 2;
+    num = (num + (avc_requests_per_access / 2)) / avc_requests_per_access;
 
     if (usec < 2) usec = 2;
 
     while (num > 0) {
-        if (access(android::base::StringPrintf(
-                       "/data/misc/logd/cannot_access_directory_%u",
-                       num).c_str(),
-                   F_OK) == 0) {
+        if (access(android::base::StringPrintf(file, num).c_str(), F_OK) == 0) {
             _exit(-1);
             // NOTREACHED
             return 0;
@@ -1002,7 +1009,7 @@
 
         // int len = get4LE(eventData + 4 + 1);
         log_msg.buf[LOGGER_ENTRY_MAX_LEN] = '\0';
-        const char *cp = strstr(eventData + 4 + 1 + 4, "): avc: ");
+        const char *cp = strstr(eventData + 4 + 1 + 4, "): avc: denied");
         if (!cp) continue;
 
         ++count;
@@ -1055,8 +1062,7 @@
     // give logd another 3 seconds to react to the burst before checking
     sepolicy_rate(rate, rate * 3);
     // maximum period at double the maximum burst rate (spam filter kicked in)
-    EXPECT_GE(((AUDIT_RATE_LIMIT_MAX * AUDIT_RATE_LIMIT_BURST_DURATION) * 130) /
-                                        100, // +30% margin
+    EXPECT_GE(threshold * 2,
               count_avc(sepolicy_rate(rate,
                                       rate * AUDIT_RATE_LIMIT_BURST_DURATION)));
     // cool down, and check unspammy rate still works
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 50788c1..1ae43fb 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -118,7 +118,6 @@
     write /proc/sys/kernel/sched_child_runs_first 0
 
     write /proc/sys/kernel/randomize_va_space 2
-    write /proc/sys/kernel/kptr_restrict 2
     write /proc/sys/vm/mmap_min_addr 32768
     write /proc/sys/net/ipv4/ping_group_range "0 2147483647"
     write /proc/sys/net/unix/max_dgram_qlen 600
@@ -357,14 +356,13 @@
     # We restorecon /data in case the userdata partition has been reset.
     restorecon /data
 
-    # start debuggerd to make debugging early-boot crashes easier.
-    start debuggerd
-    start debuggerd64
-
     # Make sure we have the device encryption key.
     start vold
     installkey /data
 
+    # start tombstoned to record early-boot crashes.
+    start tombstoned
+
     # Start bootcharting as soon as possible after the data partition is
     # mounted to collect more data.
     mkdir /data/bootchart 0755 shell shell