Merge "Suppress clang-analyzer-security.FloatLoopCounter warnings"
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 2a769c7..70f333e 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -303,6 +303,7 @@
       process_info->scudo_stack_depot = crash_info->data.d.scudo_stack_depot;
       process_info->scudo_region_info = crash_info->data.d.scudo_region_info;
       process_info->scudo_ring_buffer = crash_info->data.d.scudo_ring_buffer;
+      process_info->scudo_ring_buffer_size = crash_info->data.d.scudo_ring_buffer_size;
       FALLTHROUGH_INTENDED;
     case 1:
     case 2:
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index c64de0e..7120d73 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -187,27 +187,29 @@
  * mutex is being held, so we don't want to use any libc functions that
  * could allocate memory or hold a lock.
  */
-static void log_signal_summary(const siginfo_t* info) {
+static void log_signal_summary(const siginfo_t* si) {
   char main_thread_name[MAX_TASK_NAME_LEN + 1];
   if (!get_main_thread_name(main_thread_name, sizeof(main_thread_name))) {
     strncpy(main_thread_name, "<unknown>", sizeof(main_thread_name));
   }
 
-  if (info->si_signo == BIONIC_SIGNAL_DEBUGGER) {
+  if (si->si_signo == BIONIC_SIGNAL_DEBUGGER) {
     async_safe_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for pid %d (%s)", __getpid(),
                           main_thread_name);
     return;
   }
 
-  // Many signals don't have an address or sender.
-  char addr_desc[32] = "";  // ", fault addr 0x1234"
-  if (signal_has_si_addr(info)) {
-    async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
-  }
+  // Many signals don't have a sender or extra detail, but some do...
   pid_t self_pid = __getpid();
   char sender_desc[32] = {};  // " from pid 1234, uid 666"
-  if (signal_has_sender(info, self_pid)) {
-    get_signal_sender(sender_desc, sizeof(sender_desc), info);
+  if (signal_has_sender(si, self_pid)) {
+    get_signal_sender(sender_desc, sizeof(sender_desc), si);
+  }
+  char extra_desc[32] = {};  // ", fault addr 0x1234" or ", syscall 1234"
+  if (si->si_signo == SIGSYS && si->si_code == SYS_SECCOMP) {
+    async_safe_format_buffer(extra_desc, sizeof(extra_desc), ", syscall %d", si->si_syscall);
+  } else if (signal_has_si_addr(si)) {
+    async_safe_format_buffer(extra_desc, sizeof(extra_desc), ", fault addr %p", si->si_addr);
   }
 
   char thread_name[MAX_TASK_NAME_LEN + 1];  // one more for termination
@@ -221,8 +223,8 @@
 
   async_safe_format_log(ANDROID_LOG_FATAL, "libc",
                         "Fatal signal %d (%s), code %d (%s%s)%s in tid %d (%s), pid %d (%s)",
-                        info->si_signo, get_signame(info), info->si_code, get_sigcode(info),
-                        sender_desc, addr_desc, __gettid(), thread_name, self_pid, main_thread_name);
+                        si->si_signo, get_signame(si), si->si_code, get_sigcode(si), sender_desc,
+                        extra_desc, __gettid(), thread_name, self_pid, main_thread_name);
 }
 
 /*
@@ -371,12 +373,30 @@
       {.iov_base = thread_info->ucontext, .iov_len = sizeof(ucontext_t)},
   };
 
+  constexpr size_t kHeaderSize = sizeof(version) + sizeof(siginfo_t) + sizeof(ucontext_t);
+
   if (thread_info->process_info.fdsan_table) {
     // Dynamic executables always use version 4. There is no need to increment the version number if
     // the format changes, because the sender (linker) and receiver (crash_dump) are version locked.
     version = 4;
     expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic);
 
+    static_assert(sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic) ==
+                      kHeaderSize + sizeof(thread_info->process_info),
+                  "Wire protocol structs do not match the data sent.");
+#define ASSERT_SAME_OFFSET(MEMBER1, MEMBER2) \
+    static_assert(sizeof(CrashInfoHeader) + offsetof(CrashInfoDataDynamic, MEMBER1) == \
+                      kHeaderSize + offsetof(debugger_process_info, MEMBER2), \
+                  "Wire protocol offset does not match data sent: " #MEMBER1);
+    ASSERT_SAME_OFFSET(fdsan_table_address, fdsan_table);
+    ASSERT_SAME_OFFSET(gwp_asan_state, gwp_asan_state);
+    ASSERT_SAME_OFFSET(gwp_asan_metadata, gwp_asan_metadata);
+    ASSERT_SAME_OFFSET(scudo_stack_depot, scudo_stack_depot);
+    ASSERT_SAME_OFFSET(scudo_region_info, scudo_region_info);
+    ASSERT_SAME_OFFSET(scudo_ring_buffer, scudo_ring_buffer);
+    ASSERT_SAME_OFFSET(scudo_ring_buffer_size, scudo_ring_buffer_size);
+#undef ASSERT_SAME_OFFSET
+
     iovs[3] = {.iov_base = &thread_info->process_info,
                .iov_len = sizeof(thread_info->process_info)};
   } else {
@@ -384,6 +404,10 @@
     version = 1;
     expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic);
 
+    static_assert(
+        sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic) == kHeaderSize + sizeof(uintptr_t),
+        "Wire protocol structs do not match the data sent.");
+
     iovs[3] = {.iov_base = &thread_info->process_info.abort_msg, .iov_len = sizeof(uintptr_t)};
   }
   errno = 0;
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index 68b2e67..1f9f4e2 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -43,6 +43,7 @@
   const char* scudo_stack_depot;
   const char* scudo_region_info;
   const char* scudo_ring_buffer;
+  size_t scudo_ring_buffer_size;
 };
 
 // These callbacks are called in a signal handler, and thus must be async signal safe.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index a51e276..5a2a7ab 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -50,6 +50,7 @@
   uintptr_t scudo_stack_depot = 0;
   uintptr_t scudo_region_info = 0;
   uintptr_t scudo_ring_buffer = 0;
+  size_t scudo_ring_buffer_size = 0;
 
   bool has_fault_address = false;
   uintptr_t untagged_fault_address = 0;
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index 5d861f8..37e390b 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -45,7 +45,7 @@
   auto region_info = AllocAndReadFully(process_memory, process_info.scudo_region_info,
                                        __scudo_get_region_info_size());
   auto ring_buffer = AllocAndReadFully(process_memory, process_info.scudo_ring_buffer,
-                                       __scudo_get_ring_buffer_size());
+                                       process_info.scudo_ring_buffer_size);
   if (!stack_depot || !region_info || !ring_buffer) {
     return;
   }
diff --git a/debuggerd/protocol.h b/debuggerd/protocol.h
index f33b2f0..e7cb218 100644
--- a/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -98,6 +98,7 @@
   uintptr_t scudo_stack_depot;
   uintptr_t scudo_region_info;
   uintptr_t scudo_ring_buffer;
+  size_t scudo_ring_buffer_size;
 };
 
 struct __attribute__((__packed__)) CrashInfo {
diff --git a/debuggerd/test_permissive_mte/Android.bp b/debuggerd/test_permissive_mte/Android.bp
index 1c09240..d3f7520 100644
--- a/debuggerd/test_permissive_mte/Android.bp
+++ b/debuggerd/test_permissive_mte/Android.bp
@@ -18,6 +18,7 @@
 
 cc_binary {
   name: "mte_crash",
+  tidy: false,
   srcs: ["mte_crash.cpp"],
   sanitize: {
     memtag_heap: true,
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 610eebf..a4b9307 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -191,16 +191,30 @@
 
         // Iterate over the endpoints for this interface and see if there
         // are any that do bulk in/out.
-        for (UInt8 endpoint = 1; endpoint <= interfaceNumEndpoints; endpoint++) {
+        for (UInt8 endpoint = 1; endpoint <= interfaceNumEndpoints; ++endpoint) {
             UInt8   transferType;
-            UInt16  maxPacketSize;
+            UInt16  endPointMaxPacketSize = 0;
             UInt8   interval;
+
+            // Attempt to retrieve the 'true' packet-size from supported interface.
+            kr = (*interface)
+                 ->GetEndpointProperties(interface, 0, endpoint,
+                                       kUSBOut,
+                                       &transferType,
+                                       &endPointMaxPacketSize, &interval);
+            if (kr == kIOReturnSuccess && !endPointMaxPacketSize) {
+                ERR("GetEndpointProperties() returned zero len packet-size");
+            }
+
+            UInt16  pipePropMaxPacketSize;
             UInt8   number;
             UInt8   direction;
 
+            // Proceed with extracting the transfer direction, so we can fill in the
+            // appropriate fields (bulkIn or bulkOut).
             kr = (*interface)->GetPipeProperties(interface, endpoint,
                     &direction,
-                    &number, &transferType, &maxPacketSize, &interval);
+                    &number, &transferType, &pipePropMaxPacketSize, &interval);
 
             if (kr == 0) {
                 if (transferType != kUSBBulk) {
@@ -216,7 +230,8 @@
                 }
 
                 if (handle->info.ifc_protocol == 0x01) {
-                    handle->zero_mask = maxPacketSize - 1;
+                    handle->zero_mask = (endPointMaxPacketSize == 0) ?
+                        pipePropMaxPacketSize - 1 : endPointMaxPacketSize - 1;
                 }
             } else {
                 ERR("could not get pipe properties for endpoint %u (%08x)\n", endpoint, kr);
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index cdff06e..9eb89b6 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -395,6 +395,10 @@
     // first-stage to decide whether to launch snapuserd.
     bool IsSnapuserdRequired();
 
+    // This is primarily used to device reboot. If OTA update is in progress,
+    // init will avoid killing processes
+    bool IsUserspaceSnapshotUpdateInProgress();
+
     enum class SnapshotDriver {
         DM_SNAPSHOT,
         DM_USER,
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 6fed09c..10d2f18 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -4349,5 +4349,16 @@
     return status.source_build_fingerprint();
 }
 
+bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress() {
+    auto slot = GetCurrentSlot();
+    if (slot == Slot::Target) {
+        if (IsSnapuserdRequired()) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/healthd/Android.bp b/healthd/Android.bp
index a090b74..76b6ad0 100644
--- a/healthd/Android.bp
+++ b/healthd/Android.bp
@@ -2,17 +2,8 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-cc_library_headers {
-    name: "libhealthd_headers",
-    vendor_available: true,
-    recovery_available: true,
-    export_include_dirs: ["include"],
-    header_libs: ["libbatteryservice_headers"],
-    export_header_lib_headers: ["libbatteryservice_headers"],
-}
-
-cc_library_static {
-    name: "libbatterymonitor",
+cc_defaults {
+    name: "libbatterymonitor_defaults",
     srcs: ["BatteryMonitor.cpp"],
     cflags: ["-Wall", "-Werror"],
     vendor_available: true,
@@ -25,6 +16,66 @@
         // Need HealthInfo definition from headers of these shared
         // libraries. Clients don't need to link to these.
         "android.hardware.health@2.1",
+    ],
+    header_libs: ["libhealthd_headers"],
+    export_header_lib_headers: ["libhealthd_headers"],
+}
+
+cc_defaults {
+    name: "libhealthd_charger_ui_defaults",
+    vendor_available: true,
+    export_include_dirs: [
+        "include",
+        "include_charger",
+    ],
+
+    static_libs: [
+        "libcharger_sysprop",
+        "libhealthd_draw",
+        "libhealthloop",
+        "libminui",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libpng",
+        "libsuspend",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libhealthd_headers",
+    ],
+
+    srcs: [
+        "healthd_mode_charger.cpp",
+        "AnimationParser.cpp",
+    ],
+
+    target: {
+        vendor: {
+            exclude_static_libs: [
+                "libcharger_sysprop",
+            ],
+        },
+    },
+}
+
+cc_library_headers {
+    name: "libhealthd_headers",
+    vendor_available: true,
+    recovery_available: true,
+    export_include_dirs: ["include"],
+    header_libs: ["libbatteryservice_headers"],
+    export_header_lib_headers: ["libbatteryservice_headers"],
+}
+
+cc_library_static {
+    name: "libbatterymonitor",
+    defaults: ["libbatterymonitor_defaults"],
+    static_libs: [
         "android.hardware.health-V1-ndk",
     ],
     whole_static_libs: [
@@ -32,8 +83,20 @@
         // BatteryMonitor.
         "android.hardware.health-translate-ndk",
     ],
-    header_libs: ["libhealthd_headers"],
-    export_header_lib_headers: ["libhealthd_headers"],
+}
+
+// TODO(b/251425963): remove when android.hardware.health is upgraded to V2.
+cc_library_static {
+    name: "libbatterymonitor-V1",
+    defaults: ["libbatterymonitor_defaults"],
+    static_libs: [
+        "android.hardware.health-V1-ndk",
+    ],
+    whole_static_libs: [
+        // Need to translate HIDL to AIDL to support legacy APIs in
+        // BatteryMonitor.
+        "android.hardware.health-translate-V1-ndk",
+    ],
 }
 
 cc_defaults {
@@ -136,50 +199,31 @@
 
 cc_library_static {
     name: "libhealthd_charger_ui",
-    vendor_available: true,
-    export_include_dirs: [
-        "include",
-        "include_charger",
-    ],
+    defaults: ["libhealthd_charger_ui_defaults"],
 
     static_libs: [
         "android.hardware.health-V1-ndk",
         "android.hardware.health-translate-ndk",
-        "libcharger_sysprop",
-        "libhealthd_draw",
-        "libhealthloop",
-        "libminui",
-    ],
-
-    shared_libs: [
-        "libbase",
-        "libcutils",
-        "liblog",
-        "libpng",
-        "libsuspend",
-        "libutils",
-    ],
-
-    header_libs: [
-        "libhealthd_headers",
     ],
 
     export_static_lib_headers: [
         "android.hardware.health-V1-ndk",
     ],
+}
 
-    srcs: [
-        "healthd_mode_charger.cpp",
-        "AnimationParser.cpp",
+// TODO(b/251425963): remove when android.hardware.health is upgraded to V2.
+cc_library_static {
+    name: "libhealthd_charger_ui-V1",
+    defaults: ["libhealthd_charger_ui_defaults"],
+
+    static_libs: [
+        "android.hardware.health-V1-ndk",
+        "android.hardware.health-translate-V1-ndk",
     ],
 
-    target: {
-        vendor: {
-            exclude_static_libs: [
-                "libcharger_sysprop",
-            ],
-        },
-    },
+    export_static_lib_headers: [
+        "android.hardware.health-V1-ndk",
+    ],
 }
 
 cc_library_static {
diff --git a/init/README.md b/init/README.md
index 957eb9e..4a5d0ec 100644
--- a/init/README.md
+++ b/init/README.md
@@ -244,6 +244,10 @@
   "r", "w" or "rw".  For native executables see libcutils
   android\_get\_control\_file().
 
+`gentle_kill`
+> This service will be sent SIGTERM instead of SIGKILL when stopped. After a 200 ms timeout, it will
+  be sent SIGKILL.
+
 `group <groupname> [ <groupname>\* ]`
 > Change to 'groupname' before exec'ing this service.  Additional
   groupnames beyond the (required) first one are used to set the
diff --git a/init/apex_init_util.cpp b/init/apex_init_util.cpp
index d618a6e..c818f8f 100644
--- a/init/apex_init_util.cpp
+++ b/init/apex_init_util.cpp
@@ -18,7 +18,6 @@
 
 #include <glob.h>
 
-#include <map>
 #include <vector>
 
 #include <android-base/logging.h>
@@ -66,18 +65,20 @@
 }
 
 static Result<void> ParseConfigs(const std::vector<std::string>& configs) {
-    Parser parser = CreateApexConfigParser(ActionManager::GetInstance(),
-                     ServiceList::GetInstance());
-    bool success = true;
+    Parser parser =
+            CreateApexConfigParser(ActionManager::GetInstance(), ServiceList::GetInstance());
+    std::vector<std::string> errors;
     for (const auto& c : configs) {
-        success &= parser.ParseConfigFile(c);
+        auto result = parser.ParseConfigFile(c);
+        // We should handle other config files even when there's an error.
+        if (!result.ok()) {
+            errors.push_back(result.error().message());
+        }
     }
-
-    if (success) {
-        return {};
-    } else {
-        return Error() << "Unable to parse apex configs";
+    if (!errors.empty()) {
+        return Error() << "Unable to parse apex configs: " << base::Join(errors, "|");
     }
+    return {};
 }
 
 Result<void> ParseApexConfigs(const std::string& apex_name) {
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 18a08c7..1e69ede 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -16,13 +16,16 @@
 
 #include <functional>
 #include <string_view>
+#include <thread>
 #include <type_traits>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <android/api-level.h>
 #include <gtest/gtest.h>
 #include <selinux/selinux.h>
+#include <sys/resource.h>
 
 #include "action.h"
 #include "action_manager.h"
@@ -626,6 +629,105 @@
     ASSERT_EQ(1u, parser.parse_error_count());
 }
 
+TEST(init, MemLockLimit) {
+    // Test is enforced only for U+ devices
+    if (android::base::GetIntProperty("ro.vendor.api_level", 0) < __ANDROID_API_U__) {
+        GTEST_SKIP();
+    }
+
+    // Verify we are running memlock at, or under, 64KB
+    const unsigned long max_limit = 65536;
+    struct rlimit curr_limit;
+    ASSERT_EQ(getrlimit(RLIMIT_MEMLOCK, &curr_limit), 0);
+    ASSERT_LE(curr_limit.rlim_cur, max_limit);
+    ASSERT_LE(curr_limit.rlim_max, max_limit);
+}
+
+static std::vector<const char*> ConvertToArgv(const std::vector<std::string>& args) {
+    std::vector<const char*> argv;
+    argv.reserve(args.size() + 1);
+    for (const auto& arg : args) {
+        if (argv.empty()) {
+            LOG(DEBUG) << arg;
+        } else {
+            LOG(DEBUG) << "    " << arg;
+        }
+        argv.emplace_back(arg.data());
+    }
+    argv.emplace_back(nullptr);
+    return argv;
+}
+
+pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
+    auto argv = ConvertToArgv(args);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        close(STDIN_FILENO);
+        close(STDOUT_FILENO);
+        close(STDERR_FILENO);
+
+        execvp(argv[0], const_cast<char**>(argv.data()));
+        PLOG(ERROR) << "exec in ForkExecvpAsync init test";
+        _exit(EXIT_FAILURE);
+    }
+    if (pid == -1) {
+        PLOG(ERROR) << "fork in ForkExecvpAsync init test";
+        return -1;
+    }
+    return pid;
+}
+
+TEST(init, GentleKill) {
+    std::string init_script = R"init(
+service test_gentle_kill /system/bin/sleep 1000
+    disabled
+    oneshot
+    gentle_kill
+    user root
+    group root
+    seclabel u:r:toolbox:s0
+)init";
+
+    ActionManager action_manager;
+    ServiceList service_list;
+    TestInitText(init_script, BuiltinFunctionMap(), {}, &action_manager, &service_list);
+    ASSERT_EQ(std::distance(service_list.begin(), service_list.end()), 1);
+
+    auto service = service_list.begin()->get();
+    ASSERT_NE(service, nullptr);
+    ASSERT_RESULT_OK(service->Start());
+    const pid_t pid = service->pid();
+    ASSERT_GT(pid, 0);
+    EXPECT_NE(getsid(pid), 0);
+
+    TemporaryFile logfile;
+    logfile.DoNotRemove();
+    ASSERT_TRUE(logfile.fd != -1);
+
+    std::vector<std::string> cmd;
+    cmd.push_back("system/bin/strace");
+    cmd.push_back("-o");
+    cmd.push_back(logfile.path);
+    cmd.push_back("-e");
+    cmd.push_back("signal");
+    cmd.push_back("-p");
+    cmd.push_back(std::to_string(pid));
+    pid_t strace_pid = ForkExecvpAsync(cmd);
+
+    // Give strace a moment to connect
+    std::this_thread::sleep_for(1s);
+    service->Stop();
+
+    int status;
+    waitpid(strace_pid, &status, 0);
+
+    std::string logs;
+    android::base::ReadFdToString(logfile.fd, &logs);
+    int pos = logs.find("killed by SIGTERM");
+    ASSERT_NE(pos, (int)std::string::npos);
+}
+
 class TestCaseLogger : public ::testing::EmptyTestEventListener {
     void OnTestStart(const ::testing::TestInfo& test_info) override {
 #ifdef __ANDROID__
diff --git a/init/parser.cpp b/init/parser.cpp
index 0a388db..adb41ad 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -141,19 +141,19 @@
     return true;
 }
 
-bool Parser::ParseConfigFile(const std::string& path) {
+Result<void> Parser::ParseConfigFile(const std::string& path) {
     LOG(INFO) << "Parsing file " << path << "...";
     android::base::Timer t;
     auto config_contents = ReadFile(path);
     if (!config_contents.ok()) {
-        LOG(INFO) << "Unable to read config file '" << path << "': " << config_contents.error();
-        return false;
+        return Error() << "Unable to read config file '" << path
+                       << "': " << config_contents.error();
     }
 
     ParseData(path, &config_contents.value());
 
     LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
-    return true;
+    return {};
 }
 
 bool Parser::ParseConfigDir(const std::string& path) {
@@ -176,8 +176,8 @@
     // Sort first so we load files in a consistent order (bug 31996208)
     std::sort(files.begin(), files.end());
     for (const auto& file : files) {
-        if (!ParseConfigFile(file)) {
-            LOG(ERROR) << "could not import file '" << file << "'";
+        if (auto result = ParseConfigFile(file); !result.ok()) {
+            LOG(ERROR) << "could not import file '" << file << "': " << result.error();
         }
     }
     return true;
@@ -187,7 +187,11 @@
     if (is_dir(path.c_str())) {
         return ParseConfigDir(path);
     }
-    return ParseConfigFile(path);
+    auto result = ParseConfigFile(path);
+    if (!result.ok()) {
+        LOG(INFO) << result.error();
+    }
+    return result.ok();
 }
 
 }  // namespace init
diff --git a/init/parser.h b/init/parser.h
index 95b0cd7..980ae0c 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -72,7 +72,7 @@
     Parser();
 
     bool ParseConfig(const std::string& path);
-    bool ParseConfigFile(const std::string& path);
+    Result<void> ParseConfigFile(const std::string& path);
     void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser);
     void AddSingleLineParser(const std::string& prefix, LineCallback callback);
 
diff --git a/init/reboot.cpp b/init/reboot.cpp
index a3fc534..27a7876 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -51,6 +51,7 @@
 #include <bootloader_message/bootloader_message.h>
 #include <cutils/android_reboot.h>
 #include <fs_mgr.h>
+#include <libsnapshot/snapshot.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
 #include <selinux/selinux.h>
@@ -422,11 +423,31 @@
     if (run_fsck && !FindPartitionsToUmount(&block_devices, &emulated_devices, false)) {
         return UMOUNT_STAT_ERROR;
     }
-
+    auto sm = snapshot::SnapshotManager::New();
+    bool ota_update_in_progress = false;
+    if (sm->IsUserspaceSnapshotUpdateInProgress()) {
+        LOG(INFO) << "OTA update in progress";
+        ota_update_in_progress = true;
+    }
     UmountStat stat = UmountPartitions(timeout - t.duration());
     if (stat != UMOUNT_STAT_SUCCESS) {
         LOG(INFO) << "umount timeout, last resort, kill all and try";
         if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
+        // Since umount timedout, we will try to kill all processes
+        // and do one more attempt to umount the partitions.
+        //
+        // However, if OTA update is in progress, we don't want
+        // to kill the snapuserd daemon as the daemon will
+        // be serving I/O requests. Killing the daemon will
+        // end up with I/O failures. If the update is in progress,
+        // we will just return the umount failure status immediately.
+        // This is ok, given the fact that killing the processes
+        // and doing an umount is just a last effort. We are
+        // still not doing fsck when all processes are killed.
+        //
+        if (ota_update_in_progress) {
+            return stat;
+        }
         KillAllProcesses();
         // even if it succeeds, still it is timeout and do not run fsck with all processes killed
         UmountStat st = UmountPartitions(0ms);
diff --git a/init/service.cpp b/init/service.cpp
index b9b3309..87d9c3a 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -26,6 +26,7 @@
 #include <sys/time.h>
 #include <termios.h>
 #include <unistd.h>
+#include <thread>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -887,6 +888,10 @@
     }
 
     if (pid_) {
+        if (flags_ & SVC_GENTLE_KILL) {
+            KillProcessGroup(SIGTERM);
+            if (!process_cgroup_empty()) std::this_thread::sleep_for(200ms);
+        }
         KillProcessGroup(SIGKILL);
         NotifyStateChange("stopping");
     } else {
diff --git a/init/service.h b/init/service.h
index f9749d2..3ef8902 100644
--- a/init/service.h
+++ b/init/service.h
@@ -56,6 +56,8 @@
                                      // should not be killed during shutdown
 #define SVC_TEMPORARY 0x1000  // This service was started by 'exec' and should be removed from the
                               // service list once it is reaped.
+#define SVC_GENTLE_KILL 0x2000  // This service should be stopped with SIGTERM instead of SIGKILL
+                                // Will still be SIGKILLed after timeout period of 200 ms
 
 #define NR_SVC_SUPP_GIDS 12    // twelve supplementary groups
 
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 24a2024..3563084 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -151,6 +151,11 @@
     return {};
 }
 
+Result<void> ServiceParser::ParseGentleKill(std::vector<std::string>&& args) {
+    service_->flags_ |= SVC_GENTLE_KILL;
+    return {};
+}
+
 Result<void> ServiceParser::ParseGroup(std::vector<std::string>&& args) {
     auto gid = DecodeUid(args[1]);
     if (!gid.ok()) {
@@ -584,6 +589,7 @@
         {"disabled",                {0,     0,    &ServiceParser::ParseDisabled}},
         {"enter_namespace",         {2,     2,    &ServiceParser::ParseEnterNamespace}},
         {"file",                    {2,     2,    &ServiceParser::ParseFile}},
+        {"gentle_kill",             {0,     0,    &ServiceParser::ParseGentleKill}},
         {"group",                   {1,     NR_SVC_SUPP_GIDS + 1, &ServiceParser::ParseGroup}},
         {"interface",               {2,     2,    &ServiceParser::ParseInterface}},
         {"ioprio",                  {2,     2,    &ServiceParser::ParseIoprio}},
diff --git a/init/service_parser.h b/init/service_parser.h
index 54503dd..670a5c6 100644
--- a/init/service_parser.h
+++ b/init/service_parser.h
@@ -53,6 +53,7 @@
     Result<void> ParseDisabled(std::vector<std::string>&& args);
     Result<void> ParseEnterNamespace(std::vector<std::string>&& args);
     Result<void> ParseGroup(std::vector<std::string>&& args);
+    Result<void> ParseGentleKill(std::vector<std::string>&& args);
     Result<void> ParsePriority(std::vector<std::string>&& args);
     Result<void> ParseInterface(std::vector<std::string>&& args);
     Result<void> ParseIoprio(std::vector<std::string>&& args);
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
index 3188337..6728cc6 100644
--- a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -60,6 +60,10 @@
         if (prctl(PR_SET_TAGGED_ADDR_CTRL, res & ~PR_MTE_TCF_SYNC, 0, 0, 0) == -1) abort();
     }
     std::unique_ptr<volatile char[]> f(new char[1]);
+    // This out-of-bounds is on purpose: we are testing MTE, which is designed to turn
+    // out-of-bound errors into segfaults.
+    // This binary gets run by src/com/android/tests/init/MteUpgradeTest.java, which
+    // asserts that it crashes as expected.
     f[17] = 'x';
     char buf[1];
     read(1, buf, 1);
diff --git a/libcutils/include/cutils/qtaguid.h b/libcutils/include/cutils/qtaguid.h
index a5ffb03..8902c2b 100644
--- a/libcutils/include/cutils/qtaguid.h
+++ b/libcutils/include/cutils/qtaguid.h
@@ -33,12 +33,6 @@
  */
 extern int qtaguid_untagSocket(int sockfd);
 
-/*
- * Enable/disable qtaguid functionnality at a lower level.
- * When pacified, the kernel will accept commands but do nothing.
- */
-extern int qtaguid_setPacifier(int on);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/libdiskconfig/diskconfig.c b/libdiskconfig/diskconfig.c
index c7e1b43..5f34748 100644
--- a/libdiskconfig/diskconfig.c
+++ b/libdiskconfig/diskconfig.c
@@ -398,7 +398,7 @@
         case PART_SCHEME_GPT:
             /* not supported yet */
         default:
-            ALOGE("Uknown partition scheme.");
+            ALOGE("Unknown partition scheme.");
             break;
     }
 
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 8c00326..468d796 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -49,7 +49,7 @@
 
 static constexpr const char* CGROUP_PROCS_FILE = "/cgroup.procs";
 static constexpr const char* CGROUP_TASKS_FILE = "/tasks";
-static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.tasks";
+static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.threads";
 
 uint32_t CgroupController::version() const {
     CHECK(HasValue());
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index 4b8fc19..e44d3bf 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -462,7 +462,7 @@
           {
             "Controller": "blkio",
             "Path": "background"
-	  }
+          }
         },
         {
           "Name": "SetAttribute",
@@ -502,7 +502,7 @@
           {
             "Controller": "blkio",
             "Path": ""
-	  }
+          }
         },
         {
           "Name": "SetAttribute",
@@ -542,7 +542,7 @@
           {
             "Controller": "blkio",
             "Path": ""
-	  }
+          }
         },
         {
           "Name": "SetAttribute",
@@ -582,7 +582,7 @@
           {
             "Controller": "blkio",
             "Path": ""
-	  }
+          }
         },
         {
           "Name": "SetAttribute",
diff --git a/mkbootfs/mkbootfs.c b/mkbootfs/mkbootfs.c
index 05d1940..64e5a8c 100644
--- a/mkbootfs/mkbootfs.c
+++ b/mkbootfs/mkbootfs.c
@@ -1,17 +1,23 @@
 
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <string.h>
-#include <ctype.h>
+#include <unistd.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <dirent.h>
 
 #include <stdarg.h>
 #include <fcntl.h>
 
+#include <linux/kdev_t.h>
+
 #include <private/android_filesystem_config.h>
 #include <private/fs_config.h>
 
@@ -21,7 +27,6 @@
 **   an explanation of this file format
 ** - dotfiles are ignored
 ** - directories named 'root' are ignored
-** - device notes, pipes, etc are not supported (error)
 */
 
 static void die(const char* why, ...) {
@@ -86,6 +91,10 @@
         fs_config(path, is_dir, target_out_path, &s->st_uid, &s->st_gid, &st_mode, &capabilities);
         s->st_mode = (typeof(s->st_mode)) st_mode;
     }
+
+    if (S_ISREG(s->st_mode) || S_ISDIR(s->st_mode) || S_ISLNK(s->st_mode)) {
+        s->st_rdev = 0;
+    }
 }
 
 static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
@@ -115,8 +124,8 @@
            datasize,
            0, // volmajor
            0, // volminor
-           0, // devmajor
-           0, // devminor,
+           major(s->st_rdev),
+           minor(s->st_rdev),
            olen + 1,
            0,
            out,
@@ -267,6 +276,9 @@
         size = readlink(in, buf, 1024);
         if(size < 0) die("cannot read symlink '%s'", in);
         _eject(&s, out, olen, buf, size);
+    } else if(S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) ||
+              S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode)) {
+        _eject(&s, out, olen, NULL, 0);
     } else {
         die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
     }
@@ -327,34 +339,157 @@
     fclose(f);
 }
 
+static void devnodes_desc_error(const char* filename, unsigned long line_num,
+                              const char* msg)
+{
+    errx(EXIT_FAILURE, "failed to read nodes desc file '%s' line %lu: %s", filename, line_num, msg);
+}
+
+static int append_devnodes_desc_dir(char* path, char* args)
+{
+    struct stat s;
+
+    if (sscanf(args, "%o %d %d", &s.st_mode, &s.st_uid, &s.st_gid) != 3) return -1;
+
+    s.st_mode |= S_IFDIR;
+
+    _eject(&s, path, strlen(path), NULL, 0);
+
+    return 0;
+}
+
+static int append_devnodes_desc_nod(char* path, char* args)
+{
+    int minor, major;
+    struct stat s;
+    char dev;
+
+    if (sscanf(args, "%o %d %d %c %d %d", &s.st_mode, &s.st_uid, &s.st_gid,
+               &dev, &major, &minor) != 6) return -1;
+
+    s.st_rdev = MKDEV(major, minor);
+    switch (dev) {
+    case 'b':
+        s.st_mode |= S_IFBLK;
+        break;
+    case 'c':
+        s.st_mode |= S_IFCHR;
+        break;
+    default:
+        return -1;
+    }
+
+    _eject(&s, path, strlen(path), NULL, 0);
+
+    return 0;
+}
+
+static void append_devnodes_desc(const char* filename)
+{
+    FILE* f = fopen(filename, "re");
+    if (!f) err(EXIT_FAILURE, "failed to open nodes description file '%s'", filename);
+
+    char *line, *args, *type, *path;
+    unsigned long line_num = 0;
+    size_t allocated_len;
+
+    while (getline(&line, &allocated_len, f) != -1) {
+        char* type;
+
+        line_num++;
+
+        if (*line == '#') continue;
+
+        if (!(type = strtok(line, " \t"))) {
+            devnodes_desc_error(filename, line_num, "a type is missing");
+        }
+
+        if (*type == '\n') continue;
+
+        if (!(path = strtok(NULL, " \t"))) {
+            devnodes_desc_error(filename, line_num, "a path is missing");
+        }
+
+        if (!(args = strtok(NULL, "\n"))) {
+            devnodes_desc_error(filename, line_num, "args are missing");
+        }
+
+        if (!strcmp(type, "dir")) {
+            if (append_devnodes_desc_dir(path, args)) {
+                devnodes_desc_error(filename, line_num, "bad arguments for dir");
+            }
+        } else if (!strcmp(type, "nod")) {
+            if (append_devnodes_desc_nod(path, args)) {
+                devnodes_desc_error(filename, line_num, "bad arguments for nod");
+            }
+        } else {
+            devnodes_desc_error(filename, line_num, "type unknown");
+        }
+    }
+
+    free(line);
+    fclose(f);
+}
+
+static const struct option long_options[] = {
+    { "dirname",    required_argument,  NULL,   'd' },
+    { "file",       required_argument,  NULL,   'f' },
+    { "help",       no_argument,        NULL,   'h' },
+    { "nodes",      required_argument,  NULL,   'n' },
+    { NULL,         0,                  NULL,   0   },
+};
+
+static void usage(void)
+{
+    fprintf(stderr,
+            "Usage: mkbootfs [-n FILE] [-d DIR|-F FILE] DIR...\n"
+            "\n"
+            "\t-d, --dirname=DIR: fs-config directory\n"
+            "\t-f, --file=FILE: Canned configuration file\n"
+            "\t-h, --help: Print this help\n"
+            "\t-n, --nodes=FILE: Dev nodes description file\n"
+            "\nDev nodes description:\n"
+            "\t[dir|nod] [perms] [uid] [gid] [c|b] [minor] [major]\n"
+            "\tExample:\n"
+            "\t\t# My device nodes\n"
+            "\t\tdir dev 0755 0 0\n"
+            "\t\tnod dev/null 0600 0 0 c 1 5\n"
+    );
+}
 
 int main(int argc, char *argv[])
 {
-    if (argc == 1) {
-        fprintf(stderr,
-                "usage: %s [-d TARGET_OUTPUT_PATH] [-f CANNED_CONFIGURATION_PATH] DIRECTORIES...\n",
-                argv[0]);
-        exit(1);
+    int opt, unused;
+
+    while ((opt = getopt_long(argc, argv, "hd:f:n:", long_options, &unused)) != -1) {
+        switch (opt) {
+        case 'd':
+            target_out_path = argv[optind - 1];
+            break;
+        case 'f':
+            read_canned_config(argv[optind - 1]);
+            break;
+        case 'h':
+            usage();
+            return 0;
+        case 'n':
+            append_devnodes_desc(argv[optind - 1]);
+            break;
+        default:
+            usage();
+            die("Unknown option %s", argv[optind - 1]);
+        }
     }
 
-    argc--;
-    argv++;
+    int num_dirs = argc - optind;
+    argv += optind;
 
-    if (argc > 1 && strcmp(argv[0], "-d") == 0) {
-        target_out_path = argv[1];
-        argc -= 2;
-        argv += 2;
+    if (num_dirs <= 0) {
+        usage();
+        die("no directories to process?!");
     }
 
-    if (argc > 1 && strcmp(argv[0], "-f") == 0) {
-        read_canned_config(argv[1]);
-        argc -= 2;
-        argv += 2;
-    }
-
-    if(argc == 0) die("no directories to process?!");
-
-    while(argc-- > 0){
+    while(num_dirs-- > 0){
         char *x = strchr(*argv, '=');
         if(x != 0) {
             *x++ = 0;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 55be31a..efad37c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -47,6 +47,9 @@
     # Allow up to 32K FDs per process
     setrlimit nofile 32768 32768
 
+    # set RLIMIT_MEMLOCK to 64KB
+    setrlimit memlock 65536 65536
+
     # Set up linker config subdirectories based on mount namespaces
     mkdir /linkerconfig/bootstrap 0755
     mkdir /linkerconfig/default 0755
@@ -490,18 +493,26 @@
 service boringssl_self_test32 /system/bin/boringssl_self_test32
     reboot_on_failure reboot,boringssl-self-check-failed
     stdio_to_kmsg
+    # Explicitly specify that boringssl_self_test32 doesn't require any capabilities
+    capabilities
 
 service boringssl_self_test64 /system/bin/boringssl_self_test64
     reboot_on_failure reboot,boringssl-self-check-failed
     stdio_to_kmsg
+    # Explicitly specify that boringssl_self_test64 doesn't require any capabilities
+    capabilities
 
 service boringssl_self_test_apex32 /apex/com.android.conscrypt/bin/boringssl_self_test32
     reboot_on_failure reboot,boringssl-self-check-failed
     stdio_to_kmsg
+    # Explicitly specify that boringssl_self_test_apex32 doesn't require any capabilities
+    capabilities
 
 service boringssl_self_test_apex64 /apex/com.android.conscrypt/bin/boringssl_self_test64
     reboot_on_failure reboot,boringssl-self-check-failed
     stdio_to_kmsg
+    # Explicitly specify that boringssl_self_test_apex64 doesn't require any capabilities
+    capabilities
 
 
 # Healthd can trigger a full boot from charger mode by signaling this
@@ -839,7 +850,7 @@
     # Delete any stale files owned by the old virtualizationservice uid (b/230056726).
     chmod 0770 /data/misc/virtualizationservice
     exec - virtualizationservice system -- /bin/rm -rf /data/misc/virtualizationservice
-    mkdir /data/misc/virtualizationservice 0770 system system
+    mkdir /data/misc/virtualizationservice 0771 system system
 
     # /data/preloads uses encryption=None because it only contains preloaded
     # files that are public information, similar to the system image.
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index 63b09c0..2f0ec8a 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -7,6 +7,9 @@
     socket usap_pool_primary stream 660 root system
     onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
     onrestart write /sys/power/state on
+    # NOTE: If the wakelock name here is changed, then also
+    # update it in SystemSuspend.cpp
+    onrestart write /sys/power/wake_lock zygote_kwl
     onrestart restart audioserver
     onrestart restart cameraserver
     onrestart restart media
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index b6ca5c0..74a64c8 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -7,6 +7,9 @@
     socket usap_pool_primary stream 660 root system
     onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
     onrestart write /sys/power/state on
+    # NOTE: If the wakelock name here is changed, then also
+    # update it in SystemSuspend.cpp
+    onrestart write /sys/power/wake_lock zygote_kwl
     onrestart restart audioserver
     onrestart restart cameraserver
     onrestart restart media
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index 0609709..7b4aa26 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -22,8 +22,21 @@
 # For gatekeeper, we include the generic -service and -impl to use legacy
 # HAL loading of gatekeeper.trusty.
 
+# Allow the KeyMint HAL service implementation to be selected at build time.  This needs to be
+# done in sync with the TA implementation included in Trusty.  Possible values are:
+#
+# - Rust implementation:   export TRUSTY_KEYMINT_IMPL=rust
+# - C++ implementation:    (any other value of TRUSTY_KEYMINT_IMPL)
+
+ifeq ($(TRUSTY_KEYMINT_IMPL),rust)
+    LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.rust.trusty
+else
+    # Default to the C++ implementation
+    LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.trusty
+endif
+
 PRODUCT_PACKAGES += \
-	android.hardware.security.keymint-service.trusty \
+	$(LOCAL_KEYMINT_PRODUCT_PACKAGE) \
 	android.hardware.gatekeeper@1.0-service.trusty \
 	trusty_apploader \
 	RemoteProvisioner