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

Commit a6c44309 authored by Michael Wachenschwanz's avatar Michael Wachenschwanz Committed by Android (Google) Code Review
Browse files

Merge "Native Side of Binder Proxy Tracking by Uid"

parents ece73060 d296d0cd
Loading
Loading
Loading
Loading
+109 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <cutils/compiler.h>
#include <utils/Log.h>

#include <stdio.h>
@@ -32,6 +33,23 @@ namespace android {

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

Mutex BpBinder::sTrackingLock;
std::unordered_map<int32_t,uint32_t> BpBinder::sTrackingMap;
int BpBinder::sNumTrackedUids = 0;
std::atomic_bool BpBinder::sCountByUidEnabled(false);
binder_proxy_limit_callback BpBinder::sLimitCallback;
bool BpBinder::sBinderProxyThrottleCreate = false;

// Arbitrarily high value that probably distinguishes a bad behaving app
uint32_t BpBinder::sBinderProxyCountHighWatermark = 2500;
// Another arbitrary value a binder count needs to drop below before another callback will be called
uint32_t BpBinder::sBinderProxyCountLowWatermark = 2000;

enum {
    CALLBACK_TRIGGERED_MASK = 0x80000000,   // A flag denoting that the callback has been called
    COUNTING_VALUE_MASK = 0x7FFFFFFF,       // A mask of the remaining bits for the count value
};

BpBinder::ObjectManager::ObjectManager()
{
}
@@ -87,11 +105,47 @@ void BpBinder::ObjectManager::kill()

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

BpBinder::BpBinder(int32_t handle)

BpBinder* BpBinder::create(int32_t handle) {
    int32_t trackedUid = -1;
    if (sCountByUidEnabled) {
        BpBinder* out;
        trackedUid = IPCThreadState::self()->getCallingUid();
        AutoMutex _l(sTrackingLock);
        if ((sTrackingMap[trackedUid] & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
            ALOGE("Too many binder proxy objects sent to uid %d from uid %d (over %d proxies held)",
                   getuid(), trackedUid, sBinderProxyCountHighWatermark);

            if (sBinderProxyThrottleCreate) {
                ALOGE("Returning Null Binder Proxy Object to uid %d", trackedUid);
                out = nullptr;
            } else {
                // increment and construct here in case callback has an async kill causing a race
                sTrackingMap[trackedUid]++;
                out = new BpBinder(handle, trackedUid);
            }

            if (sLimitCallback && !(sTrackingMap[trackedUid] & CALLBACK_TRIGGERED_MASK)) {
                sTrackingMap[trackedUid] |= CALLBACK_TRIGGERED_MASK;
                sLimitCallback(trackedUid);
            }
        } else {
            sTrackingMap[trackedUid]++;
            out = new BpBinder(handle, trackedUid);
        }

        return out;
    } else {
        return new BpBinder(handle, trackedUid);
    }
}

BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
    : mHandle(handle)
    , mAlive(1)
    , mObitsSent(0)
    , mObituaries(NULL)
    , mTrackedUid(trackedUid)
{
    ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);

@@ -315,6 +369,24 @@ BpBinder::~BpBinder()

    IPCThreadState* ipc = IPCThreadState::self();

    if (mTrackedUid >= 0) {
        AutoMutex _l(sTrackingLock);
        if (CC_UNLIKELY(sTrackingMap[mTrackedUid] == 0)) {
            ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this, mHandle);
        } else {
            if (CC_UNLIKELY(
                (sTrackingMap[mTrackedUid] & CALLBACK_TRIGGERED_MASK) &&
                ((sTrackingMap[mTrackedUid] & COUNTING_VALUE_MASK) <= sBinderProxyCountLowWatermark)
                )) {
                // Clear the Callback Triggered bit when crossing below the low watermark
                sTrackingMap[mTrackedUid] &= ~CALLBACK_TRIGGERED_MASK;
            }
            if (--sTrackingMap[mTrackedUid] == 0) {
                sTrackingMap.erase(mTrackedUid);
            }
        }
    }

    mLock.lock();
    Vector<Obituary>* obits = mObituaries;
    if(obits != NULL) {
@@ -360,6 +432,42 @@ bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
    return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
}

uint32_t BpBinder::getBinderProxyCount(uint32_t uid)
{
    AutoMutex _l(sTrackingLock);
    auto it = sTrackingMap.find(uid);
    if (it != sTrackingMap.end()) {
        return it->second & COUNTING_VALUE_MASK;
    }
    return 0;
}

void BpBinder::getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts)
{
    AutoMutex _l(sTrackingLock);
    uids.setCapacity(sTrackingMap.size());
    counts.setCapacity(sTrackingMap.size());
    for (const auto& it : sTrackingMap) {
        uids.push_back(it.first);
        counts.push_back(it.second & COUNTING_VALUE_MASK);
    }
}

void BpBinder::enableCountByUid() { sCountByUidEnabled.store(true); }
void BpBinder::disableCountByUid() { sCountByUidEnabled.store(false); }
void BpBinder::setCountByUidEnabled(bool enable) { sCountByUidEnabled.store(enable); }

void BpBinder::setLimitCallback(binder_proxy_limit_callback cb) {
    AutoMutex _l(sTrackingLock);
    sLimitCallback = cb;
}

void BpBinder::setBinderProxyCountWatermarks(int high, int low) {
    AutoMutex _l(sTrackingLock);
    sBinderProxyCountHighWatermark = high;
    sBinderProxyCountLowWatermark = low;
}

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

}; // namespace android
+2 −2
Original line number Diff line number Diff line
@@ -276,7 +276,7 @@ sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
                   return NULL;
            }

            b = new BpBinder(handle); 
            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
@@ -310,7 +310,7 @@ wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle)
        // arriving from the driver.
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            b = new BpBinder(handle);
            b = BpBinder::create(handle);
            result = b;
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
+25 −1
Original line number Diff line number Diff line
@@ -19,15 +19,20 @@

#include <binder/IBinder.h>
#include <utils/KeyedVector.h>
#include <utils/Mutex.h>
#include <utils/threads.h>

#include <unordered_map>

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

using binder_proxy_limit_callback = void(*)(int);

class BpBinder : public IBinder
{
public:
                        BpBinder(int32_t handle);
    static BpBinder*    create(int32_t handle);

    inline  int32_t     handle() const { return mHandle; }

@@ -61,6 +66,14 @@ public:
            status_t    setConstantData(const void* data, size_t size);
            void        sendObituary();

    static uint32_t     getBinderProxyCount(uint32_t uid);
    static void         getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts);
    static void         enableCountByUid();
    static void         disableCountByUid();
    static void         setCountByUidEnabled(bool enable);
    static void         setLimitCallback(binder_proxy_limit_callback cb);
    static void         setBinderProxyCountWatermarks(int high, int low);

    class ObjectManager
    {
    public:
@@ -91,6 +104,7 @@ public:
    };

protected:
                        BpBinder(int32_t handle,int32_t trackedUid);
    virtual             ~BpBinder();
    virtual void        onFirstRef();
    virtual void        onLastStrongRef(const void* id);
@@ -115,6 +129,16 @@ private:
            ObjectManager       mObjects;
            Parcel*             mConstantData;
    mutable String16            mDescriptorCache;
            int32_t             mTrackedUid;

    static Mutex                                sTrackingLock;
    static std::unordered_map<int32_t,uint32_t> sTrackingMap;
    static int                                  sNumTrackedUids;
    static std::atomic_bool                     sCountByUidEnabled;
    static binder_proxy_limit_callback          sLimitCallback;
    static uint32_t                             sBinderProxyCountHighWatermark;
    static uint32_t                             sBinderProxyCountLowWatermark;
    static bool                                 sBinderProxyThrottleCreate;
};

}; // namespace android