diff options
author | Tianjie Xu <xunchang@google.com> | 2019-04-16 01:38:43 +0200 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-04-16 01:38:43 +0200 |
commit | 2e1c88306bebb93bfd10e2b54b1c004968e5136f (patch) | |
tree | 0223ab799c88ef1df7c1267696f9eb6f6ddef41d | |
parent | [automerger skipped] Merge "Import translations. DO NOT MERGE" am: 0b172415fd -s ours am: 440d03ede2 -s ours (diff) | |
parent | Merge "Move wipe cache|data to libinstall" am: 9fc764f1f0 (diff) | |
download | android_bootable_recovery-2e1c88306bebb93bfd10e2b54b1c004968e5136f.tar android_bootable_recovery-2e1c88306bebb93bfd10e2b54b1c004968e5136f.tar.gz android_bootable_recovery-2e1c88306bebb93bfd10e2b54b1c004968e5136f.tar.bz2 android_bootable_recovery-2e1c88306bebb93bfd10e2b54b1c004968e5136f.tar.lz android_bootable_recovery-2e1c88306bebb93bfd10e2b54b1c004968e5136f.tar.xz android_bootable_recovery-2e1c88306bebb93bfd10e2b54b1c004968e5136f.tar.zst android_bootable_recovery-2e1c88306bebb93bfd10e2b54b1c004968e5136f.zip |
-rw-r--r-- | Android.bp | 3 | ||||
-rw-r--r-- | install/Android.bp | 1 | ||||
-rw-r--r-- | install/adb_install.cpp | 9 | ||||
-rw-r--r-- | install/fuse_sdcard_install.cpp | 4 | ||||
-rw-r--r-- | install/include/install/adb_install.h | 2 | ||||
-rw-r--r-- | install/include/install/fuse_sdcard_install.h | 2 | ||||
-rw-r--r-- | install/include/install/install.h | 9 | ||||
-rw-r--r-- | install/include/install/wipe_data.h | 32 | ||||
-rw-r--r-- | install/install.cpp | 18 | ||||
-rw-r--r-- | install/wipe_data.cpp | 190 | ||||
-rw-r--r-- | otautil/Android.bp | 1 | ||||
-rw-r--r-- | otautil/include/otautil/logging.h (renamed from logging.h) | 5 | ||||
-rw-r--r-- | otautil/logging.cpp (renamed from logging.cpp) | 25 | ||||
-rw-r--r-- | recovery-persist.cpp | 2 | ||||
-rw-r--r-- | recovery-refresh.cpp | 2 | ||||
-rw-r--r-- | recovery.cpp | 217 | ||||
-rw-r--r-- | recovery_main.cpp | 5 |
17 files changed, 303 insertions, 224 deletions
diff --git a/Android.bp b/Android.bp index 582f3b623..0eb5fd9e5 100644 --- a/Android.bp +++ b/Android.bp @@ -107,7 +107,6 @@ cc_binary { ], srcs: [ - "logging.cpp", "recovery_main.cpp", ], @@ -139,7 +138,6 @@ cc_binary { ], srcs: [ - "logging.cpp", "recovery-persist.cpp", ], @@ -167,7 +165,6 @@ cc_binary { ], srcs: [ - "logging.cpp", "recovery-refresh.cpp", ], diff --git a/install/Android.bp b/install/Android.bp index 2ffc4421c..b18e29021 100644 --- a/install/Android.bp +++ b/install/Android.bp @@ -65,6 +65,7 @@ cc_library_static { "install.cpp", "package.cpp", "verifier.cpp", + "wipe_data.cpp", ], shared_libs: [ diff --git a/install/adb_install.cpp b/install/adb_install.cpp index dc7ee0b32..548b6e5b9 100644 --- a/install/adb_install.cpp +++ b/install/adb_install.cpp @@ -81,7 +81,7 @@ static bool WriteStatusToFd(MinadbdCommandStatus status, int fd) { } // Installs the package from FUSE. Returns true if the installation succeeds, and false otherwise. -static bool AdbInstallPackageHandler(bool* wipe_cache, RecoveryUI* ui, int* result) { +static bool AdbInstallPackageHandler(RecoveryUI* ui, int* result) { // How long (in seconds) we wait for the package path to be ready. It doesn't need to be too long // because the minadbd service has already issued an install command. FUSE_SIDELOAD_HOST_PATHNAME // will start to exist once the host connects and starts serving a package. Poll for its @@ -99,7 +99,7 @@ static bool AdbInstallPackageHandler(bool* wipe_cache, RecoveryUI* ui, int* resu break; } } - *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, false, 0, ui); + *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, ui); break; } @@ -280,7 +280,7 @@ static void CreateMinadbdServiceAndExecuteCommands( signal(SIGPIPE, SIG_DFL); } -int apply_from_adb(bool* wipe_cache, RecoveryUI* ui) { +int apply_from_adb(RecoveryUI* ui) { // Save the usb state to restore after the sideload operation. std::string usb_state = android::base::GetProperty("sys.usb.state", "none"); // Clean up state and stop adbd. @@ -295,8 +295,7 @@ int apply_from_adb(bool* wipe_cache, RecoveryUI* ui) { int install_result = INSTALL_ERROR; std::map<MinadbdCommands, CommandFunction> command_map{ - { MinadbdCommands::kInstall, - std::bind(&AdbInstallPackageHandler, wipe_cache, ui, &install_result) }, + { MinadbdCommands::kInstall, std::bind(&AdbInstallPackageHandler, ui, &install_result) }, }; CreateMinadbdServiceAndExecuteCommands(command_map); diff --git a/install/fuse_sdcard_install.cpp b/install/fuse_sdcard_install.cpp index dde289f80..1aa8768e7 100644 --- a/install/fuse_sdcard_install.cpp +++ b/install/fuse_sdcard_install.cpp @@ -133,7 +133,7 @@ static bool StartSdcardFuse(const std::string& path) { return run_fuse_sideload(std::move(file_data_reader)) == 0; } -int ApplyFromSdcard(Device* device, bool* wipe_cache, RecoveryUI* ui) { +int ApplyFromSdcard(Device* device, RecoveryUI* ui) { if (ensure_path_mounted(SDCARD_ROOT) != 0) { LOG(ERROR) << "\n-- Couldn't mount " << SDCARD_ROOT << ".\n"; return INSTALL_ERROR; @@ -184,7 +184,7 @@ int ApplyFromSdcard(Device* device, bool* wipe_cache, RecoveryUI* ui) { } } - result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, false, 0 /*retry_count*/, ui); + result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /*retry_count*/, ui); break; } diff --git a/install/include/install/adb_install.h b/install/include/install/adb_install.h index dbc824501..f7b065b64 100644 --- a/install/include/install/adb_install.h +++ b/install/include/install/adb_install.h @@ -18,4 +18,4 @@ #include <recovery_ui/ui.h> -int apply_from_adb(bool* wipe_cache, RecoveryUI* ui); +int apply_from_adb(RecoveryUI* ui); diff --git a/install/include/install/fuse_sdcard_install.h b/install/include/install/fuse_sdcard_install.h index 345aea45b..d9214ca3b 100644 --- a/install/include/install/fuse_sdcard_install.h +++ b/install/include/install/fuse_sdcard_install.h @@ -19,4 +19,4 @@ #include "recovery_ui/device.h" #include "recovery_ui/ui.h" -int ApplyFromSdcard(Device* device, bool* wipe_cache, RecoveryUI* ui); +int ApplyFromSdcard(Device* device, RecoveryUI* ui); diff --git a/install/include/install/install.h b/install/include/install/install.h index 74fb3d170..1e41b4843 100644 --- a/install/include/install/install.h +++ b/install/include/install/install.h @@ -43,10 +43,11 @@ enum class OtaType { BRICK, }; -// Installs the given update package. If INSTALL_SUCCESS is returned and *wipe_cache is true on -// exit, caller should wipe the cache partition. -int install_package(const std::string& package, bool* wipe_cache, bool needs_mount, int retry_count, - RecoveryUI* ui); +// Installs the given update package. This function should also wipe the cache partition after a +// successful installation if |should_wipe_cache| is true or an updater command asks to wipe the +// cache. +int install_package(const std::string& package, bool should_wipe_cache, bool needs_mount, + int retry_count, RecoveryUI* ui); // Verifies the package by ota keys. Returns true if the package is verified successfully, // otherwise returns false. diff --git a/install/include/install/wipe_data.h b/install/include/install/wipe_data.h new file mode 100644 index 000000000..06b1b95d4 --- /dev/null +++ b/install/include/install/wipe_data.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <functional> + +#include "recovery_ui/device.h" +#include "recovery_ui/ui.h" + +struct selabel_handle; + +void SetWipeDataSehandle(selabel_handle* handle); + +// Returns true on success. +bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm); + +// Returns true on success. +bool WipeData(Device* device, bool convert_fbe); diff --git a/install/install.cpp b/install/install.cpp index a1124c361..e2d470096 100644 --- a/install/install.cpp +++ b/install/install.cpp @@ -48,6 +48,7 @@ #include "install/package.h" #include "install/verifier.h" +#include "install/wipe_data.h" #include "otautil/error_code.h" #include "otautil/paths.h" #include "otautil/roots.h" @@ -631,10 +632,9 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo return result; } -int install_package(const std::string& path, bool* wipe_cache, bool needs_mount, int retry_count, - RecoveryUI* ui) { +int install_package(const std::string& path, bool should_wipe_cache, bool needs_mount, + int retry_count, RecoveryUI* ui) { CHECK(!path.empty()); - CHECK(wipe_cache != nullptr); auto start = std::chrono::system_clock::now(); @@ -647,8 +647,10 @@ int install_package(const std::string& path, bool* wipe_cache, bool needs_mount, LOG(ERROR) << "failed to set up expected mounts for install; aborting"; result = INSTALL_ERROR; } else { - result = really_install_package(path, wipe_cache, needs_mount, &log_buffer, retry_count, - &max_temperature, ui); + bool updater_wipe_cache = false; + result = really_install_package(path, &updater_wipe_cache, needs_mount, &log_buffer, + retry_count, &max_temperature, ui); + should_wipe_cache = should_wipe_cache || updater_wipe_cache; } // Measure the time spent to apply OTA update in seconds. @@ -703,6 +705,12 @@ int install_package(const std::string& path, bool* wipe_cache, bool needs_mount, // Write a copy into last_log. LOG(INFO) << log_content; + if (result == INSTALL_SUCCESS && should_wipe_cache) { + if (!WipeCache(ui, nullptr)) { + result = INSTALL_ERROR; + } + } + return result; } diff --git a/install/wipe_data.cpp b/install/wipe_data.cpp new file mode 100644 index 000000000..7db79048a --- /dev/null +++ b/install/wipe_data.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "install/wipe_data.h" + +#include <dirent.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> + +#include <functional> +#include <memory> +#include <vector> + +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/stringprintf.h> + +#include "otautil/dirutil.h" +#include "otautil/logging.h" +#include "otautil/roots.h" +#include "recovery_ui/ui.h" + +constexpr const char* CACHE_ROOT = "/cache"; +constexpr const char* DATA_ROOT = "/data"; +constexpr const char* METADATA_ROOT = "/metadata"; + +constexpr const char* CACHE_LOG_DIR = "/cache/recovery"; + +static struct selabel_handle* sehandle; + +void SetWipeDataSehandle(selabel_handle* handle) { + sehandle = handle; +} + +struct saved_log_file { + std::string name; + struct stat sb; + std::string data; +}; + +static bool EraseVolume(const char* volume, RecoveryUI* ui, bool convert_fbe) { + bool is_cache = (strcmp(volume, CACHE_ROOT) == 0); + bool is_data = (strcmp(volume, DATA_ROOT) == 0); + + ui->SetBackground(RecoveryUI::ERASING); + ui->SetProgressType(RecoveryUI::INDETERMINATE); + + std::vector<saved_log_file> log_files; + + if (is_cache) { + // If we're reformatting /cache, we load any past logs + // (i.e. "/cache/recovery/last_*") and the current log + // ("/cache/recovery/log") into memory, so we can restore them after + // the reformat. + + ensure_path_mounted(volume); + + struct dirent* de; + std::unique_ptr<DIR, decltype(&closedir)> d(opendir(CACHE_LOG_DIR), closedir); + if (d) { + while ((de = readdir(d.get())) != nullptr) { + if (strncmp(de->d_name, "last_", 5) == 0 || strcmp(de->d_name, "log") == 0) { + std::string path = android::base::StringPrintf("%s/%s", CACHE_LOG_DIR, de->d_name); + + struct stat sb; + if (stat(path.c_str(), &sb) == 0) { + // truncate files to 512kb + if (sb.st_size > (1 << 19)) { + sb.st_size = 1 << 19; + } + + std::string data(sb.st_size, '\0'); + FILE* f = fopen(path.c_str(), "rbe"); + fread(&data[0], 1, data.size(), f); + fclose(f); + + log_files.emplace_back(saved_log_file{ path, sb, data }); + } + } + } + } else { + if (errno != ENOENT) { + PLOG(ERROR) << "Failed to opendir " << CACHE_LOG_DIR; + } + } + } + + ui->Print("Formatting %s...\n", volume); + + ensure_path_unmounted(volume); + + int result; + if (is_data && convert_fbe) { + constexpr const char* CONVERT_FBE_DIR = "/tmp/convert_fbe"; + constexpr const char* CONVERT_FBE_FILE = "/tmp/convert_fbe/convert_fbe"; + // Create convert_fbe breadcrumb file to signal init to convert to file based encryption, not + // full disk encryption. + if (mkdir(CONVERT_FBE_DIR, 0700) != 0) { + PLOG(ERROR) << "Failed to mkdir " << CONVERT_FBE_DIR; + return false; + } + FILE* f = fopen(CONVERT_FBE_FILE, "wbe"); + if (!f) { + PLOG(ERROR) << "Failed to convert to file encryption"; + return false; + } + fclose(f); + result = format_volume(volume, CONVERT_FBE_DIR); + remove(CONVERT_FBE_FILE); + rmdir(CONVERT_FBE_DIR); + } else { + result = format_volume(volume); + } + + if (is_cache) { + // Re-create the log dir and write back the log entries. + if (ensure_path_mounted(CACHE_LOG_DIR) == 0 && + mkdir_recursively(CACHE_LOG_DIR, 0777, false, sehandle) == 0) { + for (const auto& log : log_files) { + if (!android::base::WriteStringToFile(log.data, log.name, log.sb.st_mode, log.sb.st_uid, + log.sb.st_gid)) { + PLOG(ERROR) << "Failed to write to " << log.name; + } + } + } else { + PLOG(ERROR) << "Failed to mount / create " << CACHE_LOG_DIR; + } + + // Any part of the log we'd copied to cache is now gone. + // Reset the pointer so we copy from the beginning of the temp + // log. + reset_tmplog_offset(); + copy_logs(true /* save_current_log */, true /* has_cache */, sehandle); + } + + return (result == 0); +} + +bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm_func) { + bool has_cache = volume_for_mount_point("/cache") != nullptr; + if (!has_cache) { + ui->Print("No /cache partition found.\n"); + return false; + } + + if (confirm_func && !confirm_func()) { + return false; + } + + ui->Print("\n-- Wiping cache...\n"); + bool success = EraseVolume("/cache", ui, false); + ui->Print("Cache wipe %s.\n", success ? "complete" : "failed"); + return success; +} + +bool WipeData(Device* device, bool convert_fbe) { + RecoveryUI* ui = device->GetUI(); + ui->Print("\n-- Wiping data...\n"); + bool success = device->PreWipeData(); + if (success) { + success &= EraseVolume(DATA_ROOT, ui, convert_fbe); + bool has_cache = volume_for_mount_point("/cache") != nullptr; + if (has_cache) { + success &= EraseVolume(CACHE_ROOT, ui, false); + } + if (volume_for_mount_point(METADATA_ROOT) != nullptr) { + success &= EraseVolume(METADATA_ROOT, ui, false); + } + } + if (success) { + success &= device->PostWipeData(); + } + ui->Print("Data wipe %s.\n", success ? "complete" : "failed"); + return success; +}
\ No newline at end of file diff --git a/otautil/Android.bp b/otautil/Android.bp index c9ecba788..73398c3aa 100644 --- a/otautil/Android.bp +++ b/otautil/Android.bp @@ -40,6 +40,7 @@ cc_library_static { android: { srcs: [ "dirutil.cpp", + "logging.cpp", "mounts.cpp", "parse_install_logs.cpp", "roots.cpp", diff --git a/logging.h b/otautil/include/otautil/logging.h index 3cfbc7af6..c4f13292b 100644 --- a/logging.h +++ b/otautil/include/otautil/logging.h @@ -26,6 +26,8 @@ static constexpr int KEEP_LOG_COUNT = 10; +struct selabel_handle; + ssize_t logbasename(log_id_t id, char prio, const char* filename, const char* buf, size_t len, void* arg); @@ -41,8 +43,7 @@ void rotate_logs(const char* last_log_file, const char* last_kmsg_file); void check_and_fclose(FILE* fp, const std::string& name); void copy_log_file_to_pmsg(const std::string& source, const std::string& destination); -void copy_log_file(const std::string& source, const std::string& destination, bool append); -void copy_logs(bool modified_flash, bool has_cache); +void copy_logs(bool save_current_log, bool has_cache, const selabel_handle* sehandle); void reset_tmplog_offset(); void save_kernel_log(const char* destination); diff --git a/logging.cpp b/otautil/logging.cpp index 48f9ec317..7c330ac61 100644 --- a/logging.cpp +++ b/otautil/logging.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "logging.h" +#include "otautil/logging.h" #include <stdio.h> #include <string.h> @@ -29,8 +29,8 @@ #include <android-base/stringprintf.h> #include <private/android_filesystem_config.h> /* for AID_SYSTEM */ #include <private/android_logger.h> /* private pmsg functions */ +#include <selinux/label.h> -#include "common.h" #include "otautil/dirutil.h" #include "otautil/paths.h" #include "otautil/roots.h" @@ -45,7 +45,7 @@ static const std::string LAST_LOG_FILTER = "recovery/last_log"; // fopen(3)'s the given file, by mounting volumes and making parent dirs as necessary. Returns the // file pointer, or nullptr on error. -static FILE* fopen_path(const std::string& path, const char* mode) { +static FILE* fopen_path(const std::string& path, const char* mode, const selabel_handle* sehandle) { if (ensure_path_mounted(path) != 0) { LOG(ERROR) << "Can't mount " << path; return nullptr; @@ -165,8 +165,9 @@ void reset_tmplog_offset() { tmplog_offset = 0; } -void copy_log_file(const std::string& source, const std::string& destination, bool append) { - FILE* dest_fp = fopen_path(destination, append ? "ae" : "we"); +static void copy_log_file(const std::string& source, const std::string& destination, bool append, + const selabel_handle* sehandle) { + FILE* dest_fp = fopen_path(destination, append ? "ae" : "we", sehandle); if (dest_fp == nullptr) { PLOG(ERROR) << "Can't open " << destination; } else { @@ -189,11 +190,11 @@ void copy_log_file(const std::string& source, const std::string& destination, bo } } -void copy_logs(bool modified_flash, bool has_cache) { - // We only rotate and record the log of the current session if there are actual attempts to modify - // the flash, such as wipes, installs from BCB or menu selections. This is to avoid unnecessary +void copy_logs(bool save_current_log, bool has_cache, const selabel_handle* sehandle) { + // We only rotate and record the log of the current session if explicitly requested. This usually + // happens after wipes, installation from BCB or menu selections. This is to avoid unnecessary // rotation (and possible deletion) of log files, if it does not do anything loggable. - if (!modified_flash) { + if (!save_current_log) { return; } @@ -211,9 +212,9 @@ void copy_logs(bool modified_flash, bool has_cache) { rotate_logs(LAST_LOG_FILE, LAST_KMSG_FILE); // Copy logs to cache so the system can find out what happened. - copy_log_file(Paths::Get().temporary_log_file(), LOG_FILE, true); - copy_log_file(Paths::Get().temporary_log_file(), LAST_LOG_FILE, false); - copy_log_file(Paths::Get().temporary_install_file(), LAST_INSTALL_FILE, false); + copy_log_file(Paths::Get().temporary_log_file(), LOG_FILE, true, sehandle); + copy_log_file(Paths::Get().temporary_log_file(), LAST_LOG_FILE, false, sehandle); + copy_log_file(Paths::Get().temporary_install_file(), LAST_INSTALL_FILE, false, sehandle); save_kernel_log(LAST_KMSG_FILE); chmod(LOG_FILE, 0600); chown(LOG_FILE, AID_SYSTEM, AID_SYSTEM); diff --git a/recovery-persist.cpp b/recovery-persist.cpp index e2a6699f6..294017a12 100644 --- a/recovery-persist.cpp +++ b/recovery-persist.cpp @@ -43,7 +43,7 @@ #include <metricslogger/metrics_logger.h> #include <private/android_logger.h> /* private pmsg functions */ -#include "logging.h" +#include "otautil/logging.h" #include "otautil/parse_install_logs.h" constexpr const char* LAST_LOG_FILE = "/data/misc/recovery/last_log"; diff --git a/recovery-refresh.cpp b/recovery-refresh.cpp index aee1ca592..d41755d0a 100644 --- a/recovery-refresh.cpp +++ b/recovery-refresh.cpp @@ -42,7 +42,7 @@ #include <private/android_logger.h> /* private pmsg functions */ -#include "logging.h" +#include "otautil/logging.h" int main(int argc, char **argv) { static const char filter[] = "recovery/"; diff --git a/recovery.cpp b/recovery.cpp index 034918498..0e6e4976d 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -27,7 +27,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -55,30 +54,27 @@ #include "install/fuse_sdcard_install.h" #include "install/install.h" #include "install/package.h" -#include "logging.h" -#include "otautil/dirutil.h" +#include "install/wipe_data.h" #include "otautil/error_code.h" +#include "otautil/logging.h" #include "otautil/paths.h" #include "otautil/roots.h" #include "otautil/sysutil.h" #include "recovery_ui/screen_ui.h" #include "recovery_ui/ui.h" -static constexpr const char* CACHE_LOG_DIR = "/cache/recovery"; static constexpr const char* COMMAND_FILE = "/cache/recovery/command"; static constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg"; static constexpr const char* LAST_LOG_FILE = "/cache/recovery/last_log"; static constexpr const char* LOCALE_FILE = "/cache/recovery/last_locale"; static constexpr const char* CACHE_ROOT = "/cache"; -static constexpr const char* DATA_ROOT = "/data"; -static constexpr const char* METADATA_ROOT = "/metadata"; // We define RECOVERY_API_VERSION in Android.mk, which will be picked up by build system and packed // into target_files.zip. Assert the version defined in code and in Android.mk are consistent. static_assert(kRecoveryApiVersion == RECOVERY_API_VERSION, "Mismatching recovery API versions."); -static bool modified_flash = false; +static bool save_current_log = false; std::string stage; const char* reason = nullptr; @@ -148,7 +144,7 @@ static void finish_recovery() { } } - copy_logs(modified_flash, has_cache); + copy_logs(save_current_log, has_cache, sehandle); // Reset to normal system boot so recovery won't cycle indefinitely. std::string err; @@ -167,110 +163,6 @@ static void finish_recovery() { sync(); // For good measure. } -struct saved_log_file { - std::string name; - struct stat sb; - std::string data; -}; - -static bool erase_volume(const char* volume) { - bool is_cache = (strcmp(volume, CACHE_ROOT) == 0); - bool is_data = (strcmp(volume, DATA_ROOT) == 0); - - ui->SetBackground(RecoveryUI::ERASING); - ui->SetProgressType(RecoveryUI::INDETERMINATE); - - std::vector<saved_log_file> log_files; - - if (is_cache) { - // If we're reformatting /cache, we load any past logs - // (i.e. "/cache/recovery/last_*") and the current log - // ("/cache/recovery/log") into memory, so we can restore them after - // the reformat. - - ensure_path_mounted(volume); - - struct dirent* de; - std::unique_ptr<DIR, decltype(&closedir)> d(opendir(CACHE_LOG_DIR), closedir); - if (d) { - while ((de = readdir(d.get())) != nullptr) { - if (strncmp(de->d_name, "last_", 5) == 0 || strcmp(de->d_name, "log") == 0) { - std::string path = android::base::StringPrintf("%s/%s", CACHE_LOG_DIR, de->d_name); - - struct stat sb; - if (stat(path.c_str(), &sb) == 0) { - // truncate files to 512kb - if (sb.st_size > (1 << 19)) { - sb.st_size = 1 << 19; - } - - std::string data(sb.st_size, '\0'); - FILE* f = fopen(path.c_str(), "rbe"); - fread(&data[0], 1, data.size(), f); - fclose(f); - - log_files.emplace_back(saved_log_file{ path, sb, data }); - } - } - } - } else { - if (errno != ENOENT) { - PLOG(ERROR) << "Failed to opendir " << CACHE_LOG_DIR; - } - } - } - - ui->Print("Formatting %s...\n", volume); - - ensure_path_unmounted(volume); - - int result; - if (is_data && reason && strcmp(reason, "convert_fbe") == 0) { - static constexpr const char* CONVERT_FBE_DIR = "/tmp/convert_fbe"; - static constexpr const char* CONVERT_FBE_FILE = "/tmp/convert_fbe/convert_fbe"; - // Create convert_fbe breadcrumb file to signal init to convert to file based encryption, not - // full disk encryption. - if (mkdir(CONVERT_FBE_DIR, 0700) != 0) { - PLOG(ERROR) << "Failed to mkdir " << CONVERT_FBE_DIR; - return false; - } - FILE* f = fopen(CONVERT_FBE_FILE, "wbe"); - if (!f) { - PLOG(ERROR) << "Failed to convert to file encryption"; - return false; - } - fclose(f); - result = format_volume(volume, CONVERT_FBE_DIR); - remove(CONVERT_FBE_FILE); - rmdir(CONVERT_FBE_DIR); - } else { - result = format_volume(volume); - } - - if (is_cache) { - // Re-create the log dir and write back the log entries. - if (ensure_path_mounted(CACHE_LOG_DIR) == 0 && - mkdir_recursively(CACHE_LOG_DIR, 0777, false, sehandle) == 0) { - for (const auto& log : log_files) { - if (!android::base::WriteStringToFile(log.data, log.name, log.sb.st_mode, log.sb.st_uid, - log.sb.st_gid)) { - PLOG(ERROR) << "Failed to write to " << log.name; - } - } - } else { - PLOG(ERROR) << "Failed to mount / create " << CACHE_LOG_DIR; - } - - // Any part of the log we'd copied to cache is now gone. - // Reset the pointer so we copy from the beginning of the temp - // log. - reset_tmplog_offset(); - copy_logs(modified_flash, has_cache); - } - - return (result == 0); -} - static bool yes_no(Device* device, const char* question1, const char* question2) { std::vector<std::string> headers{ question1, question2 }; std::vector<std::string> items{ " No", " Yes" }; @@ -292,28 +184,6 @@ static bool ask_to_wipe_data(Device* device) { return (chosen_item == 1); } -// Return true on success. -static bool wipe_data(Device* device) { - modified_flash = true; - - ui->Print("\n-- Wiping data...\n"); - bool success = device->PreWipeData(); - if (success) { - success &= erase_volume(DATA_ROOT); - if (has_cache) { - success &= erase_volume(CACHE_ROOT); - } - if (volume_for_mount_point(METADATA_ROOT) != nullptr) { - success &= erase_volume(METADATA_ROOT); - } - } - if (success) { - success &= device->PostWipeData(); - } - ui->Print("Data wipe %s.\n", success ? "complete" : "failed"); - return success; -} - static InstallResult prompt_and_wipe_data(Device* device) { // Use a single string and let ScreenRecoveryUI handles the wrapping. std::vector<std::string> wipe_data_menu_headers{ @@ -341,7 +211,8 @@ static InstallResult prompt_and_wipe_data(Device* device) { } if (ask_to_wipe_data(device)) { - if (wipe_data(device)) { + bool convert_fbe = reason && strcmp(reason, "convert_fbe") == 0; + if (WipeData(device, convert_fbe)) { return INSTALL_SUCCESS; } else { return INSTALL_ERROR; @@ -350,25 +221,6 @@ static InstallResult prompt_and_wipe_data(Device* device) { } } -// Return true on success. -static bool wipe_cache(bool should_confirm, Device* device) { - if (!has_cache) { - ui->Print("No /cache partition found.\n"); - return false; - } - - if (should_confirm && !yes_no(device, "Wipe cache?", " THIS CAN NOT BE UNDONE!")) { - return false; - } - - modified_flash = true; - - ui->Print("\n-- Wiping cache...\n"); - bool success = erase_volume("/cache"); - ui->Print("Cache wipe %s.\n", success ? "complete" : "failed"); - return success; -} - // Secure-wipe a given partition. It uses BLKSECDISCARD, if supported. Otherwise, it goes with // BLKDISCARD (if device supports BLKDISCARDZEROES) or BLKZEROOUT. static bool secure_wipe_partition(const std::string& partition) { @@ -653,7 +505,6 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) { ? Device::REBOOT : device->InvokeMenuItem(chosen_item); - bool should_wipe_cache = false; switch (chosen_action) { case Device::NO_ACTION: break; @@ -666,41 +517,40 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) { return chosen_action; case Device::WIPE_DATA: + save_current_log = true; if (ui->IsTextVisible()) { if (ask_to_wipe_data(device)) { - wipe_data(device); + WipeData(device, false); } } else { - wipe_data(device); + WipeData(device, false); return Device::NO_ACTION; } break; - case Device::WIPE_CACHE: - wipe_cache(ui->IsTextVisible(), device); + case Device::WIPE_CACHE: { + save_current_log = true; + std::function<bool()> confirm_func = [&device]() { + return yes_no(device, "Wipe cache?", " THIS CAN NOT BE UNDONE!"); + }; + WipeCache(ui, ui->IsTextVisible() ? confirm_func : nullptr); if (!ui->IsTextVisible()) return Device::NO_ACTION; break; - + } case Device::APPLY_ADB_SIDELOAD: case Device::APPLY_SDCARD: { - modified_flash = true; + save_current_log = true; bool adb = (chosen_action == Device::APPLY_ADB_SIDELOAD); if (adb) { - status = apply_from_adb(&should_wipe_cache, ui); + status = apply_from_adb(ui); } else { - status = ApplyFromSdcard(device, &should_wipe_cache, ui); - } - - if (status == INSTALL_SUCCESS && should_wipe_cache) { - if (!wipe_cache(false, device)) { - status = INSTALL_ERROR; - } + status = ApplyFromSdcard(device, ui); } if (status != INSTALL_SUCCESS) { ui->SetBackground(RecoveryUI::ERROR); ui->Print("Installation aborted.\n"); - copy_logs(modified_flash, has_cache); + copy_logs(save_current_log, has_cache, sehandle); } else if (!ui->IsTextVisible()) { return Device::NO_ACTION; // reboot if logs aren't visible } else { @@ -987,7 +837,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri if (update_package != nullptr) { // It's not entirely true that we will modify the flash. But we want // to log the update attempt since update_package is non-NULL. - modified_flash = true; + save_current_log = true; int required_battery_level; if (retry_count == 0 && !is_battery_ok(&required_battery_level)) { @@ -1009,11 +859,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri set_retry_bootloader_message(retry_count + 1, args); } - modified_flash = true; - status = install_package(update_package, &should_wipe_cache, true, retry_count, ui); - if (status == INSTALL_SUCCESS && should_wipe_cache) { - wipe_cache(false, device); - } + status = install_package(update_package, should_wipe_cache, true, retry_count, ui); if (status != INSTALL_SUCCESS) { ui->Print("Installation aborted.\n"); @@ -1021,7 +867,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri // RETRY_LIMIT times before we abandon this OTA update. static constexpr int RETRY_LIMIT = 4; if (status == INSTALL_RETRY && retry_count < RETRY_LIMIT) { - copy_logs(modified_flash, has_cache); + copy_logs(save_current_log, has_cache, sehandle); retry_count += 1; set_retry_bootloader_message(retry_count, args); // Print retry count on screen. @@ -1045,12 +891,14 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri } } } else if (should_wipe_data) { - if (!wipe_data(device)) { + save_current_log = true; + bool convert_fbe = reason && strcmp(reason, "convert_fbe") == 0; + if (!WipeData(device, convert_fbe)) { status = INSTALL_ERROR; } } else if (should_prompt_and_wipe_data) { // Trigger the logging to capture the cause, even if user chooses to not wipe data. - modified_flash = true; + save_current_log = true; ui->ShowText(true); ui->SetBackground(RecoveryUI::ERROR); @@ -1059,7 +907,8 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri ui->ShowText(false); } } else if (should_wipe_cache) { - if (!wipe_cache(false, device)) { + save_current_log = true; + if (!WipeCache(ui, nullptr)) { status = INSTALL_ERROR; } } else if (should_wipe_ab) { @@ -1073,15 +922,11 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri // sideload finishes even if there are errors. Unless one turns on the // text display during the installation. This is to enable automated // testing. + save_current_log = true; if (!sideload_auto_reboot) { ui->ShowText(true); } - status = apply_from_adb(&should_wipe_cache, ui); - if (status == INSTALL_SUCCESS && should_wipe_cache) { - if (!wipe_cache(false, device)) { - status = INSTALL_ERROR; - } - } + status = apply_from_adb(ui); ui->Print("\nInstall from ADB complete (status: %d).\n", status); if (sideload_auto_reboot) { ui->Print("Rebooting automatically.\n"); diff --git a/recovery_main.cpp b/recovery_main.cpp index 8b4ad5a32..8f3f2a781 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -50,7 +50,8 @@ #include "common.h" #include "fastboot/fastboot.h" -#include "logging.h" +#include "install/wipe_data.h" +#include "otautil/logging.h" #include "otautil/paths.h" #include "otautil/roots.h" #include "otautil/sysutil.h" @@ -434,6 +435,8 @@ int main(int argc, char** argv) { ui->Print("Warning: No file_contexts\n"); } + SetWipeDataSehandle(sehandle); + std::atomic<Device::BuiltinAction> action; std::thread listener_thread(ListenRecoverySocket, ui, std::ref(action)); listener_thread.detach(); |