statsd checks permissions using SCS
The checkCallingPermission function is not supported by libbinder_ndk.
To circumvent this issue, statsd will now ask StatsCompanionService
(SCS) to do that check using a synchronous Binder call. Once
libbinder_ndk does support checkCallingPermission, this workaround will
be unnecessary.
Test: m -j
Test: atest GtsStatsdHostTestCases
Bug: 145566180
Change-Id: I11f0e82f88aa5921cf531fd041b0a18d3a26a0a0
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index c1a8d69..05281f7 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -30,7 +30,6 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
#include <binder/PermissionController.h>
#include <cutils/multiuser.h>
#include <dirent.h>
@@ -77,6 +76,25 @@
return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
}
+
+static bool checkPermission(const char* permission) {
+ sp<IStatsCompanionService> scs = getStatsCompanionService();
+ if (scs == nullptr) {
+ return false;
+ }
+
+ bool success;
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+
+ binder::Status status = scs->checkPermission(String16(permission), pid, uid, &success);
+ if (!status.isOk()) {
+ return false;
+ }
+ return success;
+}
+
+
binder::Status checkUid(uid_t expectedUid) {
uid_t uid = IPCThreadState::self()->getCallingUid();
if (uid == expectedUid || uid == AID_ROOT) {
@@ -97,11 +115,11 @@
}
// Caller must be granted these permissions
- if (!checkCallingPermission(String16(kPermissionDump))) {
+ if (!checkPermission(kPermissionDump)) {
return exception(binder::Status::EX_SECURITY,
StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump));
}
- if (!checkCallingPermission(String16(kPermissionUsage))) {
+ if (!checkPermission(kPermissionUsage)) {
return exception(binder::Status::EX_SECURITY,
StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage));
}
@@ -285,7 +303,7 @@
* TODO: Come up with a more robust method of enacting <serviceutils/PriorityDumper.h>.
*/
status_t StatsService::dump(int fd, const Vector<String16>& args) {
- if (!checkCallingPermission(String16(kPermissionDump))) {
+ if (!checkPermission(kPermissionDump)) {
return PERMISSION_DENIED;
}
int lastArg = args.size() - 1;
@@ -914,7 +932,7 @@
IPCThreadState* ipc = IPCThreadState::self();
VLOG("StatsService::cmd_clear_puller_cache with Pid %i, Uid %i",
ipc->getCallingPid(), ipc->getCallingUid());
- if (checkCallingPermission(String16(kPermissionDump))) {
+ if (checkPermission(kPermissionDump)) {
int cleared = mPullerManager->ForceClearPullerCache();
dprintf(out, "Puller removed %d cached data!\n", cleared);
return NO_ERROR;
@@ -927,7 +945,7 @@
IPCThreadState* ipc = IPCThreadState::self();
VLOG("StatsService::cmd_print_logs with Pid %i, Uid %i", ipc->getCallingPid(),
ipc->getCallingUid());
- if (checkCallingPermission(String16(kPermissionDump))) {
+ if (checkPermission(kPermissionDump)) {
bool enabled = true;
if (args.size() >= 2) {
enabled = atoi(args[1].c_str()) != 0;
@@ -1314,12 +1332,12 @@
// Root, system, and shell always have access
if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) {
// Caller must be granted these permissions
- if (!checkCallingPermission(String16(kPermissionDump))) {
+ if (!checkPermission(kPermissionDump)) {
return exception(binder::Status::EX_SECURITY,
StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
kPermissionDump));
}
- if (!checkCallingPermission(String16(kPermissionUsage))) {
+ if (!checkPermission(kPermissionUsage)) {
return exception(binder::Status::EX_SECURITY,
StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
kPermissionUsage));
@@ -1410,12 +1428,12 @@
// Root, system, and shell always have access
if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) {
// Caller must be granted these permissions
- if (!checkCallingPermission(String16(kPermissionDump))) {
+ if (!checkPermission(kPermissionDump)) {
return exception(binder::Status::EX_SECURITY,
StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
kPermissionDump));
}
- if (!checkCallingPermission(String16(kPermissionUsage))) {
+ if (!checkPermission(kPermissionUsage)) {
return exception(binder::Status::EX_SECURITY,
StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
kPermissionUsage));