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

Commit 375f5636 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

new Permission class used to improve permission checks speed (by caching results)

parent 5e78e096
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -78,6 +78,8 @@ status_t getService(const String16& name, sp<INTERFACE>* outService)
bool checkCallingPermission(const String16& permission);
bool checkCallingPermission(const String16& permission,
                            int32_t* outPid, int32_t* outUid);
bool checkPermission(const String16& permission, pid_t pid, uid_t uid);


// ----------------------------------------------------------------------

+68 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef BINDER_PERMISSION_H
#define BINDER_PERMISSION_H

#include <stdint.h>
#include <unistd.h>

#include <utils/SortedVector.h>
#include <utils/String16.h>
#include <utils/threads.h>

namespace android {
// ---------------------------------------------------------------------------

/*
 * Permission caches the result of the permission check for the given
 * permission name and the provided uid/pid. It also handles a few
 * known cases efficiently (caller is in the same process or is root).
 * The package manager does something similar but lives in dalvik world
 * and is therefore extremely slow to access.
 */

class Permission
{
public:
            Permission(char const* name);
            Permission(const String16& name);
            Permission(const Permission& rhs);
    virtual ~Permission();

    bool operator < (const Permission& rhs) const;

    // checks the current binder call's caller has access to this permission
    bool checkCalling() const;
    
    // checks the specified pid/uid has access to this permission
    bool check(pid_t pid, uid_t uid) const;
    
protected:
    virtual bool doCheckPermission(pid_t pid, uid_t uid) const;

private:
    Permission& operator = (const Permission& rhs) const;
    const String16 mPermissionName;
    mutable SortedVector<uid_t> mGranted;
    const pid_t mPid;
    mutable Mutex mLock;
};

// ---------------------------------------------------------------------------
}; // namespace android

#endif /* BINDER_PERMISSION_H */
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ LOCAL_SRC_FILES:= \
    MemoryHeapBase.cpp \
    MemoryHeapPmem.cpp \
	Parcel.cpp \
	Permission.cpp \
	ProcessState.cpp \
	Static.cpp

+10 −5
Original line number Diff line number Diff line
@@ -19,8 +19,8 @@
#include <binder/IServiceManager.h>

#include <utils/Debug.h>
#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
@@ -53,14 +53,19 @@ bool checkCallingPermission(const String16& permission)

static String16 _permission("permission");


bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid)
{
    IPCThreadState* ipcState = IPCThreadState::self();
    int32_t pid = ipcState->getCallingPid();
    int32_t uid = ipcState->getCallingUid();
    pid_t pid = ipcState->getCallingPid();
    uid_t uid = ipcState->getCallingUid();
    if (outPid) *outPid = pid;
    if (outUid) *outUid = uid;
    return checkPermission(permission, pid, uid);
}

bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
{
    sp<IPermissionController> pc;
    gDefaultServiceManagerLock.lock();
    pc = gPermissionController;
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdint.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/Permission.h>

namespace android {
// ---------------------------------------------------------------------------

Permission::Permission(char const* name)
    : mPermissionName(name), mPid(getpid())
{
}

Permission::Permission(const String16& name)
    : mPermissionName(name), mPid(getpid())
{
}

Permission::Permission(const Permission& rhs)
    : mPermissionName(rhs.mPermissionName),
    mGranted(rhs.mGranted),
    mPid(rhs.mPid)
{
}

Permission::~Permission()
{
}

bool Permission::operator < (const Permission& rhs) const
{
    return mPermissionName < rhs.mPermissionName;
}

bool Permission::checkCalling() const
{
    IPCThreadState* ipcState = IPCThreadState::self();
    pid_t pid = ipcState->getCallingPid();
    uid_t uid = ipcState->getCallingUid();
    return doCheckPermission(pid, uid);
}

bool Permission::check(pid_t pid, uid_t uid) const
{
    return doCheckPermission(pid, uid);
}

bool Permission::doCheckPermission(pid_t pid, uid_t uid) const
{
    if ((uid == 0) || (pid == mPid)) {
        // root and ourselves is always okay
        return true;
    } else {
        // see if we already granted this permission for this uid
        Mutex::Autolock _l(mLock);
        if (mGranted.indexOf(uid) >= 0)
            return true;
    }

    bool granted = checkPermission(mPermissionName, pid, uid);
    if (granted) {
        Mutex::Autolock _l(mLock);
        // no need to check again, the old item will be replaced if it is
        // already there.
        mGranted.add(uid);
    }
    return granted;
}

// ---------------------------------------------------------------------------
}; // namespace android
Loading