Merge "init: Cleanly exit subcontext processes upon init's death"
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 93f7572..577e336 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -34,6 +34,7 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/macros.h>
 #include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
@@ -282,6 +283,7 @@
   switch (crash_info->header.version) {
     case 2:
       *fdsan_table_address = crash_info->data.v2.fdsan_table_address;
+      FALLTHROUGH_INTENDED;
     case 1:
       *abort_msg_address = crash_info->data.v1.abort_msg_address;
       *siginfo = crash_info->data.v1.siginfo;
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 817afd0..8e6c125 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -148,6 +148,11 @@
     { nullptr,    "system_other.img", "system.sig",   "system",   true,  ImageType::Normal },
     { "userdata", "userdata.img",     "userdata.sig", "userdata", true,  ImageType::Extra },
     { "vbmeta",   "vbmeta.img",       "vbmeta.sig",   "vbmeta",   true,  ImageType::BootCritical },
+    { "vbmeta_mainline",
+                  "vbmeta_mainline.img",
+                                      "vbmeta_mainline.sig",
+                                                      "vbmeta_mainline",
+                                                                  true,  ImageType::BootCritical },
     { "vendor",   "vendor.img",       "vendor.sig",   "vendor",   true,  ImageType::Normal },
     { nullptr,    "vendor_other.img", "vendor.sig",   "vendor",   true,  ImageType::Normal },
         // clang-format on
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index f56043c..10cd9e7 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -805,6 +805,23 @@
     return true;
 }
 
+static bool call_vdc_ret(const std::vector<std::string>& args, int* ret) {
+    std::vector<char const*> argv;
+    argv.emplace_back("/system/bin/vdc");
+    for (auto& arg : args) {
+        argv.emplace_back(arg.c_str());
+    }
+    LOG(INFO) << "Calling: " << android::base::Join(argv, ' ');
+    int err = android_fork_execvp(argv.size(), const_cast<char**>(argv.data()), ret, false, true);
+    if (err != 0) {
+        LOG(ERROR) << "vdc call failed with error code: " << err;
+        return false;
+    }
+    LOG(DEBUG) << "vdc finished successfully";
+    *ret = WEXITSTATUS(*ret);
+    return true;
+}
+
 bool fs_mgr_update_logical_partition(struct fstab_rec* rec) {
     // Logical partitions are specified with a named partition rather than a
     // block device, so if the block device is a path, then it has already
@@ -823,6 +840,24 @@
     return true;
 }
 
+bool fs_mgr_update_checkpoint_partition(struct fstab_rec* rec) {
+    if (fs_mgr_is_checkpoint(rec)) {
+        if (!strcmp(rec->fs_type, "f2fs")) {
+            std::string opts(rec->fs_options);
+
+            opts += ",checkpoint=disable";
+            free(rec->fs_options);
+            rec->fs_options = strdup(opts.c_str());
+        } else {
+            LERROR << rec->fs_type << " does not implement checkpoints.";
+        }
+    } else if (rec->fs_mgr_flags & MF_CHECKPOINT_BLK) {
+        LERROR << "Block based checkpoint not implemented.";
+        return false;
+    }
+    return true;
+}
+
 /* When multiple fstab records share the same mount_point, it will
  * try to mount each one in turn, and ignore any duplicates after a
  * first successful mount.
@@ -836,6 +871,7 @@
     int mret = -1;
     int mount_errno = 0;
     int attempted_idx = -1;
+    int need_checkpoint = -1;
     FsManagerAvbUniquePtr avb_handle(nullptr);
 
     if (!fstab) {
@@ -882,6 +918,18 @@
             }
         }
 
+        if (fs_mgr_is_checkpoint(&fstab->recs[i])) {
+            if (need_checkpoint == -1 &&
+                !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &need_checkpoint)) {
+                LERROR << "Failed to find if checkpointing is needed. Assuming no.";
+                need_checkpoint = 0;
+            }
+            if (need_checkpoint == 1 && !fs_mgr_update_checkpoint_partition(&fstab->recs[i])) {
+                LERROR << "Could not set up checkpoint partition, skipping!";
+                continue;
+            }
+        }
+
         if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
             !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
             LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all";
@@ -1081,9 +1129,8 @@
  * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
  * in turn, and stop on 1st success, or no more match.
  */
-int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
-                    char *tmp_mount_point)
-{
+static int fs_mgr_do_mount_helper(struct fstab* fstab, const char* n_name, char* n_blk_device,
+                                  char* tmp_mount_point, int need_checkpoint) {
     int i = 0;
     int mount_errors = 0;
     int first_mount_errno = 0;
@@ -1116,6 +1163,18 @@
             }
         }
 
+        if (fs_mgr_is_checkpoint(&fstab->recs[i])) {
+            if (need_checkpoint == -1 &&
+                !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &need_checkpoint)) {
+                LERROR << "Failed to find if checkpointing is needed. Assuming no.";
+                need_checkpoint = 0;
+            }
+            if (need_checkpoint == 1 && !fs_mgr_update_checkpoint_partition(&fstab->recs[i])) {
+                LERROR << "Could not set up checkpoint partition, skipping!";
+                continue;
+            }
+        }
+
         /* First check the filesystem if requested */
         if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
             LERROR << "Skipping mounting '" << n_blk_device << "'";
@@ -1185,6 +1244,16 @@
     return FS_MGR_DOMNT_FAILED;
 }
 
+int fs_mgr_do_mount(struct fstab* fstab, const char* n_name, char* n_blk_device,
+                    char* tmp_mount_point) {
+    return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1);
+}
+
+int fs_mgr_do_mount(struct fstab* fstab, const char* n_name, char* n_blk_device,
+                    char* tmp_mount_point, bool needs_cp) {
+    return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_cp);
+}
+
 /*
  * mount a tmpfs filesystem at the given point.
  * return 0 on success, non-zero on failure.
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index f87a3b1..250793a 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -80,37 +80,39 @@
 };
 
 static struct flag_list fs_mgr_flags[] = {
-    {"wait", MF_WAIT},
-    {"check", MF_CHECK},
-    {"encryptable=", MF_CRYPT},
-    {"forceencrypt=", MF_FORCECRYPT},
-    {"fileencryption=", MF_FILEENCRYPTION},
-    {"forcefdeorfbe=", MF_FORCEFDEORFBE},
-    {"keydirectory=", MF_KEYDIRECTORY},
-    {"nonremovable", MF_NONREMOVABLE},
-    {"voldmanaged=", MF_VOLDMANAGED},
-    {"length=", MF_LENGTH},
-    {"recoveryonly", MF_RECOVERYONLY},
-    {"swapprio=", MF_SWAPPRIO},
-    {"zramsize=", MF_ZRAMSIZE},
-    {"max_comp_streams=", MF_MAX_COMP_STREAMS},
-    {"verifyatboot", MF_VERIFYATBOOT},
-    {"verify", MF_VERIFY},
-    {"avb", MF_AVB},
-    {"noemulatedsd", MF_NOEMULATEDSD},
-    {"notrim", MF_NOTRIM},
-    {"formattable", MF_FORMATTABLE},
-    {"slotselect", MF_SLOTSELECT},
-    {"nofail", MF_NOFAIL},
-    {"latemount", MF_LATEMOUNT},
-    {"reservedsize=", MF_RESERVEDSIZE},
-    {"quota", MF_QUOTA},
-    {"eraseblk=", MF_ERASEBLKSIZE},
-    {"logicalblk=", MF_LOGICALBLKSIZE},
-    {"sysfs_path=", MF_SYSFS},
-    {"defaults", 0},
-    {"logical", MF_LOGICAL},
-    {0, 0},
+        {"wait", MF_WAIT},
+        {"check", MF_CHECK},
+        {"encryptable=", MF_CRYPT},
+        {"forceencrypt=", MF_FORCECRYPT},
+        {"fileencryption=", MF_FILEENCRYPTION},
+        {"forcefdeorfbe=", MF_FORCEFDEORFBE},
+        {"keydirectory=", MF_KEYDIRECTORY},
+        {"nonremovable", MF_NONREMOVABLE},
+        {"voldmanaged=", MF_VOLDMANAGED},
+        {"length=", MF_LENGTH},
+        {"recoveryonly", MF_RECOVERYONLY},
+        {"swapprio=", MF_SWAPPRIO},
+        {"zramsize=", MF_ZRAMSIZE},
+        {"max_comp_streams=", MF_MAX_COMP_STREAMS},
+        {"verifyatboot", MF_VERIFYATBOOT},
+        {"verify", MF_VERIFY},
+        {"avb", MF_AVB},
+        {"noemulatedsd", MF_NOEMULATEDSD},
+        {"notrim", MF_NOTRIM},
+        {"formattable", MF_FORMATTABLE},
+        {"slotselect", MF_SLOTSELECT},
+        {"nofail", MF_NOFAIL},
+        {"latemount", MF_LATEMOUNT},
+        {"reservedsize=", MF_RESERVEDSIZE},
+        {"quota", MF_QUOTA},
+        {"eraseblk=", MF_ERASEBLKSIZE},
+        {"logicalblk=", MF_LOGICALBLKSIZE},
+        {"sysfs_path=", MF_SYSFS},
+        {"defaults", 0},
+        {"logical", MF_LOGICAL},
+        {"checkpoint=block", MF_CHECKPOINT_BLK},
+        {"checkpoint=fs", MF_CHECKPOINT_FS},
+        {0, 0},
 };
 
 #define EM_AES_256_XTS  1
@@ -1004,3 +1006,15 @@
 int fs_mgr_is_logical(const struct fstab_rec* fstab) {
     return fstab->fs_mgr_flags & MF_LOGICAL;
 }
+
+int fs_mgr_is_checkpoint(const struct fstab_rec* fstab) {
+    return fstab->fs_mgr_flags & (MF_CHECKPOINT_FS | MF_CHECKPOINT_BLK);
+}
+
+int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab) {
+    return fstab->fs_mgr_flags & MF_CHECKPOINT_FS;
+}
+
+int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) {
+    return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
+}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 720dcfd..b39a418 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -109,9 +109,9 @@
     struct statvfs vst;
     if (statvfs(mount_point, &vst)) return true;
 
-    static constexpr int percent = 1;  // 1%
+    static constexpr int kPercentThreshold = 1;  // 1%
 
-    return (vst.f_bfree >= (vst.f_blocks * percent / 100));
+    return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100));
 }
 
 bool fs_mgr_overlayfs_enabled(const struct fstab_rec* fsrec) {
@@ -123,22 +123,24 @@
            !fs_mgr_filesystem_has_space(fsrec->mount_point);
 }
 
-constexpr char upper_name[] = "upper";
-constexpr char work_name[] = "work";
+const auto kUpperName = "upper"s;
+const auto kWorkName = "work"s;
+const auto kOverlayTopDir = "/overlay"s;
 
 std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
     if (!fs_mgr_is_dir(mount_point)) return "";
-    auto dir = kOverlayMountPoint + "/overlay/" + android::base::Basename(mount_point) + "/";
-    auto upper = dir + upper_name;
+    auto dir =
+            kOverlayMountPoint + kOverlayTopDir + "/" + android::base::Basename(mount_point) + "/";
+    auto upper = dir + kUpperName;
     if (!fs_mgr_is_dir(upper)) return "";
-    auto work = dir + work_name;
+    auto work = dir + kWorkName;
     if (!fs_mgr_is_dir(work)) return "";
     if (!fs_mgr_dir_is_writable(work)) return "";
     return dir;
 }
 
-constexpr char lowerdir_option[] = "lowerdir=";
-constexpr char upperdir_option[] = "upperdir=";
+const auto kLowerdirOption = "lowerdir="s;
+const auto kUpperdirOption = "upperdir="s;
 
 // default options for mount_point, returns empty string for none available.
 std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) {
@@ -147,8 +149,8 @@
 
     auto context = fs_mgr_get_context(mount_point);
     if (!context.empty()) context = ",rootcontext="s + context;
-    return "override_creds=off,"s + lowerdir_option + mount_point + "," + upperdir_option +
-           candidate + upper_name + ",workdir=" + candidate + work_name + context;
+    return "override_creds=off,"s + kLowerdirOption + mount_point + "," + kUpperdirOption +
+           candidate + kUpperName + ",workdir=" + candidate + kWorkName + context;
 }
 
 bool fs_mgr_system_root_image(const fstab* fstab) {
@@ -265,16 +267,16 @@
     return ret;
 }
 
-constexpr char overlayfs_file_context[] = "u:object_r:overlayfs_file:s0";
+constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
 
 bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& mount_point,
                                 bool* change) {
     auto ret = true;
-    auto fsrec_mount_point = overlay + android::base::Basename(mount_point) + "/";
+    auto fsrec_mount_point = overlay + "/" + android::base::Basename(mount_point) + "/";
 
-    if (setfscreatecon(overlayfs_file_context)) {
+    if (setfscreatecon(kOverlayfsFileContext)) {
         ret = false;
-        PERROR << "overlayfs setfscreatecon " << overlayfs_file_context;
+        PERROR << "overlayfs setfscreatecon " << kOverlayfsFileContext;
     }
     auto save_errno = errno;
     if (!mkdir(fsrec_mount_point.c_str(), 0755)) {
@@ -287,11 +289,11 @@
     }
 
     save_errno = errno;
-    if (!mkdir((fsrec_mount_point + work_name).c_str(), 0755)) {
+    if (!mkdir((fsrec_mount_point + kWorkName).c_str(), 0755)) {
         if (change) *change = true;
     } else if (errno != EEXIST) {
         ret = false;
-        PERROR << "overlayfs mkdir " << fsrec_mount_point << work_name;
+        PERROR << "overlayfs mkdir " << fsrec_mount_point << kWorkName;
     } else {
         errno = save_errno;
     }
@@ -302,7 +304,7 @@
         ret = false;
         PERROR << "overlayfs setfscreatecon " << new_context;
     }
-    auto upper = fsrec_mount_point + upper_name;
+    auto upper = fsrec_mount_point + kUpperName;
     save_errno = errno;
     if (!mkdir(upper.c_str(), 0755)) {
         if (change) *change = true;
@@ -325,7 +327,7 @@
     auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
     const auto opt_list = android::base::Split(options, ",");
     for (const auto opt : opt_list) {
-        if (android::base::StartsWith(opt, upperdir_option)) {
+        if (android::base::StartsWith(opt, kUpperdirOption)) {
             report = report + "," + opt;
             break;
         }
@@ -347,7 +349,7 @@
     std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(
             fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab);
     if (!fstab) return false;
-    const auto lowerdir = std::string(lowerdir_option) + mount_point;
+    const auto lowerdir = kLowerdirOption + mount_point;
     for (auto i = 0; i < fstab->num_entries; ++i) {
         const auto fsrec = &fstab->recs[i];
         const auto fs_type = fsrec->fs_type;
@@ -436,10 +438,10 @@
     auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(fstab.get(), mount_point));
     if (fstab && mounts.empty()) return ret;
 
-    if (setfscreatecon(overlayfs_file_context)) {
-        PERROR << "overlayfs setfscreatecon " << overlayfs_file_context;
+    if (setfscreatecon(kOverlayfsFileContext)) {
+        PERROR << "overlayfs setfscreatecon " << kOverlayfsFileContext;
     }
-    auto overlay = kOverlayMountPoint + "/overlay/";
+    auto overlay = kOverlayMountPoint + kOverlayTopDir;
     auto save_errno = errno;
     if (!mkdir(overlay.c_str(), 0755)) {
         if (change) *change = true;
@@ -467,8 +469,8 @@
                                              .get(),
                                      mount_point);
     auto ret = true;
-    const auto overlay = kOverlayMountPoint + "/overlay";
-    const auto oldpath = overlay + (mount_point ?: "");
+    const auto overlay = kOverlayMountPoint + kOverlayTopDir;
+    const auto oldpath = overlay + (mount_point ? "/"s + mount_point : ""s);
     const auto newpath = oldpath + ".teardown";
     ret &= fs_mgr_rm_all(newpath);
     auto save_errno = errno;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index ebc4a0f..506e81d 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -113,6 +113,8 @@
 #define MF_KEYDIRECTORY    0X4000000
 #define MF_SYSFS           0X8000000
 #define MF_LOGICAL        0x10000000
+#define MF_CHECKPOINT_BLK 0x20000000
+#define MF_CHECKPOINT_FS  0x40000000
 // clang-format on
 
 #define DM_BUF_SIZE 4096
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 1049fb6..cee069b 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -70,6 +70,8 @@
 
 int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
                     char *tmp_mount_point);
+int fs_mgr_do_mount(struct fstab* fstab, const char* n_name, char* n_blk_device,
+                    char* tmp_mount_point, bool need_cp);
 int fs_mgr_do_mount_one(struct fstab_rec *rec);
 int fs_mgr_do_tmpfs_mount(const char *n_name);
 struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index b1ee328..bb40511 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -86,6 +86,9 @@
 int fs_mgr_is_latemount(const struct fstab_rec* fstab);
 int fs_mgr_is_quota(const struct fstab_rec* fstab);
 int fs_mgr_is_logical(const struct fstab_rec* fstab);
+int fs_mgr_is_checkpoint(const struct fstab_rec* fstab);
+int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab);
+int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab);
 int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
 
 std::string fs_mgr_get_slot_suffix();
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index ad84b22..9dd2745 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -94,7 +94,8 @@
     }
     // Make sure we're writing within the space reserved.
     if (blob->size() > geometry.metadata_max_size) {
-        LERROR << "Logical partition metadata is too large.";
+        LERROR << "Logical partition metadata is too large. " << blob->size() << " > "
+               << geometry.metadata_max_size;
         return false;
     }
 
diff --git a/init/init.cpp b/init/init.cpp
index 3ab0a52..e5c1548 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -19,6 +19,7 @@
 #include <dirent.h>
 #include <fcntl.h>
 #include <pthread.h>
+#include <seccomp_policy.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
@@ -40,6 +41,7 @@
 #include <cutils/android_reboot.h>
 #include <keyutils.h>
 #include <libavb/libavb.h>
+#include <selinux/android.h>
 
 #ifndef RECOVERY
 #include <binder/ProcessState.h>
@@ -585,6 +587,43 @@
     android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
 }
 
+static void GlobalSeccomp() {
+    import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
+                                    bool in_qemu) {
+        if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) {
+            LOG(FATAL) << "Failed to globally enable seccomp!";
+        }
+    });
+}
+
+static void SetupSelinux(char** argv) {
+    android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
+        RebootSystem(ANDROID_RB_RESTART2, "bootloader");
+    });
+
+    // Set up SELinux, loading the SELinux policy.
+    SelinuxSetupKernelLogging();
+    SelinuxInitialize();
+
+    // We're in the kernel domain and want to transition to the init domain.  File systems that
+    // store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here,
+    // but other file systems do.  In particular, this is needed for ramdisks such as the
+    // recovery image for A/B devices.
+    if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
+        PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
+    }
+
+    setenv("SELINUX_INITIALIZED", "true", 1);
+
+    const char* path = "/system/bin/init";
+    const char* args[] = {path, nullptr};
+    execv(path, const_cast<char**>(args));
+
+    // execv() only returns if an error happened, in which case we
+    // panic and never return from this function.
+    PLOG(FATAL) << "execv(\"" << path << "\") failed";
+}
+
 int main(int argc, char** argv) {
     if (!strcmp(basename(argv[0]), "ueventd")) {
         return ueventd_main(argc, argv);
@@ -600,9 +639,16 @@
         InstallRebootSignalHandlers();
     }
 
+    if (getenv("SELINUX_INITIALIZED") == nullptr) {
+        SetupSelinux(argv);
+    }
+
     InitKernelLogging(argv);
     LOG(INFO) << "init second stage started!";
 
+    // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
+    GlobalSeccomp();
+
     // Set up a session keyring that all processes will have access to. It
     // will hold things like FBE encryption keys. No process should override
     // its session keyring.
@@ -631,6 +677,7 @@
     if (avb_version) property_set("ro.boot.avb_version", avb_version);
 
     // Clean up our environment.
+    unsetenv("SELINUX_INITIALIZED");
     unsetenv("INIT_STARTED_AT");
     unsetenv("INIT_SELINUX_TOOK");
     unsetenv("INIT_AVB_VERSION");
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index 466cde3..0c4a110 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <paths.h>
-#include <seccomp_policy.h>
 #include <stdlib.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
@@ -30,11 +29,9 @@
 #include <android-base/logging.h>
 #include <cutils/android_reboot.h>
 #include <private/android_filesystem_config.h>
-#include <selinux/android.h>
 
 #include "first_stage_mount.h"
 #include "reboot_utils.h"
-#include "selinux.h"
 #include "util.h"
 
 using android::base::boot_clock;
@@ -42,15 +39,6 @@
 namespace android {
 namespace init {
 
-static void GlobalSeccomp() {
-    import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
-                                    bool in_qemu) {
-        if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) {
-            LOG(FATAL) << "Failed to globally enable seccomp!";
-        }
-    });
-}
-
 int main(int argc, char** argv) {
     if (REBOOT_BOOTLOADER_ON_PANIC) {
         InstallRebootSignalHandlers();
@@ -130,22 +118,6 @@
 
     SetInitAvbVersionInRecovery();
 
-    // Does this need to be done in first stage init or can it be done later?
-    // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
-    GlobalSeccomp();
-
-    // Set up SELinux, loading the SELinux policy.
-    SelinuxSetupKernelLogging();
-    SelinuxInitialize();
-
-    // We're in the kernel domain and want to transition to the init domain when we exec second
-    // stage init.  File systems that store SELabels in their xattrs, such as ext4 do not need an
-    // explicit restorecon here, but other file systems do.  In particular, this is needed for
-    // ramdisks such as the recovery image for A/B devices.
-    if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
-        PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
-    }
-
     static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
     uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
     setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);
diff --git a/init/tokenizer.cpp b/init/tokenizer.cpp
index bb143f1..7e05a0a 100644
--- a/init/tokenizer.cpp
+++ b/init/tokenizer.cpp
@@ -1,5 +1,7 @@
 #include "tokenizer.h"
 
+#include <android-base/macros.h>
+
 namespace android {
 namespace init {
 
@@ -106,6 +108,7 @@
                     continue;
                 }
                 x++;
+                FALLTHROUGH_INTENDED;
             case '\n':
                     /* \ <lf> -> line continuation */
                 state->line++;
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index d1f20f4..383d0e7 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -131,7 +131,7 @@
 
 static bool isLogdwActive() {
   std::string logdwSignature =
-      popenToString("grep /dev/socket/logdw /proc/net/unix");
+      popenToString("grep -a /dev/socket/logdw /proc/net/unix");
   size_t beginning = logdwSignature.find(' ');
   if (beginning == std::string::npos) return true;
   beginning = logdwSignature.find(' ', beginning + 1);
@@ -145,7 +145,7 @@
   end = logdwSignature.find(' ', end + 1);
   if (end == std::string::npos) return true;
   std::string allLogdwEndpoints = popenToString(
-      "grep ' 00000002" + logdwSignature.substr(beginning, end - beginning) +
+      "grep -a ' 00000002" + logdwSignature.substr(beginning, end - beginning) +
       " ' /proc/net/unix | " +
       "sed -n 's/.* \\([0-9][0-9]*\\)$/ -> socket:[\\1]/p'");
   if (allLogdwEndpoints.length() == 0) return true;
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 6061f61..57a780e 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -461,6 +461,7 @@
       if (reg == eval_info->cie->return_address_register) {
         eval_info->return_address_undefined = true;
       }
+      break;
     default:
       break;
   }
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index add6e14..f8d1356 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -122,21 +122,36 @@
 #endif
 }
 
+static bool isZipStringEqual(const uint8_t* start, const ZipString& zip_string,
+                             const ZipStringOffset& zip_string_offset) {
+  const ZipString from_offset = zip_string_offset.GetZipString(start);
+  return from_offset == zip_string;
+}
+
+/**
+ * Returns offset of ZipString#name from the start of the central directory in the memory map.
+ * For valid ZipStrings contained in the zip archive mmap, 0 < offset < 0xffffff.
+ */
+static inline uint32_t GetOffset(const uint8_t* name, const uint8_t* start) {
+  CHECK_GT(name, start);
+  CHECK_LT(name, start + 0xffffff);
+  return static_cast<uint32_t>(name - start);
+}
+
 /*
  * Convert a ZipEntry to a hash table index, verifying that it's in a
  * valid range.
  */
-static int64_t EntryToIndex(const ZipString* hash_table, const uint32_t hash_table_size,
-                            const ZipString& name) {
+static int64_t EntryToIndex(const ZipStringOffset* hash_table, const uint32_t hash_table_size,
+                            const ZipString& name, const uint8_t* start) {
   const uint32_t hash = ComputeHash(name);
 
   // NOTE: (hash_table_size - 1) is guaranteed to be non-negative.
   uint32_t ent = hash & (hash_table_size - 1);
-  while (hash_table[ent].name != NULL) {
-    if (hash_table[ent] == name) {
+  while (hash_table[ent].name_offset != 0) {
+    if (isZipStringEqual(start, name, hash_table[ent])) {
       return ent;
     }
-
     ent = (ent + 1) & (hash_table_size - 1);
   }
 
@@ -147,8 +162,8 @@
 /*
  * Add a new entry to the hash table.
  */
-static int32_t AddToHash(ZipString* hash_table, const uint64_t hash_table_size,
-                         const ZipString& name) {
+static int32_t AddToHash(ZipStringOffset* hash_table, const uint64_t hash_table_size,
+                         const ZipString& name, const uint8_t* start) {
   const uint64_t hash = ComputeHash(name);
   uint32_t ent = hash & (hash_table_size - 1);
 
@@ -156,20 +171,26 @@
    * We over-allocated the table, so we're guaranteed to find an empty slot.
    * Further, we guarantee that the hashtable size is not 0.
    */
-  while (hash_table[ent].name != NULL) {
-    if (hash_table[ent] == name) {
+  while (hash_table[ent].name_offset != 0) {
+    if (isZipStringEqual(start, name, hash_table[ent])) {
       // We've found a duplicate entry. We don't accept it
       ALOGW("Zip: Found duplicate entry %.*s", name.name_length, name.name);
       return kDuplicateEntry;
     }
     ent = (ent + 1) & (hash_table_size - 1);
   }
-
-  hash_table[ent].name = name.name;
+  hash_table[ent].name_offset = GetOffset(name.name, start);
   hash_table[ent].name_length = name.name_length;
   return 0;
 }
 
+#if defined(__BIONIC__)
+uint64_t GetOwnerTag(const ZipArchive* archive) {
+  return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_ZIPARCHIVE,
+                                        reinterpret_cast<uint64_t>(archive));
+}
+#endif
+
 ZipArchive::ZipArchive(const int fd, bool assume_ownership)
     : mapped_zip(fd),
       close_file(assume_ownership),
@@ -181,7 +202,7 @@
       hash_table(nullptr) {
 #if defined(__BIONIC__)
   if (assume_ownership) {
-    android_fdsan_exchange_owner_tag(fd, 0, reinterpret_cast<uint64_t>(this));
+    android_fdsan_exchange_owner_tag(fd, 0, GetOwnerTag(this));
   }
 #endif
 }
@@ -199,7 +220,7 @@
 ZipArchive::~ZipArchive() {
   if (close_file && mapped_zip.GetFileDescriptor() >= 0) {
 #if defined(__BIONIC__)
-    android_fdsan_close_with_tag(mapped_zip.GetFileDescriptor(), reinterpret_cast<uint64_t>(this));
+    android_fdsan_close_with_tag(mapped_zip.GetFileDescriptor(), GetOwnerTag(this));
 #else
     close(mapped_zip.GetFileDescriptor());
 #endif
@@ -209,7 +230,8 @@
 }
 
 static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* archive,
-                                    off64_t file_length, off64_t read_amount, uint8_t* scan_buffer) {
+                                    off64_t file_length, off64_t read_amount,
+                                    uint8_t* scan_buffer) {
   const off64_t search_start = file_length - read_amount;
 
   if (!archive->mapped_zip.ReadAtOffset(scan_buffer, read_amount, search_start)) {
@@ -362,7 +384,7 @@
    */
   archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3);
   archive->hash_table =
-      reinterpret_cast<ZipString*>(calloc(archive->hash_table_size, sizeof(ZipString)));
+      reinterpret_cast<ZipStringOffset*>(calloc(archive->hash_table_size, sizeof(ZipStringOffset)));
   if (archive->hash_table == nullptr) {
     ALOGW("Zip: unable to allocate the %u-entry hash_table, entry size: %zu",
           archive->hash_table_size, sizeof(ZipString));
@@ -418,7 +440,8 @@
     ZipString entry_name;
     entry_name.name = file_name;
     entry_name.name_length = file_name_length;
-    const int add_result = AddToHash(archive->hash_table, archive->hash_table_size, entry_name);
+    const int add_result = AddToHash(archive->hash_table, archive->hash_table_size, entry_name,
+                                     archive->central_directory.GetBasePtr());
     if (add_result != 0) {
       ALOGW("Zip: Error adding entry to hash table %d", add_result);
       return add_result;
@@ -538,7 +561,9 @@
   // Recover the start of the central directory entry from the filename
   // pointer.  The filename is the first entry past the fixed-size data,
   // so we can just subtract back from that.
-  const uint8_t* ptr = archive->hash_table[ent].name;
+  const ZipString from_offset =
+      archive->hash_table[ent].GetZipString(archive->central_directory.GetBasePtr());
+  const uint8_t* ptr = from_offset.name;
   ptr -= sizeof(CentralDirectoryRecord);
 
   // This is the base of our mmapped region, we have to sanity check that
@@ -648,8 +673,9 @@
       ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset));
       return kIoError;
     }
-
-    if (memcmp(archive->hash_table[ent].name, name_buf.data(), nameLen)) {
+    const ZipString from_offset =
+        archive->hash_table[ent].GetZipString(archive->central_directory.GetBasePtr());
+    if (memcmp(from_offset.name, name_buf.data(), nameLen)) {
       return kInconsistentInformation;
     }
 
@@ -747,19 +773,19 @@
     return kInvalidEntryName;
   }
 
-  const int64_t ent = EntryToIndex(archive->hash_table, archive->hash_table_size, entryName);
-
+  const int64_t ent = EntryToIndex(archive->hash_table, archive->hash_table_size, entryName,
+                                   archive->central_directory.GetBasePtr());
   if (ent < 0) {
     ALOGV("Zip: Could not find entry %.*s", entryName.name_length, entryName.name);
     return ent;
   }
-
   return FindEntry(archive, ent, data);
 }
 
 int32_t Next(void* cookie, ZipEntry* data, ZipString* name) {
   IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie);
   if (handle == NULL) {
+    ALOGW("Zip: Null ZipArchiveHandle");
     return kInvalidHandle;
   }
 
@@ -771,19 +797,19 @@
 
   const uint32_t currentOffset = handle->position;
   const uint32_t hash_table_length = archive->hash_table_size;
-  const ZipString* hash_table = archive->hash_table;
-
+  const ZipStringOffset* hash_table = archive->hash_table;
   for (uint32_t i = currentOffset; i < hash_table_length; ++i) {
-    if (hash_table[i].name != NULL &&
-        (handle->prefix.name_length == 0 || hash_table[i].StartsWith(handle->prefix)) &&
-        (handle->suffix.name_length == 0 || hash_table[i].EndsWith(handle->suffix))) {
+    const ZipString from_offset =
+        hash_table[i].GetZipString(archive->central_directory.GetBasePtr());
+    if (hash_table[i].name_offset != 0 &&
+        (handle->prefix.name_length == 0 || from_offset.StartsWith(handle->prefix)) &&
+        (handle->suffix.name_length == 0 || from_offset.EndsWith(handle->suffix))) {
       handle->position = (i + 1);
       const int error = FindEntry(archive, i, data);
       if (!error) {
-        name->name = hash_table[i].name;
+        name->name = from_offset.name;
         name->name_length = hash_table[i].name_length;
       }
-
       return error;
     }
   }
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index 0a73300..83cb11f 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -136,6 +136,26 @@
   size_t length_;
 };
 
+/**
+ * More space efficient string representation of strings in an mmaped zipped file than
+ * std::string_view or ZipString. Using ZipString as an entry in the ZipArchive hashtable wastes
+ * space. ZipString stores a pointer to a string (on 64 bit, 8 bytes) and the length to read from
+ * that pointer, 2 bytes. Because of alignment, the structure consumes 16 bytes, wasting 6 bytes.
+ * ZipStringOffset stores a 4 byte offset from a fixed location in the memory mapped file instead
+ * of the entire address, consuming 8 bytes with alignment.
+ */
+struct ZipStringOffset {
+  uint32_t name_offset;
+  uint16_t name_length;
+
+  const ZipString GetZipString(const uint8_t* start) const {
+    ZipString zip_string;
+    zip_string.name = start + name_offset;
+    zip_string.name_length = name_length;
+    return zip_string;
+  }
+};
+
 struct ZipArchive {
   // open Zip archive
   mutable MappedZipFile mapped_zip;
@@ -154,7 +174,7 @@
   // allocate so the maximum number entries can never be higher than
   // ((4 * UINT16_MAX) / 3 + 1) which can safely fit into a uint32_t.
   uint32_t hash_table_size;
-  ZipString* hash_table;
+  ZipStringOffset* hash_table;
 
   ZipArchive(const int fd, bool assume_ownership);
   ZipArchive(void* address, size_t length);
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index f2892f8..d3e80c9 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -8,7 +8,6 @@
 dir.system = /system/bin/
 dir.system = /system/xbin/
 dir.system = /%PRODUCT%/bin/
-dir.system = /%PRODUCT_SERVICES%/bin/
 
 dir.vendor = /odm/bin/
 dir.vendor = /vendor/bin/
@@ -78,9 +77,9 @@
 namespace.default.asan.search.paths  = /data/asan/system/${LIB}
 namespace.default.asan.search.paths +=           /system/${LIB}
 namespace.default.asan.search.paths += /data/asan/product/${LIB}
-namespace.default.asan.search.paths +=           /product/${LIB}
+namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
 namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
-namespace.default.asan.search.paths +=           /product_services/${LIB}
+namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
 namespace.default.asan.permitted.paths  = /data
 namespace.default.asan.permitted.paths += /system/${LIB}/drm
@@ -345,7 +344,9 @@
 namespace.system.asan.search.paths  = /data/asan/system/${LIB}
 namespace.system.asan.search.paths +=           /system/${LIB}
 namespace.system.asan.search.paths += /data/asan/product/${LIB}
-namespace.system.asan.search.paths +=           /product/${LIB}
+namespace.system.asan.search.paths +=           /%PRODUCT%/${LIB}
+namespace.system.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.system.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
 ###############################################################################
 # Namespace config for binaries under /postinstall.
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index db65c14..7e354ac 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -7,7 +7,7 @@
 # absolute path of an executable is selected.
 dir.system = /system/bin/
 dir.system = /system/xbin/
-dir.system = /product/bin/
+dir.system = /%PRODUCT%/bin/
 
 dir.vendor = /odm/bin/
 dir.vendor = /vendor/bin/
@@ -41,7 +41,8 @@
 namespace.default.search.paths  = /system/${LIB}
 namespace.default.search.paths += /odm/${LIB}
 namespace.default.search.paths += /vendor/${LIB}
-namespace.default.search.paths += /product/${LIB}
+namespace.default.search.paths += /%PRODUCT%/${LIB}
+namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
 
 namespace.default.asan.search.paths  = /data/asan/system/${LIB}
 namespace.default.asan.search.paths +=           /system/${LIB}
@@ -50,7 +51,9 @@
 namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
 namespace.default.asan.search.paths +=           /vendor/${LIB}
 namespace.default.asan.search.paths += /data/asan/product/${LIB}
-namespace.default.asan.search.paths +=           /product/${LIB}
+namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
+namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
 ###############################################################################
 # "sphal" namespace
@@ -209,7 +212,8 @@
 namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
 namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
 namespace.default.search.paths += /system/${LIB}
-namespace.default.search.paths += /product/${LIB}
+namespace.default.search.paths += /%PRODUCT%/${LIB}
+namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
 
 namespace.default.asan.search.paths  = /data/asan/odm/${LIB}
 namespace.default.asan.search.paths +=           /odm/${LIB}
@@ -230,7 +234,9 @@
 namespace.default.asan.search.paths += /data/asan/system/${LIB}
 namespace.default.asan.search.paths +=           /system/${LIB}
 namespace.default.asan.search.paths += /data/asan/product/${LIB}
-namespace.default.asan.search.paths +=           /product/${LIB}
+namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
+namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
 
 ###############################################################################
 # Namespace config for binaries under /postinstall.
@@ -243,4 +249,5 @@
 [postinstall]
 namespace.default.isolated = false
 namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /product/${LIB}
+namespace.default.search.paths += /%PRODUCT%/${LIB}
+namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}