diff options
60 files changed, 923 insertions, 572 deletions
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp index cf4d2944a..380dfa653 100644 --- a/adb/daemon/remount_service.cpp +++ b/adb/daemon/remount_service.cpp @@ -146,6 +146,10 @@ static bool remount_partition(int fd, const char* dir) { return true; } bool is_root = strcmp(dir, "/") == 0; + if (is_root && !find_mount("/system", false).empty()) { + dir = "/system"; + is_root = false; + } std::string dev = find_mount(dir, is_root); // Even if the device for the root is not found, we still try to remount it // as rw. This typically only happens when running Android in a container: @@ -216,13 +220,19 @@ void remount_service(unique_fd fd, const std::string& cmd) { // If we can use overlayfs, lets get it in place first // before we struggle with determining deduplication operations. - if (!verity_enabled && fs_mgr_overlayfs_setup() && fs_mgr_overlayfs_mount_all()) { - WriteFdExactly(fd.get(), "overlayfs mounted\n"); + if (!verity_enabled && fs_mgr_overlayfs_setup()) { + std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(), + fs_mgr_free_fstab); + if (fs_mgr_overlayfs_mount_all(fstab.get())) { + WriteFdExactly(fd.get(), "overlayfs mounted\n"); + } } // Find partitions that are deduplicated, and can be un-deduplicated. std::set<std::string> dedup; - for (const auto& partition : partitions) { + for (const auto& part : partitions) { + auto partition = part; + if ((part == "/") && !find_mount("/system", false).empty()) partition = "/system"; std::string dev = find_mount(partition.c_str(), partition == "/"); if (dev.empty() || !fs_mgr_has_shared_blocks(partition, dev)) { continue; diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp index 841769043..2bac48653 100644 --- a/adb/daemon/services.cpp +++ b/adb/daemon/services.cpp @@ -103,7 +103,9 @@ void reboot_service(unique_fd fd, const std::string& arg) { if (reboot_arg.empty()) reboot_arg = "adb"; std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str()); - if (reboot_arg == "fastboot" && access("/dev/socket/recovery", F_OK) == 0) { + if (reboot_arg == "fastboot" && + android::base::GetBoolProperty("ro.boot.logical_partitions", false) && + access("/dev/socket/recovery", F_OK) == 0) { LOG(INFO) << "Recovery specific reboot fastboot"; /* * The socket is created to allow switching between recovery and diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp index dee87bdf3..98a73eb0e 100644 --- a/adb/fdevent.cpp +++ b/adb/fdevent.cpp @@ -147,24 +147,34 @@ fdevent* fdevent_create(int fd, fd_func func, void* arg) { return fde; } -void fdevent_destroy(fdevent* fde) { +unique_fd fdevent_release(fdevent* fde) { check_main_thread(); - if (fde == nullptr) return; + if (!fde) { + return {}; + } + if (!(fde->state & FDE_CREATED)) { LOG(FATAL) << "destroying fde not created by fdevent_create(): " << dump_fde(fde); } + unique_fd result = std::move(fde->fd); if (fde->state & FDE_ACTIVE) { - g_poll_node_map.erase(fde->fd.get()); + g_poll_node_map.erase(result.get()); + if (fde->state & FDE_PENDING) { g_pending_list.remove(fde); } - fde->fd.reset(); fde->state = 0; fde->events = 0; } delete fde; + return result; +} + +void fdevent_destroy(fdevent* fde) { + // Release, and then let unique_fd's destructor cleanup. + fdevent_release(fde); } static void fdevent_update(fdevent* fde, unsigned events) { diff --git a/adb/fdevent.h b/adb/fdevent.h index d501b8660..df2339a97 100644 --- a/adb/fdevent.h +++ b/adb/fdevent.h @@ -50,11 +50,12 @@ struct fdevent { */ fdevent *fdevent_create(int fd, fd_func func, void *arg); -/* Uninitialize and deallocate an fdevent object that was -** created by fdevent_create() -*/ +// Deallocate an fdevent object that was created by fdevent_create. void fdevent_destroy(fdevent *fde); +// fdevent_destroy, except releasing the file descriptor previously owned by the fdevent. +unique_fd fdevent_release(fdevent* fde); + /* Change which events should cause notifications */ void fdevent_set(fdevent *fde, unsigned events); diff --git a/adb/test_device.py b/adb/test_device.py index 9f451150f..c3166ffe1 100644..100755 --- a/adb/test_device.py +++ b/adb/test_device.py @@ -751,7 +751,7 @@ class FileOperationsTest(DeviceTest): shutil.rmtree(host_dir) def test_push_empty(self): - """Push a directory containing an empty directory to the device.""" + """Push an empty directory to the device.""" self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR]) self.device.shell(['mkdir', self.DEVICE_TEMP_DIR]) @@ -767,9 +767,10 @@ class FileOperationsTest(DeviceTest): self.device.push(empty_dir_path, self.DEVICE_TEMP_DIR) - test_empty_cmd = ['[', '-d', - os.path.join(self.DEVICE_TEMP_DIR, 'empty')] + remote_path = os.path.join(self.DEVICE_TEMP_DIR, "empty") + test_empty_cmd = ["[", "-d", remote_path, "]"] rc, _, _ = self.device.shell_nocheck(test_empty_cmd) + self.assertEqual(rc, 0) self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR]) finally: diff --git a/base/Android.bp b/base/Android.bp index 3d80d9719..daa820ab4 100644 --- a/base/Android.bp +++ b/base/Android.bp @@ -56,6 +56,7 @@ cc_defaults { "test_utils.cpp", ], + cppflags: ["-Wexit-time-destructors"], shared_libs: ["liblog"], target: { android: { @@ -68,13 +69,11 @@ cc_defaults { srcs: [ "errors_unix.cpp", ], - cppflags: ["-Wexit-time-destructors"], }, darwin: { srcs: [ "errors_unix.cpp", ], - cppflags: ["-Wexit-time-destructors"], }, linux_bionic: { enabled: true, diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp index c17e00ffe..6700b6cae 100644 --- a/bootstat/bootstat.cpp +++ b/bootstat/bootstat.cpp @@ -236,7 +236,7 @@ const std::map<std::string, int32_t> kBootReasonMap = { {"reboot,rescueparty", 90}, {"charge", 91}, {"oem_tz_crash", 92}, - {"uvlo", 93}, + {"uvlo", 93}, // aliasReasons converts to reboot,undervoltage {"oem_ps_hold", 94}, {"abnormal_reset", 95}, {"oemerr_unknown", 96}, @@ -248,9 +248,9 @@ const std::map<std::string, int32_t> kBootReasonMap = { {"watchdog_nonsec", 102}, {"watchdog_apps_bark", 103}, {"reboot_dmverity_corrupted", 104}, - {"reboot_smpl", 105}, + {"reboot_smpl", 105}, // aliasReasons converts to reboot,powerloss {"watchdog_sdi_apps_reset", 106}, - {"smpl", 107}, + {"smpl", 107}, // aliasReasons converts to reboot,powerloss {"oem_modem_failed_to_powerup", 108}, {"reboot_normal", 109}, {"oem_lpass_cfg", 110}, @@ -262,8 +262,8 @@ const std::map<std::string, int32_t> kBootReasonMap = { {"oem_rpm_undef_error", 116}, {"oem_crash_on_the_lk", 117}, {"oem_rpm_reset", 118}, - {"REUSE1", 119}, // Former dupe, can be re-used - {"REUSE2", 120}, // Former dupe, can be re-used + {"reboot,powerloss", 119}, + {"reboot,undervoltage", 120}, {"factory_cable", 121}, {"oem_ar6320_failed_to_powerup", 122}, {"watchdog_rpm_bite", 123}, @@ -840,6 +840,8 @@ std::string BootReasonStrToReason(const std::string& boot_reason) { {"reboot,tool", "tool_by_pass_pwk"}, {"!reboot,longkey", "reboot_longkey"}, {"!reboot,longkey", "kpdpwr"}, + {"!reboot,undervoltage", "uvlo"}, + {"!reboot,powerloss", "smpl"}, {"bootloader", ""}, }; diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp index 93f757236..577e336b0 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 @@ static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo, 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/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp index f0fe1d0d9..f0bdfbfde 100644 --- a/debuggerd/crasher/crasher.cpp +++ b/debuggerd/crasher/crasher.cpp @@ -224,7 +224,7 @@ noinline int do_action(const char* arg) { // Prefixes. if (!strncmp(arg, "wait-", strlen("wait-"))) { char buf[1]; - TEMP_FAILURE_RETRY(read(STDIN_FILENO, buf, sizeof(buf))); + UNUSED(TEMP_FAILURE_RETRY(read(STDIN_FILENO, buf, sizeof(buf)))); return do_action(arg + strlen("wait-")); } else if (!strncmp(arg, "exhaustfd-", strlen("exhaustfd-"))) { errno = 0; @@ -258,10 +258,14 @@ noinline int do_action(const char* arg) { __assert("some_file.c", 123, "false"); } else if (!strcasecmp(arg, "assert2")) { __assert2("some_file.c", 123, "some_function", "false"); +#if !defined(__clang_analyzer__) } else if (!strcasecmp(arg, "fortify")) { + // FORTIFY is disabled when running clang-tidy and other tools, so this + // shouldn't depend on internal implementation details of it. char buf[10]; __read_chk(-1, buf, 32, 10); while (true) pause(); +#endif } else if (!strcasecmp(arg, "fdsan_file")) { FILE* f = fopen("/dev/null", "r"); close(fileno(f)); diff --git a/fastboot/bootimg_utils.cpp b/fastboot/bootimg_utils.cpp index 115200797..e4337875d 100644 --- a/fastboot/bootimg_utils.cpp +++ b/fastboot/bootimg_utils.cpp @@ -39,27 +39,27 @@ void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline) { strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str()); } -boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size, - void* second, int64_t second_size, size_t base, - const boot_img_hdr_v1& src, int64_t* bootimg_size) { +boot_img_hdr_v1* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk, + const std::vector<char>& second, size_t base, const boot_img_hdr_v1& src, + std::vector<char>* out) { const size_t page_mask = src.page_size - 1; int64_t header_actual = (sizeof(boot_img_hdr_v1) + page_mask) & (~page_mask); - int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask); - int64_t ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask); - int64_t second_actual = (second_size + page_mask) & (~page_mask); + int64_t kernel_actual = (kernel.size() + page_mask) & (~page_mask); + int64_t ramdisk_actual = (ramdisk.size() + page_mask) & (~page_mask); + int64_t second_actual = (second.size() + page_mask) & (~page_mask); - *bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual; + int64_t bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual; + out->resize(bootimg_size); - boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(calloc(*bootimg_size, 1)); - if (hdr == nullptr) die("couldn't allocate boot image: %" PRId64 " bytes", *bootimg_size); + boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(out->data()); *hdr = src; memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE); - hdr->kernel_size = kernel_size; - hdr->ramdisk_size = ramdisk_size; - hdr->second_size = second_size; + hdr->kernel_size = kernel.size(); + hdr->ramdisk_size = ramdisk.size(); + hdr->second_size = second.size(); hdr->kernel_addr += base; hdr->ramdisk_addr += base; @@ -70,8 +70,9 @@ boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int hdr->header_size = sizeof(boot_img_hdr_v1); } - memcpy(hdr->magic + hdr->page_size, kernel, kernel_size); - memcpy(hdr->magic + hdr->page_size + kernel_actual, ramdisk, ramdisk_size); - memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual, second, second_size); + memcpy(hdr->magic + hdr->page_size, kernel.data(), kernel.size()); + memcpy(hdr->magic + hdr->page_size + kernel_actual, ramdisk.data(), ramdisk.size()); + memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual, second.data(), + second.size()); return hdr; } diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h index fe805b007..a4e8870d9 100644 --- a/fastboot/bootimg_utils.h +++ b/fastboot/bootimg_utils.h @@ -33,8 +33,9 @@ #include <sys/types.h> #include <string> +#include <vector> -boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size, - void* second, int64_t second_size, size_t base, - const boot_img_hdr_v1& src, int64_t* bootimg_size); +boot_img_hdr_v1* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk, + const std::vector<char>& second, size_t base, const boot_img_hdr_v1& src, + std::vector<char>* out); void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline); diff --git a/fastboot/constants.h b/fastboot/constants.h index 57e25fc59..2a68a2b03 100644 --- a/fastboot/constants.h +++ b/fastboot/constants.h @@ -32,6 +32,7 @@ #define FB_CMD_DELETE_PARTITION "delete-logical-partition" #define FB_CMD_RESIZE_PARTITION "resize-logical-partition" #define FB_CMD_UPDATE_SUPER "update-super" +#define FB_CMD_OEM "oem" #define RESPONSE_OKAY "OKAY" #define RESPONSE_FAIL "FAIL" diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp index 0ec09945b..b7cafac4a 100644 --- a/fastboot/device/commands.cpp +++ b/fastboot/device/commands.cpp @@ -40,6 +40,9 @@ using ::android::hardware::hidl_string; using ::android::hardware::boot::V1_0::BoolResult; using ::android::hardware::boot::V1_0::CommandResult; using ::android::hardware::boot::V1_0::Slot; +using ::android::hardware::fastboot::V1_0::Result; +using ::android::hardware::fastboot::V1_0::Status; + using namespace android::fs_mgr; struct VariableHandlers { @@ -133,6 +136,24 @@ bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) return device->WriteStatus(FastbootResult::FAIL, "Erasing failed"); } +bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args) { + auto fastboot_hal = device->fastboot_hal(); + if (!fastboot_hal) { + return device->WriteStatus(FastbootResult::FAIL, "Unable to open fastboot HAL"); + } + + Result ret; + auto ret_val = fastboot_hal->doOemCommand(args[0], [&](Result result) { ret = result; }); + if (!ret_val.isOk()) { + return device->WriteStatus(FastbootResult::FAIL, "Unable to do OEM command"); + } + if (ret.status != Status::SUCCESS) { + return device->WriteStatus(FastbootResult::FAIL, ret.message); + } + + return device->WriteStatus(FastbootResult::OKAY, ret.message); +} + bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) { if (args.size() < 2) { return device->WriteStatus(FastbootResult::FAIL, "size argument unspecified"); @@ -159,6 +180,12 @@ bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) if (args.size() < 2) { return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments"); } + + if (GetDeviceLockStatus()) { + return device->WriteStatus(FastbootResult::FAIL, + "Flashing is not allowed on locked devices"); + } + int ret = Flash(device, args[1]); if (ret < 0) { return device->WriteStatus(FastbootResult::FAIL, strerror(-ret)); @@ -304,6 +331,10 @@ bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::strin return device->WriteFail("Invalid partition name and size"); } + if (GetDeviceLockStatus()) { + return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices"); + } + uint64_t partition_size; std::string partition_name = args[1]; if (!android::base::ParseUint(args[2].c_str(), &partition_size)) { @@ -344,6 +375,10 @@ bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::strin return device->WriteFail("Invalid partition name and size"); } + if (GetDeviceLockStatus()) { + return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices"); + } + PartitionBuilder builder(device); if (!builder.Valid()) { return device->WriteFail("Could not open super partition"); @@ -360,6 +395,10 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin return device->WriteFail("Invalid partition name and size"); } + if (GetDeviceLockStatus()) { + return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices"); + } + uint64_t partition_size; std::string partition_name = args[1]; if (!android::base::ParseUint(args[2].c_str(), &partition_size)) { @@ -388,6 +427,11 @@ bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& if (args.size() < 2) { return device->WriteFail("Invalid arguments"); } + + if (GetDeviceLockStatus()) { + return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices"); + } + bool wipe = (args.size() >= 3 && args[2] == "wipe"); return UpdateSuper(device, args[1], wipe); } diff --git a/fastboot/device/commands.h b/fastboot/device/commands.h index 4778d2350..9df43a90c 100644 --- a/fastboot/device/commands.h +++ b/fastboot/device/commands.h @@ -45,3 +45,4 @@ bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::strin bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args); bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args); bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args); +bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args); diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp index ae2e7a607..6862741b6 100644 --- a/fastboot/device/fastboot_device.cpp +++ b/fastboot/device/fastboot_device.cpp @@ -48,6 +48,7 @@ FastbootDevice::FastbootDevice() {FB_CMD_DELETE_PARTITION, DeletePartitionHandler}, {FB_CMD_RESIZE_PARTITION, ResizePartitionHandler}, {FB_CMD_UPDATE_SUPER, UpdateSuperHandler}, + {FB_CMD_OEM, OemCmdHandler}, }), transport_(std::make_unique<ClientUsbTransport>()), boot_control_hal_(IBootControl::getService()), @@ -120,10 +121,20 @@ void FastbootDevice::ExecuteCommands() { command[bytes_read] = '\0'; LOG(INFO) << "Fastboot command: " << command; - auto args = android::base::Split(command, ":"); - auto found_command = kCommandMap.find(args[0]); + + std::vector<std::string> args; + std::string cmd_name; + if (android::base::StartsWith(command, "oem ")) { + args = {command}; + cmd_name = "oem"; + } else { + args = android::base::Split(command, ":"); + cmd_name = args[0]; + } + + auto found_command = kCommandMap.find(cmd_name); if (found_command == kCommandMap.end()) { - WriteStatus(FastbootResult::FAIL, "Unrecognized command"); + WriteStatus(FastbootResult::FAIL, "Unrecognized command " + args[0]); continue; } if (!found_command->second(this, args)) { diff --git a/fastboot/device/utility.cpp b/fastboot/device/utility.cpp index 261a2026c..02f6f2ca8 100644 --- a/fastboot/device/utility.cpp +++ b/fastboot/device/utility.cpp @@ -21,6 +21,7 @@ #include <sys/types.h> #include <unistd.h> +#include <android-base/file.h> #include <android-base/logging.h> #include <fs_mgr_dm_linear.h> #include <liblp/liblp.h> @@ -159,3 +160,9 @@ std::vector<std::string> ListPartitions(FastbootDevice* device) { } return partitions; } + +bool GetDeviceLockStatus() { + std::string cmdline; + android::base::ReadFileToString("/proc/cmdline", &cmdline); + return cmdline.find("androidboot.verifiedbootstate=orange") == std::string::npos; +} diff --git a/fastboot/device/utility.h b/fastboot/device/utility.h index 4f0d0791e..bb08f726b 100644 --- a/fastboot/device/utility.h +++ b/fastboot/device/utility.h @@ -58,3 +58,4 @@ bool LogicalPartitionExists(const std::string& name, const std::string& slot_suf bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle); bool GetSlotNumber(const std::string& slot, android::hardware::boot::V1_0::Slot* number); std::vector<std::string> ListPartitions(FastbootDevice* device); +bool GetDeviceLockStatus(); diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp index 75352489e..002e04349 100644 --- a/fastboot/device/variables.cpp +++ b/fastboot/device/variables.cpp @@ -148,7 +148,7 @@ bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::str bool GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */, std::string* message) { - *message = "yes"; + *message = GetDeviceLockStatus() ? "no" : "yes"; return true; } diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp index 0ac57afc5..a43e7a6bb 100644 --- a/fastboot/engine.cpp +++ b/fastboot/engine.cpp @@ -103,9 +103,9 @@ void fb_flash_fd(const std::string& partition, int fd, uint32_t sz) { RUN_COMMAND(fb->Flash(partition)); } -void fb_flash(const std::string& partition, void* data, uint32_t sz) { - Status(StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024)); - RUN_COMMAND(fb->Download(static_cast<char*>(data), sz)); +void fb_flash(const std::string& partition, const std::vector<char>& data) { + Status(StringPrintf("Sending '%s' (%zu KB)", partition.c_str(), data.size() / 1024)); + RUN_COMMAND(fb->Download(data)); Status("Writing '" + partition + "'"); RUN_COMMAND(fb->Flash(partition)); @@ -136,69 +136,6 @@ void fb_resize_partition(const std::string& partition, const std::string& size) RUN_COMMAND(fb->RawCommand(FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size)); } -static int match(const char* str, const char** value, unsigned count) { - unsigned n; - - for (n = 0; n < count; n++) { - const char *val = value[n]; - int len = strlen(val); - int match; - - if ((len > 1) && (val[len-1] == '*')) { - len--; - match = !strncmp(val, str, len); - } else { - match = !strcmp(val, str); - } - - if (match) return 1; - } - - return 0; -} - -void fb_require(const std::string& product, const std::string& var, bool invert, size_t count, - const char** values) { - Status("Checking '" + var + "'"); - - double start = now(); - - std::string var_value; - auto status = fb->GetVar(var, &var_value); - - if (status) { - fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str()); - die("requirements not met!"); - } - - if (!product.empty()) { - if (product != cur_product) { - double split = now(); - fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n", cur_product, - product.c_str(), (split - start)); - return; - } - } - - int yes = match(var_value.c_str(), values, count); - if (invert) yes = !yes; - - if (yes) { - double split = now(); - fprintf(stderr, "OKAY [%7.3fs]\n", (split - start)); - return; - } - - fprintf(stderr, "FAILED\n\n"); - fprintf(stderr, "Device %s is '%s'.\n", var.c_str(), var_value.c_str()); - fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", values[0]); - for (size_t n = 1; n < count; n++) { - fprintf(stderr, " or '%s'", values[n]); - } - fprintf(stderr, ".\n\n"); - die("requirements not met!"); -} - void fb_display(const std::string& label, const std::string& var) { std::string value; auto status = fb->GetVar(var, &value); @@ -210,18 +147,6 @@ void fb_display(const std::string& label, const std::string& var) { fprintf(stderr, "%s: %s\n", label.c_str(), value.c_str()); } -void fb_query_save(const std::string& var, char* dest, uint32_t dest_size) { - std::string value; - auto status = fb->GetVar(var, &value); - - if (status) { - fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str()); - return; - } - - strncpy(dest, value.c_str(), dest_size); -} - void fb_reboot() { fprintf(stderr, "Rebooting"); fb->Reboot(); @@ -233,9 +158,9 @@ void fb_command(const std::string& cmd, const std::string& msg) { RUN_COMMAND(fb->RawCommand(cmd)); } -void fb_download(const std::string& name, void* data, uint32_t size) { +void fb_download(const std::string& name, const std::vector<char>& data) { Status("Downloading '" + name + "'"); - RUN_COMMAND(fb->Download(static_cast<char*>(data), size)); + RUN_COMMAND(fb->Download(data)); } void fb_download_fd(const std::string& name, int fd, uint32_t sz) { diff --git a/fastboot/engine.h b/fastboot/engine.h index d78cb1380..b681f5ab3 100644 --- a/fastboot/engine.h +++ b/fastboot/engine.h @@ -48,18 +48,15 @@ void fb_init(fastboot::FastBootDriver& fbi); void fb_reinit(Transport* transport); bool fb_getvar(const std::string& key, std::string* value); -void fb_flash(const std::string& partition, void* data, uint32_t sz); +void fb_flash(const std::string& partition, const std::vector<char>& data); void fb_flash_fd(const std::string& partition, int fd, uint32_t sz); void fb_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz, size_t current, size_t total); void fb_erase(const std::string& partition); -void fb_require(const std::string& prod, const std::string& var, bool invert, size_t nvalues, - const char** values); void fb_display(const std::string& label, const std::string& var); -void fb_query_save(const std::string& var, char* dest, uint32_t dest_size); void fb_reboot(); void fb_command(const std::string& cmd, const std::string& msg); -void fb_download(const std::string& name, void* data, uint32_t size); +void fb_download(const std::string& name, const std::vector<char>& data); void fb_download_fd(const std::string& name, int fd, uint32_t sz); void fb_upload(const std::string& outfile); void fb_notice(const std::string& notice); diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 8e6c125c2..5173babeb 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -43,6 +43,7 @@ #include <chrono> #include <functional> +#include <regex> #include <thread> #include <utility> #include <vector> @@ -69,14 +70,15 @@ #include "udp.h" #include "usb.h" +using android::base::ReadFully; +using android::base::Split; +using android::base::Trim; using android::base::unique_fd; #ifndef O_BINARY #define O_BINARY 0 #endif -char cur_product[FB_RESPONSE_SZ + 1]; - static const char* serial = nullptr; static bool g_long_listing = false; @@ -179,38 +181,22 @@ static std::string find_item(const std::string& item) { static int64_t get_file_size(int fd) { struct stat sb; - return fstat(fd, &sb) == -1 ? -1 : sb.st_size; + if (fstat(fd, &sb) == -1) { + die("could not get file size"); + } + return sb.st_size; } -static void* load_fd(int fd, int64_t* sz) { - int errno_tmp; - char* data = nullptr; +bool ReadFileToVector(const std::string& file, std::vector<char>* out) { + out->clear(); - *sz = get_file_size(fd); - if (*sz < 0) { - goto oops; + unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY))); + if (fd == -1) { + return false; } - data = (char*) malloc(*sz); - if (data == nullptr) goto oops; - - if(read(fd, data, *sz) != *sz) goto oops; - close(fd); - - return data; - -oops: - errno_tmp = errno; - close(fd); - if(data != 0) free(data); - errno = errno_tmp; - return 0; -} - -static void* load_file(const std::string& path, int64_t* sz) { - int fd = open(path.c_str(), O_RDONLY | O_BINARY); - if (fd == -1) return nullptr; - return load_fd(fd, sz); + out->resize(get_file_size(fd)); + return ReadFully(fd, out->data(), out->size()); } static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) { @@ -418,70 +404,71 @@ static int show_help() { return 0; } -static void* load_bootable_image(const std::string& kernel, const std::string& ramdisk, - const std::string& second_stage, int64_t* sz) { - int64_t ksize; - void* kdata = load_file(kernel.c_str(), &ksize); - if (kdata == nullptr) die("cannot load '%s': %s", kernel.c_str(), strerror(errno)); +static std::vector<char> LoadBootableImage(const std::string& kernel, const std::string& ramdisk, + const std::string& second_stage) { + std::vector<char> kernel_data; + if (!ReadFileToVector(kernel, &kernel_data)) { + die("cannot load '%s': %s", kernel.c_str(), strerror(errno)); + } // Is this actually a boot image? - if (ksize < static_cast<int64_t>(sizeof(boot_img_hdr_v1))) { + if (kernel_data.size() < sizeof(boot_img_hdr_v1)) { die("cannot load '%s': too short", kernel.c_str()); } - if (!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { + if (!memcmp(kernel_data.data(), BOOT_MAGIC, BOOT_MAGIC_SIZE)) { if (!g_cmdline.empty()) { - bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), g_cmdline); + bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kernel_data.data()), g_cmdline); } if (!ramdisk.empty()) die("cannot boot a boot.img *and* ramdisk"); - *sz = ksize; - return kdata; + return kernel_data; } - void* rdata = nullptr; - int64_t rsize = 0; + std::vector<char> ramdisk_data; if (!ramdisk.empty()) { - rdata = load_file(ramdisk.c_str(), &rsize); - if (rdata == nullptr) die("cannot load '%s': %s", ramdisk.c_str(), strerror(errno)); + if (!ReadFileToVector(ramdisk, &ramdisk_data)) { + die("cannot load '%s': %s", ramdisk.c_str(), strerror(errno)); + } } - void* sdata = nullptr; - int64_t ssize = 0; + std::vector<char> second_stage_data; if (!second_stage.empty()) { - sdata = load_file(second_stage.c_str(), &ssize); - if (sdata == nullptr) die("cannot load '%s': %s", second_stage.c_str(), strerror(errno)); + if (!ReadFileToVector(second_stage, &second_stage_data)) { + die("cannot load '%s': %s", second_stage.c_str(), strerror(errno)); + } } - fprintf(stderr,"creating boot image...\n"); - boot_img_hdr_v1* bdata = mkbootimg(kdata, ksize, rdata, rsize, sdata, ssize, - g_base_addr, g_boot_img_hdr, sz); - if (bdata == nullptr) die("failed to create boot.img"); - if (!g_cmdline.empty()) bootimg_set_cmdline(bdata, g_cmdline); - fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", *sz); + std::vector<char> out; + boot_img_hdr_v1* boot_image_data = mkbootimg(kernel_data, ramdisk_data, second_stage_data, + g_base_addr, g_boot_img_hdr, &out); + + if (!g_cmdline.empty()) bootimg_set_cmdline(boot_image_data, g_cmdline); + fprintf(stderr, "creating boot image - %zu bytes\n", out.size()); - return bdata; + return out; } -static void* unzip_to_memory(ZipArchiveHandle zip, const char* entry_name, int64_t* sz) { - ZipString zip_entry_name(entry_name); +static bool UnzipToMemory(ZipArchiveHandle zip, const std::string& entry_name, + std::vector<char>* out) { + ZipString zip_entry_name(entry_name.c_str()); ZipEntry zip_entry; if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) { - fprintf(stderr, "archive does not contain '%s'\n", entry_name); - return nullptr; + fprintf(stderr, "archive does not contain '%s'\n", entry_name.c_str()); + return false; } - *sz = zip_entry.uncompressed_length; + out->resize(zip_entry.uncompressed_length); - fprintf(stderr, "extracting %s (%" PRId64 " MB) to RAM...\n", entry_name, *sz / 1024 / 1024); - uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length)); - if (data == nullptr) die("failed to allocate %" PRId64 " bytes for '%s'", *sz, entry_name); + fprintf(stderr, "extracting %s (%zu MB) to RAM...\n", entry_name.c_str(), + out->size() / 1024 / 1024); - int error = ExtractToMemory(zip, &zip_entry, data, zip_entry.uncompressed_length); - if (error != 0) die("failed to extract '%s': %s", entry_name, ErrorCodeString(error)); + int error = ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()), + out->size()); + if (error != 0) die("failed to extract '%s': %s", entry_name.c_str(), ErrorCodeString(error)); - return data; + return true; } #if defined(_WIN32) @@ -602,109 +589,145 @@ static int unzip_to_file(ZipArchiveHandle zip, const char* entry_name) { return fd.release(); } -static char* strip(char* s) { - while (*s && isspace(*s)) s++; +static void CheckRequirement(const std::string& cur_product, const std::string& var, + const std::string& product, bool invert, + const std::vector<std::string>& options) { + Status("Checking '" + var + "'"); - int n = strlen(s); - while (n-- > 0) { - if (!isspace(s[n])) break; - s[n] = 0; + double start = now(); + + if (!product.empty()) { + if (product != cur_product) { + double split = now(); + fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n", + cur_product.c_str(), product.c_str(), (split - start)); + return; + } + } + + std::string var_value; + if (!fb_getvar(var, &var_value)) { + fprintf(stderr, "FAILED\n\n"); + fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(), fb_get_error().c_str()); + die("requirements not met!"); + } + + bool match = false; + for (const auto& option : options) { + if (option == var_value || (option.back() == '*' && + !var_value.compare(0, option.length() - 1, option, 0, + option.length() - 1))) { + match = true; + break; + } + } + + if (invert) { + match = !match; } - return s; -} -#define MAX_OPTIONS 32 -static void check_requirement(char* line) { - char *val[MAX_OPTIONS]; - unsigned count; - char *x; - int invert = 0; + if (match) { + double split = now(); + fprintf(stderr, "OKAY [%7.3fs]\n", (split - start)); + return; + } + + fprintf(stderr, "FAILED\n\n"); + fprintf(stderr, "Device %s is '%s'.\n", var.c_str(), var_value.c_str()); + fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", options[0].c_str()); + for (auto it = std::next(options.begin()); it != options.end(); ++it) { + fprintf(stderr, " or '%s'", it->c_str()); + } + fprintf(stderr, ".\n\n"); + die("requirements not met!"); +} +bool ParseRequirementLine(const std::string& line, std::string* name, std::string* product, + bool* invert, std::vector<std::string>* options) { // "require product=alpha|beta|gamma" // "require version-bootloader=1234" // "require-for-product:gamma version-bootloader=istanbul|constantinople" // "require partition-exists=vendor" + *product = ""; + *invert = false; + + auto require_reject_regex = std::regex{"(require\\s+|reject\\s+)?\\s*(\\S+)\\s*=\\s*(.*)"}; + auto require_product_regex = + std::regex{"require-for-product:\\s*(\\S+)\\s+(\\S+)\\s*=\\s*(.*)"}; + std::smatch match_results; + + if (std::regex_match(line, match_results, require_reject_regex)) { + *invert = Trim(match_results[1]) == "reject"; + } else if (std::regex_match(line, match_results, require_product_regex)) { + *product = match_results[1]; + } else { + return false; + } - char* name = line; - const char* product = ""; - if (!strncmp(name, "reject ", 7)) { - name += 7; - invert = 1; - } else if (!strncmp(name, "require ", 8)) { - name += 8; - invert = 0; - } else if (!strncmp(name, "require-for-product:", 20)) { - // Get the product and point name past it - product = name + 20; - name = strchr(name, ' '); - if (!name) die("android-info.txt syntax error: %s", line); - *name = 0; - name += 1; - invert = 0; - } - - x = strchr(name, '='); - if (x == 0) return; - *x = 0; - val[0] = x + 1; - - name = strip(name); - - // "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` in the `images` array. - if (!strcmp(name, "partition-exists")) { - const char* partition_name = val[0]; - std::string has_slot; - if (!fb_getvar(std::string("has-slot:") + partition_name, &has_slot) || - (has_slot != "yes" && has_slot != "no")) { - die("device doesn't have required partition %s!", partition_name); - } - bool known_partition = false; - 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; - known_partition = true; - } - } - if (!known_partition) { - die("device requires partition %s which is not known to this version of fastboot", - partition_name); - } - return; + *name = match_results[2]; + // Work around an unfortunate name mismatch. + if (*name == "board") { + *name = "product"; } - for(count = 1; count < MAX_OPTIONS; count++) { - x = strchr(val[count - 1],'|'); - if (x == 0) break; - *x = 0; - val[count] = x + 1; + auto raw_options = Split(match_results[3], "|"); + for (const auto& option : raw_options) { + auto trimmed_option = Trim(option); + options->emplace_back(trimmed_option); } - // Work around an unfortunate name mismatch. - const char* var = name; - if (!strcmp(name, "board")) var = "product"; + return true; +} - const char** out = reinterpret_cast<const char**>(malloc(sizeof(char*) * count)); - if (out == nullptr) die("out of memory"); +// "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` in the `images` array. +static void HandlePartitionExists(const std::vector<std::string>& options) { + const std::string& partition_name = options[0]; + std::string has_slot; + if (!fb_getvar("has-slot:" + partition_name, &has_slot) || + (has_slot != "yes" && has_slot != "no")) { + die("device doesn't have required partition %s!", partition_name.c_str()); + } + bool known_partition = false; + for (size_t i = 0; i < arraysize(images); ++i) { + if (images[i].nickname && images[i].nickname == partition_name) { + images[i].optional_if_no_image = false; + known_partition = true; + } + } + if (!known_partition) { + die("device requires partition %s which is not known to this version of fastboot", + partition_name.c_str()); + } +} - for (size_t i = 0; i < count; ++i) { - out[i] = xstrdup(strip(val[i])); +static void CheckRequirements(const std::string& data) { + std::string cur_product; + if (!fb_getvar("product", &cur_product)) { + fprintf(stderr, "getvar:product FAILED (%s)\n", fb_get_error().c_str()); } - fb_require(product, var, invert, count, out); -} + auto lines = Split(data, "\n"); + for (const auto& line : lines) { + if (line.empty()) { + continue; + } -static void check_requirements(char* data, int64_t sz) { - char* s = data; - while (sz-- > 0) { - if (*s == '\n') { - *s++ = 0; - check_requirement(data); - data = s; + std::string name; + std::string product; + bool invert; + std::vector<std::string> options; + + if (!ParseRequirementLine(line, &name, &product, &invert, &options)) { + fprintf(stderr, "android-info.txt syntax error: %s\n", line.c_str()); + continue; + } + if (name == "partition-exists") { + HandlePartitionExists(options); } else { - s++; + CheckRequirement(cur_product, name, product, invert, options); } } } @@ -1097,7 +1120,7 @@ static void reboot_to_userspace_fastboot() { class ImageSource { public: - virtual void* ReadFile(const std::string& name, int64_t* size) const = 0; + virtual bool ReadFile(const std::string& name, std::vector<char>* out) const = 0; virtual int OpenFile(const std::string& name) const = 0; }; @@ -1166,12 +1189,11 @@ void FlashAllTool::Flash() { } void FlashAllTool::CheckRequirements() { - int64_t sz; - void* data = source_.ReadFile("android-info.txt", &sz); - if (data == nullptr) { + std::vector<char> contents; + if (!source_.ReadFile("android-info.txt", &contents)) { die("could not read android-info.txt"); } - check_requirements(reinterpret_cast<char*>(data), sz); + ::CheckRequirements({contents.data(), contents.size()}); } void FlashAllTool::DetermineSecondarySlot() { @@ -1224,10 +1246,9 @@ void FlashAllTool::FlashImages(const std::vector<std::pair<const Image*, std::st void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf) { auto flash = [&, this](const std::string& partition_name) { - int64_t sz; - void* data = source_.ReadFile(image.sig_name, &sz); - if (data) { - fb_download("signature", data, sz); + std::vector<char> signature_data; + if (source_.ReadFile(image.sig_name, &signature_data)) { + fb_download("signature", signature_data); fb_command("signature", "installing signature"); } @@ -1263,15 +1284,15 @@ void FlashAllTool::UpdateSuperPartition() { class ZipImageSource final : public ImageSource { public: explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {} - void* ReadFile(const std::string& name, int64_t* size) const override; + bool ReadFile(const std::string& name, std::vector<char>* out) const override; int OpenFile(const std::string& name) const override; private: ZipArchiveHandle zip_; }; -void* ZipImageSource::ReadFile(const std::string& name, int64_t* size) const { - return unzip_to_memory(zip_, name.c_str(), size); +bool ZipImageSource::ReadFile(const std::string& name, std::vector<char>* out) const { + return UnzipToMemory(zip_, name, out); } int ZipImageSource::OpenFile(const std::string& name) const { @@ -1281,8 +1302,6 @@ int ZipImageSource::OpenFile(const std::string& name) const { static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary) { dump_info(); - fb_query_save("product", cur_product, sizeof(cur_product)); - ZipArchiveHandle zip; int error = OpenArchive(filename, &zip); if (error != 0) { @@ -1297,16 +1316,16 @@ static void do_update(const char* filename, const std::string& slot_override, bo class LocalImageSource final : public ImageSource { public: - void* ReadFile(const std::string& name, int64_t* size) const override; + bool ReadFile(const std::string& name, std::vector<char>* out) const override; int OpenFile(const std::string& name) const override; }; -void* LocalImageSource::ReadFile(const std::string& name, int64_t* size) const { +bool LocalImageSource::ReadFile(const std::string& name, std::vector<char>* out) const { auto path = find_item_given_name(name); if (path.empty()) { - return nullptr; + return false; } - return load_file(path.c_str(), size); + return ReadFileToVector(path, out); } int LocalImageSource::OpenFile(const std::string& name) const { @@ -1318,8 +1337,6 @@ static void do_flashall(const std::string& slot_override, bool skip_secondary, b std::string fname; dump_info(); - fb_query_save("product", cur_product, sizeof(cur_product)); - FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe); tool.Flash(); } @@ -1473,8 +1490,6 @@ int FastBootTool::Main(int argc, char* argv[]) { bool wants_set_active = false; bool skip_secondary = false; bool set_fbe_marker = false; - void *data; - int64_t sz; int longindex; std::string slot_override; std::string next_active; @@ -1678,10 +1693,12 @@ int FastBootTool::Main(int argc, char* argv[]) { do_for_partitions(partition.c_str(), slot_override, format, true); } else if (command == "signature") { std::string filename = next_arg(&args); - data = load_file(filename.c_str(), &sz); - if (data == nullptr) die("could not load '%s': %s", filename.c_str(), strerror(errno)); - if (sz != 256) die("signature must be 256 bytes (got %" PRId64 ")", sz); - fb_download("signature", data, sz); + std::vector<char> data; + if (!ReadFileToVector(filename, &data)) { + die("could not load '%s': %s", filename.c_str(), strerror(errno)); + } + if (data.size() != 256) die("signature must be 256 bytes (got %zu)", data.size()); + fb_download("signature", data); fb_command("signature", "installing signature"); } else if (command == "reboot") { wants_reboot = true; @@ -1718,8 +1735,8 @@ int FastBootTool::Main(int argc, char* argv[]) { std::string second_stage; if (!args.empty()) second_stage = next_arg(&args); - data = load_bootable_image(kernel, ramdisk, second_stage, &sz); - fb_download("boot.img", data, sz); + auto data = LoadBootableImage(kernel, ramdisk, second_stage); + fb_download("boot.img", data); fb_command("boot", "booting"); } else if (command == "flash") { std::string pname = next_arg(&args); @@ -1744,9 +1761,9 @@ int FastBootTool::Main(int argc, char* argv[]) { std::string second_stage; if (!args.empty()) second_stage = next_arg(&args); - data = load_bootable_image(kernel, ramdisk, second_stage, &sz); - auto flashraw = [&](const std::string& partition) { - fb_flash(partition, data, sz); + auto data = LoadBootableImage(kernel, ramdisk, second_stage); + auto flashraw = [&data](const std::string& partition) { + fb_flash(partition, data); }; do_for_partitions(partition, slot_override, flashraw, true); } else if (command == "flashall") { diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp index 4a14131a7..72ba6194b 100644 --- a/fastboot/fastboot_driver.cpp +++ b/fastboot/fastboot_driver.cpp @@ -147,28 +147,6 @@ RetCode FastBootDriver::Partitions(std::vector<std::tuple<std::string, uint64_t> return SUCCESS; } -RetCode FastBootDriver::Require(const std::string& var, const std::vector<std::string>& allowed, - bool* reqmet, bool invert) { - *reqmet = invert; - RetCode ret; - std::string response; - if ((ret = GetVar(var, &response))) { - return ret; - } - - // Now check if we have a match - for (const auto s : allowed) { - // If it ends in *, and starting substring match - if (response == s || (s.length() && s.back() == '*' && - !response.compare(0, s.length() - 1, s, 0, s.length() - 1))) { - *reqmet = !invert; - break; - } - } - - return SUCCESS; -} - RetCode FastBootDriver::Download(int fd, size_t size, std::string* response, std::vector<std::string>* info) { RetCode ret; @@ -194,24 +172,19 @@ RetCode FastBootDriver::Download(int fd, size_t size, std::string* response, RetCode FastBootDriver::Download(const std::vector<char>& buf, std::string* response, std::vector<std::string>* info) { - return Download(buf.data(), buf.size(), response, info); -} - -RetCode FastBootDriver::Download(const char* buf, uint32_t size, std::string* response, - std::vector<std::string>* info) { RetCode ret; error_ = ""; - if ((size == 0 || size > MAX_DOWNLOAD_SIZE) && !disable_checks_) { + if ((buf.size() == 0 || buf.size() > MAX_DOWNLOAD_SIZE) && !disable_checks_) { error_ = "Buffer is too large or 0 bytes"; return BAD_ARG; } - if ((ret = DownloadCommand(size, response, info))) { + if ((ret = DownloadCommand(buf.size(), response, info))) { return ret; } // Write the buffer - if ((ret = SendBuffer(buf, size))) { + if ((ret = SendBuffer(buf))) { return ret; } diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h index 4d85ba05e..2d45085fd 100644 --- a/fastboot/fastboot_driver.h +++ b/fastboot/fastboot_driver.h @@ -74,9 +74,6 @@ class FastBootDriver { std::vector<std::string>* info = nullptr); RetCode Download(const std::vector<char>& buf, std::string* response = nullptr, std::vector<std::string>* info = nullptr); - // This will be removed after fastboot is modified to use a vector - RetCode Download(const char* buf, uint32_t size, std::string* response = nullptr, - std::vector<std::string>* info = nullptr); RetCode Download(sparse_file* s, bool use_crc = false, std::string* response = nullptr, std::vector<std::string>* info = nullptr); RetCode Erase(const std::string& part, std::string* response = nullptr, diff --git a/fastboot/fastboot_test.cpp b/fastboot/fastboot_test.cpp index 43201face..e0bbd561f 100644 --- a/fastboot/fastboot_test.cpp +++ b/fastboot/fastboot_test.cpp @@ -59,3 +59,145 @@ TEST(FastBoot, ParseOsVersion) { EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.128.3"), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.2.128"), "bad OS version"); } + +extern bool ParseRequirementLine(const std::string& line, std::string* name, std::string* product, + bool* invert, std::vector<std::string>* options); + +static void ParseRequirementLineTest(const std::string& line, const std::string& expected_name, + const std::string& expected_product, bool expected_invert, + const std::vector<std::string>& expected_options) { + std::string name; + std::string product; + bool invert; + std::vector<std::string> options; + + EXPECT_TRUE(ParseRequirementLine(line, &name, &product, &invert, &options)) << line; + + EXPECT_EQ(expected_name, name) << line; + EXPECT_EQ(expected_product, product) << line; + EXPECT_EQ(expected_invert, invert) << line; + EXPECT_EQ(expected_options, options) << line; +} + +TEST(FastBoot, ParseRequirementLineSuccesses) { + // Examples provided in the code + slight variations. + ParseRequirementLineTest("require product=alpha", "product", "", false, {"alpha"}); + ParseRequirementLineTest("require product=alpha|beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require version-bootloader=1234", "version-bootloader", "", false, + {"1234"}); + ParseRequirementLineTest("require-for-product:gamma version-bootloader=istanbul", + "version-bootloader", "gamma", false, {"istanbul"}); + ParseRequirementLineTest("require-for-product:gamma version-bootloader=istanbul|constantinople", + "version-bootloader", "gamma", false, {"istanbul", "constantinople"}); + ParseRequirementLineTest("require partition-exists=vendor", "partition-exists", "", false, + {"vendor"}); + ParseRequirementLineTest("reject product=alpha", "product", "", true, {"alpha"}); + ParseRequirementLineTest("reject product=alpha|beta|gamma", "product", "", true, + {"alpha", "beta", "gamma"}); + + // Without any prefix, assume 'require' + ParseRequirementLineTest("product=alpha|beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + // Including if the variable name is otherwise a prefix keyword + ParseRequirementLineTest("require = alpha", "require", "", false, {"alpha"}); + ParseRequirementLineTest("reject = alpha", "reject", "", false, {"alpha"}); + ParseRequirementLineTest("require-for-product:gamma = alpha", "require-for-product:gamma", "", + false, {"alpha"}); + + // Extra spaces are allowed. + ParseRequirementLineTest("require product=alpha|beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require product =alpha|beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require product= alpha|beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require product = alpha|beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require product=alpha |beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require product=alpha| beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require product=alpha | beta|gamma", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require product=alpha|beta|gamma ", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("product = alpha | beta | gamma ", "product", "", false, + {"alpha", "beta", "gamma"}); + ParseRequirementLineTest("require-for-product: gamma version-bootloader=istanbul", + "version-bootloader", "gamma", false, {"istanbul"}); + + // Extraneous ending | is okay, implies accepting an empty string. + ParseRequirementLineTest("require product=alpha|", "product", "", false, {"alpha", ""}); + ParseRequirementLineTest("require product=alpha|beta|gamma|", "product", "", false, + {"alpha", "beta", "gamma", ""}); + + // Accept empty options, double ||, etc, implies accepting an empty string. + ParseRequirementLineTest("require product=alpha||beta| |gamma", "product", "", false, + {"alpha", "", "beta", "", "gamma"}); + ParseRequirementLineTest("require product=alpha||beta|gamma", "product", "", false, + {"alpha", "", "beta", "gamma"}); + ParseRequirementLineTest("require product=alpha|beta| |gamma", "product", "", false, + {"alpha", "beta", "", "gamma"}); + ParseRequirementLineTest("require product=alpha||", "product", "", false, {"alpha", "", ""}); + ParseRequirementLineTest("require product=alpha|| ", "product", "", false, {"alpha", "", ""}); + ParseRequirementLineTest("require product=alpha| ", "product", "", false, {"alpha", ""}); + ParseRequirementLineTest("require product=alpha|beta| ", "product", "", false, + {"alpha", "beta", ""}); + + // No option string is also treating as accepting an empty string. + ParseRequirementLineTest("require =", "require", "", false, {""}); + ParseRequirementLineTest("require = |", "require", "", false, {"", ""}); + ParseRequirementLineTest("reject =", "reject", "", false, {""}); + ParseRequirementLineTest("reject = |", "reject", "", false, {"", ""}); + ParseRequirementLineTest("require-for-product: =", "require-for-product:", "", false, {""}); + ParseRequirementLineTest("require-for-product: = | ", "require-for-product:", "", false, + {"", ""}); + ParseRequirementLineTest("require product=", "product", "", false, {""}); + ParseRequirementLineTest("require product = ", "product", "", false, {""}); + ParseRequirementLineTest("require product = | ", "product", "", false, {"", ""}); + ParseRequirementLineTest("reject product=", "product", "", true, {""}); + ParseRequirementLineTest("reject product = ", "product", "", true, {""}); + ParseRequirementLineTest("reject product = | ", "product", "", true, {"", ""}); + ParseRequirementLineTest("require-for-product:gamma product=", "product", "gamma", false, {""}); + ParseRequirementLineTest("require-for-product:gamma product = ", "product", "gamma", false, + {""}); + ParseRequirementLineTest("require-for-product:gamma product = |", "product", "gamma", false, + {"", ""}); + + // Check for board -> product substitution. + ParseRequirementLineTest("require board=alpha", "product", "", false, {"alpha"}); + ParseRequirementLineTest("board=alpha", "product", "", false, {"alpha"}); +} + +static void ParseRequirementLineTestMalformed(const std::string& line) { + std::string name; + std::string product; + bool invert; + std::vector<std::string> options; + + EXPECT_FALSE(ParseRequirementLine(line, &name, &product, &invert, &options)) << line; +} + +TEST(FastBoot, ParseRequirementLineMalformed) { + ParseRequirementLineTestMalformed("nothing"); + ParseRequirementLineTestMalformed(""); + ParseRequirementLineTestMalformed("="); + ParseRequirementLineTestMalformed("|"); + + ParseRequirementLineTestMalformed("require"); + ParseRequirementLineTestMalformed("require "); + ParseRequirementLineTestMalformed("reject"); + ParseRequirementLineTestMalformed("reject "); + ParseRequirementLineTestMalformed("require-for-product:"); + ParseRequirementLineTestMalformed("require-for-product: "); + + ParseRequirementLineTestMalformed("require product"); + ParseRequirementLineTestMalformed("reject product"); + + ParseRequirementLineTestMalformed("require-for-product:gamma"); + ParseRequirementLineTestMalformed("require-for-product:gamma product"); + + // No spaces allowed before between require-for-product and :. + ParseRequirementLineTestMalformed("require-for-product :"); +} diff --git a/fastboot/util.cpp b/fastboot/util.cpp index 125182d73..7d15047ff 100644 --- a/fastboot/util.cpp +++ b/fastboot/util.cpp @@ -74,9 +74,3 @@ void Status(const std::string& message) { static constexpr char kStatusFormat[] = "%-50s "; fprintf(stderr, kStatusFormat, message.c_str()); } - -char* xstrdup(const char* s) { - char* result = strdup(s); - if (!result) die("out of memory"); - return result; -} diff --git a/fastboot/util.h b/fastboot/util.h index 20be46167..533d2c708 100644 --- a/fastboot/util.h +++ b/fastboot/util.h @@ -9,7 +9,6 @@ /* util stuff */ double now(); -char* xstrdup(const char*); void set_verbose(); void Status(const std::string& message); diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index f56043cd5..d29ccf438 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -569,8 +569,7 @@ static int fs_match(const char *in1, const char *in2) * -1 on failure with errno set to match the 1st mount failure. * 0 on success. */ -static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_idx, int *attempted_idx) -{ +static int mount_with_alternatives(fstab* fstab, int start_idx, int* end_idx, int* attempted_idx) { int i; int mount_errno = 0; int mounted = 0; @@ -805,6 +804,23 @@ static bool call_vdc(const std::vector<std::string>& args) { 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,19 +839,37 @@ bool fs_mgr_update_logical_partition(struct fstab_rec* rec) { 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. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ -int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) -{ +int fs_mgr_mount_all(fstab* fstab, int mount_mode) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; + int need_checkpoint = -1; FsManagerAvbUniquePtr avb_handle(nullptr); if (!fstab) { @@ -882,6 +916,18 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } } + 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"; @@ -1045,7 +1091,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } #if ALLOW_ADBD_DISABLE_VERITY == 1 // "userdebug" build - fs_mgr_overlayfs_mount_all(); + fs_mgr_overlayfs_mount_all(fstab); #endif if (error_count) { @@ -1081,9 +1127,8 @@ int fs_mgr_do_mount_one(struct fstab_rec *rec) * 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(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 +1161,18 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, } } + 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 +1242,15 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, return FS_MGR_DOMNT_FAILED; } +int fs_mgr_do_mount(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(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. @@ -1207,8 +1273,7 @@ int fs_mgr_do_tmpfs_mount(const char *n_name) /* This must be called after mount_all, because the mkswap command needs to be * available. */ -int fs_mgr_swapon_all(struct fstab *fstab) -{ +int fs_mgr_swapon_all(fstab* fstab) { int i = 0; int flags = 0; int err = 0; @@ -1298,7 +1363,7 @@ int fs_mgr_swapon_all(struct fstab *fstab) return ret; } -struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab) { +struct fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab) { int i; if (!fstab) { @@ -1322,7 +1387,7 @@ struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab) { * * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long */ -void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size) { +void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size) { struct fstab_rec const* rec = fs_mgr_get_crypt_entry(fstab); if (key_loc) { if (rec) { diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index f87a3b148..250793abf 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -80,37 +80,39 @@ static struct flag_list mount_flags[] = { }; 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_has_sysfs_path(const struct fstab_rec *fstab) 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 720dcfda6..7fe21b645 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -49,7 +49,7 @@ using namespace std::literals; #if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs -bool fs_mgr_overlayfs_mount_all() { +bool fs_mgr_overlayfs_mount_all(const fstab*) { return false; } @@ -109,9 +109,9 @@ bool fs_mgr_filesystem_has_space(const char* mount_point) { 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 @@ bool fs_mgr_overlayfs_enabled(const struct fstab_rec* fsrec) { !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 @@ std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) { 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) { @@ -192,6 +194,31 @@ bool fs_mgr_wants_overlayfs() { return overlayfs_in_kernel; } +bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point) { + std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab("/proc/mounts"), + fs_mgr_free_fstab); + if (!fstab) return false; + 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; + if (!fs_type) continue; + if (("overlay"s != fs_type) && ("overlayfs"s != fs_type)) continue; + auto fsrec_mount_point = fsrec->mount_point; + if (!fsrec_mount_point) continue; + if (mount_point != fsrec_mount_point) continue; + const auto fs_options = fsrec->fs_options; + if (!fs_options) continue; + const auto options = android::base::Split(fs_options, ","); + for (const auto& opt : options) { + if (opt == lowerdir) { + return true; + } + } + } + return false; +} + bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) { if (!fsrec) return false; @@ -233,7 +260,7 @@ bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr) { errno = save_errno; return true; } - PERROR << "overlayfs open " << path; + PERROR << "opendir " << path; return false; } dirent* entry; @@ -251,7 +278,7 @@ bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr) { if (change) *change = true; } else { ret = false; - PERROR << "overlayfs rmdir " << file; + PERROR << "rmdir " << file; } continue; } @@ -259,39 +286,39 @@ bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr) { if (change) *change = true; } else { ret = false; - PERROR << "overlayfs rm " << file; + PERROR << "rm " << file; } } 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 << "setfscreatecon " << kOverlayfsFileContext; } auto save_errno = errno; if (!mkdir(fsrec_mount_point.c_str(), 0755)) { if (change) *change = true; } else if (errno != EEXIST) { ret = false; - PERROR << "overlayfs mkdir " << fsrec_mount_point; + PERROR << "mkdir " << fsrec_mount_point; } else { errno = save_errno; } 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 << "mkdir " << fsrec_mount_point << kWorkName; } else { errno = save_errno; } @@ -300,15 +327,15 @@ bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& m auto new_context = fs_mgr_get_context(mount_point); if (!new_context.empty() && setfscreatecon(new_context.c_str())) { ret = false; - PERROR << "overlayfs setfscreatecon " << new_context; + PERROR << "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; } else if (errno != EEXIST) { ret = false; - PERROR << "overlayfs mkdir " << upper; + PERROR << "mkdir " << upper; } else { errno = save_errno; } @@ -325,7 +352,7 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) { 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; } @@ -343,31 +370,6 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) { } } -bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point) { - 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; - for (auto i = 0; i < fstab->num_entries; ++i) { - const auto fsrec = &fstab->recs[i]; - const auto fs_type = fsrec->fs_type; - if (!fs_type) continue; - if (("overlay"s != fs_type) && ("overlayfs"s != fs_type)) continue; - auto fsrec_mount_point = fsrec->mount_point; - if (!fsrec_mount_point) continue; - if (mount_point != fsrec_mount_point) continue; - const auto fs_options = fsrec->fs_options; - if (!fs_options) continue; - const auto options = android::base::Split(fs_options, ","); - for (const auto opt : options) { - if (opt == lowerdir) { - return true; - } - } - } - return false; -} - std::vector<std::string> fs_mgr_candidate_list(const fstab* fstab, const char* mount_point = nullptr) { std::vector<std::string> mounts; @@ -398,16 +400,14 @@ std::vector<std::string> fs_mgr_candidate_list(const fstab* fstab, } // namespace -bool fs_mgr_overlayfs_mount_all() { +bool fs_mgr_overlayfs_mount_all(const fstab* fstab) { auto ret = false; if (!fs_mgr_wants_overlayfs()) return ret; - std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(), - fs_mgr_free_fstab); if (!fstab) return ret; - for (const auto& mount_point : fs_mgr_candidate_list(fstab.get())) { + for (const auto& mount_point : fs_mgr_candidate_list(fstab)) { if (fs_mgr_overlayfs_already_mounted(mount_point)) continue; if (fs_mgr_overlayfs_mount(mount_point)) ret = true; } @@ -426,25 +426,25 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* if (!fs_mgr_wants_overlayfs()) return ret; if (!fs_mgr_boot_completed()) { errno = EBUSY; - PERROR << "overlayfs setup"; + PERROR << "setup"; return ret; } - std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(), - fs_mgr_free_fstab); + std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(), + fs_mgr_free_fstab); 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; + if (setfscreatecon(kOverlayfsFileContext)) { + PERROR << "setfscreatecon " << kOverlayfsFileContext; } - auto overlay = kOverlayMountPoint + "/overlay/"; + auto overlay = kOverlayMountPoint + kOverlayTopDir; auto save_errno = errno; if (!mkdir(overlay.c_str(), 0755)) { if (change) *change = true; } else if (errno != EEXIST) { - PERROR << "overlayfs mkdir " << overlay; + PERROR << "mkdir " << overlay; } else { errno = save_errno; } @@ -462,13 +462,13 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* // If something is altered, set *change. bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { if (change) *change = false; - mount_point = fs_mgr_mount_point(std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)>( + mount_point = fs_mgr_mount_point(std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)>( fs_mgr_read_fstab_default(), fs_mgr_free_fstab) .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; @@ -476,7 +476,7 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { if (change) *change = true; } else if (errno != ENOENT) { ret = false; - PERROR << "overlayfs mv " << oldpath << " " << newpath; + PERROR << "mv " << oldpath << " " << newpath; } else { errno = save_errno; } @@ -486,7 +486,7 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { if (change) *change = true; } else if (errno != ENOENT) { ret = false; - PERROR << "overlayfs rmdir " << newpath; + PERROR << "rmdir " << newpath; } else { errno = save_errno; } @@ -496,7 +496,7 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { if (change) *change = true; } else if ((errno != ENOENT) && (errno != ENOTEMPTY)) { ret = false; - PERROR << "overlayfs rmdir " << overlay; + PERROR << "rmdir " << overlay; } else { errno = save_errno; } @@ -511,7 +511,7 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { // caller that there may still be more to do. if (!fs_mgr_boot_completed()) { errno = EBUSY; - PERROR << "overlayfs teardown"; + PERROR << "teardown"; ret = false; } return ret; diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index ebc4a0f08..506e81d06 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 1049fb6cc..cee069b3b 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -70,6 +70,8 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode); 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/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h index ceb45de3e..251dd9b91 100644 --- a/fs_mgr/include/fs_mgr_overlayfs.h +++ b/fs_mgr/include/fs_mgr_overlayfs.h @@ -20,7 +20,7 @@ #include <string> -bool fs_mgr_overlayfs_mount_all(); +bool fs_mgr_overlayfs_mount_all(const fstab* fstab); bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr, bool* change = nullptr); bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr); diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h index b1ee32885..bb4051148 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_nofail(const struct fstab_rec* fstab); 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/builder.cpp b/fs_mgr/liblp/builder.cpp index 018c2802c..352647b8e 100644 --- a/fs_mgr/liblp/builder.cpp +++ b/fs_mgr/liblp/builder.cpp @@ -482,6 +482,14 @@ uint64_t MetadataBuilder::AllocatableSpace() const { return (geometry_.last_logical_sector - geometry_.first_logical_sector + 1) * LP_SECTOR_SIZE; } +uint64_t MetadataBuilder::UsedSpace() const { + uint64_t size = 0; + for (const auto& partition : partitions_) { + size += partition->size(); + } + return size; +} + uint64_t MetadataBuilder::AlignSector(uint64_t sector) { // Note: when reading alignment info from the Kernel, we don't assume it // is aligned to the sector size, so we round up to the nearest sector. diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp index da9c8f37e..0c7e43d24 100644 --- a/fs_mgr/liblp/builder_test.cpp +++ b/fs_mgr/liblp/builder_test.cpp @@ -202,14 +202,28 @@ TEST(liblp, InternalPartitionAlignment) { } TEST(liblp, UseAllDiskSpace) { - unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2); - EXPECT_EQ(builder->AllocatableSpace(), 1036288); + static constexpr uint64_t total = 1024 * 1024; + static constexpr uint64_t metadata = 1024; + static constexpr uint64_t slots = 2; + unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(total, metadata, slots); + // We reserve a geometry block (4KB) plus space for each copy of the + // maximum size of a metadata blob. Then, we double that space since + // we store a backup copy of everything. + static constexpr uint64_t geometry = 4 * 1024; + static constexpr uint64_t allocatable = total - (metadata * slots + geometry) * 2; + EXPECT_EQ(builder->AllocatableSpace(), allocatable); + EXPECT_EQ(builder->UsedSpace(), 0); Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY); ASSERT_NE(system, nullptr); - EXPECT_EQ(builder->ResizePartition(system, 1036288), true); - EXPECT_EQ(system->size(), 1036288); - EXPECT_EQ(builder->ResizePartition(system, 1036289), false); + EXPECT_EQ(builder->ResizePartition(system, allocatable), true); + EXPECT_EQ(system->size(), allocatable); + EXPECT_EQ(builder->UsedSpace(), allocatable); + EXPECT_EQ(builder->AllocatableSpace(), allocatable); + EXPECT_EQ(builder->ResizePartition(system, allocatable + 1), false); + EXPECT_EQ(system->size(), allocatable); + EXPECT_EQ(builder->UsedSpace(), allocatable); + EXPECT_EQ(builder->AllocatableSpace(), allocatable); } TEST(liblp, BuildComplex) { diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h index 38842a4e6..27808256f 100644 --- a/fs_mgr/liblp/include/liblp/builder.h +++ b/fs_mgr/liblp/include/liblp/builder.h @@ -184,6 +184,7 @@ class MetadataBuilder { // Amount of space that can be allocated to logical partitions. uint64_t AllocatableSpace() const; + uint64_t UsedSpace() const; // Merge new block device information into previous values. Alignment values // are only overwritten if the new values are non-zero. diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp index 329a9016a..eda68fd66 100644 --- a/fs_mgr/liblp/io_test.cpp +++ b/fs_mgr/liblp/io_test.cpp @@ -117,6 +117,9 @@ TEST(liblp, CreateFakeDisk) { uint64_t size; ASSERT_TRUE(GetDescriptorSize(fd, &size)); ASSERT_EQ(size, kDiskSize); + + // Verify that we can't read unwritten metadata. + ASSERT_EQ(ReadMetadata(fd, 1), nullptr); } // Flashing metadata should not work if the metadata was created for a larger @@ -191,9 +194,6 @@ TEST(liblp, UpdateAnyMetadataSlot) { ASSERT_EQ(imported->partitions.size(), 1); EXPECT_EQ(GetPartitionName(imported->partitions[0]), "system"); - // Verify that we can't read unwritten metadata. - ASSERT_EQ(ReadMetadata(fd, 1), nullptr); - // Change the name before writing to the next slot. strncpy(imported->partitions[0].name, "vendor", sizeof(imported->partitions[0].name)); ASSERT_TRUE(UpdatePartitionTable(fd, *imported.get(), 1)); diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp index ad84b2208..9dd274511 100644 --- a/fs_mgr/liblp/writer.cpp +++ b/fs_mgr/liblp/writer.cpp @@ -94,7 +94,8 @@ static bool ValidateAndSerializeMetadata(int fd, const LpMetadata& metadata, std } // 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/first_stage_mount.cpp b/init/first_stage_mount.cpp index 79cfbcb4e..71a8e0de6 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -120,14 +120,18 @@ static inline bool IsDtVbmetaCompatible() { return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta"); } -static bool IsRecoveryMode() { +static bool ForceNormalBoot() { static bool force_normal_boot = []() { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos; }(); - return !force_normal_boot && access("/system/bin/recovery", F_OK) == 0; + return force_normal_boot; +} + +static bool IsRecoveryMode() { + return !ForceNormalBoot() && access("/system/bin/recovery", F_OK) == 0; } static inline bool IsDmLinearEnabled() { @@ -368,11 +372,15 @@ bool FirstStageMount::MountPartitions() { // 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 || - rec->mount_point == "/system_recovery_mount"s; - }); + 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 (ForceNormalBoot()) { + free((*system_partition)->mount_point); + (*system_partition)->mount_point = strdup("/system_recovery_mount"); + } + if (!MountPartition(*system_partition)) { return false; } @@ -388,7 +396,7 @@ bool FirstStageMount::MountPartitions() { } } - fs_mgr_overlayfs_mount_all(); + fs_mgr_overlayfs_mount_all(device_tree_fstab_.get()); return true; } diff --git a/init/init.cpp b/init/init.cpp index e5c154893..47cfe3209 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -346,12 +346,12 @@ static void export_oem_lock_status() { if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) { return; } - - std::string value = GetProperty("ro.boot.verifiedbootstate", ""); - - if (!value.empty()) { - property_set("ro.boot.flash.locked", value == "orange" ? "0" : "1"); - } + import_kernel_cmdline( + false, [](const std::string& key, const std::string& value, bool in_qemu) { + if (key == "androidboot.verifiedbootstate") { + property_set("ro.boot.flash.locked", value == "orange" ? "0" : "1"); + } + }); } static void export_kernel_boot_props() { diff --git a/init/reboot.cpp b/init/reboot.cpp index 2f88121b7..b84bfd3d6 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -464,6 +464,12 @@ bool HandlePowerctlMessage(const std::string& command) { cmd = ANDROID_RB_RESTART2; if (cmd_params.size() >= 2) { reboot_target = cmd_params[1]; + // adb reboot fastboot should boot into bootloader for devices not + // supporting logical partitions. + if (reboot_target == "fastboot" && + !android::base::GetBoolProperty("ro.boot.logical_partitions", false)) { + reboot_target = "bootloader"; + } // When rebooting to the bootloader notify the bootloader writing // also the BCB. if (reboot_target == "bootloader") { diff --git a/init/subcontext.cpp b/init/subcontext.cpp index c2a21d45c..092c51ceb 100644 --- a/init/subcontext.cpp +++ b/init/subcontext.cpp @@ -62,7 +62,9 @@ constexpr size_t kBufferSize = 4096; Result<std::string> ReadMessage(int socket) { char buffer[kBufferSize] = {}; auto result = TEMP_FAILURE_RETRY(recv(socket, buffer, sizeof(buffer), 0)); - if (result <= 0) { + if (result == 0) { + return Error(); + } else if (result < 0) { return ErrnoError(); } return std::string(buffer, result); @@ -175,6 +177,12 @@ void SubcontextProcess::MainLoop() { auto init_message = ReadMessage(init_fd_); if (!init_message) { + if (init_message.error_errno() == 0) { + // If the init file descriptor was closed, let's exit quietly. If + // this was accidental, init will restart us. If init died, this + // avoids calling abort(3) unnecessarily. + return; + } LOG(FATAL) << "Could not read message from init: " << init_message.error(); } diff --git a/init/tokenizer.cpp b/init/tokenizer.cpp index bb143f18a..7e05a0a74 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 @@ textresume: continue; } x++; + FALLTHROUGH_INTENDED; case '\n': /* \ <lf> -> line continuation */ state->line++; diff --git a/libgrallocusage/Android.bp b/libgrallocusage/Android.bp index bcc061691..d27feb99a 100644 --- a/libgrallocusage/Android.bp +++ b/libgrallocusage/Android.bp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -cc_library_static { +cc_library { name: "libgrallocusage", vendor_available: true, cflags: [ diff --git a/libgrallocusage/OWNERS b/libgrallocusage/OWNERS new file mode 100644 index 000000000..154dc6d1b --- /dev/null +++ b/libgrallocusage/OWNERS @@ -0,0 +1,3 @@ +jessehall@google.com +olv@google.com +stoza@google.com diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp index d1f20f495..383d0e7ca 100644 --- a/liblog/tests/liblog_test.cpp +++ b/liblog/tests/liblog_test.cpp @@ -131,7 +131,7 @@ static bool isPmsgActive() { 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 @@ static bool isLogdwActive() { 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/libmemunreachable/HeapWalker.h b/libmemunreachable/HeapWalker.h index 5c7ec136b..92a832585 100644 --- a/libmemunreachable/HeapWalker.h +++ b/libmemunreachable/HeapWalker.h @@ -52,7 +52,7 @@ class HeapWalker { allocation_bytes_(0), roots_(allocator), root_vals_(allocator), - segv_handler_(allocator), + segv_handler_(), walking_ptr_(0) { valid_allocations_range_.end = 0; valid_allocations_range_.begin = ~valid_allocations_range_.end; diff --git a/libmemunreachable/LeakFolding.cpp b/libmemunreachable/LeakFolding.cpp index 69f320cc7..074dc48dd 100644 --- a/libmemunreachable/LeakFolding.cpp +++ b/libmemunreachable/LeakFolding.cpp @@ -57,7 +57,7 @@ void LeakFolding::ComputeDAG() { } void LeakFolding::AccumulateLeaks(SCCInfo* dominator) { - std::function<void(SCCInfo*)> walk(std::allocator_arg, allocator_, [&](SCCInfo* scc) { + std::function<void(SCCInfo*)> walk([&](SCCInfo* scc) { if (scc->accumulator != dominator) { scc->accumulator = dominator; dominator->cuumulative_size += scc->size; diff --git a/libmemunreachable/ScopedSignalHandler.h b/libmemunreachable/ScopedSignalHandler.h index ff53fad8f..9e08a8ecc 100644 --- a/libmemunreachable/ScopedSignalHandler.h +++ b/libmemunreachable/ScopedSignalHandler.h @@ -32,15 +32,14 @@ class ScopedSignalHandler { public: using Fn = std::function<void(ScopedSignalHandler&, int, siginfo_t*, void*)>; - explicit ScopedSignalHandler(Allocator<Fn> allocator) : allocator_(allocator), signal_(-1) {} + explicit ScopedSignalHandler() : signal_(-1) {} ~ScopedSignalHandler() { reset(); } template <class F> void install(int signal, F&& f) { if (signal_ != -1) MEM_LOG_ALWAYS_FATAL("ScopedSignalHandler already installed"); - handler_ = SignalFn(std::allocator_arg, allocator_, - [=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); }); + handler_ = SignalFn([=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); }); struct sigaction act {}; act.sa_sigaction = [](int signal, siginfo_t* si, void* uctx) { handler_(signal, si, uctx); }; @@ -68,7 +67,6 @@ class ScopedSignalHandler { private: using SignalFn = std::function<void(int, siginfo_t*, void*)>; DISALLOW_COPY_AND_ASSIGN(ScopedSignalHandler); - Allocator<Fn> allocator_; int signal_; struct sigaction old_act_; // TODO(ccross): to support multiple ScopedSignalHandlers handler_ would need diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp index 6061f6137..57a780ece 100644 --- a/libunwindstack/DwarfSection.cpp +++ b/libunwindstack/DwarfSection.cpp @@ -461,6 +461,7 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3 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 add6e14cb..f8d1356aa 100644 --- a/libziparchive/zip_archive.cc +++ b/libziparchive/zip_archive.cc @@ -122,21 +122,36 @@ static uint32_t ComputeHash(const ZipString& name) { #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 @@ static int64_t EntryToIndex(const ZipString* hash_table, const uint32_t hash_tab /* * 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 @@ static int32_t AddToHash(ZipString* hash_table, const uint64_t hash_table_size, * 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 @@ ZipArchive::ZipArchive(const int fd, bool assume_ownership) 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(void* address, size_t length) 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 @@ ZipArchive::~ZipArchive() { } 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 @@ static int32_t ParseZipArchive(ZipArchive* archive) { */ 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 @@ static int32_t ParseZipArchive(ZipArchive* archive) { 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 @@ static int32_t FindEntry(const ZipArchive* archive, const int ent, ZipEntry* dat // 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 @@ static int32_t FindEntry(const ZipArchive* archive, const int ent, ZipEntry* dat 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 @@ int32_t FindEntry(const ZipArchiveHandle handle, const ZipString& entryName, Zip 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 @@ int32_t Next(void* cookie, ZipEntry* data, ZipString* name) { 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 0a73300eb..83cb11f2b 100644 --- a/libziparchive/zip_archive_private.h +++ b/libziparchive/zip_archive_private.h @@ -136,6 +136,26 @@ class CentralDirectory { 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 @@ struct ZipArchive { // 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/mkbootimg/Android.bp b/mkbootimg/Android.bp index 576a677e7..c3cf74651 100644 --- a/mkbootimg/Android.bp +++ b/mkbootimg/Android.bp @@ -31,3 +31,34 @@ cc_library { header_libs: ["libmkbootimg_abi_headers"], export_header_lib_headers: ["libmkbootimg_abi_headers"], } + +python_defaults { + name: "mkbootimg_defaults", + + version: { + py2: { + enabled: true, + embedded_launcher: true, + }, + py3: { + enabled: false, + embedded_launcher: false, + }, + }, +} + +python_binary_host { + name: "mkbootimg", + defaults: ["mkbootimg_defaults"], + srcs: [ + "mkbootimg.py", + ], +} + +python_binary_host { + name: "unpack_bootimg", + defaults: ["mkbootimg_defaults"], + srcs: [ + "unpack_bootimg.py", + ], +} diff --git a/mkbootimg/Android.mk b/mkbootimg/Android.mk deleted file mode 100644 index 92e1e27d2..000000000 --- a/mkbootimg/Android.mk +++ /dev/null @@ -1,20 +0,0 @@ - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := mkbootimg -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_IS_HOST_MODULE := true - -LOCAL_MODULE := mkbootimg - -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := unpack_bootimg -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_IS_HOST_MODULE := true - -LOCAL_MODULE := unpack_bootimg - -include $(BUILD_PREBUILT) diff --git a/mkbootimg/include/bootimg/bootimg.h b/mkbootimg/include/bootimg/bootimg.h index bce308b02..4432f9ec9 100644 --- a/mkbootimg/include/bootimg/bootimg.h +++ b/mkbootimg/include/bootimg/bootimg.h @@ -110,25 +110,25 @@ typedef struct boot_img_hdr_v0 boot_img_hdr; */ struct boot_img_hdr_v1 : public boot_img_hdr_v0 { - uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO image */ - uint64_t recovery_dtbo_offset; /* offset to recovery dtbo in boot image */ + uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO/ACPIO image */ + uint64_t recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */ uint32_t header_size; } __attribute__((packed)); /* When the boot image header has a version of 1, the structure of the boot * image is as follows: * - * +-----------------+ - * | boot header | 1 page - * +-----------------+ - * | kernel | n pages - * +-----------------+ - * | ramdisk | m pages - * +-----------------+ - * | second stage | o pages - * +-----------------+ - * | recovery dtbo | p pages - * +-----------------+ + * +---------------------+ + * | boot header | 1 page + * +---------------------+ + * | kernel | n pages + * +---------------------+ + * | ramdisk | m pages + * +---------------------+ + * | second stage | o pages + * +---------------------+ + * | recovery dtbo/acpio | p pages + * +---------------------+ * n = (kernel_size + page_size - 1) / page_size * m = (ramdisk_size + page_size - 1) / page_size * o = (second_size + page_size - 1) / page_size @@ -136,13 +136,14 @@ struct boot_img_hdr_v1 : public boot_img_hdr_v0 { * * 0. all entities are page_size aligned in flash * 1. kernel and ramdisk are required (size != 0) - * 2. recovery_dtbo is required for recovery.img in non-A/B devices(recovery_dtbo_size != 0) + * 2. recovery_dtbo/recovery_acpio is required for recovery.img in non-A/B + * devices(recovery_dtbo_size != 0) * 3. second is optional (second_size == 0 -> no second) * 4. load each element (kernel, ramdisk, second) at * the specified physical address (kernel_addr, etc) - * 5. If booting to recovery mode in a non-A/B device, extract recovery dtbo and - * apply the correct set of overlays on the base device tree depending on the - * hardware/product revision. + * 5. If booting to recovery mode in a non-A/B device, extract recovery + * dtbo/acpio and apply the correct set of overlays on the base device tree + * depending on the hardware/product revision. * 6. prepare tags at tag_addr. kernel_args[] is * appended to the kernel commandline in the tags. * 7. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr diff --git a/mkbootimg/mkbootimg b/mkbootimg/mkbootimg.py index fda9af0d2..2eb2bab56 100755..100644 --- a/mkbootimg/mkbootimg +++ b/mkbootimg/mkbootimg.py @@ -161,7 +161,10 @@ def parse_cmdline(): required=True) parser.add_argument('--ramdisk', help='path to the ramdisk', type=FileType('rb')) parser.add_argument('--second', help='path to the 2nd bootloader', type=FileType('rb')) - parser.add_argument('--recovery_dtbo', help='path to the recovery DTBO', type=FileType('rb')) + recovery_dtbo_group = parser.add_mutually_exclusive_group() + recovery_dtbo_group.add_argument('--recovery_dtbo', help='path to the recovery DTBO', type=FileType('rb')) + recovery_dtbo_group.add_argument('--recovery_acpio', help='path to the recovery ACPIO', + type=FileType('rb'), metavar='RECOVERY_ACPIO', dest='recovery_dtbo') parser.add_argument('--cmdline', help='extra arguments to be passed on the ' 'kernel command line', default='', action=ValidateStrLenAction, maxlen=1536) parser.add_argument('--base', help='base address', type=parse_int, default=0x10000000) diff --git a/mkbootimg/unpack_bootimg b/mkbootimg/unpack_bootimg.py index c37acd5ac..c37acd5ac 100755..100644 --- a/mkbootimg/unpack_bootimg +++ b/mkbootimg/unpack_bootimg.py diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt index f2892f8a9..d3e80c992 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.permitted.paths += /mnt/expand 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.search.paths += /%PRODUCT_SERVICES%/${LIB} 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 db65c14fc..7e354aca6 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.isolated = false 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 += /odm/${LIB} 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 += /vendor/${LIB}/vndk-sp 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 += /system/${LIB}/vndk-sp%VNDK_VER 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 @@ namespace.default.asan.search.paths += /product/${LIB} [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} diff --git a/rootdir/init.rc b/rootdir/init.rc index 915540eff..f39ea7c09 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -407,6 +407,9 @@ on post-fs-data mkdir /data/bootchart 0755 shell shell bootchart start + # Start apexd as soon as we can + start apexd + # Avoid predictable entropy pool. Carry over entropy from previous boot. copy /data/system/entropy.dat /dev/urandom |