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}