Merge "Set errno for all error return cases."
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index 869e858..f1bf559 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -30,6 +30,7 @@
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/debuggerd/libdebuggerd/open_files_list.cpp b/debuggerd/libdebuggerd/open_files_list.cpp
index 03e4e8e..743a2e7 100644
--- a/debuggerd/libdebuggerd/open_files_list.cpp
+++ b/debuggerd/libdebuggerd/open_files_list.cpp
@@ -18,6 +18,7 @@
#include "libdebuggerd/open_files_list.h"
+#include <android/fdsan.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
@@ -122,8 +123,10 @@
const std::optional<std::string>& path = entry.path;
const std::optional<uint64_t>& fdsan_owner = entry.fdsan_owner;
if (path && fdsan_owner) {
- _LOG(log, logtype::OPEN_FILES, "%sfd %i: %s (owned by %#" PRIx64 ")\n", prefix, fd,
- path->c_str(), *fdsan_owner);
+ const char* type = android_fdsan_get_tag_type(*fdsan_owner);
+ uint64_t value = android_fdsan_get_tag_value(*fdsan_owner);
+ _LOG(log, logtype::OPEN_FILES, "%sfd %i: %s (owned by %s %#" PRIx64 ")\n", prefix, fd,
+ path->c_str(), type, value);
} else if (path && !fdsan_owner) {
_LOG(log, logtype::OPEN_FILES, "%sfd %i: %s (unowned)\n", prefix, fd, path->c_str());
} else if (!path && fdsan_owner) {
diff --git a/fastboot/README.md b/fastboot/README.md
index 15b5965..c224448 100644
--- a/fastboot/README.md
+++ b/fastboot/README.md
@@ -136,10 +136,6 @@
should not support "upload" unless it supports an
oem command that requires "upload" capabilities.
- verify:%08x Send a digital signature to verify the downloaded
- data. Required if the bootloader is "secure"
- otherwise "flash" and "boot" will be ignored.
-
flash:%s Write the previously downloaded image to the
named partition (if possible).
@@ -159,8 +155,6 @@
the bootloader and then upgrading other partitions
using the new bootloader.
- powerdown Power off the device.
-
## Client Variables
diff --git a/fastboot/constants.h b/fastboot/constants.h
index 6542b83..063cd40 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -18,7 +18,6 @@
#define FB_CMD_GETVAR "getvar"
#define FB_CMD_DOWNLOAD "download"
#define FB_CMD_UPLOAD "upload"
-#define FB_CMD_VERIFY "verify"
#define FB_CMD_FLASH "flash"
#define FB_CMD_ERASE "erase"
#define FB_CMD_BOOT "boot"
@@ -29,7 +28,6 @@
#define FB_CMD_REBOOT_BOOTLOADER "reboot-bootloader"
#define FB_CMD_REBOOT_RECOVERY "reboot-recovery"
#define FB_CMD_REBOOT_FASTBOOT "reboot-fastboot"
-#define FB_CMD_POWERDOWN "powerdown"
#define FB_CMD_CREATE_PARTITION "create-logical-partition"
#define FB_CMD_DELETE_PARTITION "delete-logical-partition"
#define FB_CMD_RESIZE_PARTITION "resize-logical-partition"
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 6cf544f..331b0c8 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -107,46 +107,56 @@
int64_t image_size;
};
+enum class ImageType {
+ // Must be flashed for device to boot into the kernel.
+ BootCritical,
+ // Normal partition to be flashed during "flashall".
+ Normal,
+ // Partition that is never flashed during "flashall".
+ Extra
+};
+
struct Image {
const char* nickname;
const char* img_name;
const char* sig_name;
const char* part_name;
bool optional_if_no_image;
- bool optional_if_no_partition;
- bool flashall;
+ ImageType type;
bool IsSecondary() const { return nickname == nullptr; }
};
static Image images[] = {
// clang-format off
- { "boot", "boot.img", "boot.sig", "boot", false, false, true, },
- { nullptr, "boot_other.img", "boot.sig", "boot", true, false, true, },
- { "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, false, true, },
- { "dts", "dt.img", "dt.sig", "dts", true, false, true, },
- { "odm", "odm.img", "odm.sig", "odm", true, false, true, },
- { "product", "product.img", "product.sig", "product", true, false, true, },
+ { "boot", "boot.img", "boot.sig", "boot", false, ImageType::BootCritical },
+ { nullptr, "boot_other.img", "boot.sig", "boot", true, ImageType::Normal },
+ { "cache", "cache.img", "cache.sig", "cache", true, ImageType::Extra },
+ { "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, ImageType::BootCritical },
+ { "dts", "dt.img", "dt.sig", "dts", true, ImageType::BootCritical },
+ { "odm", "odm.img", "odm.sig", "odm", true, ImageType::Normal },
+ { "product", "product.img", "product.sig", "product", true, ImageType::Normal },
{ "product_services",
"product_services.img",
"product_services.sig",
"product_services",
- true, true, true, },
- { "recovery", "recovery.img", "recovery.sig", "recovery", true, false, true, },
- { "system", "system.img", "system.sig", "system", false, true, true, },
- { nullptr, "system_other.img", "system.sig", "system", true, false, true, },
- { "vbmeta", "vbmeta.img", "vbmeta.sig", "vbmeta", true, false, true, },
- { "vendor", "vendor.img", "vendor.sig", "vendor", true, true, true, },
- { nullptr, "vendor_other.img", "vendor.sig", "vendor", true, false, true, },
- { "super", "super.img", "super.sig", "super", true, true, false, },
+ true, ImageType::Normal },
+ { "recovery", "recovery.img", "recovery.sig", "recovery", true, ImageType::BootCritical },
+ { "super", "super.img", "super.sig", "super", true, ImageType::Extra },
+ { "system", "system.img", "system.sig", "system", false, ImageType::Normal },
+ { 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 },
+ { "vendor", "vendor.img", "vendor.sig", "vendor", true, ImageType::Normal },
+ { nullptr, "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
// clang-format on
};
-static std::string find_item_given_name(const char* img_name) {
+static std::string find_item_given_name(const std::string& img_name) {
char* dir = getenv("ANDROID_PRODUCT_OUT");
if (dir == nullptr || dir[0] == '\0') {
die("ANDROID_PRODUCT_OUT not set");
}
- return android::base::StringPrintf("%s/%s", dir, img_name);
+ return std::string(dir) + "/" + img_name;
}
static std::string find_item(const std::string& item) {
@@ -156,9 +166,6 @@
}
}
- if (item == "userdata") return find_item_given_name("userdata.img");
- if (item == "cache") return find_item_given_name("cache.img");
-
fprintf(stderr, "unknown partition '%s'\n", item.c_str());
return "";
}
@@ -638,8 +645,7 @@
// "require partition-exists=x" is a special case, added because of the trouble we had when
// Pixel 2 shipped with new partitions and users used old versions of fastboot to flash them,
// missing out new partitions. A device with new partitions can use "partition-exists" to
- // override the fields `optional_if_no_image` and 'optional_if_no_partition' in the `images`
- // array.
+ // override the fields `optional_if_no_image` in the `images` array.
if (!strcmp(name, "partition-exists")) {
const char* partition_name = val[0];
std::string has_slot;
@@ -651,7 +657,6 @@
for (size_t i = 0; i < arraysize(images); ++i) {
if (images[i].nickname && !strcmp(images[i].nickname, partition_name)) {
images[i].optional_if_no_image = false;
- images[i].optional_if_no_partition = false;
known_partition = true;
}
}
@@ -1126,11 +1131,6 @@
die("non-optional file %s missing", images[i].img_name);
}
- if (images[i].optional_if_no_partition &&
- !if_partition_exists(images[i].part_name, slot)) {
- continue;
- }
-
fastboot_buffer buf;
if (!load_buf_fd(fd, &buf)) {
die("cannot load %s from flash: %s", images[i].img_name, strerror(errno));
@@ -1216,6 +1216,26 @@
fb_execute_queue();
}
+static void flash_images(const std::vector<std::pair<const Image*, std::string>>& images) {
+ // Flash each partition in the list if it has a corresponding image.
+ for (const auto& [image, slot] : images) {
+ auto fname = find_item_given_name(image->img_name);
+ fastboot_buffer buf;
+ if (!load_buf(fname.c_str(), &buf)) {
+ if (image->optional_if_no_image) continue;
+ die("could not load '%s': %s", image->img_name, strerror(errno));
+ }
+ auto flashall = [&](const std::string &partition) {
+ do_send_signature(fname.c_str());
+ if (is_logical(partition)) {
+ fb_queue_resize_partition(partition, std::to_string(buf.image_size));
+ }
+ flash_buf(partition.c_str(), &buf);
+ };
+ do_for_partitions(image->part_name, slot, flashall, false);
+ }
+}
+
static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe) {
std::string fname;
queue_info_dump();
@@ -1246,12 +1266,10 @@
}
}
- update_super_partition(wipe);
-
// List of partitions to flash and their slots.
- std::vector<std::pair<const Image*, std::string>> entries;
+ std::vector<std::pair<const Image*, std::string>> boot_images;
+ std::vector<std::pair<const Image*, std::string>> os_images;
for (size_t i = 0; i < arraysize(images); i++) {
- if (!images[i].flashall) continue;
const char* slot = NULL;
if (images[i].IsSecondary()) {
if (!skip_secondary) slot = secondary.c_str();
@@ -1259,39 +1277,33 @@
slot = slot_override.c_str();
}
if (!slot) continue;
- entries.emplace_back(&images[i], slot);
+ if (images[i].type == ImageType::BootCritical) {
+ boot_images.emplace_back(&images[i], slot);
+ } else if (images[i].type == ImageType::Normal) {
+ os_images.emplace_back(&images[i], slot);
+ }
+ }
- // Resize any logical partition to 0, so each partition is reset to 0
- // extents, and will achieve more optimal allocation.
+ // First flash boot partitions. We allow this to happen either in userspace
+ // or in bootloader fastboot.
+ flash_images(boot_images);
+
+ // Sync the super partition. This will reboot to userspace fastboot if needed.
+ update_super_partition(wipe);
+
+ // Resize any logical partition to 0, so each partition is reset to 0
+ // extents, and will achieve more optimal allocation.
+ for (const auto& [image, slot] : os_images) {
auto resize_partition = [](const std::string& partition) -> void {
if (is_logical(partition)) {
fb_queue_resize_partition(partition, "0");
}
};
- do_for_partitions(images[i].part_name, slot, resize_partition, false);
+ do_for_partitions(image->part_name, slot, resize_partition, false);
}
- // Flash each partition in the list if it has a corresponding image.
- for (const auto& [image, slot] : entries) {
- fname = find_item_given_name(image->img_name);
- fastboot_buffer buf;
- if (!load_buf(fname.c_str(), &buf)) {
- if (image->optional_if_no_image) continue;
- die("could not load '%s': %s", image->img_name, strerror(errno));
- }
- if (image->optional_if_no_partition &&
- !if_partition_exists(image->part_name, slot)) {
- continue;
- }
- auto flashall = [&](const std::string &partition) {
- do_send_signature(fname.c_str());
- if (is_logical(partition)) {
- fb_queue_resize_partition(partition, std::to_string(buf.image_size));
- }
- flash_buf(partition.c_str(), &buf);
- };
- do_for_partitions(image->part_name, slot, flashall, false);
- }
+ // Flash OS images, resizing logical partitions as needed.
+ flash_images(os_images);
if (slot_override == "all") {
set_active("a");
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index e8587c7..ceee066 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -89,10 +89,6 @@
return GetVar("all", &tmp, response);
}
-RetCode FastBootDriver::Powerdown(std::string* response, std::vector<std::string>* info) {
- return RawCommand(Commands::POWERDOWN, response, info);
-}
-
RetCode FastBootDriver::Reboot(std::string* response, std::vector<std::string>* info) {
return RawCommand(Commands::REBOOT, response, info);
}
@@ -107,11 +103,6 @@
return RawCommand(Commands::SET_ACTIVE + part, response, info);
}
-RetCode FastBootDriver::Verify(uint32_t num, std::string* response, std::vector<std::string>* info) {
- std::string cmd = android::base::StringPrintf("%s%08" PRIx32, Commands::VERIFY.c_str(), num);
- return RawCommand(cmd, response, info);
-}
-
RetCode FastBootDriver::FlashPartition(const std::string& part, const std::vector<char>& data) {
RetCode ret;
if ((ret = Download(data))) {
@@ -436,11 +427,9 @@
const std::string FastBootDriver::Commands::ERASE = "erase:";
const std::string FastBootDriver::Commands::FLASH = "flash:";
const std::string FastBootDriver::Commands::GET_VAR = "getvar:";
-const std::string FastBootDriver::Commands::POWERDOWN = "powerdown";
const std::string FastBootDriver::Commands::REBOOT = "reboot";
const std::string FastBootDriver::Commands::SET_ACTIVE = "set_active:";
const std::string FastBootDriver::Commands::UPLOAD = "upload";
-const std::string FastBootDriver::Commands::VERIFY = "verify:";
/******************************* PRIVATE **************************************/
RetCode FastBootDriver::SendBuffer(int fd, size_t size) {
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index a97ed2c..4647945 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -86,7 +86,6 @@
RetCode GetVar(const std::string& key, std::string* val,
std::vector<std::string>* info = nullptr);
RetCode GetVarAll(std::vector<std::string>* response);
- RetCode Powerdown(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
RetCode Reboot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
RetCode RebootTo(std::string target, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
@@ -94,8 +93,6 @@
std::vector<std::string>* info = nullptr);
RetCode Upload(const std::string& outfile, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
- RetCode Verify(uint32_t num, std::string* response = nullptr,
- std::vector<std::string>* info = nullptr);
/* HIGHER LEVEL COMMANDS -- Composed of the commands above */
RetCode FlashPartition(const std::string& part, const std::vector<char>& data);
@@ -136,11 +133,9 @@
static const std::string ERASE;
static const std::string FLASH;
static const std::string GET_VAR;
- static const std::string POWERDOWN;
static const std::string REBOOT;
static const std::string SET_ACTIVE;
static const std::string UPLOAD;
- static const std::string VERIFY;
};
Transport* transport_;
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index 14bf5bf..1d30f8b 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -86,9 +86,8 @@
const std::string DEFAULT_OUPUT_NAME = "out.img";
// const char scratch_partition[] = "userdata";
-const std::vector<std::string> CMDS{"boot", "continue", "download:", "erase:",
- "flash:", "getvar:", "powerdown", "reboot",
- "set_active:", "upload", "verify"};
+const std::vector<std::string> CMDS{"boot", "continue", "download:", "erase:", "flash:",
+ "getvar:", "reboot", "set_active:", "upload"};
// For pretty printing we need all these overloads
::std::ostream& operator<<(::std::ostream& os, const RetCode& ret) {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index b0c55e3..e3c2c2b 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -791,7 +791,8 @@
argv.emplace_back(arg.c_str());
}
LOG(INFO) << "Calling: " << android::base::Join(argv, ' ');
- int ret = android_fork_execvp(4, const_cast<char**>(argv.data()), nullptr, false, true);
+ int ret =
+ android_fork_execvp(argv.size(), const_cast<char**>(argv.data()), nullptr, false, true);
if (ret != 0) {
LOG(ERROR) << "vdc returned error code: " << ret;
return false;
@@ -853,7 +854,8 @@
}
/* Skip mounting the root partition, as it will already have been mounted */
- if (!strcmp(fstab->recs[i].mount_point, "/")) {
+ if (!strcmp(fstab->recs[i].mount_point, "/") ||
+ !strcmp(fstab->recs[i].mount_point, "/system")) {
if ((fstab->recs[i].fs_mgr_flags & MS_RDONLY) != 0) {
fs_mgr_set_blk_ro(fstab->recs[i].blk_device);
}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 531610e..720dcfd 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -265,10 +265,17 @@
return ret;
}
+constexpr char overlayfs_file_context[] = "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) + "/";
+
+ if (setfscreatecon(overlayfs_file_context)) {
+ ret = false;
+ PERROR << "overlayfs setfscreatecon " << overlayfs_file_context;
+ }
auto save_errno = errno;
if (!mkdir(fsrec_mount_point.c_str(), 0755)) {
if (change) *change = true;
@@ -288,6 +295,7 @@
} else {
errno = save_errno;
}
+ setfscreatecon(nullptr);
auto new_context = fs_mgr_get_context(mount_point);
if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
@@ -360,6 +368,34 @@
return false;
}
+std::vector<std::string> fs_mgr_candidate_list(const fstab* fstab,
+ const char* mount_point = nullptr) {
+ std::vector<std::string> mounts;
+ if (!fstab) return mounts;
+
+ for (auto i = 0; i < fstab->num_entries; i++) {
+ const auto fsrec = &fstab->recs[i];
+ if (!fs_mgr_wants_overlayfs(fsrec)) continue;
+ std::string new_mount_point(fs_mgr_mount_point(fstab, fsrec->mount_point));
+ if (mount_point && (new_mount_point != mount_point)) continue;
+ auto duplicate_or_more_specific = false;
+ for (auto it = mounts.begin(); it != mounts.end();) {
+ if ((*it == new_mount_point) ||
+ (android::base::StartsWith(new_mount_point, *it + "/"))) {
+ duplicate_or_more_specific = true;
+ break;
+ }
+ if (android::base::StartsWith(*it, new_mount_point + "/")) {
+ it = mounts.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point);
+ }
+ return mounts;
+}
+
} // namespace
bool fs_mgr_overlayfs_mount_all() {
@@ -371,10 +407,7 @@
fs_mgr_free_fstab);
if (!fstab) return ret;
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- if (!fs_mgr_wants_overlayfs(fsrec)) continue;
- std::string mount_point(fs_mgr_mount_point(fstab.get(), fsrec->mount_point));
+ for (const auto& mount_point : fs_mgr_candidate_list(fstab.get())) {
if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
}
@@ -399,21 +432,13 @@
std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
fs_mgr_free_fstab);
- std::vector<std::string> mounts;
- mount_point = fs_mgr_mount_point(fstab.get(), mount_point);
- if (fstab) {
- if (!fs_mgr_get_entry_for_mount_point(fstab.get(), kOverlayMountPoint)) return ret;
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- auto fsrec_mount_point = fs_mgr_mount_point(fstab.get(), fsrec->mount_point);
- if (!fsrec_mount_point) continue;
- if (mount_point && strcmp(fsrec_mount_point, mount_point)) continue;
- if (!fs_mgr_wants_overlayfs(fsrec)) continue;
- mounts.emplace_back(fsrec_mount_point);
- }
- if (mounts.empty()) return ret;
- }
+ if (fstab && !fs_mgr_get_entry_for_mount_point(fstab.get(), kOverlayMountPoint)) return ret;
+ 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;
+ }
auto overlay = kOverlayMountPoint + "/overlay/";
auto save_errno = errno;
if (!mkdir(overlay.c_str(), 0755)) {
@@ -423,6 +448,7 @@
} else {
errno = save_errno;
}
+ setfscreatecon(nullptr);
if (!fstab && mount_point && fs_mgr_overlayfs_setup_one(overlay, mount_point, change)) {
ret = true;
}
diff --git a/init/Android.mk b/init/Android.mk
index ada87b8..dc400ad 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -47,6 +47,7 @@
init_first_stage.cpp \
reboot_utils.cpp \
selinux.cpp \
+ switch_root.cpp \
uevent_listener.cpp \
util.cpp \
@@ -54,8 +55,15 @@
LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
-LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)
+LOCAL_UNSTRIPPED_PATH := $(TARGET_RAMDISK_OUT_UNSTRIPPED)
+
+# Set up the same mount points on the ramdisk that system-as-root contains.
+LOCAL_POST_INSTALL_CMD := \
+ mkdir -p $(TARGET_RAMDISK_OUT)/dev \
+ mkdir -p $(TARGET_RAMDISK_OUT)/mnt \
+ mkdir -p $(TARGET_RAMDISK_OUT)/proc \
+ mkdir -p $(TARGET_RAMDISK_OUT)/sys \
LOCAL_STATIC_LIBRARIES := \
libfs_mgr \
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 0c5cf76..1496935 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -29,19 +29,22 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
+#include <fs_mgr.h>
+#include <fs_mgr_avb.h>
+#include <fs_mgr_dm_linear.h>
+#include <fs_mgr_overlayfs.h>
#include <liblp/metadata_format.h>
#include "devices.h"
-#include "fs_mgr.h"
-#include "fs_mgr_avb.h"
-#include "fs_mgr_dm_linear.h"
-#include "fs_mgr_overlayfs.h"
+#include "switch_root.h"
#include "uevent.h"
#include "uevent_listener.h"
#include "util.h"
using android::base::Timer;
+using namespace std::literals;
+
namespace android {
namespace init {
@@ -63,6 +66,7 @@
bool InitRequiredDevices();
bool InitMappedDevice(const std::string& verity_device);
bool CreateLogicalPartitions();
+ bool MountPartition(fstab_rec* fstab_rec);
bool MountPartitions();
bool GetBackingDmLinearDevices();
@@ -333,26 +337,51 @@
return true;
}
-bool FirstStageMount::MountPartitions() {
- for (auto fstab_rec : mount_fstab_recs_) {
- if (fs_mgr_is_logical(fstab_rec)) {
- if (!fs_mgr_update_logical_partition(fstab_rec)) {
- return false;
- }
- if (!InitMappedDevice(fstab_rec->blk_device)) {
- return false;
- }
- }
- if (!SetUpDmVerity(fstab_rec)) {
- PLOG(ERROR) << "Failed to setup verity for '" << fstab_rec->mount_point << "'";
+bool FirstStageMount::MountPartition(fstab_rec* fstab_rec) {
+ if (fs_mgr_is_logical(fstab_rec)) {
+ if (!fs_mgr_update_logical_partition(fstab_rec)) {
return false;
}
- if (fs_mgr_do_mount_one(fstab_rec)) {
- PLOG(ERROR) << "Failed to mount '" << fstab_rec->mount_point << "'";
+ if (!InitMappedDevice(fstab_rec->blk_device)) {
return false;
}
}
+ if (!SetUpDmVerity(fstab_rec)) {
+ PLOG(ERROR) << "Failed to setup verity for '" << fstab_rec->mount_point << "'";
+ return false;
+ }
+ if (fs_mgr_do_mount_one(fstab_rec)) {
+ PLOG(ERROR) << "Failed to mount '" << fstab_rec->mount_point << "'";
+ return false;
+ }
+ return true;
+}
+
+bool FirstStageMount::MountPartitions() {
+ // If system is in the fstab then we're not a system-as-root device, and in
+ // this case, we mount system first then pivot to it. From that point on,
+ // we are effectively identical to a system-as-root device.
+ auto system_partition =
+ std::find_if(mount_fstab_recs_.begin(), mount_fstab_recs_.end(),
+ [](const auto& rec) { return rec->mount_point == "/system"s; });
+ if (system_partition != mount_fstab_recs_.end()) {
+ if (!MountPartition(*system_partition)) {
+ return false;
+ }
+
+ SwitchRoot("/system");
+
+ mount_fstab_recs_.erase(system_partition);
+ }
+
+ for (auto fstab_rec : mount_fstab_recs_) {
+ if (!MountPartition(fstab_rec)) {
+ return false;
+ }
+ }
+
fs_mgr_overlayfs_mount_all();
+
return true;
}
diff --git a/init/switch_root.cpp b/init/switch_root.cpp
new file mode 100644
index 0000000..0e59b57
--- /dev/null
+++ b/init/switch_root.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "switch_root.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <mntent.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+
+using android::base::StartsWith;
+
+using namespace std::literals;
+
+namespace android {
+namespace init {
+
+namespace {
+
+void FreeRamdisk(DIR* dir, dev_t dev) {
+ int dfd = dirfd(dir);
+
+ dirent* de;
+ while ((de = readdir(dir)) != nullptr) {
+ if (de->d_name == "."s || de->d_name == ".."s) {
+ continue;
+ }
+
+ bool is_dir = false;
+
+ if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) {
+ struct stat info;
+ if (fstatat(dfd, de->d_name, &info, AT_SYMLINK_NOFOLLOW) != 0) {
+ continue;
+ }
+
+ if (info.st_dev != dev) {
+ continue;
+ }
+
+ if (S_ISDIR(info.st_mode)) {
+ is_dir = true;
+ auto fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+ if (fd >= 0) {
+ auto subdir =
+ std::unique_ptr<DIR, decltype(&closedir)>{fdopendir(fd), closedir};
+ if (subdir) {
+ FreeRamdisk(subdir.get(), dev);
+ } else {
+ close(fd);
+ }
+ }
+ }
+ }
+ unlinkat(dfd, de->d_name, is_dir ? AT_REMOVEDIR : 0);
+ }
+}
+
+std::vector<std::string> GetMounts(const std::string& new_root) {
+ auto fp = std::unique_ptr<std::FILE, decltype(&endmntent)>{setmntent("/proc/mounts", "re"),
+ endmntent};
+ if (fp == nullptr) {
+ PLOG(FATAL) << "Failed to open /proc/mounts";
+ }
+
+ std::vector<std::string> result;
+ mntent* mentry;
+ while ((mentry = getmntent(fp.get())) != nullptr) {
+ // We won't try to move rootfs.
+ if (mentry->mnt_dir == "/"s) {
+ continue;
+ }
+
+ // The new root mount is handled separately.
+ if (mentry->mnt_dir == new_root) {
+ continue;
+ }
+
+ // Move operates on subtrees, so do not try to move children of other mounts.
+ if (std::find_if(result.begin(), result.end(), [&mentry](const auto& older_mount) {
+ return StartsWith(mentry->mnt_dir, older_mount);
+ }) != result.end()) {
+ continue;
+ }
+
+ result.emplace_back(mentry->mnt_dir);
+ }
+
+ return result;
+}
+
+} // namespace
+
+void SwitchRoot(const std::string& new_root) {
+ auto mounts = GetMounts(new_root);
+
+ for (const auto& mount_path : mounts) {
+ auto new_mount_path = new_root + mount_path;
+ if (mount(mount_path.c_str(), new_mount_path.c_str(), nullptr, MS_MOVE, nullptr) != 0) {
+ PLOG(FATAL) << "Unable to move mount at '" << mount_path << "'";
+ }
+ }
+
+ auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
+ if (!old_root_dir) {
+ PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
+ }
+
+ struct stat old_root_info;
+ if (stat("/", &old_root_info) != 0) {
+ PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
+ old_root_dir.reset();
+ }
+
+ if (chdir(new_root.c_str()) != 0) {
+ PLOG(FATAL) << "Could not chdir to new_root, '" << new_root << "'";
+ }
+
+ if (mount(new_root.c_str(), "/", nullptr, MS_MOVE, nullptr) != 0) {
+ PLOG(FATAL) << "Unable to move root mount to new_root, '" << new_root << "'";
+ }
+
+ if (chroot(".") != 0) {
+ PLOG(FATAL) << "Unable to chroot to new root";
+ }
+
+ if (old_root_dir) {
+ FreeRamdisk(old_root_dir.get(), old_root_info.st_dev);
+ }
+}
+
+} // namespace init
+} // namespace android
diff --git a/init/switch_root.h b/init/switch_root.h
new file mode 100644
index 0000000..d515e5d
--- /dev/null
+++ b/init/switch_root.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace android {
+namespace init {
+
+void SwitchRoot(const std::string& new_root);
+
+} // namespace init
+} // namespace android
diff --git a/libcutils/tests/sched_policy_test.cpp b/libcutils/tests/sched_policy_test.cpp
index 5942ee5..1f657e2 100644
--- a/libcutils/tests/sched_policy_test.cpp
+++ b/libcutils/tests/sched_policy_test.cpp
@@ -67,6 +67,21 @@
}
TEST(SchedPolicy, set_sched_policy) {
+ if (!schedboost_enabled()) {
+ // schedboost_enabled() (i.e. CONFIG_CGROUP_SCHEDTUNE) is optional;
+ // it's only needed on devices using energy-aware scheduler.
+ GTEST_LOG_(INFO) << "skipping test that requires CONFIG_CGROUP_SCHEDTUNE";
+ return;
+ }
+
+ ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+ AssertPolicy(SP_BACKGROUND);
+
+ ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
+ AssertPolicy(SP_FOREGROUND);
+}
+
+TEST(SchedPolicy, set_sched_policy_timerslack) {
if (!hasCapSysNice()) {
GTEST_LOG_(INFO) << "skipping test that requires CAP_SYS_NICE";
return;
@@ -82,11 +97,9 @@
const unsigned int BG_FG_SLACK_FACTOR = 100;
ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
- AssertPolicy(SP_BACKGROUND);
auto bgSleepTime = medianSleepTime();
ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
- AssertPolicy(SP_FOREGROUND);
auto fgSleepTime = medianSleepTime();
ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR);
}
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index c7306cd..14883f4 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -72,8 +72,7 @@
LOCAL_SRC_FILES_mips64 := $(PIXELFLINGER_SRC_FILES_mips64)
LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS) \
- external/safe-iop/include
+LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS)
LOCAL_SHARED_LIBRARIES := libcutils liblog libutils
include $(BUILD_SHARED_LIBRARY)
diff --git a/libpixelflinger/arch-arm64/t32cb16blend.S b/libpixelflinger/arch-arm64/t32cb16blend.S
index b1a950d..a9733c0 100644
--- a/libpixelflinger/arch-arm64/t32cb16blend.S
+++ b/libpixelflinger/arch-arm64/t32cb16blend.S
@@ -49,7 +49,7 @@
* upper 16-bit pixels in DREG into FB
*
*
- * clobbered: w6, w7, w16, w17, w18
+ * clobbered: w6, w7, w15, w16, w17
*
*/
@@ -73,8 +73,8 @@
add w16, w6, w16, lsr #8
cmp w16, #0x1F
orr w17, \FB, #(0x1F<<(16 + 11))
- orr w18, \FB, w16, lsl #(16 + 11)
- csel \FB, w17, w18, hi
+ orr w15, \FB, w16, lsl #(16 + 11)
+ csel \FB, w17, w15, hi
// green
and w6, \DREG, #(0x3F<<(16 + 5))
lsr w17,w6,#(16+5)
@@ -84,8 +84,8 @@
add w6, w16, w6, lsr #8
cmp w6, #0x3F
orr w17, \FB, #(0x3F<<(16 + 5))
- orr w18, \FB, w6, lsl #(16 + 5)
- csel \FB, w17, w18, hi
+ orr w15, \FB, w6, lsl #(16 + 5)
+ csel \FB, w17, w15, hi
// blue
and w16, \DREG, #(0x1F << 16)
lsr w17,w16,#16
@@ -95,8 +95,8 @@
add w16, w6, w16, lsr #8
cmp w16, #0x1F
orr w17, \FB, #(0x1F << 16)
- orr w18, \FB, w16, lsl #16
- csel \FB, w17, w18, hi
+ orr w15, \FB, w16, lsl #16
+ csel \FB, w17, w15, hi
.else //Blending even pixel present in bottom 16 bits of DREG register
@@ -109,8 +109,8 @@
add w16, w6, w16, lsr #8
cmp w16, #0x1F
mov w17, #(0x1F<<11)
- lsl w18, w16, #11
- csel \FB, w17, w18, hi
+ lsl w15, w16, #11
+ csel \FB, w17, w15, hi
// green
@@ -121,8 +121,8 @@
add w6, w16, w6, lsr #(5+8)
cmp w6, #0x3F
orr w17, \FB, #(0x3F<<5)
- orr w18, \FB, w6, lsl #5
- csel \FB, w17, w18, hi
+ orr w15, \FB, w6, lsl #5
+ csel \FB, w17, w15, hi
// blue
and w16, \DREG, #0x1F
@@ -132,8 +132,8 @@
add w16, w6, w16, lsr #8
cmp w16, #0x1F
orr w17, \FB, #0x1F
- orr w18, \FB, w16
- csel \FB, w17, w18, hi
+ orr w15, \FB, w16
+ csel \FB, w17, w15, hi
.endif // End of blending even pixel
diff --git a/libutils/Android.bp b/libutils/Android.bp
index d635e65..1c1bdf7 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -58,7 +58,6 @@
"-Wall",
"-Werror",
],
- include_dirs: ["external/safe-iop/include"],
header_libs: [
"libutils_headers",
],
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index 00a904d..e16f88d 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -24,8 +24,6 @@
#include <log/log.h>
-#include <safe_iop.h>
-
#include "SharedBuffer.h"
/*****************************************************************************/
@@ -342,7 +340,7 @@
}
size_t new_allocation_size = 0;
- LOG_ALWAYS_FATAL_IF(!safe_mul(&new_allocation_size, new_capacity, mItemSize));
+ LOG_ALWAYS_FATAL_IF(__builtin_mul_overflow(new_capacity, mItemSize, &new_allocation_size));
SharedBuffer* sb = SharedBuffer::alloc(new_allocation_size);
if (sb) {
void* array = sb->data();
@@ -386,7 +384,7 @@
this, (int)where, (int)amount, (int)mCount); // caller already checked
size_t new_size;
- LOG_ALWAYS_FATAL_IF(!safe_add(&new_size, mCount, amount), "new_size overflow");
+ LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(mCount, amount, &new_size), "new_size overflow");
if (capacity() < new_size) {
// NOTE: This implementation used to resize vectors as per ((3*x + 1) / 2)
@@ -397,17 +395,18 @@
//
// This approximates the old calculation, using (x + (x/2) + 1) instead.
size_t new_capacity = 0;
- LOG_ALWAYS_FATAL_IF(!safe_add(&new_capacity, new_size, (new_size / 2)),
+ LOG_ALWAYS_FATAL_IF(__builtin_add_overflow(new_size, (new_size / 2), &new_capacity),
"new_capacity overflow");
- LOG_ALWAYS_FATAL_IF(!safe_add(&new_capacity, new_capacity, static_cast<size_t>(1u)),
- "new_capacity overflow");
+ LOG_ALWAYS_FATAL_IF(
+ __builtin_add_overflow(new_capacity, static_cast<size_t>(1u), &new_capacity),
+ "new_capacity overflow");
new_capacity = max(kMinVectorCapacity, new_capacity);
size_t new_alloc_size = 0;
- LOG_ALWAYS_FATAL_IF(!safe_mul(&new_alloc_size, new_capacity, mItemSize),
+ LOG_ALWAYS_FATAL_IF(__builtin_mul_overflow(new_capacity, mItemSize, &new_alloc_size),
"new_alloc_size overflow");
-// ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
+ // ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
if ((mStorage) &&
(mCount==where) &&
(mFlags & HAS_TRIVIAL_COPY) &&
@@ -464,7 +463,7 @@
this, (int)where, (int)amount, (int)mCount); // caller already checked
size_t new_size;
- LOG_ALWAYS_FATAL_IF(!safe_sub(&new_size, mCount, amount));
+ LOG_ALWAYS_FATAL_IF(__builtin_sub_overflow(mCount, amount, &new_size));
if (new_size < (capacity() / 2)) {
// NOTE: (new_size * 2) is safe because capacity didn't overflow and
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 48551f2..bb55d1f 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -738,6 +738,8 @@
}
void* llkThread(void* obj) {
+ prctl(PR_SET_DUMPABLE, 0);
+
LOG(INFO) << "started";
std::string name = std::to_string(::gettid());
diff --git a/llkd/llkd.cpp b/llkd/llkd.cpp
index f10253d..1920198 100644
--- a/llkd/llkd.cpp
+++ b/llkd/llkd.cpp
@@ -17,6 +17,7 @@
#include "llkd.h"
#include <sched.h>
+#include <sys/prctl.h>
#include <unistd.h>
#include <chrono>
@@ -26,6 +27,8 @@
using namespace std::chrono;
int main(int, char**) {
+ prctl(PR_SET_DUMPABLE, 0);
+
LOG(INFO) << "started";
bool enabled = llkInit();
diff --git a/rootdir/init.rc b/rootdir/init.rc
index db89ea8..1c2ef64 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -716,12 +716,12 @@
class_start main
on property:vold.decrypt=trigger_restart_framework
- stop surfaceflinger
- start surfaceflinger
# A/B update verifier that marks a successful boot.
exec_start update_verifier
class_start main
class_start late_start
+ setprop service.bootanim.exit 0
+ start bootanim
on property:vold.decrypt=trigger_shutdown_framework
class_reset late_start