Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0563e3b1 authored by Ruchir Rastogi's avatar Ruchir Rastogi
Browse files

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
parent e0206059
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -61,4 +61,11 @@ interface IStatsCompanionService {

    /** Tells StatsCompaionService to grab the uid map snapshot and send it to statsd. */
    oneway void triggerUidSnapshot();

    /**
     * Ask StatsCompanionService if the given permission is allowed for a particular process
     * and user ID. statsd is incapable of doing this check itself because checkCallingPermission
     * is not currently supported by libbinder_ndk.
     */
    boolean checkPermission(String permission, int pid, int uid);
}
+5 −0
Original line number Diff line number Diff line
@@ -516,6 +516,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
        }
    }

    @Override // Binder call
    public boolean checkPermission(String permission, int pid, int uid) {
        StatsCompanion.enforceStatsCompanionPermission(mContext);
        return mContext.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED;
    }

    // Statsd related code

+28 −10
Original line number Diff line number Diff line
@@ -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 @@ static binder::Status exception(uint32_t code, const std::string& msg) {
    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 @@ binder::Status checkDumpAndUsageStats(const String16& packageName) {
    }

    // 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 @@ status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* rep
 * 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 @@ status_t StatsService::cmd_clear_puller_cache(int out) {
    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 @@ status_t StatsService::cmd_print_logs(int out, const Vector<String8>& args) {
    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 @@ Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& tra
    // 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 @@ Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackType
    // 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));