diff options
Diffstat (limited to 'gsi_tool.cpp')
-rw-r--r-- | gsi_tool.cpp | 78 |
1 files changed, 63 insertions, 15 deletions
diff --git a/gsi_tool.cpp b/gsi_tool.cpp index 181452b..6aa0fb5 100644 --- a/gsi_tool.cpp +++ b/gsi_tool.cpp @@ -19,6 +19,7 @@ #include <sysexits.h> #include <unistd.h> +#include <algorithm> #include <chrono> #include <condition_variable> #include <functional> @@ -70,14 +71,50 @@ static const std::map<std::string, CommandCallback> kCommandMap = { // clang-format on }; +// Commands not allowed for locked DSU +static const std::vector<std::string> kEnforceNonLockedDsu = { + // clang-format off + "disable", + "enable", + "wipe", + // clang-format on +}; + static std::string ErrorMessage(const android::binder::Status& status, int error_code = IGsiService::INSTALL_ERROR_GENERIC) { if (!status.isOk()) { - return status.exceptionMessage().string(); + return status.exceptionMessage().c_str(); } return "error code " + std::to_string(error_code); } +static inline bool IsRoot() { + return getuid() == 0; +} + +static int EnforceNonLockedDsu(sp<IGsiService> gsid) { + bool running; + auto status = gsid->isGsiRunning(&running); + if (!status.isOk()) { + std::cerr << "Could not get DSU running status: " << ErrorMessage(status) << std::endl; + return EX_SOFTWARE; + } + if (!running) { + return 0; + } + std::string dsuSlot = {}; + status = gsid->getActiveDsuSlot(&dsuSlot); + if (!status.isOk()) { + std::cerr << "Could not get the active DSU slot: " << ErrorMessage(status) << std::endl; + return EX_SOFTWARE; + } + if (android::base::EndsWith(dsuSlot, ".lock") && !IsRoot()) { + std::cerr << "Must be root to access a locked DSU" << std::endl; + return EX_NOPERM; + } + return 0; +} + class ProgressBar { public: explicit ProgressBar(sp<IGsiService> gsid) : gsid_(gsid) {} @@ -210,7 +247,7 @@ static int Install(sp<IGsiService> gsid, int argc, char** argv) { bool reboot = true; std::string installDir = ""; std::string partition = kDefaultPartition; - if (getuid() != 0) { + if (!IsRoot()) { std::cerr << "must be root to install a GSI" << std::endl; return EX_NOPERM; } @@ -376,7 +413,7 @@ static int CreatePartition(sp<IGsiService> gsid, int argc, char** argv) { } } - if (getuid() != 0) { + if (!IsRoot()) { std::cerr << "must be root to install a DSU" << std::endl; return EX_NOPERM; } @@ -496,7 +533,7 @@ static int WipeData(sp<IGsiService> gsid, int argc, char** /* argv */) { bool running; auto status = gsid->isGsiRunning(&running); if (!status.isOk()) { - std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + std::cerr << "error: " << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } if (running) { @@ -507,7 +544,7 @@ static int WipeData(sp<IGsiService> gsid, int argc, char** /* argv */) { bool installed; status = gsid->isGsiInstalled(&installed); if (!status.isOk()) { - std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + std::cerr << "error: " << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } if (!installed) { @@ -532,7 +569,7 @@ static int Status(sp<IGsiService> gsid, int argc, char** /* argv */) { bool running; auto status = gsid->isGsiRunning(&running); if (!status.isOk()) { - std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + std::cerr << "error: " << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } else if (running) { std::cout << "running" << std::endl; @@ -540,7 +577,7 @@ static int Status(sp<IGsiService> gsid, int argc, char** /* argv */) { bool installed; status = gsid->isGsiInstalled(&installed); if (!status.isOk()) { - std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + std::cerr << "error: " << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } else if (installed) { std::cout << "installed" << std::endl; @@ -548,21 +585,21 @@ static int Status(sp<IGsiService> gsid, int argc, char** /* argv */) { bool enabled; status = gsid->isGsiEnabled(&enabled); if (!status.isOk()) { - std::cerr << status.exceptionMessage().string() << std::endl; + std::cerr << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } else if (running || installed) { std::cout << (enabled ? "enabled" : "disabled") << std::endl; } else { std::cout << "normal" << std::endl; } - if (getuid() != 0) { + if (!IsRoot()) { return 0; } std::vector<std::string> dsu_slots; status = gsid->getInstalledDsuSlots(&dsu_slots); if (!status.isOk()) { - std::cerr << status.exceptionMessage().string() << std::endl; + std::cerr << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } int n = 0; @@ -571,13 +608,18 @@ static int Status(sp<IGsiService> gsid, int argc, char** /* argv */) { sp<IImageService> image_service = nullptr; status = gsid->openImageService("dsu/" + dsu_slot + "/", &image_service); if (!status.isOk()) { - std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + if (running) { + // openImageService through binder (gsid) could fail if running, + // because we can't stat the "outside" userdata. + continue; + } + std::cerr << "error: " << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } std::vector<std::string> images; status = image_service->getAllBackingImages(&images); if (!status.isOk()) { - std::cerr << "error: " << status.exceptionMessage().string() << std::endl; + std::cerr << "error: " << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } for (auto&& image : images) { @@ -603,7 +645,7 @@ static int Cancel(sp<IGsiService> gsid, int /* argc */, char** /* argv */) { bool cancelled = false; auto status = gsid->cancelGsiInstall(&cancelled); if (!status.isOk()) { - std::cerr << status.exceptionMessage().string() << std::endl; + std::cerr << status.exceptionMessage().c_str() << std::endl; return EX_SOFTWARE; } if (!cancelled) { @@ -671,7 +713,6 @@ static int Disable(sp<IGsiService> gsid, int argc, char** /* argv */) { std::cerr << "Unrecognized arguments to disable." << std::endl; return EX_USAGE; } - bool installing = false; gsid->isGsiInstallInProgress(&installing); if (installing) { @@ -729,12 +770,19 @@ int main(int argc, char** argv) { std::string command = argv[1]; + int rc; + const auto& vec = kEnforceNonLockedDsu; + if (std::find(vec.begin(), vec.end(), command) != vec.end() && + (rc = EnforceNonLockedDsu(service)) != 0) { + return rc; + } + auto iter = kCommandMap.find(command); if (iter == kCommandMap.end()) { std::cerr << "Unrecognized command: " << command << std::endl; return usage(argc, argv); } - int rc = iter->second(service, argc - 1, argv + 1); + rc = iter->second(service, argc - 1, argv + 1); return rc; } |