X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=cmds%2Fstatsd%2Fsrc%2FStatsService.cpp;h=8545d76c4324e596772eba83937e0ca724d04545;hb=936c0868f8e5d71d61449b94e16a56e1ceaea424;hp=e26806b0434d8c64a8903f39dd27b4a2c8a97f96;hpb=8be1197c5dba21b785e9f24ae9ade2c9a082ae9c;p=android-x86%2Fframeworks-base.git diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index e26806b0434d..8545d76c4324 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -27,8 +27,10 @@ #include "subscriber/SubscriberReporter.h" #include +#include #include #include +#include #include #include #include @@ -42,13 +44,83 @@ using namespace android; +using android::base::StringPrintf; + namespace android { namespace os { namespace statsd { constexpr const char* kPermissionDump = "android.permission.DUMP"; +constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS"; + +constexpr const char* kOpUsage = "android:get_usage_stats"; + #define STATS_SERVICE_DIR "/data/misc/stats-service" +static binder::Status ok() { + return binder::Status::ok(); +} + +static binder::Status exception(uint32_t code, const std::string& msg) { + ALOGE("%s (%d)", msg.c_str(), code); + return binder::Status::fromExceptionCode(code, String8(msg.c_str())); +} + +binder::Status checkUid(uid_t expectedUid) { + uid_t uid = IPCThreadState::self()->getCallingUid(); + if (uid == expectedUid || uid == AID_ROOT) { + return ok(); + } else { + return exception(binder::Status::EX_SECURITY, + StringPrintf("UID %d is not expected UID %d", uid, expectedUid)); + } +} + +binder::Status checkDumpAndUsageStats(const String16& packageName) { + pid_t pid = IPCThreadState::self()->getCallingPid(); + uid_t uid = IPCThreadState::self()->getCallingUid(); + + // Root, system, and shell always have access + if (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL) { + return ok(); + } + + // Caller must be granted these permissions + if (!checkCallingPermission(String16(kPermissionDump))) { + return exception(binder::Status::EX_SECURITY, + StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump)); + } + if (!checkCallingPermission(String16(kPermissionUsage))) { + return exception(binder::Status::EX_SECURITY, + StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage)); + } + + // Caller must also have usage stats op granted + PermissionController pc; + switch (pc.noteOp(String16(kOpUsage), uid, packageName)) { + case PermissionController::MODE_ALLOWED: + case PermissionController::MODE_DEFAULT: + return ok(); + default: + return exception(binder::Status::EX_SECURITY, + StringPrintf("UID %d / PID %d lacks app-op %s", uid, pid, kOpUsage)); + } +} + +#define ENFORCE_UID(uid) { \ + binder::Status status = checkUid((uid)); \ + if (!status.isOk()) { \ + return status; \ + } \ +} + +#define ENFORCE_DUMP_AND_USAGE_STATS(packageName) { \ + binder::Status status = checkDumpAndUsageStats(packageName); \ + if (!status.isOk()) { \ + return status; \ + } \ +} + StatsService::StatsService(const sp& handlerLooper) : mAnomalyAlarmMonitor(new AlarmMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS, [](const sp& sc, int64_t timeMillis) { @@ -212,7 +284,10 @@ void StatsService::dump_impl(FILE* out, bool verbose, bool proto) { * Implementation of the adb shell cmd stats command. */ status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector& args) { - // TODO: Permission check + uid_t uid = IPCThreadState::self()->getCallingUid(); + if (uid != AID_ROOT && uid != AID_SHELL) { + return PERMISSION_DENIED; + } const int argCount = args.size(); if (argCount >= 1) { @@ -661,13 +736,9 @@ status_t StatsService::cmd_clear_puller_cache(FILE* out) { Status StatsService::informAllUidData(const vector& uid, const vector& version, const vector& app) { - VLOG("StatsService::informAllUidData was called"); - - if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call informAllUidData"); - } + ENFORCE_UID(AID_SYSTEM); + VLOG("StatsService::informAllUidData was called"); mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app); VLOG("StatsService::informAllUidData succeeded"); @@ -675,36 +746,26 @@ Status StatsService::informAllUidData(const vector& uid, const vectorgetCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call informOnePackage"); - } + VLOG("StatsService::informOnePackage was called"); mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version); return Status::ok(); } Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) { - VLOG("StatsService::informOnePackageRemoved was called"); + ENFORCE_UID(AID_SYSTEM); - if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call informOnePackageRemoved"); - } + VLOG("StatsService::informOnePackageRemoved was called"); mUidMap->removeApp(getElapsedRealtimeNs(), app, uid); mConfigManager->RemoveConfigs(uid); return Status::ok(); } Status StatsService::informAnomalyAlarmFired() { - VLOG("StatsService::informAnomalyAlarmFired was called"); - - if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call informAnomalyAlarmFired"); - } + ENFORCE_UID(AID_SYSTEM); + VLOG("StatsService::informAnomalyAlarmFired was called"); int64_t currentTimeSec = getElapsedRealtimeSec(); std::unordered_set, SpHash> alarmSet = mAnomalyAlarmMonitor->popSoonerThan(static_cast(currentTimeSec)); @@ -718,14 +779,9 @@ Status StatsService::informAnomalyAlarmFired() { } Status StatsService::informAlarmForSubscriberTriggeringFired() { - VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called"); - - if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode( - Status::EX_SECURITY, - "Only system uid can call informAlarmForSubscriberTriggeringFired"); - } + ENFORCE_UID(AID_SYSTEM); + VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called"); int64_t currentTimeSec = getElapsedRealtimeSec(); std::unordered_set, SpHash> alarmSet = mPeriodicAlarmMonitor->popSoonerThan(static_cast(currentTimeSec)); @@ -739,44 +795,28 @@ Status StatsService::informAlarmForSubscriberTriggeringFired() { } Status StatsService::informPollAlarmFired() { - VLOG("StatsService::informPollAlarmFired was called"); - - if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call informPollAlarmFired"); - } + ENFORCE_UID(AID_SYSTEM); + VLOG("StatsService::informPollAlarmFired was called"); mProcessor->informPullAlarmFired(getElapsedRealtimeNs()); - VLOG("StatsService::informPollAlarmFired succeeded"); - return Status::ok(); } Status StatsService::systemRunning() { - if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call systemRunning"); - } + ENFORCE_UID(AID_SYSTEM); // When system_server is up and running, schedule the dropbox task to run. VLOG("StatsService::systemRunning"); - sayHiToStatsCompanion(); - return Status::ok(); } Status StatsService::writeDataToDisk() { - if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call systemRunning"); - } + ENFORCE_UID(AID_SYSTEM); VLOG("StatsService::writeDataToDisk"); - mProcessor->WriteDataToDisk(); - return Status::ok(); } @@ -791,13 +831,9 @@ void StatsService::sayHiToStatsCompanion() { } Status StatsService::statsCompanionReady() { - VLOG("StatsService::statsCompanionReady was called"); - - if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { - return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call statsCompanionReady"); - } + ENFORCE_UID(AID_SYSTEM); + VLOG("StatsService::statsCompanionReady was called"); sp statsCompanion = getStatsCompanionService(); if (statsCompanion == nullptr) { return Status::fromExceptionCode( @@ -821,33 +857,31 @@ void StatsService::OnLogEvent(LogEvent* event, bool reconnectionStarts) { mProcessor->OnLogEvent(event, reconnectionStarts); } -Status StatsService::getData(int64_t key, vector* output) { +Status StatsService::getData(int64_t key, const String16& packageName, vector* output) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + IPCThreadState* ipc = IPCThreadState::self(); VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid()); - if (!checkCallingPermission(String16(kPermissionDump))) { - return Status::fromExceptionCode(binder::Status::EX_SECURITY); - } ConfigKey configKey(ipc->getCallingUid(), key); mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/, output); return Status::ok(); } -Status StatsService::getMetadata(vector* output) { +Status StatsService::getMetadata(const String16& packageName, vector* output) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + IPCThreadState* ipc = IPCThreadState::self(); VLOG("StatsService::getMetadata with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid()); - if (!checkCallingPermission(String16(kPermissionDump))) { - return Status::fromExceptionCode(binder::Status::EX_SECURITY); - } StatsdStats::getInstance().dumpStats(output, false); // Don't reset the counters. return Status::ok(); } -Status StatsService::addConfiguration(int64_t key, const vector & config) { - if (!checkCallingPermission(String16(kPermissionDump))) { - return Status::fromExceptionCode(binder::Status::EX_SECURITY); - } +Status StatsService::addConfiguration(int64_t key, const vector & config, + const String16& packageName) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + IPCThreadState* ipc = IPCThreadState::self(); if (addConfigurationChecked(ipc->getCallingUid(), key, config)) { return Status::ok(); @@ -870,30 +904,29 @@ bool StatsService::addConfigurationChecked(int uid, int64_t key, const vectorgetCallingUid(), key); mConfigManager->RemoveConfigReceiver(configKey); return Status::ok(); } -Status StatsService::setDataFetchOperation(int64_t key, const sp& intentSender) { - if (!checkCallingPermission(String16(kPermissionDump))) { - return Status::fromExceptionCode(binder::Status::EX_SECURITY); - } +Status StatsService::setDataFetchOperation(int64_t key, + const sp& intentSender, + const String16& packageName) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), key); mConfigManager->SetConfigReceiver(configKey, intentSender); return Status::ok(); } -Status StatsService::removeConfiguration(int64_t key) { - if (!checkCallingPermission(String16(kPermissionDump))) { - return Status::fromExceptionCode(binder::Status::EX_SECURITY); - } +Status StatsService::removeConfiguration(int64_t key, const String16& packageName) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), key); mConfigManager->RemoveConfig(configKey); @@ -903,11 +936,11 @@ Status StatsService::removeConfiguration(int64_t key) { Status StatsService::setBroadcastSubscriber(int64_t configId, int64_t subscriberId, - const sp& intentSender) { + const sp& intentSender, + const String16& packageName) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + VLOG("StatsService::setBroadcastSubscriber called."); - if (!checkCallingPermission(String16(kPermissionDump))) { - return Status::fromExceptionCode(binder::Status::EX_SECURITY); - } IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), configId); SubscriberReporter::getInstance() @@ -916,11 +949,11 @@ Status StatsService::setBroadcastSubscriber(int64_t configId, } Status StatsService::unsetBroadcastSubscriber(int64_t configId, - int64_t subscriberId) { + int64_t subscriberId, + const String16& packageName) { + ENFORCE_DUMP_AND_USAGE_STATS(packageName); + VLOG("StatsService::unsetBroadcastSubscriber called."); - if (!checkCallingPermission(String16(kPermissionDump))) { - return Status::fromExceptionCode(binder::Status::EX_SECURITY); - } IPCThreadState* ipc = IPCThreadState::self(); ConfigKey configKey(ipc->getCallingUid(), configId); SubscriberReporter::getInstance() @@ -928,7 +961,6 @@ Status StatsService::unsetBroadcastSubscriber(int64_t configId, return Status::ok(); } - void StatsService::binderDied(const wp & who) { ALOGW("statscompanion service died"); mProcessor->WriteDataToDisk();