summaryrefslogtreecommitdiff
path: root/gsi_tool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gsi_tool.cpp')
-rw-r--r--gsi_tool.cpp78
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;
}