Snap for 5681426 from 8c9388a1188ef98b9f36d5e8b6dbd462ad08f6e1 to qt-release
Change-Id: Icb6c28c84955a1f109dc2d4e536f0b3681fbc733
diff --git a/Android.bp b/Android.bp
index 4cefc42..e5cedd8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -68,6 +68,7 @@
"gsi_aidl_interface-cpp",
"libbase",
"libbinder",
+ "libext4_utils",
"libfs_mgr",
"libgsi",
"liblog",
diff --git a/aidl/android/gsi/IGsiService.aidl b/aidl/android/gsi/IGsiService.aidl
index 8a0201d..4ffdf62 100644
--- a/aidl/android/gsi/IGsiService.aidl
+++ b/aidl/android/gsi/IGsiService.aidl
@@ -172,4 +172,13 @@
* @return 0 on success, an error code on failure.
*/
int beginGsiInstall(in GsiInstallParams params);
+
+ /**
+ * Wipe the userdata of an existing GSI install. This will not work if the
+ * GSI is currently running. The userdata image will not be removed, but the
+ * first block will be zeroed ensuring that the next GSI boot formats /data.
+ *
+ * @return 0 on success, an error code on failure.
+ */
+ int wipeGsiUserdata();
}
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 615f77e..3efec40 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -34,6 +34,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android/gsi/IGsiService.h>
+#include <ext4_utils/ext4_utils.h>
#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
#include <fstab/fstab.h>
@@ -372,6 +373,20 @@
return binder::Status::ok();
}
+binder::Status GsiService::wipeGsiUserdata(int* _aidl_return) {
+ ENFORCE_SYSTEM_OR_SHELL;
+ std::lock_guard<std::mutex> guard(main_lock_);
+
+ if (IsGsiRunning() || !IsGsiInstalled()) {
+ *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
+ return binder::Status::ok();
+ }
+
+ *_aidl_return = WipeUserdata();
+
+ return binder::Status::ok();
+}
+
binder::Status GsiService::CheckUid(AccessLevel level) {
std::vector<uid_t> allowed_uids{AID_ROOT, AID_SYSTEM};
if (level == AccessLevel::SystemOrShell) {
@@ -726,6 +741,7 @@
}
return true;
}
+ uint64_t Size() override { return get_block_device_size(fd_); }
private:
std::string path_;
@@ -743,6 +759,7 @@
bool Flush() override {
return writer_->Flush();
}
+ uint64_t Size() override { return writer_->size(); }
private:
SplitFiemap* writer_;
@@ -933,6 +950,53 @@
return INSTALL_OK;
}
+int GsiService::WipeUserdata() {
+ // Note: this metadata is only used to recover the original partition sizes.
+ // We do not trust the extent information, which will get rebuilt later.
+ auto old_metadata = ReadFromImageFile(kGsiLpMetadataFile);
+ if (!old_metadata) {
+ LOG(ERROR) << "GSI install is incomplete";
+ return INSTALL_ERROR_GENERIC;
+ }
+
+ install_dir_ = GetInstalledImageDir();
+ system_gsi_path_ = GetImagePath(install_dir_, "system_gsi");
+ if (int error = DetermineReadWriteMethod()) {
+ return error;
+ }
+
+ // Recover parition information.
+ Image userdata_image;
+ if (int error = GetExistingImage(*old_metadata.get(), "userdata_gsi", &userdata_image)) {
+ return error;
+ }
+ partitions_.emplace(std::make_pair("userdata_gsi", std::move(userdata_image)));
+
+ metadata_ = CreateMetadata();
+ if (!metadata_) {
+ return INSTALL_ERROR_GENERIC;
+ }
+
+ auto writer = OpenPartition("userdata_gsi");
+ if (!writer) {
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+
+ // Wipe the first 1MiB of the device, ensuring both the first block and
+ // the superblock are destroyed.
+ static constexpr uint64_t kEraseSize = 1024 * 1024;
+
+ std::string zeroes(4096, 0);
+ uint64_t erase_size = std::min(kEraseSize, writer->Size());
+ for (uint64_t i = 0; i < erase_size; i += zeroes.size()) {
+ if (!writer->Write(zeroes.data(), zeroes.size())) {
+ PLOG(ERROR) << "write userdata_gsi";
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+ }
+ return INSTALL_OK;
+}
+
static uint64_t GetPartitionSize(const LpMetadata& metadata, const LpMetadataPartition& partition) {
uint64_t total = 0;
for (size_t i = 0; i < partition.num_extents; i++) {
diff --git a/gsi_service.h b/gsi_service.h
index 8ec69a3..30b5782 100644
--- a/gsi_service.h
+++ b/gsi_service.h
@@ -58,6 +58,7 @@
binder::Status getUserdataImageSize(int64_t* _aidl_return) override;
binder::Status getGsiBootStatus(int* _aidl_return) override;
binder::Status getInstalledGsiImageDir(std::string* _aidl_return) override;
+ binder::Status wipeGsiUserdata(int* _aidl_return) override;
static char const* getServiceName() { return kGsiServiceName; }
@@ -70,6 +71,7 @@
virtual ~WriteHelper() {};
virtual bool Write(const void* data, uint64_t bytes) = 0;
virtual bool Flush() = 0;
+ virtual uint64_t Size() = 0;
WriteHelper() = default;
WriteHelper(const WriteHelper&) = delete;
@@ -100,6 +102,7 @@
bool CommitGsiChunk(const void* data, size_t bytes);
int SetGsiBootable(bool one_shot);
int ReenableGsi(bool one_shot);
+ int WipeUserdata();
bool DisableGsiInstall();
bool AddPartitionFiemap(android::fs_mgr::MetadataBuilder* builder,
android::fs_mgr::Partition* partition, const Image& image,
diff --git a/gsi_tool.cpp b/gsi_tool.cpp
index a9a6920..ee6094b 100644
--- a/gsi_tool.cpp
+++ b/gsi_tool.cpp
@@ -45,6 +45,7 @@
static int Enable(sp<IGsiService> gsid, int argc, char** argv);
static int Install(sp<IGsiService> gsid, int argc, char** argv);
static int Wipe(sp<IGsiService> gsid, int argc, char** argv);
+static int WipeData(sp<IGsiService> gsid, int argc, char** argv);
static int Status(sp<IGsiService> gsid, int argc, char** argv);
static int Cancel(sp<IGsiService> gsid, int argc, char** argv);
@@ -53,6 +54,7 @@
{"enable", Enable},
{"install", Install},
{"wipe", Wipe},
+ {"wipe-data", WipeData},
{"status", Status},
{"cancel", Cancel},
};
@@ -330,6 +332,43 @@
return 0;
}
+static int WipeData(sp<IGsiService> gsid, int argc, char** /* argv */) {
+ if (argc > 1) {
+ std::cerr << "Unrecognized arguments to wipe-data.\n";
+ return EX_USAGE;
+ }
+
+ bool running;
+ auto status = gsid->isGsiRunning(&running);
+ if (!status.isOk()) {
+ std::cerr << "error: " << status.exceptionMessage().string() << std::endl;
+ return EX_SOFTWARE;
+ }
+ if (running) {
+ std::cerr << "Cannot wipe GSI userdata while running a GSI.\n";
+ return EX_USAGE;
+ }
+
+ bool installed;
+ status = gsid->isGsiInstalled(&installed);
+ if (!status.isOk()) {
+ std::cerr << "error: " << status.exceptionMessage().string() << std::endl;
+ return EX_SOFTWARE;
+ }
+ if (!installed) {
+ std::cerr << "No GSI is installed.\n";
+ return EX_USAGE;
+ }
+
+ int error;
+ status = gsid->wipeGsiUserdata(&error);
+ if (!status.isOk() || error) {
+ std::cerr << "Could not wipe GSI userdata: " << ErrorMessage(status, error) << "\n";
+ return EX_SOFTWARE;
+ }
+ return 0;
+}
+
static int Status(sp<IGsiService> gsid, int argc, char** /* argv */) {
if (argc > 1) {
std::cerr << "Unrecognized arguments to status." << std::endl;
@@ -459,6 +498,7 @@
" --userdata-size (the latter defaults to 8GiB)\n"
" --wipe (remove old gsi userdata first)\n"
" wipe Completely remove a GSI and its associated data\n"
+ " wipe-data Ensure the GSI's userdata will be formatted\n"
" cancel Cancel the installation\n"
" status Show status\n",
argv[0], argv[0]);