Merge "liblog: tests: liblog.__security property failure"
diff --git a/init/Android.mk b/init/Android.mk
index 2a1ad9c..d48f152 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -5,9 +5,15 @@
 # --
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_PERMISSIVE_SELINUX=1
+init_options += \
+    -DALLOW_LOCAL_PROP_OVERRIDE=1 \
+    -DALLOW_PERMISSIVE_SELINUX=1 \
+    -DREBOOT_BOOTLOADER_ON_PANIC=1
 else
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=0 -DALLOW_PERMISSIVE_SELINUX=0
+init_options += \
+    -DALLOW_LOCAL_PROP_OVERRIDE=0 \
+    -DALLOW_PERMISSIVE_SELINUX=0 \
+    -DREBOOT_BOOTLOADER_ON_PANIC=0
 endif
 
 init_options += -DLOG_UEVENTS=0
diff --git a/init/README.md b/init/README.md
index d3dd73a..99522b9 100644
--- a/init/README.md
+++ b/init/README.md
@@ -203,7 +203,9 @@
 
 `writepid <file...>`
 > Write the child's pid to the given files when it forks. Meant for
-  cgroup/cpuset usage.
+  cgroup/cpuset usage. If no files under /dev/cpuset/ are specified, but the
+  system property 'ro.cpuset.default' is set to a non-empty cpuset name (e.g.
+  '/foreground'), then the pid is written to file /dev/cpuset/_cpuset\_name_/tasks.
 
 `priority <priority>`
 > Scheduling priority of the service process. This value has to be in range
diff --git a/init/init.cpp b/init/init.cpp
index d095685..0ce1c05 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -1099,6 +1099,31 @@
     return success;
 }
 
+static void install_reboot_signal_handlers() {
+    // Instead of panic'ing the kernel as is the default behavior when init crashes,
+    // we prefer to reboot to bootloader on development builds, as this will prevent
+    // boot looping bad configurations and allow both developers and test farms to easily
+    // recover.
+    struct sigaction action;
+    memset(&action, 0, sizeof(action));
+    sigfillset(&action.sa_mask);
+    action.sa_handler = [](int) {
+        // panic() reboots to bootloader
+        panic();
+    };
+    action.sa_flags = SA_RESTART;
+    sigaction(SIGABRT, &action, nullptr);
+    sigaction(SIGBUS, &action, nullptr);
+    sigaction(SIGFPE, &action, nullptr);
+    sigaction(SIGILL, &action, nullptr);
+    sigaction(SIGSEGV, &action, nullptr);
+#if defined(SIGSTKFLT)
+    sigaction(SIGSTKFLT, &action, nullptr);
+#endif
+    sigaction(SIGSYS, &action, nullptr);
+    sigaction(SIGTRAP, &action, nullptr);
+}
+
 int main(int argc, char** argv) {
     if (!strcmp(basename(argv[0]), "ueventd")) {
         return ueventd_main(argc, argv);
@@ -1108,6 +1133,10 @@
         return watchdogd_main(argc, argv);
     }
 
+    if (REBOOT_BOOTLOADER_ON_PANIC) {
+        install_reboot_signal_handlers();
+    }
+
     add_environment("PATH", _PATH_DEFPATH);
 
     bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
diff --git a/init/service.cpp b/init/service.cpp
index ba901fd..35aaa56 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -630,6 +630,28 @@
         std::for_each(descriptors_.begin(), descriptors_.end(),
                       std::bind(&DescriptorInfo::CreateAndPublish, std::placeholders::_1, scon));
 
+        // See if there were "writepid" instructions to write to files under /dev/cpuset/.
+        auto cpuset_predicate = [](const std::string& path) {
+            return android::base::StartsWith(path, "/dev/cpuset/");
+        };
+        auto iter = std::find_if(writepid_files_.begin(), writepid_files_.end(), cpuset_predicate);
+        if (iter == writepid_files_.end()) {
+            // There were no "writepid" instructions for cpusets, check if the system default
+            // cpuset is specified to be used for the process.
+            std::string default_cpuset = property_get("ro.cpuset.default");
+            if (!default_cpuset.empty()) {
+                // Make sure the cpuset name starts and ends with '/'.
+                // A single '/' means the 'root' cpuset.
+                if (default_cpuset.front() != '/') {
+                    default_cpuset.insert(0, 1, '/');
+                }
+                if (default_cpuset.back() != '/') {
+                    default_cpuset.push_back('/');
+                }
+                writepid_files_.push_back(
+                    StringPrintf("/dev/cpuset%stasks", default_cpuset.c_str()));
+            }
+        }
         std::string pid_str = StringPrintf("%d", getpid());
         for (const auto& file : writepid_files_) {
             if (!WriteStringToFile(pid_str, file)) {