summaryrefslogtreecommitdiffstats
path: root/install
diff options
context:
space:
mode:
authorxunchang <xunchang@google.com>2019-04-13 01:22:15 +0200
committerxunchang <xunchang@google.com>2019-04-15 21:22:11 +0200
commit316e9717461890dd319dc370970069fe4532a561 (patch)
treebe9173eec48b83689ea9c4222e660a6341ece9d3 /install
parentMerge "Add socket communication between recovery and minadbd" (diff)
downloadandroid_bootable_recovery-316e9717461890dd319dc370970069fe4532a561.tar
android_bootable_recovery-316e9717461890dd319dc370970069fe4532a561.tar.gz
android_bootable_recovery-316e9717461890dd319dc370970069fe4532a561.tar.bz2
android_bootable_recovery-316e9717461890dd319dc370970069fe4532a561.tar.lz
android_bootable_recovery-316e9717461890dd319dc370970069fe4532a561.tar.xz
android_bootable_recovery-316e9717461890dd319dc370970069fe4532a561.tar.zst
android_bootable_recovery-316e9717461890dd319dc370970069fe4532a561.zip
Diffstat (limited to 'install')
-rw-r--r--install/Android.bp1
-rw-r--r--install/adb_install.cpp9
-rw-r--r--install/fuse_sdcard_install.cpp4
-rw-r--r--install/include/install/adb_install.h2
-rw-r--r--install/include/install/fuse_sdcard_install.h2
-rw-r--r--install/include/install/install.h9
-rw-r--r--install/include/install/wipe_data.h32
-rw-r--r--install/install.cpp18
-rw-r--r--install/wipe_data.cpp190
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