diff options
Diffstat (limited to 'libs/binder/ProcessState.cpp')
-rw-r--r-- | libs/binder/ProcessState.cpp | 132 |
1 files changed, 80 insertions, 52 deletions
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 4b773e816f..bade9187ac 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -27,11 +27,12 @@ #include <utils/String8.h> #include <utils/threads.h> -#include <private/binder/binder_module.h> #include "Static.h" +#include "binder_module.h" #include <errno.h> #include <fcntl.h> +#include <mutex> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -42,6 +43,7 @@ #define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2) #define DEFAULT_MAX_BINDER_THREADS 15 +#define DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION 1 #ifdef __ANDROID_VNDK__ const char* kDefaultDriver = "/dev/vndbinder"; @@ -73,38 +75,49 @@ protected: sp<ProcessState> ProcessState::self() { - Mutex::Autolock _l(gProcessMutex); - if (gProcess != nullptr) { - return gProcess; - } - gProcess = new ProcessState(kDefaultDriver); - return gProcess; + return init(kDefaultDriver, false /*requireDefault*/); } sp<ProcessState> ProcessState::initWithDriver(const char* driver) { - Mutex::Autolock _l(gProcessMutex); - if (gProcess != nullptr) { - // Allow for initWithDriver to be called repeatedly with the same - // driver. - if (!strcmp(gProcess->getDriverName().c_str(), driver)) { - return gProcess; - } - LOG_ALWAYS_FATAL("ProcessState was already initialized."); - } - - if (access(driver, R_OK) == -1) { - ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver); - driver = "/dev/binder"; - } - - gProcess = new ProcessState(driver); - return gProcess; + return init(driver, true /*requireDefault*/); } sp<ProcessState> ProcessState::selfOrNull() { - Mutex::Autolock _l(gProcessMutex); + return init(nullptr, false /*requireDefault*/); +} + +sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault) +{ + [[clang::no_destroy]] static sp<ProcessState> gProcess; + [[clang::no_destroy]] static std::mutex gProcessMutex; + + if (driver == nullptr) { + std::lock_guard<std::mutex> l(gProcessMutex); + return gProcess; + } + + [[clang::no_destroy]] static std::once_flag gProcessOnce; + std::call_once(gProcessOnce, [&](){ + if (access(driver, R_OK) == -1) { + ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver); + driver = "/dev/binder"; + } + + std::lock_guard<std::mutex> l(gProcessMutex); + gProcess = sp<ProcessState>::make(driver); + }); + + if (requireDefault) { + // Detect if we are trying to initialize with a different driver, and + // consider that an error. ProcessState will only be initialized once above. + LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver, + "ProcessState was already initialized with %s," + " can't initialize with %s.", + gProcess->getDriverName().c_str(), driver); + } + return gProcess; } @@ -112,14 +125,14 @@ sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/) { sp<IBinder> context = getStrongProxyForHandle(0); - if (context == nullptr) { - ALOGW("Not able to get context object on %s.", mDriverName.c_str()); + if (context) { + // The root object is special since we get it directly from the driver, it is never + // written by Parcell::writeStrongBinder. + internal::Stability::markCompilationUnit(context.get()); + } else { + ALOGW("Not able to get context object on %s.", mDriverName.c_str()); } - // The root object is special since we get it directly from the driver, it is never - // written by Parcell::writeStrongBinder. - internal::Stability::tryMarkCompilationUnit(context.get()); - return context; } @@ -132,11 +145,9 @@ void ProcessState::startThreadPool() } } -bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData) +bool ProcessState::becomeContextManager() { AutoMutex _l(mLock); - mBinderContextCheckFunc = checkFunc; - mBinderContextUserData = userData; flat_binder_object obj { .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX, @@ -148,13 +159,11 @@ bool ProcessState::becomeContextManager(context_check_func checkFunc, void* user if (result != 0) { android_errorWriteLog(0x534e4554, "121035042"); - int dummy = 0; - result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy); + int unused = 0; + result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused); } if (result == -1) { - mBinderContextCheckFunc = nullptr; - mBinderContextUserData = nullptr; ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno)); } @@ -196,11 +205,13 @@ ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf) // that the handle points to. Can only be used by the servicemanager. // // Returns -1 in case of failure, otherwise the strong reference count. -ssize_t ProcessState::getStrongRefCountForNodeByHandle(int32_t handle) { +ssize_t ProcessState::getStrongRefCountForNode(const sp<BpBinder>& binder) { + if (binder->isRpcBinder()) return -1; + binder_node_info_for_ref info; memset(&info, 0, sizeof(binder_node_info_for_ref)); - info.handle = handle; + info.handle = binder->getPrivateAccessorForId().binderHandle(); status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info); @@ -274,15 +285,23 @@ sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) // a driver API to get a handle to the context manager with // proper reference counting. + IPCThreadState* ipc = IPCThreadState::self(); + + CallRestriction originalCallRestriction = ipc->getCallRestriction(); + ipc->setCallRestriction(CallRestriction::NONE); + Parcel data; - status_t status = IPCThreadState::self()->transact( + status_t status = ipc->transact( 0, IBinder::PING_TRANSACTION, data, nullptr, 0); + + ipc->setCallRestriction(originalCallRestriction); + if (status == DEAD_OBJECT) return nullptr; } - b = BpBinder::create(handle); - e->binder = b; + sp<BpBinder> b = BpBinder::create(handle); + e->binder = b.get(); if (b) e->refs = b->getWeakRefs(); result = b; } else { @@ -322,12 +341,14 @@ void ProcessState::spawnPooledThread(bool isMain) if (mThreadPoolStarted) { String8 name = makeBinderThreadName(); ALOGV("Spawning new pooled thread, name=%s\n", name.string()); - sp<Thread> t = new PoolThread(isMain); + sp<Thread> t = sp<PoolThread>::make(isMain); t->run(name.string()); } } status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) { + LOG_ALWAYS_FATAL_IF(mThreadPoolStarted && maxThreads < mMaxThreads, + "Binder threadpool cannot be shrunk after starting"); status_t result = NO_ERROR; if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) != -1) { mMaxThreads = maxThreads; @@ -338,6 +359,15 @@ status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) { return result; } +status_t ProcessState::enableOnewaySpamDetection(bool enable) { + uint32_t enableDetection = enable ? 1 : 0; + if (ioctl(mDriverFD, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enableDetection) == -1) { + ALOGI("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno)); + return -errno; + } + return NO_ERROR; +} + void ProcessState::giveThreadPoolName() { androidSetThreadName( makeBinderThreadName().string() ); } @@ -368,6 +398,11 @@ static int open_driver(const char *driver) if (result == -1) { ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno)); } + uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION; + result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable); + if (result == -1) { + ALOGD("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno)); + } } else { ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno)); } @@ -381,20 +416,13 @@ ProcessState::ProcessState(const char *driver) , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER) , mThreadCountDecrement(PTHREAD_COND_INITIALIZER) , mExecutingThreadsCount(0) + , mWaitingForThreads(0) , mMaxThreads(DEFAULT_MAX_BINDER_THREADS) , mStarvationStartTimeMs(0) - , mBinderContextCheckFunc(nullptr) - , mBinderContextUserData(nullptr) , mThreadPoolStarted(false) , mThreadPoolSeq(1) , mCallRestriction(CallRestriction::NONE) { - -// TODO(b/139016109): enforce in build system -#if defined(__ANDROID_APEX__) - LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable."); -#endif - if (mDriverFD >= 0) { // mmap the binder, providing a chunk of virtual address space to receive transactions. mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); |