PermissionCache.cpp revision 99b49840d309727678b77403d6cc9f920111623f
199b49840d309727678b77403d6cc9f920111623fMathias Agopian/*
299b49840d309727678b77403d6cc9f920111623fMathias Agopian * Copyright (C) 2009 The Android Open Source Project
399b49840d309727678b77403d6cc9f920111623fMathias Agopian *
499b49840d309727678b77403d6cc9f920111623fMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
599b49840d309727678b77403d6cc9f920111623fMathias Agopian * you may not use this file except in compliance with the License.
699b49840d309727678b77403d6cc9f920111623fMathias Agopian * You may obtain a copy of the License at
799b49840d309727678b77403d6cc9f920111623fMathias Agopian *
899b49840d309727678b77403d6cc9f920111623fMathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
999b49840d309727678b77403d6cc9f920111623fMathias Agopian *
1099b49840d309727678b77403d6cc9f920111623fMathias Agopian * Unless required by applicable law or agreed to in writing, software
1199b49840d309727678b77403d6cc9f920111623fMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
1299b49840d309727678b77403d6cc9f920111623fMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1399b49840d309727678b77403d6cc9f920111623fMathias Agopian * See the License for the specific language governing permissions and
1499b49840d309727678b77403d6cc9f920111623fMathias Agopian * limitations under the License.
1599b49840d309727678b77403d6cc9f920111623fMathias Agopian */
1699b49840d309727678b77403d6cc9f920111623fMathias Agopian
1799b49840d309727678b77403d6cc9f920111623fMathias Agopian#define LOG_TAG "PermissionCache"
1899b49840d309727678b77403d6cc9f920111623fMathias Agopian
1999b49840d309727678b77403d6cc9f920111623fMathias Agopian#include <stdint.h>
2099b49840d309727678b77403d6cc9f920111623fMathias Agopian#include <utils/Log.h>
2199b49840d309727678b77403d6cc9f920111623fMathias Agopian#include <binder/IPCThreadState.h>
2299b49840d309727678b77403d6cc9f920111623fMathias Agopian#include <binder/IServiceManager.h>
2399b49840d309727678b77403d6cc9f920111623fMathias Agopian#include <binder/PermissionCache.h>
2499b49840d309727678b77403d6cc9f920111623fMathias Agopian#include <utils/String8.h>
2599b49840d309727678b77403d6cc9f920111623fMathias Agopian
2699b49840d309727678b77403d6cc9f920111623fMathias Agopiannamespace android {
2799b49840d309727678b77403d6cc9f920111623fMathias Agopian
2899b49840d309727678b77403d6cc9f920111623fMathias Agopian// ----------------------------------------------------------------------------
2999b49840d309727678b77403d6cc9f920111623fMathias Agopian
3099b49840d309727678b77403d6cc9f920111623fMathias AgopianANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache) ;
3199b49840d309727678b77403d6cc9f920111623fMathias Agopian
3299b49840d309727678b77403d6cc9f920111623fMathias Agopian// ----------------------------------------------------------------------------
3399b49840d309727678b77403d6cc9f920111623fMathias Agopian
3499b49840d309727678b77403d6cc9f920111623fMathias AgopianPermissionCache::PermissionCache() {
3599b49840d309727678b77403d6cc9f920111623fMathias Agopian}
3699b49840d309727678b77403d6cc9f920111623fMathias Agopian
3799b49840d309727678b77403d6cc9f920111623fMathias Agopianstatus_t PermissionCache::check(bool* granted,
3899b49840d309727678b77403d6cc9f920111623fMathias Agopian        const String16& permission, uid_t uid) const {
3999b49840d309727678b77403d6cc9f920111623fMathias Agopian    Mutex::Autolock _l(mLock);
4099b49840d309727678b77403d6cc9f920111623fMathias Agopian    Entry e;
4199b49840d309727678b77403d6cc9f920111623fMathias Agopian    e.name = permission;
4299b49840d309727678b77403d6cc9f920111623fMathias Agopian    e.uid  = uid;
4399b49840d309727678b77403d6cc9f920111623fMathias Agopian    ssize_t index = mCache.indexOf(e);
4499b49840d309727678b77403d6cc9f920111623fMathias Agopian    if (index >= 0) {
4599b49840d309727678b77403d6cc9f920111623fMathias Agopian        *granted = mCache.itemAt(index).granted;
4699b49840d309727678b77403d6cc9f920111623fMathias Agopian        return NO_ERROR;
4799b49840d309727678b77403d6cc9f920111623fMathias Agopian    }
4899b49840d309727678b77403d6cc9f920111623fMathias Agopian    return NAME_NOT_FOUND;
4999b49840d309727678b77403d6cc9f920111623fMathias Agopian}
5099b49840d309727678b77403d6cc9f920111623fMathias Agopian
5199b49840d309727678b77403d6cc9f920111623fMathias Agopianvoid PermissionCache::cache(const String16& permission,
5299b49840d309727678b77403d6cc9f920111623fMathias Agopian        uid_t uid, bool granted) {
5399b49840d309727678b77403d6cc9f920111623fMathias Agopian    Mutex::Autolock _l(mLock);
5499b49840d309727678b77403d6cc9f920111623fMathias Agopian    Entry e;
5599b49840d309727678b77403d6cc9f920111623fMathias Agopian    ssize_t index = mPermissionNamesPool.indexOf(permission);
5699b49840d309727678b77403d6cc9f920111623fMathias Agopian    if (index > 0) {
5799b49840d309727678b77403d6cc9f920111623fMathias Agopian        e.name = mPermissionNamesPool.itemAt(index);
5899b49840d309727678b77403d6cc9f920111623fMathias Agopian    } else {
5999b49840d309727678b77403d6cc9f920111623fMathias Agopian        mPermissionNamesPool.add(permission);
6099b49840d309727678b77403d6cc9f920111623fMathias Agopian        e.name = permission;
6199b49840d309727678b77403d6cc9f920111623fMathias Agopian    }
6299b49840d309727678b77403d6cc9f920111623fMathias Agopian    // note, we don't need to store the pid, which is not actually used in
6399b49840d309727678b77403d6cc9f920111623fMathias Agopian    // permission checks
6499b49840d309727678b77403d6cc9f920111623fMathias Agopian    e.uid  = uid;
6599b49840d309727678b77403d6cc9f920111623fMathias Agopian    e.granted = granted;
6699b49840d309727678b77403d6cc9f920111623fMathias Agopian    index = mCache.indexOf(e);
6799b49840d309727678b77403d6cc9f920111623fMathias Agopian    if (index < 0) {
6899b49840d309727678b77403d6cc9f920111623fMathias Agopian        mCache.add(e);
6999b49840d309727678b77403d6cc9f920111623fMathias Agopian    }
7099b49840d309727678b77403d6cc9f920111623fMathias Agopian}
7199b49840d309727678b77403d6cc9f920111623fMathias Agopian
7299b49840d309727678b77403d6cc9f920111623fMathias Agopianvoid PermissionCache::purge() {
7399b49840d309727678b77403d6cc9f920111623fMathias Agopian    Mutex::Autolock _l(mLock);
7499b49840d309727678b77403d6cc9f920111623fMathias Agopian    mCache.clear();
7599b49840d309727678b77403d6cc9f920111623fMathias Agopian}
7699b49840d309727678b77403d6cc9f920111623fMathias Agopian
7799b49840d309727678b77403d6cc9f920111623fMathias Agopianbool PermissionCache::checkCallingPermission(const String16& permission) {
7899b49840d309727678b77403d6cc9f920111623fMathias Agopian    return PermissionCache::checkCallingPermission(permission, NULL, NULL);
7999b49840d309727678b77403d6cc9f920111623fMathias Agopian}
8099b49840d309727678b77403d6cc9f920111623fMathias Agopian
8199b49840d309727678b77403d6cc9f920111623fMathias Agopianbool PermissionCache::checkCallingPermission(
8299b49840d309727678b77403d6cc9f920111623fMathias Agopian        const String16& permission, int32_t* outPid, int32_t* outUid) {
8399b49840d309727678b77403d6cc9f920111623fMathias Agopian    IPCThreadState* ipcState = IPCThreadState::self();
8499b49840d309727678b77403d6cc9f920111623fMathias Agopian    pid_t pid = ipcState->getCallingPid();
8599b49840d309727678b77403d6cc9f920111623fMathias Agopian    uid_t uid = ipcState->getCallingUid();
8699b49840d309727678b77403d6cc9f920111623fMathias Agopian    if (outPid) *outPid = pid;
8799b49840d309727678b77403d6cc9f920111623fMathias Agopian    if (outUid) *outUid = uid;
8899b49840d309727678b77403d6cc9f920111623fMathias Agopian    return PermissionCache::checkPermission(permission, pid, uid);
8999b49840d309727678b77403d6cc9f920111623fMathias Agopian}
9099b49840d309727678b77403d6cc9f920111623fMathias Agopian
9199b49840d309727678b77403d6cc9f920111623fMathias Agopianbool PermissionCache::checkPermission(
9299b49840d309727678b77403d6cc9f920111623fMathias Agopian        const String16& permission, pid_t pid, uid_t uid) {
9399b49840d309727678b77403d6cc9f920111623fMathias Agopian    if ((uid == 0) || (pid == getpid())) {
9499b49840d309727678b77403d6cc9f920111623fMathias Agopian        // root and ourselves is always okay
9599b49840d309727678b77403d6cc9f920111623fMathias Agopian        return true;
9699b49840d309727678b77403d6cc9f920111623fMathias Agopian    }
9799b49840d309727678b77403d6cc9f920111623fMathias Agopian
9899b49840d309727678b77403d6cc9f920111623fMathias Agopian    PermissionCache& pc(PermissionCache::getInstance());
9999b49840d309727678b77403d6cc9f920111623fMathias Agopian    bool granted = false;
10099b49840d309727678b77403d6cc9f920111623fMathias Agopian    if (pc.check(&granted, permission, uid) != NO_ERROR) {
10199b49840d309727678b77403d6cc9f920111623fMathias Agopian        nsecs_t t = -systemTime();
10299b49840d309727678b77403d6cc9f920111623fMathias Agopian        granted = android::checkPermission(permission, pid, uid);
10399b49840d309727678b77403d6cc9f920111623fMathias Agopian        t += systemTime();
10499b49840d309727678b77403d6cc9f920111623fMathias Agopian        LOGD("checking %s for uid=%d => %s (%d us)",
10599b49840d309727678b77403d6cc9f920111623fMathias Agopian                String8(permission).string(), uid,
10699b49840d309727678b77403d6cc9f920111623fMathias Agopian                granted?"granted":"denied", (int)ns2us(t));
10799b49840d309727678b77403d6cc9f920111623fMathias Agopian        pc.cache(permission, uid, granted);
10899b49840d309727678b77403d6cc9f920111623fMathias Agopian    }
10999b49840d309727678b77403d6cc9f920111623fMathias Agopian    return granted;
11099b49840d309727678b77403d6cc9f920111623fMathias Agopian}
11199b49840d309727678b77403d6cc9f920111623fMathias Agopian
11299b49840d309727678b77403d6cc9f920111623fMathias Agopian// ---------------------------------------------------------------------------
11399b49840d309727678b77403d6cc9f920111623fMathias Agopian}; // namespace android
114