diff options
author | Tianjie Xu <xunchang@google.com> | 2019-04-16 00:34:19 +0200 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-04-16 00:34:19 +0200 |
commit | 9fc764f1f0e6c4c581a5236d7558d97a1f90b38e (patch) | |
tree | c1ebcae66a7fbf7aaa79a6c1d894f2fa708ac441 /install | |
parent | Merge "Import translations. DO NOT MERGE" (diff) | |
parent | Move wipe cache|data to libinstall (diff) | |
download | android_bootable_recovery-9fc764f1f0e6c4c581a5236d7558d97a1f90b38e.tar android_bootable_recovery-9fc764f1f0e6c4c581a5236d7558d97a1f90b38e.tar.gz android_bootable_recovery-9fc764f1f0e6c4c581a5236d7558d97a1f90b38e.tar.bz2 android_bootable_recovery-9fc764f1f0e6c4c581a5236d7558d97a1f90b38e.tar.lz android_bootable_recovery-9fc764f1f0e6c4c581a5236d7558d97a1f90b38e.tar.xz android_bootable_recovery-9fc764f1f0e6c4c581a5236d7558d97a1f90b38e.tar.zst android_bootable_recovery-9fc764f1f0e6c4c581a5236d7558d97a1f90b38e.zip |
Diffstat (limited to 'install')
-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 |
9 files changed, 249 insertions, 18 deletions
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 |