From b24760fd49d6475885eb4edae7b2f42888d5e30f Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Fri, 3 Feb 2017 13:40:04 -0800 Subject: [PATCH] Fix permissions for lshal Instead of IServiceManager::debugDump, lshal now relies on list and get. lshal itself will call getDebugInfo on each interface, so that each interface can check if the call is from a root user, then decide to leak addresses or not. Bug: 34899586 Test: lshal Change-Id: I8eb9168c3b071b8b1f27dbeaa0ac27d2067200d7 --- cmds/lshal/lshal.cpp | 156 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 52 deletions(-) diff --git a/cmds/lshal/lshal.cpp b/cmds/lshal/lshal.cpp index bc5eaf24c5..07cd9f44a6 100644 --- a/cmds/lshal/lshal.cpp +++ b/cmds/lshal/lshal.cpp @@ -28,16 +28,20 @@ #include #include -template +using ::android::hardware::hidl_string; + +template void printColumn(std::stringstream &stream, - const A &a, const B &b, const C &c, const D &d, const E &e) { + const A &a, const B &b, const C &c, const D &d, const E &, const F &f) { using namespace ::std; stream << left << setw(70) << a << "\t" << setw(20) << b << "\t" << setw(10) << c << "\t" << setw(5) << d << "\t" - << setw(0) << e + // TODO(b/34984175): enable selecting columns + // << setw(16) << e << "\t" + << setw(0) << f << endl; } @@ -47,12 +51,20 @@ std::string toHexString(uint64_t t) { return os.str(); } -::android::status_t getReferencedPids( +std::pair split(const hidl_string &s, char c) { + const char *pos = strchr(s.c_str(), c); + if (pos == nullptr) { + return {s, {}}; + } + return {hidl_string(s.c_str(), pos - s.c_str()), hidl_string(pos + 1)}; +} + +bool getReferencedPids( pid_t serverPid, std::map *objects) { std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid)); if (!ifs.is_open()) { - return ::android::PERMISSION_DENIED; + return false; } static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+"); @@ -77,66 +89,106 @@ std::string toHexString(uint64_t t) { (*objects)[ptr] += line.substr(pos + proc.size()); } } - return ::android::OK; + return true; } - -int dump() { +void dumpBinderized(std::stringstream &stream, const std::string &mode, + const sp &manager) { using namespace ::std; using namespace ::android::hardware; using namespace ::android::hidl::manager::V1_0; - - std::map> mapping = { - {"hwbinder", defaultServiceManager()}, - {"passthrough", getPassthroughServiceManager()} - }; - - std::stringstream stream; - - stream << "All services:" << endl; - stream << left; - printColumn(stream, "Interface", "Instance", "Transport", "Server", "Clients"); - - for (const auto &pair : mapping) { - const std::string &mode = pair.first; - const ::android::sp &manager = pair.second; - - if (manager == nullptr) { - cerr << "Failed to get IServiceManager for " << mode << "!" << endl; - continue; - } - - auto ret = manager->debugDump([&](const auto ®istered) { - // server pid, .ptr value of binder object, child pids - std::map> allPids; - for (const auto &info : registered) { - if (info.pid < 0) { - continue; - } - pid_t serverPid = info.pid; - allPids[serverPid].clear(); + using namespace ::android::hidl::base::V1_0; + auto listRet = manager->list([&] (const auto &fqInstanceNames) { + // server pid, .ptr value of binder object, child pids + std::map allDebugInfos; + std::map> allPids; + for (const auto &fqInstanceName : fqInstanceNames) { + const auto pair = split(fqInstanceName, '/'); + const auto &serviceName = pair.first; + const auto &instanceName = pair.second; + auto getRet = manager->get(serviceName, instanceName); + if (!getRet.isOk()) { + cerr << "Warning: Skipping \"" << fqInstanceName << "\": " + << "cannot be fetched from service manager:" + << getRet.description() << endl; + continue; } - for (auto &pair : allPids) { - pid_t serverPid = pair.first; - if (getReferencedPids(serverPid, &allPids[serverPid]) != ::android::OK) { - std::cerr << "Warning: no information for PID " << serverPid - << ", are you root?" << std::endl; + sp service = getRet; + if (service == nullptr) { + cerr << "Warning: Skipping \"" << fqInstanceName << "\": " + << "cannot be fetched from service manager (null)"; + continue; + } + auto debugRet = service->getDebugInfo([&] (const auto &debugInfo) { + allDebugInfos[fqInstanceName] = debugInfo; + if (debugInfo.pid >= 0) { + allPids[static_cast(debugInfo.pid)].clear(); } + }); + if (!debugRet.isOk()) { + cerr << "Warning: Skipping \"" << fqInstanceName << "\": " + << "debugging information cannot be retrieved:" + << debugRet.description() << endl; + } + } + for (auto &pair : allPids) { + pid_t serverPid = pair.first; + if (!getReferencedPids(serverPid, &allPids[serverPid])) { + std::cerr << "Warning: no information for PID " << serverPid + << ", are you root?" << std::endl; } - for (const auto &info : registered) { + } + for (const auto &fqInstanceName : fqInstanceNames) { + const auto pair = split(fqInstanceName, '/'); + const auto &serviceName = pair.first; + const auto &instanceName = pair.second; + auto it = allDebugInfos.find(fqInstanceName); + if (it == allDebugInfos.end()) { printColumn(stream, - info.interfaceName, - info.instanceName.empty() ? "N/A" : info.instanceName, + serviceName, + instanceName, mode, - info.pid < 0 ? "N/A" : std::to_string(info.pid), - info.pid < 0 || info.ptr == 0 ? "" : allPids[info.pid][info.ptr]); + "N/A", + "N/A", + "" + ); + continue; } - }); - if (!ret.isOk()) { - cerr << "Failed to list services for " << mode << ": " - << ret.description() << endl; + const DebugInfo &info = it->second; + printColumn(stream, + serviceName, + instanceName, + mode, + info.pid < 0 ? "N/A" : std::to_string(info.pid), + info.ptr == 0 ? "N/A" : toHexString(info.ptr), + info.pid < 0 || info.ptr == 0 ? "" : allPids[info.pid][info.ptr] + ); } + + }); + if (!listRet.isOk()) { + cerr << "Error: Failed to list services for " << mode << ": " + << listRet.description() << endl; + } +} + +int dump() { + using namespace ::std; + using namespace ::android::hardware; + + std::stringstream stream; + + stream << "All services:" << endl; + stream << left; + printColumn(stream, "Interface", "Instance", "Transport", "Server", "PTR", "Clients"); + + auto bManager = defaultServiceManager(); + if (bManager == nullptr) { + cerr << "Failed to get defaultServiceManager()!" << endl; + } else { + dumpBinderized(stream, "hwbinder", bManager); } + cout << stream.rdbuf(); return 0; } -- 2.11.0