Merge QQ3A.200605.002 into master

Bug: 158095402
Merged-In: Ia91690b4826ce358a08766ebe6e756cb1fec0ba1
Change-Id: Ic755f590685f40ee90c08c7c8be3a62e56b98cd5
This commit is contained in:
Xin Li 2020-06-03 10:44:41 -07:00
commit 674edaf2ed
6 changed files with 87 additions and 1 deletions

View file

@ -72,6 +72,7 @@ cc_defaults {
], ],
static_libs: [ static_libs: [
"libc++fs",
"libinstall", "libinstall",
"librecovery_fastboot", "librecovery_fastboot",
"libminui", "libminui",
@ -95,6 +96,7 @@ cc_library_static {
], ],
shared_libs: [ shared_libs: [
"libfusesideload",
"librecovery_ui", "librecovery_ui",
], ],
} }

View file

@ -63,3 +63,7 @@ bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::st
// pre-device and serial number (if presents). A/B OTA specific checks: pre-build version, // pre-device and serial number (if presents). A/B OTA specific checks: pre-build version,
// fingerprint, timestamp. // fingerprint, timestamp.
bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type); bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type);
// Ensures the path to the update package is mounted. Also set the |should_use_fuse| to true if the
// package stays on a removable media.
bool SetupPackageMount(const std::string& package_path, bool* should_use_fuse);

View file

@ -30,6 +30,7 @@
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include <condition_variable> #include <condition_variable>
#include <filesystem>
#include <functional> #include <functional>
#include <limits> #include <limits>
#include <mutex> #include <mutex>
@ -652,3 +653,49 @@ bool verify_package(Package* package, RecoveryUI* ui) {
} }
return true; return true;
} }
bool SetupPackageMount(const std::string& package_path, bool* should_use_fuse) {
CHECK(should_use_fuse != nullptr);
if (package_path.empty()) {
return false;
}
*should_use_fuse = true;
if (package_path[0] == '@') {
auto block_map_path = package_path.substr(1);
if (ensure_path_mounted(block_map_path) != 0) {
LOG(ERROR) << "Failed to mount " << block_map_path;
return false;
}
// uncrypt only produces block map only if the package stays on /data.
*should_use_fuse = false;
return true;
}
// Package is not a block map file.
if (ensure_path_mounted(package_path) != 0) {
LOG(ERROR) << "Failed to mount " << package_path;
return false;
}
// Reject the package if the input path doesn't equal the canonicalized path.
// e.g. /cache/../sdcard/update_package.
std::error_code ec;
auto canonical_path = std::filesystem::canonical(package_path, ec);
if (ec) {
LOG(ERROR) << "Failed to get canonical of " << package_path << ", " << ec.message();
return false;
}
if (canonical_path.string() != package_path) {
LOG(ERROR) << "Installation aborts. The canonical path " << canonical_path.string()
<< " doesn't equal the original path " << package_path;
return false;
}
constexpr const char* CACHE_ROOT = "/cache";
if (android::base::StartsWith(package_path, CACHE_ROOT)) {
*should_use_fuse = false;
}
return true;
}

View file

@ -752,7 +752,11 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
ensure_path_mounted(update_package); ensure_path_mounted(update_package);
} }
if (install_with_fuse) { bool should_use_fuse = false;
if (!SetupPackageMount(update_package, &should_use_fuse)) {
LOG(INFO) << "Failed to set up the package access, skipping installation";
status = INSTALL_ERROR;
} else if (install_with_fuse || should_use_fuse) {
LOG(INFO) << "Installing package " << update_package << " with fuse"; LOG(INFO) << "Installing package " << update_package << " with fuse";
status = InstallWithFuseFromPath(update_package, ui); status = InstallWithFuseFromPath(update_package, ui);
} else if (auto memory_package = Package::CreateMemoryPackage( } else if (auto memory_package = Package::CreateMemoryPackage(

View file

@ -92,6 +92,7 @@ librecovery_static_libs = [
"libhidlbase", "libhidlbase",
"liblp", "liblp",
"libtinyxml2", "libtinyxml2",
"libc++fs",
] ]
// recovery image for unittests. // recovery image for unittests.

View file

@ -35,6 +35,7 @@
#include "install/wipe_device.h" #include "install/wipe_device.h"
#include "otautil/paths.h" #include "otautil/paths.h"
#include "private/setup_commands.h" #include "private/setup_commands.h"
#include "recovery_utils/roots.h"
static void BuildZipArchive(const std::map<std::string, std::string>& file_map, int fd, static void BuildZipArchive(const std::map<std::string, std::string>& file_map, int fd,
int compression_type) { int compression_type) {
@ -513,3 +514,30 @@ TEST(InstallTest, CheckPackageMetadata_ab_post_timestamp) {
"\n"); "\n");
TestCheckPackageMetadata(metadata, OtaType::AB, true); TestCheckPackageMetadata(metadata, OtaType::AB, true);
} }
TEST(InstallTest, SetupPackageMount_package_path) {
load_volume_table();
bool install_with_fuse;
// Setup should fail if the input path doesn't exist.
ASSERT_FALSE(SetupPackageMount("/does_not_exist", &install_with_fuse));
// Package should be installed with fuse if it's not in /cache.
TemporaryDir temp_dir;
TemporaryFile update_package(temp_dir.path);
ASSERT_TRUE(SetupPackageMount(update_package.path, &install_with_fuse));
ASSERT_TRUE(install_with_fuse);
// Setup should fail if the input path isn't canonicalized.
std::string uncanonical_package_path = android::base::Join(
std::vector<std::string>{
temp_dir.path,
"..",
android::base::Basename(temp_dir.path),
android::base::Basename(update_package.path),
},
'/');
ASSERT_EQ(0, access(uncanonical_package_path.c_str(), R_OK));
ASSERT_FALSE(SetupPackageMount(uncanonical_package_path, &install_with_fuse));
}