Introduce a library to contain gsid's image creation logic.
README.md contains a full explanation. GsiInstaller's logic will be
removed in a follow-up CL.
Bug: 134536978
Test: libgsi_image_test gtest
Change-Id: I76f273e06bd8633c6c16e3f3c76ade28e59efe6f
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 3d04fe1..3ee2e12 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -32,8 +32,10 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <android/gsi/BnImageManager.h>
#include <android/gsi/IGsiService.h>
#include <fs_mgr.h>
+#include <libfiemap/image_manager.h>
#include <private/android_filesystem_config.h>
#include "file_paths.h"
@@ -86,7 +88,7 @@
binder::Status GsiService::beginGsiInstall(const GsiInstallParams& given_params,
int* _aidl_return) {
ENFORCE_SYSTEM;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
// Make sure any interrupted installations are cleaned up.
installer_ = nullptr;
@@ -111,7 +113,7 @@
binder::Status GsiService::commitGsiChunkFromStream(const android::os::ParcelFileDescriptor& stream,
int64_t bytes, bool* _aidl_return) {
ENFORCE_SYSTEM;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
if (!installer_) {
*_aidl_return = false;
@@ -153,7 +155,7 @@
binder::Status GsiService::commitGsiChunkFromMemory(const std::vector<uint8_t>& bytes,
bool* _aidl_return) {
ENFORCE_SYSTEM;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
if (!installer_) {
*_aidl_return = false;
@@ -165,7 +167,7 @@
}
binder::Status GsiService::setGsiBootable(bool one_shot, int* _aidl_return) {
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
if (installer_) {
ENFORCE_SYSTEM;
@@ -185,7 +187,7 @@
binder::Status GsiService::isGsiEnabled(bool* _aidl_return) {
ENFORCE_SYSTEM_OR_SHELL;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
std::string boot_key;
if (!GetInstallStatus(&boot_key)) {
*_aidl_return = false;
@@ -197,7 +199,7 @@
binder::Status GsiService::removeGsiInstall(bool* _aidl_return) {
ENFORCE_SYSTEM_OR_SHELL;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
// Just in case an install was left hanging.
std::string install_dir;
@@ -218,7 +220,7 @@
binder::Status GsiService::disableGsiInstall(bool* _aidl_return) {
ENFORCE_SYSTEM_OR_SHELL;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
*_aidl_return = DisableGsiInstall();
return binder::Status::ok();
@@ -226,7 +228,7 @@
binder::Status GsiService::isGsiRunning(bool* _aidl_return) {
ENFORCE_SYSTEM_OR_SHELL;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
*_aidl_return = IsGsiRunning();
return binder::Status::ok();
@@ -234,7 +236,7 @@
binder::Status GsiService::isGsiInstalled(bool* _aidl_return) {
ENFORCE_SYSTEM_OR_SHELL;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
*_aidl_return = IsGsiInstalled();
return binder::Status::ok();
@@ -242,7 +244,7 @@
binder::Status GsiService::isGsiInstallInProgress(bool* _aidl_return) {
ENFORCE_SYSTEM_OR_SHELL;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
*_aidl_return = !!installer_;
return binder::Status::ok();
@@ -251,7 +253,7 @@
binder::Status GsiService::cancelGsiInstall(bool* _aidl_return) {
ENFORCE_SYSTEM;
should_abort_ = true;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
should_abort_ = false;
installer_ = nullptr;
@@ -262,7 +264,7 @@
binder::Status GsiService::getGsiBootStatus(int* _aidl_return) {
ENFORCE_SYSTEM_OR_SHELL;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
if (!IsGsiInstalled()) {
*_aidl_return = BOOT_STATUS_NOT_INSTALLED;
@@ -301,7 +303,7 @@
binder::Status GsiService::getUserdataImageSize(int64_t* _aidl_return) {
ENFORCE_SYSTEM;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
*_aidl_return = -1;
@@ -341,7 +343,7 @@
binder::Status GsiService::getInstalledGsiImageDir(std::string* _aidl_return) {
ENFORCE_SYSTEM;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
if (IsGsiInstalled()) {
*_aidl_return = GetInstalledImageDir();
@@ -351,7 +353,7 @@
binder::Status GsiService::wipeGsiUserdata(int* _aidl_return) {
ENFORCE_SYSTEM_OR_SHELL;
- std::lock_guard<std::mutex> guard(main_lock_);
+ std::lock_guard<std::mutex> guard(lock_);
if (IsGsiRunning() || !IsGsiInstalled()) {
*_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
@@ -364,6 +366,124 @@
return binder::Status::ok();
}
+static binder::Status BinderError(const std::string& message) {
+ return binder::Status::fromExceptionCode(binder::Status::EX_SERVICE_SPECIFIC,
+ String8(message.c_str()));
+}
+
+static binder::Status UidSecurityError() {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ auto message = StringPrintf("UID %d is not allowed", uid);
+ return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
+}
+
+class ImageManagerService : public BinderService<ImageManagerService>, public BnImageManager {
+ public:
+ ImageManagerService(GsiService* parent, std::unique_ptr<ImageManager>&& impl, uid_t uid);
+ binder::Status createBackingImage(const std::string& name, int64_t size,
+ bool readonly) override;
+ binder::Status deleteBackingImage(const std::string& name) override;
+ binder::Status mapImageDevice(const std::string& name, int32_t timeout_ms,
+ MappedImage* mapping) override;
+ binder::Status unmapImageDevice(const std::string& name) override;
+
+ private:
+ bool CheckUid();
+
+ android::sp<GsiService> parent_;
+ std::unique_ptr<ImageManager> impl_;
+ uid_t uid_;
+};
+
+ImageManagerService::ImageManagerService(GsiService* parent, std::unique_ptr<ImageManager>&& impl,
+ uid_t uid)
+ : parent_(parent), impl_(std::move(impl)), uid_(uid) {}
+
+binder::Status ImageManagerService::createBackingImage(const std::string& name, int64_t size,
+ bool readonly) {
+ if (!CheckUid()) return UidSecurityError();
+
+ std::lock_guard<std::mutex> guard(*parent_->lock());
+
+ if (!impl_->CreateBackingImage(name, size, readonly, nullptr)) {
+ return BinderError("Failed to create");
+ }
+ return binder::Status::ok();
+}
+
+binder::Status ImageManagerService::deleteBackingImage(const std::string& name) {
+ if (!CheckUid()) return UidSecurityError();
+
+ std::lock_guard<std::mutex> guard(*parent_->lock());
+
+ if (!impl_->DeleteBackingImage(name)) {
+ return BinderError("Failed to delete");
+ }
+ return binder::Status::ok();
+}
+
+binder::Status ImageManagerService::mapImageDevice(const std::string& name, int32_t timeout_ms,
+ MappedImage* mapping) {
+ if (!CheckUid()) return UidSecurityError();
+
+ std::lock_guard<std::mutex> guard(*parent_->lock());
+
+ if (!impl_->MapImageDevice(name, std::chrono::milliseconds(timeout_ms), &mapping->path)) {
+ return BinderError("Failed to map");
+ }
+ return binder::Status::ok();
+}
+
+binder::Status ImageManagerService::unmapImageDevice(const std::string& name) {
+ if (!CheckUid()) return UidSecurityError();
+
+ std::lock_guard<std::mutex> guard(*parent_->lock());
+
+ if (!impl_->UnmapImageDevice(name)) {
+ return BinderError("Failed to unmap");
+ }
+ return binder::Status::ok();
+}
+
+bool ImageManagerService::CheckUid() {
+ return uid_ == IPCThreadState::self()->getCallingUid();
+}
+
+binder::Status GsiService::openImageManager(const std::string& prefix,
+ android::sp<IImageManager>* _aidl_return) {
+ static constexpr char kImageMetadataPrefix[] = "/metadata/gsi/";
+ static constexpr char kImageDataPrefix[] = "/data/gsi/";
+
+ auto metadata_dir = kImageMetadataPrefix + prefix;
+ auto data_dir = kImageDataPrefix + prefix;
+
+ if (!android::base::Realpath(metadata_dir, &metadata_dir)) {
+ LOG(ERROR) << "realpath failed: " << metadata_dir;
+ return BinderError("Invalid path");
+ }
+ if (!android::base::Realpath(data_dir, &data_dir)) {
+ LOG(ERROR) << "realpath failed: " << data_dir;
+ return BinderError("Invalid path");
+ }
+ if (!android::base::StartsWith(metadata_dir, kImageMetadataPrefix) ||
+ !android::base::StartsWith(data_dir, kImageDataPrefix)) {
+ return BinderError("Invalid path");
+ }
+
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ if (uid != AID_ROOT) {
+ return UidSecurityError();
+ }
+
+ auto impl = ImageManager::Open(metadata_dir, data_dir);
+ if (!impl) {
+ return BinderError("Unknown error");
+ }
+
+ *_aidl_return = new ImageManagerService(this, std::move(impl), uid);
+ return binder::Status::ok();
+}
+
binder::Status GsiService::CheckUid(AccessLevel level) {
std::vector<uid_t> allowed_uids{AID_ROOT, AID_SYSTEM};
if (level == AccessLevel::SystemOrShell) {
@@ -376,9 +496,7 @@
return binder::Status::ok();
}
}
-
- auto message = StringPrintf("UID %d is not allowed", uid);
- return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
+ return UidSecurityError();
}
static bool IsExternalStoragePath(const std::string& path) {