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));