• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "BpBinder"
18 //#define LOG_NDEBUG 0
19 
20 #include <binder/BpBinder.h>
21 
22 #include <binder/IPCThreadState.h>
23 #include <binder/IResultReceiver.h>
24 #include <cutils/compiler.h>
25 #include <utils/Log.h>
26 
27 #include <stdio.h>
28 
29 //#undef ALOGV
30 //#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
31 
32 namespace android {
33 
34 // ---------------------------------------------------------------------------
35 
36 Mutex BpBinder::sTrackingLock;
37 std::unordered_map<int32_t,uint32_t> BpBinder::sTrackingMap;
38 int BpBinder::sNumTrackedUids = 0;
39 std::atomic_bool BpBinder::sCountByUidEnabled(false);
40 binder_proxy_limit_callback BpBinder::sLimitCallback;
41 bool BpBinder::sBinderProxyThrottleCreate = false;
42 
43 // Arbitrarily high value that probably distinguishes a bad behaving app
44 uint32_t BpBinder::sBinderProxyCountHighWatermark = 2500;
45 // Another arbitrary value a binder count needs to drop below before another callback will be called
46 uint32_t BpBinder::sBinderProxyCountLowWatermark = 2000;
47 
48 enum {
49     LIMIT_REACHED_MASK = 0x80000000,        // A flag denoting that the limit has been reached
50     COUNTING_VALUE_MASK = 0x7FFFFFFF,       // A mask of the remaining bits for the count value
51 };
52 
ObjectManager()53 BpBinder::ObjectManager::ObjectManager()
54 {
55 }
56 
~ObjectManager()57 BpBinder::ObjectManager::~ObjectManager()
58 {
59     kill();
60 }
61 
attach(const void * objectID,void * object,void * cleanupCookie,IBinder::object_cleanup_func func)62 void BpBinder::ObjectManager::attach(
63     const void* objectID, void* object, void* cleanupCookie,
64     IBinder::object_cleanup_func func)
65 {
66     entry_t e;
67     e.object = object;
68     e.cleanupCookie = cleanupCookie;
69     e.func = func;
70 
71     if (mObjects.indexOfKey(objectID) >= 0) {
72         ALOGE("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object ID already in use",
73                 objectID, this,  object);
74         return;
75     }
76 
77     mObjects.add(objectID, e);
78 }
79 
find(const void * objectID) const80 void* BpBinder::ObjectManager::find(const void* objectID) const
81 {
82     const ssize_t i = mObjects.indexOfKey(objectID);
83     if (i < 0) return nullptr;
84     return mObjects.valueAt(i).object;
85 }
86 
detach(const void * objectID)87 void BpBinder::ObjectManager::detach(const void* objectID)
88 {
89     mObjects.removeItem(objectID);
90 }
91 
kill()92 void BpBinder::ObjectManager::kill()
93 {
94     const size_t N = mObjects.size();
95     ALOGV("Killing %zu objects in manager %p", N, this);
96     for (size_t i=0; i<N; i++) {
97         const entry_t& e = mObjects.valueAt(i);
98         if (e.func != nullptr) {
99             e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
100         }
101     }
102 
103     mObjects.clear();
104 }
105 
106 // ---------------------------------------------------------------------------
107 
108 
create(int32_t handle)109 BpBinder* BpBinder::create(int32_t handle) {
110     int32_t trackedUid = -1;
111     if (sCountByUidEnabled) {
112         trackedUid = IPCThreadState::self()->getCallingUid();
113         AutoMutex _l(sTrackingLock);
114         uint32_t trackedValue = sTrackingMap[trackedUid];
115         if (CC_UNLIKELY(trackedValue & LIMIT_REACHED_MASK)) {
116             if (sBinderProxyThrottleCreate) {
117                 return nullptr;
118             }
119         } else {
120             if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
121                 ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",
122                       getuid(), trackedUid, trackedValue);
123                 sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK;
124                 if (sLimitCallback) sLimitCallback(trackedUid);
125                 if (sBinderProxyThrottleCreate) {
126                     ALOGI("Throttling binder proxy creates from uid %d in uid %d until binder proxy"
127                           " count drops below %d",
128                           trackedUid, getuid(), sBinderProxyCountLowWatermark);
129                     return nullptr;
130                 }
131             }
132         }
133         sTrackingMap[trackedUid]++;
134     }
135     return new BpBinder(handle, trackedUid);
136 }
137 
BpBinder(int32_t handle,int32_t trackedUid)138 BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
139     : mHandle(handle)
140     , mAlive(1)
141     , mObitsSent(0)
142     , mObituaries(nullptr)
143     , mTrackedUid(trackedUid)
144 {
145     ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
146 
147     extendObjectLifetime(OBJECT_LIFETIME_WEAK);
148     IPCThreadState::self()->incWeakHandle(handle, this);
149 }
150 
isDescriptorCached() const151 bool BpBinder::isDescriptorCached() const {
152     Mutex::Autolock _l(mLock);
153     return mDescriptorCache.size() ? true : false;
154 }
155 
getInterfaceDescriptor() const156 const String16& BpBinder::getInterfaceDescriptor() const
157 {
158     if (isDescriptorCached() == false) {
159         Parcel send, reply;
160         // do the IPC without a lock held.
161         status_t err = const_cast<BpBinder*>(this)->transact(
162                 INTERFACE_TRANSACTION, send, &reply);
163         if (err == NO_ERROR) {
164             String16 res(reply.readString16());
165             Mutex::Autolock _l(mLock);
166             // mDescriptorCache could have been assigned while the lock was
167             // released.
168             if (mDescriptorCache.size() == 0)
169                 mDescriptorCache = res;
170         }
171     }
172 
173     // we're returning a reference to a non-static object here. Usually this
174     // is not something smart to do, however, with binder objects it is
175     // (usually) safe because they are reference-counted.
176 
177     return mDescriptorCache;
178 }
179 
isBinderAlive() const180 bool BpBinder::isBinderAlive() const
181 {
182     return mAlive != 0;
183 }
184 
pingBinder()185 status_t BpBinder::pingBinder()
186 {
187     Parcel send;
188     Parcel reply;
189     status_t err = transact(PING_TRANSACTION, send, &reply);
190     if (err != NO_ERROR) return err;
191     if (reply.dataSize() < sizeof(status_t)) return NOT_ENOUGH_DATA;
192     return (status_t)reply.readInt32();
193 }
194 
dump(int fd,const Vector<String16> & args)195 status_t BpBinder::dump(int fd, const Vector<String16>& args)
196 {
197     Parcel send;
198     Parcel reply;
199     send.writeFileDescriptor(fd);
200     const size_t numArgs = args.size();
201     send.writeInt32(numArgs);
202     for (size_t i = 0; i < numArgs; i++) {
203         send.writeString16(args[i]);
204     }
205     status_t err = transact(DUMP_TRANSACTION, send, &reply);
206     return err;
207 }
208 
209 // NOLINTNEXTLINE(google-default-arguments)
transact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)210 status_t BpBinder::transact(
211     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
212 {
213     // Once a binder has died, it will never come back to life.
214     if (mAlive) {
215         status_t status = IPCThreadState::self()->transact(
216             mHandle, code, data, reply, flags);
217         if (status == DEAD_OBJECT) mAlive = 0;
218         return status;
219     }
220 
221     return DEAD_OBJECT;
222 }
223 
224 // NOLINTNEXTLINE(google-default-arguments)
linkToDeath(const sp<DeathRecipient> & recipient,void * cookie,uint32_t flags)225 status_t BpBinder::linkToDeath(
226     const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
227 {
228     Obituary ob;
229     ob.recipient = recipient;
230     ob.cookie = cookie;
231     ob.flags = flags;
232 
233     LOG_ALWAYS_FATAL_IF(recipient == nullptr,
234                         "linkToDeath(): recipient must be non-NULL");
235 
236     {
237         AutoMutex _l(mLock);
238 
239         if (!mObitsSent) {
240             if (!mObituaries) {
241                 mObituaries = new Vector<Obituary>;
242                 if (!mObituaries) {
243                     return NO_MEMORY;
244                 }
245                 ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
246                 getWeakRefs()->incWeak(this);
247                 IPCThreadState* self = IPCThreadState::self();
248                 self->requestDeathNotification(mHandle, this);
249                 self->flushCommands();
250             }
251             ssize_t res = mObituaries->add(ob);
252             return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
253         }
254     }
255 
256     return DEAD_OBJECT;
257 }
258 
259 // NOLINTNEXTLINE(google-default-arguments)
unlinkToDeath(const wp<DeathRecipient> & recipient,void * cookie,uint32_t flags,wp<DeathRecipient> * outRecipient)260 status_t BpBinder::unlinkToDeath(
261     const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
262     wp<DeathRecipient>* outRecipient)
263 {
264     AutoMutex _l(mLock);
265 
266     if (mObitsSent) {
267         return DEAD_OBJECT;
268     }
269 
270     const size_t N = mObituaries ? mObituaries->size() : 0;
271     for (size_t i=0; i<N; i++) {
272         const Obituary& obit = mObituaries->itemAt(i);
273         if ((obit.recipient == recipient
274                     || (recipient == nullptr && obit.cookie == cookie))
275                 && obit.flags == flags) {
276             if (outRecipient != nullptr) {
277                 *outRecipient = mObituaries->itemAt(i).recipient;
278             }
279             mObituaries->removeAt(i);
280             if (mObituaries->size() == 0) {
281                 ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
282                 IPCThreadState* self = IPCThreadState::self();
283                 self->clearDeathNotification(mHandle, this);
284                 self->flushCommands();
285                 delete mObituaries;
286                 mObituaries = nullptr;
287             }
288             return NO_ERROR;
289         }
290     }
291 
292     return NAME_NOT_FOUND;
293 }
294 
sendObituary()295 void BpBinder::sendObituary()
296 {
297     ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
298         this, mHandle, mObitsSent ? "true" : "false");
299 
300     mAlive = 0;
301     if (mObitsSent) return;
302 
303     mLock.lock();
304     Vector<Obituary>* obits = mObituaries;
305     if(obits != nullptr) {
306         ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
307         IPCThreadState* self = IPCThreadState::self();
308         self->clearDeathNotification(mHandle, this);
309         self->flushCommands();
310         mObituaries = nullptr;
311     }
312     mObitsSent = 1;
313     mLock.unlock();
314 
315     ALOGV("Reporting death of proxy %p for %zu recipients\n",
316         this, obits ? obits->size() : 0U);
317 
318     if (obits != nullptr) {
319         const size_t N = obits->size();
320         for (size_t i=0; i<N; i++) {
321             reportOneDeath(obits->itemAt(i));
322         }
323 
324         delete obits;
325     }
326 }
327 
reportOneDeath(const Obituary & obit)328 void BpBinder::reportOneDeath(const Obituary& obit)
329 {
330     sp<DeathRecipient> recipient = obit.recipient.promote();
331     ALOGV("Reporting death to recipient: %p\n", recipient.get());
332     if (recipient == nullptr) return;
333 
334     recipient->binderDied(this);
335 }
336 
337 
attachObject(const void * objectID,void * object,void * cleanupCookie,object_cleanup_func func)338 void BpBinder::attachObject(
339     const void* objectID, void* object, void* cleanupCookie,
340     object_cleanup_func func)
341 {
342     AutoMutex _l(mLock);
343     ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
344     mObjects.attach(objectID, object, cleanupCookie, func);
345 }
346 
findObject(const void * objectID) const347 void* BpBinder::findObject(const void* objectID) const
348 {
349     AutoMutex _l(mLock);
350     return mObjects.find(objectID);
351 }
352 
detachObject(const void * objectID)353 void BpBinder::detachObject(const void* objectID)
354 {
355     AutoMutex _l(mLock);
356     mObjects.detach(objectID);
357 }
358 
remoteBinder()359 BpBinder* BpBinder::remoteBinder()
360 {
361     return this;
362 }
363 
~BpBinder()364 BpBinder::~BpBinder()
365 {
366     ALOGV("Destroying BpBinder %p handle %d\n", this, mHandle);
367 
368     IPCThreadState* ipc = IPCThreadState::self();
369 
370     if (mTrackedUid >= 0) {
371         AutoMutex _l(sTrackingLock);
372         uint32_t trackedValue = sTrackingMap[mTrackedUid];
373         if (CC_UNLIKELY((trackedValue & COUNTING_VALUE_MASK) == 0)) {
374             ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this, mHandle);
375         } else {
376             if (CC_UNLIKELY(
377                 (trackedValue & LIMIT_REACHED_MASK) &&
378                 ((trackedValue & COUNTING_VALUE_MASK) <= sBinderProxyCountLowWatermark)
379                 )) {
380                 ALOGI("Limit reached bit reset for uid %d (fewer than %d proxies from uid %d held)",
381                                    getuid(), mTrackedUid, sBinderProxyCountLowWatermark);
382                 sTrackingMap[mTrackedUid] &= ~LIMIT_REACHED_MASK;
383             }
384             if (--sTrackingMap[mTrackedUid] == 0) {
385                 sTrackingMap.erase(mTrackedUid);
386             }
387         }
388     }
389 
390     mLock.lock();
391     Vector<Obituary>* obits = mObituaries;
392     if(obits != nullptr) {
393         if (ipc) ipc->clearDeathNotification(mHandle, this);
394         mObituaries = nullptr;
395     }
396     mLock.unlock();
397 
398     if (obits != nullptr) {
399         // XXX Should we tell any remaining DeathRecipient
400         // objects that the last strong ref has gone away, so they
401         // are no longer linked?
402         delete obits;
403     }
404 
405     if (ipc) {
406         ipc->expungeHandle(mHandle, this);
407         ipc->decWeakHandle(mHandle);
408     }
409 }
410 
onFirstRef()411 void BpBinder::onFirstRef()
412 {
413     ALOGV("onFirstRef BpBinder %p handle %d\n", this, mHandle);
414     IPCThreadState* ipc = IPCThreadState::self();
415     if (ipc) ipc->incStrongHandle(mHandle, this);
416 }
417 
onLastStrongRef(const void *)418 void BpBinder::onLastStrongRef(const void* /*id*/)
419 {
420     ALOGV("onLastStrongRef BpBinder %p handle %d\n", this, mHandle);
421     IF_ALOGV() {
422         printRefs();
423     }
424     IPCThreadState* ipc = IPCThreadState::self();
425     if (ipc) ipc->decStrongHandle(mHandle);
426 }
427 
onIncStrongAttempted(uint32_t,const void *)428 bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
429 {
430     ALOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, mHandle);
431     IPCThreadState* ipc = IPCThreadState::self();
432     return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
433 }
434 
getBinderProxyCount(uint32_t uid)435 uint32_t BpBinder::getBinderProxyCount(uint32_t uid)
436 {
437     AutoMutex _l(sTrackingLock);
438     auto it = sTrackingMap.find(uid);
439     if (it != sTrackingMap.end()) {
440         return it->second & COUNTING_VALUE_MASK;
441     }
442     return 0;
443 }
444 
getCountByUid(Vector<uint32_t> & uids,Vector<uint32_t> & counts)445 void BpBinder::getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts)
446 {
447     AutoMutex _l(sTrackingLock);
448     uids.setCapacity(sTrackingMap.size());
449     counts.setCapacity(sTrackingMap.size());
450     for (const auto& it : sTrackingMap) {
451         uids.push_back(it.first);
452         counts.push_back(it.second & COUNTING_VALUE_MASK);
453     }
454 }
455 
enableCountByUid()456 void BpBinder::enableCountByUid() { sCountByUidEnabled.store(true); }
disableCountByUid()457 void BpBinder::disableCountByUid() { sCountByUidEnabled.store(false); }
setCountByUidEnabled(bool enable)458 void BpBinder::setCountByUidEnabled(bool enable) { sCountByUidEnabled.store(enable); }
459 
setLimitCallback(binder_proxy_limit_callback cb)460 void BpBinder::setLimitCallback(binder_proxy_limit_callback cb) {
461     AutoMutex _l(sTrackingLock);
462     sLimitCallback = cb;
463 }
464 
setBinderProxyCountWatermarks(int high,int low)465 void BpBinder::setBinderProxyCountWatermarks(int high, int low) {
466     AutoMutex _l(sTrackingLock);
467     sBinderProxyCountHighWatermark = high;
468     sBinderProxyCountLowWatermark = low;
469 }
470 
471 // ---------------------------------------------------------------------------
472 
473 }; // namespace android
474