summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.bp6
-rw-r--r--fsck_unshare_blocks.cpp1
-rw-r--r--fuse_sideload/include/fuse_provider.h23
-rw-r--r--install/Android.bp2
-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.h30
-rw-r--r--install/install.cpp18
-rw-r--r--install/wipe_data.cpp123
-rw-r--r--minadbd/fuse_adb_provider.h15
-rw-r--r--minadbd/minadbd_services.cpp3
-rw-r--r--otautil/Android.bp5
-rw-r--r--otautil/include/otautil/logging.h (renamed from logging.h)19
-rw-r--r--otautil/logging.cpp (renamed from logging.cpp)125
-rw-r--r--recovery-persist.cpp2
-rw-r--r--recovery-refresh.cpp2
-rw-r--r--recovery.cpp217
-rw-r--r--recovery_main.cpp5
-rw-r--r--tests/component/sideload_test.cpp22
22 files changed, 376 insertions, 268 deletions
diff --git a/Android.bp b/Android.bp
index dd18a89ad..0eb5fd9e5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -76,7 +76,6 @@ cc_defaults {
// external dependencies
"libhealthhalutils",
- "libfstab",
],
}
@@ -108,7 +107,6 @@ cc_binary {
],
srcs: [
- "logging.cpp",
"recovery_main.cpp",
],
@@ -140,7 +138,6 @@ cc_binary {
],
srcs: [
- "logging.cpp",
"recovery-persist.cpp",
],
@@ -152,7 +149,6 @@ cc_binary {
static_libs: [
"libotautil",
- "libfstab",
],
init_rc: [
@@ -169,7 +165,6 @@ cc_binary {
],
srcs: [
- "logging.cpp",
"recovery-refresh.cpp",
],
@@ -180,7 +175,6 @@ cc_binary {
static_libs: [
"libotautil",
- "libfstab",
],
init_rc: [
diff --git a/fsck_unshare_blocks.cpp b/fsck_unshare_blocks.cpp
index e74f8ba6f..0f8ffface 100644
--- a/fsck_unshare_blocks.cpp
+++ b/fsck_unshare_blocks.cpp
@@ -34,7 +34,6 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/unique_fd.h>
-#include <fstab/fstab.h>
#include "otautil/roots.h"
diff --git a/fuse_sideload/include/fuse_provider.h b/fuse_sideload/include/fuse_provider.h
index 499d57aa0..59059cf9b 100644
--- a/fuse_sideload/include/fuse_provider.h
+++ b/fuse_sideload/include/fuse_provider.h
@@ -25,8 +25,8 @@
// This is the base class to read data from source and provide the data to FUSE.
class FuseDataProvider {
public:
- FuseDataProvider(android::base::unique_fd&& fd, uint64_t file_size, uint32_t block_size)
- : fd_(std::move(fd)), file_size_(file_size), fuse_block_size_(block_size) {}
+ FuseDataProvider(uint64_t file_size, uint32_t block_size)
+ : file_size_(file_size), fuse_block_size_(block_size) {}
virtual ~FuseDataProvider() = default;
@@ -37,21 +37,15 @@ class FuseDataProvider {
return fuse_block_size_;
}
- bool Valid() const {
- return fd_ != -1;
- }
-
// Reads |fetch_size| bytes data starting from |start_block|. Puts the result in |buffer|.
virtual bool ReadBlockAlignedData(uint8_t* buffer, uint32_t fetch_size,
uint32_t start_block) const = 0;
- virtual void Close() = 0;
+ virtual void Close() {}
protected:
FuseDataProvider() = default;
- // The underlying source to read data from.
- android::base::unique_fd fd_;
// Size in bytes of the file to read.
uint64_t file_size_ = 0;
// Block size passed to the fuse, this is different from the block size of the block device.
@@ -61,13 +55,18 @@ class FuseDataProvider {
// This class reads data from a file.
class FuseFileDataProvider : public FuseDataProvider {
public:
- FuseFileDataProvider(android::base::unique_fd&& fd, uint64_t file_size, uint32_t block_size)
- : FuseDataProvider(std::move(fd), file_size, block_size) {}
-
FuseFileDataProvider(const std::string& path, uint32_t block_size);
bool ReadBlockAlignedData(uint8_t* buffer, uint32_t fetch_size,
uint32_t start_block) const override;
+ bool Valid() const {
+ return fd_ != -1;
+ }
+
void Close() override;
+
+ private:
+ // The underlying source to read data from.
+ android::base::unique_fd fd_;
};
diff --git a/install/Android.bp b/install/Android.bp
index ce4244ca4..b18e29021 100644
--- a/install/Android.bp
+++ b/install/Android.bp
@@ -47,7 +47,6 @@ cc_defaults {
// external dependencies
"libvintf_recovery",
"libvintf",
- "libfstab",
],
}
@@ -66,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..b34891f3d
--- /dev/null
+++ b/install/include/install/wipe_data.h
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+// 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..765a8152b
--- /dev/null
+++ b/install/wipe_data.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <functional>
+#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";
+
+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.
+ log_files = ReadLogFilesToMemory();
+ }
+
+ 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) {
+ RestoreLogFilesAfterFormat(log_files);
+ }
+
+ 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/minadbd/fuse_adb_provider.h b/minadbd/fuse_adb_provider.h
index 3fb689bd4..24a463d9b 100644
--- a/minadbd/fuse_adb_provider.h
+++ b/minadbd/fuse_adb_provider.h
@@ -14,25 +14,24 @@
* limitations under the License.
*/
-#ifndef __FUSE_ADB_PROVIDER_H
-#define __FUSE_ADB_PROVIDER_H
+#pragma once
#include <stdint.h>
-#include "android-base/unique_fd.h"
-
#include "fuse_provider.h"
// This class reads data from adb server.
class FuseAdbDataProvider : public FuseDataProvider {
public:
- FuseAdbDataProvider(android::base::unique_fd&& fd, uint64_t file_size, uint32_t block_size)
- : FuseDataProvider(std::move(fd), file_size, block_size) {}
+ FuseAdbDataProvider(int fd, uint64_t file_size, uint32_t block_size)
+ : FuseDataProvider(file_size, block_size), fd_(fd) {}
bool ReadBlockAlignedData(uint8_t* buffer, uint32_t fetch_size,
uint32_t start_block) const override;
void Close() override;
-};
-#endif
+ private:
+ // The underlying source to read data from (i.e. the one that talks to the host).
+ int fd_;
+};
diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp
index 79e6fc4e0..f2b65c09b 100644
--- a/minadbd/minadbd_services.cpp
+++ b/minadbd/minadbd_services.cpp
@@ -96,8 +96,7 @@ static void sideload_host_service(unique_fd sfd, const std::string& args) {
exit(kMinadbdSocketIOError);
}
- auto adb_data_reader =
- std::make_unique<FuseAdbDataProvider>(std::move(sfd), file_size, block_size);
+ auto adb_data_reader = std::make_unique<FuseAdbDataProvider>(sfd, file_size, block_size);
if (int result = run_fuse_sideload(std::move(adb_data_reader)); result != 0) {
LOG(ERROR) << "Failed to start fuse";
exit(kMinadbdFuseStartError);
diff --git a/otautil/Android.bp b/otautil/Android.bp
index b4936c08b..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",
@@ -61,6 +62,10 @@ cc_library_static {
"libfs_mgr",
"libselinux",
],
+
+ export_static_lib_headers: [
+ "libfstab",
+ ],
},
},
}
diff --git a/logging.h b/otautil/include/otautil/logging.h
index 3cfbc7af6..608349785 100644
--- a/logging.h
+++ b/otautil/include/otautil/logging.h
@@ -18,14 +18,26 @@
#define _LOGGING_H
#include <stddef.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <string>
+#include <vector>
#include <log/log_id.h>
static constexpr int KEEP_LOG_COUNT = 10;
+struct selabel_handle;
+
+struct saved_log_file {
+ std::string name;
+ struct stat sb;
+ std::string data;
+};
+
+void SetLoggingSehandle(selabel_handle* handle);
+
ssize_t logbasename(log_id_t id, char prio, const char* filename, const char* buf, size_t len,
void* arg);
@@ -41,10 +53,13 @@ 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);
+std::vector<saved_log_file> ReadLogFilesToMemory();
+
+bool RestoreLogFilesAfterFormat(const std::vector<saved_log_file>& log_files);
+
#endif //_LOGGING_H
diff --git a/logging.cpp b/otautil/logging.cpp
index 48f9ec317..484f1150f 100644
--- a/logging.cpp
+++ b/otautil/logging.cpp
@@ -14,38 +14,51 @@
* limitations under the License.
*/
-#include "logging.h"
+#include "otautil/logging.h"
+#include <dirent.h>
+#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/klog.h>
#include <sys/types.h>
+#include <algorithm>
+#include <memory>
#include <string>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.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"
-static constexpr const char* LOG_FILE = "/cache/recovery/log";
-static constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install";
-static constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
-static constexpr const char* LAST_LOG_FILE = "/cache/recovery/last_log";
+constexpr const char* LOG_FILE = "/cache/recovery/log";
+constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install";
+constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
+constexpr const char* LAST_LOG_FILE = "/cache/recovery/last_log";
-static const std::string LAST_KMSG_FILTER = "recovery/last_kmsg";
-static const std::string LAST_LOG_FILTER = "recovery/last_log";
+constexpr const char* LAST_KMSG_FILTER = "recovery/last_kmsg";
+constexpr const char* LAST_LOG_FILTER = "recovery/last_log";
+
+constexpr const char* CACHE_LOG_DIR = "/cache/recovery";
+
+static struct selabel_handle* logging_sehandle;
+
+void SetLoggingSehandle(selabel_handle* handle) {
+ logging_sehandle = handle;
+}
// 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;
@@ -74,8 +87,8 @@ void check_and_fclose(FILE* fp, const std::string& name) {
ssize_t logbasename(log_id_t /* id */, char /* prio */, const char* filename, const char* /* buf */,
size_t len, void* arg) {
bool* do_rotate = static_cast<bool*>(arg);
- if (LAST_KMSG_FILTER.find(filename) != std::string::npos ||
- LAST_LOG_FILTER.find(filename) != std::string::npos) {
+ if (std::string(LAST_KMSG_FILTER).find(filename) != std::string::npos ||
+ std::string(LAST_LOG_FILTER).find(filename) != std::string::npos) {
*do_rotate = true;
}
return len;
@@ -92,8 +105,8 @@ ssize_t logrotate(log_id_t id, char prio, const char* filename, const char* buf,
size_t dot = name.find_last_of('.');
std::string sub = name.substr(0, dot);
- if (LAST_KMSG_FILTER.find(sub) == std::string::npos &&
- LAST_LOG_FILTER.find(sub) == std::string::npos) {
+ if (std::string(LAST_KMSG_FILTER).find(sub) == std::string::npos &&
+ std::string(LAST_LOG_FILTER).find(sub) == std::string::npos) {
return __android_log_pmsg_file_write(id, prio, filename, buf, len);
}
@@ -165,8 +178,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 +203,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 +225,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);
@@ -242,3 +256,70 @@ void save_kernel_log(const char* destination) {
buffer.resize(n);
android::base::WriteStringToFile(buffer, destination);
}
+
+std::vector<saved_log_file> ReadLogFilesToMemory() {
+ ensure_path_mounted("/cache");
+
+ struct dirent* de;
+ std::unique_ptr<DIR, decltype(&closedir)> d(opendir(CACHE_LOG_DIR), closedir);
+ if (!d) {
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "Failed to opendir " << CACHE_LOG_DIR;
+ }
+ return {};
+ }
+
+ std::vector<saved_log_file> log_files;
+ 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) {
+ PLOG(ERROR) << "Failed to stat " << path;
+ continue;
+ }
+ // Truncate files to 512kb
+ size_t read_size = std::min<size_t>(sb.st_size, 1 << 19);
+ std::string data(read_size, '\0');
+
+ android::base::unique_fd log_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY)));
+ if (log_fd == -1 || !android::base::ReadFully(log_fd, data.data(), read_size)) {
+ PLOG(ERROR) << "Failed to read log file " << path;
+ continue;
+ }
+
+ log_files.emplace_back(saved_log_file{ path, sb, data });
+ }
+ }
+
+ return log_files;
+}
+
+bool RestoreLogFilesAfterFormat(const std::vector<saved_log_file>& log_files) {
+ // Re-create the log dir and write back the log entries.
+ if (ensure_path_mounted(CACHE_LOG_DIR) != 0) {
+ PLOG(ERROR) << "Failed to mount " << CACHE_LOG_DIR;
+ return false;
+ }
+
+ if (mkdir_recursively(CACHE_LOG_DIR, 0777, false, logging_sehandle) != 0) {
+ PLOG(ERROR) << "Failed to create " << CACHE_LOG_DIR;
+ return false;
+ }
+
+ 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;
+ }
+ }
+
+ // 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 */, logging_sehandle);
+
+ return true;
+}
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..5f3ab76dd 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");
}
+ SetLoggingSehandle(sehandle);
+
std::atomic<Device::BuiltinAction> action;
std::thread listener_thread(ListenRecoverySocket, ui, std::ref(action));
listener_thread.detach();
diff --git a/tests/component/sideload_test.cpp b/tests/component/sideload_test.cpp
index f5981acbd..6add99f41 100644
--- a/tests/component/sideload_test.cpp
+++ b/tests/component/sideload_test.cpp
@@ -22,7 +22,6 @@
#include <android-base/file.h>
#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
#include "fuse_provider.h"
@@ -32,17 +31,26 @@ TEST(SideloadTest, fuse_device) {
ASSERT_EQ(0, access("/dev/fuse", R_OK | W_OK));
}
+class FuseTestDataProvider : public FuseDataProvider {
+ public:
+ FuseTestDataProvider(uint64_t file_size, uint32_t block_size)
+ : FuseDataProvider(file_size, block_size) {}
+
+ private:
+ bool ReadBlockAlignedData(uint8_t*, uint32_t, uint32_t) const override {
+ return true;
+ }
+};
+
TEST(SideloadTest, run_fuse_sideload_wrong_parameters) {
- auto provider_small_block =
- std::make_unique<FuseFileDataProvider>(android::base::unique_fd(), 4096, 4095);
+ auto provider_small_block = std::make_unique<FuseTestDataProvider>(4096, 4095);
ASSERT_EQ(-1, run_fuse_sideload(std::move(provider_small_block)));
- auto provider_large_block =
- std::make_unique<FuseFileDataProvider>(android::base::unique_fd(), 4096, (1 << 22) + 1);
+ auto provider_large_block = std::make_unique<FuseTestDataProvider>(4096, (1 << 22) + 1);
ASSERT_EQ(-1, run_fuse_sideload(std::move(provider_large_block)));
- auto provider_too_many_blocks = std::make_unique<FuseFileDataProvider>(
- android::base::unique_fd(), ((1 << 18) + 1) * 4096, 4096);
+ auto provider_too_many_blocks =
+ std::make_unique<FuseTestDataProvider>(((1 << 18) + 1) * 4096, 4096);
ASSERT_EQ(-1, run_fuse_sideload(std::move(provider_too_many_blocks)));
}