Loading libs/binder/IPCThreadState.cpp +35 −9 Original line number Original line Diff line number Diff line Loading @@ -366,19 +366,45 @@ status_t IPCThreadState::clearLastError() pid_t IPCThreadState::getCallingPid() const pid_t IPCThreadState::getCallingPid() const { { checkContextIsBinderForUse(__func__); return mCallingPid; return mCallingPid; } } const char* IPCThreadState::getCallingSid() const const char* IPCThreadState::getCallingSid() const { { checkContextIsBinderForUse(__func__); return mCallingSid; return mCallingSid; } } uid_t IPCThreadState::getCallingUid() const uid_t IPCThreadState::getCallingUid() const { { checkContextIsBinderForUse(__func__); return mCallingUid; return mCallingUid; } } IPCThreadState::SpGuard* IPCThreadState::pushGetCallingSpGuard(SpGuard* guard) { SpGuard* orig = mServingStackPointerGuard; mServingStackPointerGuard = guard; return orig; } void IPCThreadState::restoreGetCallingSpGuard(SpGuard* guard) { mServingStackPointerGuard = guard; } void IPCThreadState::checkContextIsBinderForUse(const char* use) const { if (mServingStackPointerGuard == nullptr) return; if (!mServingStackPointer || mServingStackPointerGuard < mServingStackPointer) { LOG_ALWAYS_FATAL("In context %s, %s does not make sense.", mServingStackPointerGuard->context, use); } // in the case mServingStackPointer is deeper in the stack than the guard, // we must be serving a binder transaction (maybe nested). This is a binder // context, so we don't abort } int64_t IPCThreadState::clearCallingIdentity() int64_t IPCThreadState::clearCallingIdentity() { { // ignore mCallingSid for legacy reasons // ignore mCallingSid for legacy reasons Loading Loading @@ -849,13 +875,13 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) IPCThreadState::IPCThreadState() IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), : mProcess(ProcessState::self()), mServingStackPointer(nullptr), mServingStackPointer(nullptr), mServingStackPointerGuard(nullptr), mWorkSource(kUnsetWorkSource), mWorkSource(kUnsetWorkSource), mPropagateWorkSource(false), mPropagateWorkSource(false), mIsLooper(false), mIsLooper(false), mStrictModePolicy(0), mStrictModePolicy(0), mLastTransactionBinderFlags(0), mLastTransactionBinderFlags(0), mCallRestriction(mProcess->mCallRestriction) mCallRestriction(mProcess->mCallRestriction) { { pthread_setspecific(gTLS, this); pthread_setspecific(gTLS, this); clearCaller(); clearCaller(); mIn.setDataCapacity(256); mIn.setDataCapacity(256); Loading libs/binder/RpcState.cpp +16 −0 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,9 @@ #include "RpcState.h" #include "RpcState.h" #include <android-base/scopeguard.h> #include <binder/BpBinder.h> #include <binder/BpBinder.h> #include <binder/IPCThreadState.h> #include <binder/RpcServer.h> #include <binder/RpcServer.h> #include "Debug.h" #include "Debug.h" Loading @@ -28,6 +30,8 @@ namespace android { namespace android { using base::ScopeGuard; RpcState::RpcState() {} RpcState::RpcState() {} RpcState::~RpcState() {} RpcState::~RpcState() {} Loading Loading @@ -470,6 +474,18 @@ status_t RpcState::getAndExecuteCommand(const base::unique_fd& fd, const sp<RpcS status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session, status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session, const RpcWireHeader& command) { const RpcWireHeader& command) { IPCThreadState* kernelBinderState = IPCThreadState::selfOrNull(); IPCThreadState::SpGuard spGuard{"processing binder RPC command"}; IPCThreadState::SpGuard* origGuard; if (kernelBinderState != nullptr) { origGuard = kernelBinderState->pushGetCallingSpGuard(&spGuard); } ScopeGuard guardUnguard = [&]() { if (kernelBinderState != nullptr) { kernelBinderState->restoreGetCallingSpGuard(origGuard); } }; switch (command.command) { switch (command.command) { case RPC_COMMAND_TRANSACT: case RPC_COMMAND_TRANSACT: return processTransact(fd, session, command); return processTransact(fd, session, command); Loading libs/binder/include/binder/IPCThreadState.h +27 −0 Original line number Original line Diff line number Diff line Loading @@ -81,6 +81,32 @@ public: */ */ uid_t getCallingUid() const; uid_t getCallingUid() const; /** * Make it an abort to rely on getCalling* for a section of * execution. * * Usage: * IPCThreadState::SpGuard guard { "..." }; * auto* orig = pushGetCallingSpGuard(&guard); * { * // will abort if you call getCalling*, unless you are * // serving a nested binder transaction * } * restoreCallingSpGuard(orig); */ struct SpGuard { const char* context; }; SpGuard* pushGetCallingSpGuard(SpGuard* guard); void restoreGetCallingSpGuard(SpGuard* guard); /** * Used internally by getCalling*. Can also be used to assert that * you are in a binder context (getCalling* is valid). This is * intentionally not exposed as a boolean API since code should be * written to know its environment. */ void checkContextIsBinderForUse(const char* use) const; void setStrictModePolicy(int32_t policy); void setStrictModePolicy(int32_t policy); int32_t getStrictModePolicy() const; int32_t getStrictModePolicy() const; Loading Loading @@ -203,6 +229,7 @@ private: Parcel mOut; Parcel mOut; status_t mLastError; status_t mLastError; const void* mServingStackPointer; const void* mServingStackPointer; SpGuard* mServingStackPointerGuard; pid_t mCallingPid; pid_t mCallingPid; const char* mCallingSid; const char* mCallingSid; uid_t mCallingUid; uid_t mCallingUid; Loading libs/binder/tests/IBinderRpcTest.aidl +2 −0 Original line number Original line Diff line number Diff line Loading @@ -55,4 +55,6 @@ interface IBinderRpcTest { oneway void sleepMsAsync(int ms); oneway void sleepMsAsync(int ms); void die(boolean cleanup); void die(boolean cleanup); void useKernelBinderCallingId(); } } libs/binder/tests/binderLibTest.cpp +36 −0 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_REGISTER_SERVER, BINDER_LIB_TEST_REGISTER_SERVER, BINDER_LIB_TEST_ADD_SERVER, BINDER_LIB_TEST_ADD_SERVER, BINDER_LIB_TEST_ADD_POLL_SERVER, BINDER_LIB_TEST_ADD_POLL_SERVER, BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION, BINDER_LIB_TEST_CALL_BACK, BINDER_LIB_TEST_CALL_BACK, BINDER_LIB_TEST_CALL_BACK_VERIFY_BUF, BINDER_LIB_TEST_CALL_BACK_VERIFY_BUF, BINDER_LIB_TEST_DELAYED_CALL_BACK, BINDER_LIB_TEST_DELAYED_CALL_BACK, Loading Loading @@ -604,6 +605,24 @@ TEST_F(BinderLibTest, CallBack) EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR)); EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR)); } } TEST_F(BinderLibTest, NoBinderCallContextGuard) { IPCThreadState::SpGuard spGuard{"NoBinderCallContext"}; IPCThreadState::SpGuard *origGuard = IPCThreadState::self()->pushGetCallingSpGuard(&spGuard); // yes, this test uses threads, but it's careful and uses fork in addServer EXPECT_DEATH({ IPCThreadState::self()->getCallingPid(); }, "In context NoBinderCallContext, getCallingPid does not make sense."); IPCThreadState::self()->restoreGetCallingSpGuard(origGuard); } TEST_F(BinderLibTest, BinderCallContextGuard) { sp<IBinder> binder = addServer(); Parcel data, reply; EXPECT_THAT(binder->transact(BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION, data, &reply), StatusEq(DEAD_OBJECT)); } TEST_F(BinderLibTest, AddServer) TEST_F(BinderLibTest, AddServer) { { sp<IBinder> server = addServer(); sp<IBinder> server = addServer(); Loading Loading @@ -1262,6 +1281,18 @@ class BinderLibTestService : public BBinder pthread_mutex_unlock(&m_serverWaitMutex); pthread_mutex_unlock(&m_serverWaitMutex); return ret; return ret; } } case BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION: { IPCThreadState::SpGuard spGuard{"GuardInBinderTransaction"}; IPCThreadState::SpGuard *origGuard = IPCThreadState::self()->pushGetCallingSpGuard(&spGuard); // if the guard works, this should abort (void)IPCThreadState::self()->getCallingPid(); IPCThreadState::self()->restoreGetCallingSpGuard(origGuard); return NO_ERROR; } case BINDER_LIB_TEST_GETPID: case BINDER_LIB_TEST_GETPID: reply->writeInt32(getpid()); reply->writeInt32(getpid()); return NO_ERROR; return NO_ERROR; Loading Loading @@ -1489,6 +1520,11 @@ int run_server(int index, int readypipefd, bool usePoll) { { binderLibTestServiceName += String16(binderserversuffix); binderLibTestServiceName += String16(binderserversuffix); // Testing to make sure that calls that we are serving can use getCallin* // even though we don't here. IPCThreadState::SpGuard spGuard{"main server thread"}; (void)IPCThreadState::self()->pushGetCallingSpGuard(&spGuard); status_t ret; status_t ret; sp<IServiceManager> sm = defaultServiceManager(); sp<IServiceManager> sm = defaultServiceManager(); BinderLibTestService* testServicePtr; BinderLibTestService* testServicePtr; Loading Loading
libs/binder/IPCThreadState.cpp +35 −9 Original line number Original line Diff line number Diff line Loading @@ -366,19 +366,45 @@ status_t IPCThreadState::clearLastError() pid_t IPCThreadState::getCallingPid() const pid_t IPCThreadState::getCallingPid() const { { checkContextIsBinderForUse(__func__); return mCallingPid; return mCallingPid; } } const char* IPCThreadState::getCallingSid() const const char* IPCThreadState::getCallingSid() const { { checkContextIsBinderForUse(__func__); return mCallingSid; return mCallingSid; } } uid_t IPCThreadState::getCallingUid() const uid_t IPCThreadState::getCallingUid() const { { checkContextIsBinderForUse(__func__); return mCallingUid; return mCallingUid; } } IPCThreadState::SpGuard* IPCThreadState::pushGetCallingSpGuard(SpGuard* guard) { SpGuard* orig = mServingStackPointerGuard; mServingStackPointerGuard = guard; return orig; } void IPCThreadState::restoreGetCallingSpGuard(SpGuard* guard) { mServingStackPointerGuard = guard; } void IPCThreadState::checkContextIsBinderForUse(const char* use) const { if (mServingStackPointerGuard == nullptr) return; if (!mServingStackPointer || mServingStackPointerGuard < mServingStackPointer) { LOG_ALWAYS_FATAL("In context %s, %s does not make sense.", mServingStackPointerGuard->context, use); } // in the case mServingStackPointer is deeper in the stack than the guard, // we must be serving a binder transaction (maybe nested). This is a binder // context, so we don't abort } int64_t IPCThreadState::clearCallingIdentity() int64_t IPCThreadState::clearCallingIdentity() { { // ignore mCallingSid for legacy reasons // ignore mCallingSid for legacy reasons Loading Loading @@ -849,13 +875,13 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) IPCThreadState::IPCThreadState() IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), : mProcess(ProcessState::self()), mServingStackPointer(nullptr), mServingStackPointer(nullptr), mServingStackPointerGuard(nullptr), mWorkSource(kUnsetWorkSource), mWorkSource(kUnsetWorkSource), mPropagateWorkSource(false), mPropagateWorkSource(false), mIsLooper(false), mIsLooper(false), mStrictModePolicy(0), mStrictModePolicy(0), mLastTransactionBinderFlags(0), mLastTransactionBinderFlags(0), mCallRestriction(mProcess->mCallRestriction) mCallRestriction(mProcess->mCallRestriction) { { pthread_setspecific(gTLS, this); pthread_setspecific(gTLS, this); clearCaller(); clearCaller(); mIn.setDataCapacity(256); mIn.setDataCapacity(256); Loading
libs/binder/RpcState.cpp +16 −0 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,9 @@ #include "RpcState.h" #include "RpcState.h" #include <android-base/scopeguard.h> #include <binder/BpBinder.h> #include <binder/BpBinder.h> #include <binder/IPCThreadState.h> #include <binder/RpcServer.h> #include <binder/RpcServer.h> #include "Debug.h" #include "Debug.h" Loading @@ -28,6 +30,8 @@ namespace android { namespace android { using base::ScopeGuard; RpcState::RpcState() {} RpcState::RpcState() {} RpcState::~RpcState() {} RpcState::~RpcState() {} Loading Loading @@ -470,6 +474,18 @@ status_t RpcState::getAndExecuteCommand(const base::unique_fd& fd, const sp<RpcS status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session, status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session, const RpcWireHeader& command) { const RpcWireHeader& command) { IPCThreadState* kernelBinderState = IPCThreadState::selfOrNull(); IPCThreadState::SpGuard spGuard{"processing binder RPC command"}; IPCThreadState::SpGuard* origGuard; if (kernelBinderState != nullptr) { origGuard = kernelBinderState->pushGetCallingSpGuard(&spGuard); } ScopeGuard guardUnguard = [&]() { if (kernelBinderState != nullptr) { kernelBinderState->restoreGetCallingSpGuard(origGuard); } }; switch (command.command) { switch (command.command) { case RPC_COMMAND_TRANSACT: case RPC_COMMAND_TRANSACT: return processTransact(fd, session, command); return processTransact(fd, session, command); Loading
libs/binder/include/binder/IPCThreadState.h +27 −0 Original line number Original line Diff line number Diff line Loading @@ -81,6 +81,32 @@ public: */ */ uid_t getCallingUid() const; uid_t getCallingUid() const; /** * Make it an abort to rely on getCalling* for a section of * execution. * * Usage: * IPCThreadState::SpGuard guard { "..." }; * auto* orig = pushGetCallingSpGuard(&guard); * { * // will abort if you call getCalling*, unless you are * // serving a nested binder transaction * } * restoreCallingSpGuard(orig); */ struct SpGuard { const char* context; }; SpGuard* pushGetCallingSpGuard(SpGuard* guard); void restoreGetCallingSpGuard(SpGuard* guard); /** * Used internally by getCalling*. Can also be used to assert that * you are in a binder context (getCalling* is valid). This is * intentionally not exposed as a boolean API since code should be * written to know its environment. */ void checkContextIsBinderForUse(const char* use) const; void setStrictModePolicy(int32_t policy); void setStrictModePolicy(int32_t policy); int32_t getStrictModePolicy() const; int32_t getStrictModePolicy() const; Loading Loading @@ -203,6 +229,7 @@ private: Parcel mOut; Parcel mOut; status_t mLastError; status_t mLastError; const void* mServingStackPointer; const void* mServingStackPointer; SpGuard* mServingStackPointerGuard; pid_t mCallingPid; pid_t mCallingPid; const char* mCallingSid; const char* mCallingSid; uid_t mCallingUid; uid_t mCallingUid; Loading
libs/binder/tests/IBinderRpcTest.aidl +2 −0 Original line number Original line Diff line number Diff line Loading @@ -55,4 +55,6 @@ interface IBinderRpcTest { oneway void sleepMsAsync(int ms); oneway void sleepMsAsync(int ms); void die(boolean cleanup); void die(boolean cleanup); void useKernelBinderCallingId(); } }
libs/binder/tests/binderLibTest.cpp +36 −0 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_REGISTER_SERVER, BINDER_LIB_TEST_REGISTER_SERVER, BINDER_LIB_TEST_ADD_SERVER, BINDER_LIB_TEST_ADD_SERVER, BINDER_LIB_TEST_ADD_POLL_SERVER, BINDER_LIB_TEST_ADD_POLL_SERVER, BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION, BINDER_LIB_TEST_CALL_BACK, BINDER_LIB_TEST_CALL_BACK, BINDER_LIB_TEST_CALL_BACK_VERIFY_BUF, BINDER_LIB_TEST_CALL_BACK_VERIFY_BUF, BINDER_LIB_TEST_DELAYED_CALL_BACK, BINDER_LIB_TEST_DELAYED_CALL_BACK, Loading Loading @@ -604,6 +605,24 @@ TEST_F(BinderLibTest, CallBack) EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR)); EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR)); } } TEST_F(BinderLibTest, NoBinderCallContextGuard) { IPCThreadState::SpGuard spGuard{"NoBinderCallContext"}; IPCThreadState::SpGuard *origGuard = IPCThreadState::self()->pushGetCallingSpGuard(&spGuard); // yes, this test uses threads, but it's careful and uses fork in addServer EXPECT_DEATH({ IPCThreadState::self()->getCallingPid(); }, "In context NoBinderCallContext, getCallingPid does not make sense."); IPCThreadState::self()->restoreGetCallingSpGuard(origGuard); } TEST_F(BinderLibTest, BinderCallContextGuard) { sp<IBinder> binder = addServer(); Parcel data, reply; EXPECT_THAT(binder->transact(BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION, data, &reply), StatusEq(DEAD_OBJECT)); } TEST_F(BinderLibTest, AddServer) TEST_F(BinderLibTest, AddServer) { { sp<IBinder> server = addServer(); sp<IBinder> server = addServer(); Loading Loading @@ -1262,6 +1281,18 @@ class BinderLibTestService : public BBinder pthread_mutex_unlock(&m_serverWaitMutex); pthread_mutex_unlock(&m_serverWaitMutex); return ret; return ret; } } case BINDER_LIB_TEST_USE_CALLING_GUARD_TRANSACTION: { IPCThreadState::SpGuard spGuard{"GuardInBinderTransaction"}; IPCThreadState::SpGuard *origGuard = IPCThreadState::self()->pushGetCallingSpGuard(&spGuard); // if the guard works, this should abort (void)IPCThreadState::self()->getCallingPid(); IPCThreadState::self()->restoreGetCallingSpGuard(origGuard); return NO_ERROR; } case BINDER_LIB_TEST_GETPID: case BINDER_LIB_TEST_GETPID: reply->writeInt32(getpid()); reply->writeInt32(getpid()); return NO_ERROR; return NO_ERROR; Loading Loading @@ -1489,6 +1520,11 @@ int run_server(int index, int readypipefd, bool usePoll) { { binderLibTestServiceName += String16(binderserversuffix); binderLibTestServiceName += String16(binderserversuffix); // Testing to make sure that calls that we are serving can use getCallin* // even though we don't here. IPCThreadState::SpGuard spGuard{"main server thread"}; (void)IPCThreadState::self()->pushGetCallingSpGuard(&spGuard); status_t ret; status_t ret; sp<IServiceManager> sm = defaultServiceManager(); sp<IServiceManager> sm = defaultServiceManager(); BinderLibTestService* testServicePtr; BinderLibTestService* testServicePtr; Loading