Loading libs/binder/IPCThreadState.cpp +32 −6 Original line number Diff line number Diff line Loading @@ -109,9 +109,7 @@ static const char *kCommandStrings[] = { "BC_DEAD_BINDER_DONE" }; // The work source represents the UID of the process we should attribute the transaction to. // We use -1 to specify that the work source was not set using #setWorkSource. static const int kUnsetWorkSource = -1; static const int64_t kWorkSourcePropagatedBitIndex = 32; static const char* getReturnString(uint32_t cmd) { Loading Loading @@ -389,12 +387,29 @@ int32_t IPCThreadState::getStrictModePolicy() const int64_t IPCThreadState::setCallingWorkSourceUid(uid_t uid) { // Note: we currently only use half of the int64. We return an int64 for extensibility. int64_t token = mWorkSource; int64_t token = setCallingWorkSourceUidWithoutPropagation(uid); mPropagateWorkSource = true; return token; } int64_t IPCThreadState::setCallingWorkSourceUidWithoutPropagation(uid_t uid) { const int64_t propagatedBit = ((int64_t)mPropagateWorkSource) << kWorkSourcePropagatedBitIndex; int64_t token = propagatedBit | mWorkSource; mWorkSource = uid; return token; } void IPCThreadState::clearPropagateWorkSource() { mPropagateWorkSource = false; } bool IPCThreadState::shouldPropagateWorkSource() const { return mPropagateWorkSource; } uid_t IPCThreadState::getCallingWorkSourceUid() const { return mWorkSource; Loading @@ -408,7 +423,8 @@ int64_t IPCThreadState::clearCallingWorkSource() void IPCThreadState::restoreCallingWorkSource(int64_t token) { uid_t uid = (int)token; setCallingWorkSourceUid(uid); setCallingWorkSourceUidWithoutPropagation(uid); mPropagateWorkSource = ((token >> kWorkSourcePropagatedBitIndex) & 1) == 1; } void IPCThreadState::setLastTransactionBinderFlags(int32_t flags) Loading Loading @@ -765,6 +781,7 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mWorkSource(kUnsetWorkSource), mPropagateWorkSource(false), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { Loading Loading @@ -1127,6 +1144,13 @@ status_t IPCThreadState::executeCommand(int32_t cmd) const uid_t origUid = mCallingUid; const int32_t origStrictModePolicy = mStrictModePolicy; const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags; const int32_t origWorkSource = mWorkSource; const bool origPropagateWorkSet = mPropagateWorkSource; // Calling work source will be set by Parcel#enforceInterface. Parcel#enforceInterface // is only guaranteed to be called for AIDL-generated stubs so we reset the work source // here to never propagate it. clearCallingWorkSource(); clearPropagateWorkSource(); mCallingPid = tr.sender_pid; mCallingUid = tr.sender_euid; Loading Loading @@ -1179,6 +1203,8 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingUid = origUid; mStrictModePolicy = origStrictModePolicy; mLastTransactionBinderFlags = origTransactionBinderFlags; mWorkSource = origWorkSource; mPropagateWorkSource = origPropagateWorkSet; IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); Loading libs/binder/Parcel.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -599,9 +599,10 @@ bool Parcel::hasFileDescriptors() const // Write RPC headers. (previously just the interface token) status_t Parcel::writeInterfaceToken(const String16& interface) { writeInt32(IPCThreadState::self()->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER); writeInt32(IPCThreadState::self()->getCallingWorkSourceUid()); const IPCThreadState* threadState = IPCThreadState::self(); writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER); writeInt32(threadState->shouldPropagateWorkSource() ? threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource); // currently the interface identification token is just its name as a string return writeString16(interface); } Loading Loading @@ -631,7 +632,7 @@ bool Parcel::enforceInterface(const String16& interface, } // WorkSource. int32_t workSource = readInt32(); threadState->setCallingWorkSourceUid(workSource); threadState->setCallingWorkSourceUidWithoutPropagation(workSource); // Interface descriptor. const String16 str(readString16()); if (str == interface) { Loading libs/binder/include/binder/IPCThreadState.h +11 −0 Original line number Diff line number Diff line Loading @@ -49,12 +49,16 @@ public: // See Binder#setCallingWorkSourceUid in Binder.java. int64_t setCallingWorkSourceUid(uid_t uid); // Internal only. Use setCallingWorkSourceUid(uid) instead. int64_t setCallingWorkSourceUidWithoutPropagation(uid_t uid); // See Binder#getCallingWorkSourceUid in Binder.java. uid_t getCallingWorkSourceUid() const; // See Binder#clearCallingWorkSource in Binder.java. int64_t clearCallingWorkSource(); // See Binder#restoreCallingWorkSource in Binder.java. void restoreCallingWorkSource(int64_t token); void clearPropagateWorkSource(); bool shouldPropagateWorkSource() const; void setLastTransactionBinderFlags(int32_t flags); int32_t getLastTransactionBinderFlags() const; Loading Loading @@ -127,6 +131,11 @@ public: // infer information about thread state. bool isServingCall() const; // The work source represents the UID of the process we should attribute the transaction // to. // We use -1 to specify that the work source was not set using #setWorkSource. static const int32_t kUnsetWorkSource = -1; private: IPCThreadState(); ~IPCThreadState(); Loading Loading @@ -167,6 +176,8 @@ private: // The UID of the process who is responsible for this transaction. // This is used for resource attribution. int32_t mWorkSource; // Whether the work source should be propagated. bool mPropagateWorkSource; int32_t mStrictModePolicy; int32_t mLastTransactionBinderFlags; IPCThreadStateBase *mIPCThreadStateBase; Loading libs/binder/tests/binderLibTest.cpp +69 −1 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ class BinderLibTest : public ::testing::Test { public: virtual void SetUp() { m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer(); IPCThreadState::self()->restoreCallingWorkSource(0); } virtual void TearDown() { } Loading Loading @@ -953,11 +954,28 @@ TEST_F(BinderLibTest, WorkSourceSet) { status_t ret; Parcel data, reply; IPCThreadState::self()->clearCallingWorkSource(); int64_t previousWorkSource = IPCThreadState::self()->setCallingWorkSourceUid(100); data.writeInterfaceToken(binderLibTestServiceName); ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); EXPECT_EQ(100, reply.readInt32()); EXPECT_EQ(-1, previousWorkSource); EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource()); EXPECT_EQ(NO_ERROR, ret); } TEST_F(BinderLibTest, WorkSourceSetWithoutPropagation) { status_t ret; Parcel data, reply; IPCThreadState::self()->setCallingWorkSourceUidWithoutPropagation(100); EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource()); data.writeInterfaceToken(binderLibTestServiceName); ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); EXPECT_EQ(-1, reply.readInt32()); EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource()); EXPECT_EQ(NO_ERROR, ret); } Loading @@ -967,7 +985,8 @@ TEST_F(BinderLibTest, WorkSourceCleared) Parcel data, reply; IPCThreadState::self()->setCallingWorkSourceUid(100); int64_t previousWorkSource = IPCThreadState::self()->clearCallingWorkSource(); int64_t token = IPCThreadState::self()->clearCallingWorkSource(); int32_t previousWorkSource = (int32_t)token; data.writeInterfaceToken(binderLibTestServiceName); ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); Loading @@ -989,9 +1008,58 @@ TEST_F(BinderLibTest, WorkSourceRestored) ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); EXPECT_EQ(100, reply.readInt32()); EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource()); EXPECT_EQ(NO_ERROR, ret); } TEST_F(BinderLibTest, PropagateFlagSet) { status_t ret; Parcel data, reply; IPCThreadState::self()->clearPropagateWorkSource(); IPCThreadState::self()->setCallingWorkSourceUid(100); EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource()); } TEST_F(BinderLibTest, PropagateFlagCleared) { status_t ret; Parcel data, reply; IPCThreadState::self()->setCallingWorkSourceUid(100); IPCThreadState::self()->clearPropagateWorkSource(); EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource()); } TEST_F(BinderLibTest, PropagateFlagRestored) { status_t ret; Parcel data, reply; int token = IPCThreadState::self()->setCallingWorkSourceUid(100); IPCThreadState::self()->restoreCallingWorkSource(token); EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource()); } TEST_F(BinderLibTest, WorkSourcePropagatedForAllFollowingBinderCalls) { IPCThreadState::self()->setCallingWorkSourceUid(100); Parcel data, reply; status_t ret; data.writeInterfaceToken(binderLibTestServiceName); ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); Parcel data2, reply2; status_t ret2; data2.writeInterfaceToken(binderLibTestServiceName); ret2 = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data2, &reply2); EXPECT_EQ(100, reply2.readInt32()); EXPECT_EQ(NO_ERROR, ret2); } class BinderLibTestService : public BBinder { public: Loading Loading
libs/binder/IPCThreadState.cpp +32 −6 Original line number Diff line number Diff line Loading @@ -109,9 +109,7 @@ static const char *kCommandStrings[] = { "BC_DEAD_BINDER_DONE" }; // The work source represents the UID of the process we should attribute the transaction to. // We use -1 to specify that the work source was not set using #setWorkSource. static const int kUnsetWorkSource = -1; static const int64_t kWorkSourcePropagatedBitIndex = 32; static const char* getReturnString(uint32_t cmd) { Loading Loading @@ -389,12 +387,29 @@ int32_t IPCThreadState::getStrictModePolicy() const int64_t IPCThreadState::setCallingWorkSourceUid(uid_t uid) { // Note: we currently only use half of the int64. We return an int64 for extensibility. int64_t token = mWorkSource; int64_t token = setCallingWorkSourceUidWithoutPropagation(uid); mPropagateWorkSource = true; return token; } int64_t IPCThreadState::setCallingWorkSourceUidWithoutPropagation(uid_t uid) { const int64_t propagatedBit = ((int64_t)mPropagateWorkSource) << kWorkSourcePropagatedBitIndex; int64_t token = propagatedBit | mWorkSource; mWorkSource = uid; return token; } void IPCThreadState::clearPropagateWorkSource() { mPropagateWorkSource = false; } bool IPCThreadState::shouldPropagateWorkSource() const { return mPropagateWorkSource; } uid_t IPCThreadState::getCallingWorkSourceUid() const { return mWorkSource; Loading @@ -408,7 +423,8 @@ int64_t IPCThreadState::clearCallingWorkSource() void IPCThreadState::restoreCallingWorkSource(int64_t token) { uid_t uid = (int)token; setCallingWorkSourceUid(uid); setCallingWorkSourceUidWithoutPropagation(uid); mPropagateWorkSource = ((token >> kWorkSourcePropagatedBitIndex) & 1) == 1; } void IPCThreadState::setLastTransactionBinderFlags(int32_t flags) Loading Loading @@ -765,6 +781,7 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mWorkSource(kUnsetWorkSource), mPropagateWorkSource(false), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { Loading Loading @@ -1127,6 +1144,13 @@ status_t IPCThreadState::executeCommand(int32_t cmd) const uid_t origUid = mCallingUid; const int32_t origStrictModePolicy = mStrictModePolicy; const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags; const int32_t origWorkSource = mWorkSource; const bool origPropagateWorkSet = mPropagateWorkSource; // Calling work source will be set by Parcel#enforceInterface. Parcel#enforceInterface // is only guaranteed to be called for AIDL-generated stubs so we reset the work source // here to never propagate it. clearCallingWorkSource(); clearPropagateWorkSource(); mCallingPid = tr.sender_pid; mCallingUid = tr.sender_euid; Loading Loading @@ -1179,6 +1203,8 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingUid = origUid; mStrictModePolicy = origStrictModePolicy; mLastTransactionBinderFlags = origTransactionBinderFlags; mWorkSource = origWorkSource; mPropagateWorkSource = origPropagateWorkSet; IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); Loading
libs/binder/Parcel.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -599,9 +599,10 @@ bool Parcel::hasFileDescriptors() const // Write RPC headers. (previously just the interface token) status_t Parcel::writeInterfaceToken(const String16& interface) { writeInt32(IPCThreadState::self()->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER); writeInt32(IPCThreadState::self()->getCallingWorkSourceUid()); const IPCThreadState* threadState = IPCThreadState::self(); writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER); writeInt32(threadState->shouldPropagateWorkSource() ? threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource); // currently the interface identification token is just its name as a string return writeString16(interface); } Loading Loading @@ -631,7 +632,7 @@ bool Parcel::enforceInterface(const String16& interface, } // WorkSource. int32_t workSource = readInt32(); threadState->setCallingWorkSourceUid(workSource); threadState->setCallingWorkSourceUidWithoutPropagation(workSource); // Interface descriptor. const String16 str(readString16()); if (str == interface) { Loading
libs/binder/include/binder/IPCThreadState.h +11 −0 Original line number Diff line number Diff line Loading @@ -49,12 +49,16 @@ public: // See Binder#setCallingWorkSourceUid in Binder.java. int64_t setCallingWorkSourceUid(uid_t uid); // Internal only. Use setCallingWorkSourceUid(uid) instead. int64_t setCallingWorkSourceUidWithoutPropagation(uid_t uid); // See Binder#getCallingWorkSourceUid in Binder.java. uid_t getCallingWorkSourceUid() const; // See Binder#clearCallingWorkSource in Binder.java. int64_t clearCallingWorkSource(); // See Binder#restoreCallingWorkSource in Binder.java. void restoreCallingWorkSource(int64_t token); void clearPropagateWorkSource(); bool shouldPropagateWorkSource() const; void setLastTransactionBinderFlags(int32_t flags); int32_t getLastTransactionBinderFlags() const; Loading Loading @@ -127,6 +131,11 @@ public: // infer information about thread state. bool isServingCall() const; // The work source represents the UID of the process we should attribute the transaction // to. // We use -1 to specify that the work source was not set using #setWorkSource. static const int32_t kUnsetWorkSource = -1; private: IPCThreadState(); ~IPCThreadState(); Loading Loading @@ -167,6 +176,8 @@ private: // The UID of the process who is responsible for this transaction. // This is used for resource attribution. int32_t mWorkSource; // Whether the work source should be propagated. bool mPropagateWorkSource; int32_t mStrictModePolicy; int32_t mLastTransactionBinderFlags; IPCThreadStateBase *mIPCThreadStateBase; Loading
libs/binder/tests/binderLibTest.cpp +69 −1 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ class BinderLibTest : public ::testing::Test { public: virtual void SetUp() { m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer(); IPCThreadState::self()->restoreCallingWorkSource(0); } virtual void TearDown() { } Loading Loading @@ -953,11 +954,28 @@ TEST_F(BinderLibTest, WorkSourceSet) { status_t ret; Parcel data, reply; IPCThreadState::self()->clearCallingWorkSource(); int64_t previousWorkSource = IPCThreadState::self()->setCallingWorkSourceUid(100); data.writeInterfaceToken(binderLibTestServiceName); ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); EXPECT_EQ(100, reply.readInt32()); EXPECT_EQ(-1, previousWorkSource); EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource()); EXPECT_EQ(NO_ERROR, ret); } TEST_F(BinderLibTest, WorkSourceSetWithoutPropagation) { status_t ret; Parcel data, reply; IPCThreadState::self()->setCallingWorkSourceUidWithoutPropagation(100); EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource()); data.writeInterfaceToken(binderLibTestServiceName); ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); EXPECT_EQ(-1, reply.readInt32()); EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource()); EXPECT_EQ(NO_ERROR, ret); } Loading @@ -967,7 +985,8 @@ TEST_F(BinderLibTest, WorkSourceCleared) Parcel data, reply; IPCThreadState::self()->setCallingWorkSourceUid(100); int64_t previousWorkSource = IPCThreadState::self()->clearCallingWorkSource(); int64_t token = IPCThreadState::self()->clearCallingWorkSource(); int32_t previousWorkSource = (int32_t)token; data.writeInterfaceToken(binderLibTestServiceName); ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); Loading @@ -989,9 +1008,58 @@ TEST_F(BinderLibTest, WorkSourceRestored) ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); EXPECT_EQ(100, reply.readInt32()); EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource()); EXPECT_EQ(NO_ERROR, ret); } TEST_F(BinderLibTest, PropagateFlagSet) { status_t ret; Parcel data, reply; IPCThreadState::self()->clearPropagateWorkSource(); IPCThreadState::self()->setCallingWorkSourceUid(100); EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource()); } TEST_F(BinderLibTest, PropagateFlagCleared) { status_t ret; Parcel data, reply; IPCThreadState::self()->setCallingWorkSourceUid(100); IPCThreadState::self()->clearPropagateWorkSource(); EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource()); } TEST_F(BinderLibTest, PropagateFlagRestored) { status_t ret; Parcel data, reply; int token = IPCThreadState::self()->setCallingWorkSourceUid(100); IPCThreadState::self()->restoreCallingWorkSource(token); EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource()); } TEST_F(BinderLibTest, WorkSourcePropagatedForAllFollowingBinderCalls) { IPCThreadState::self()->setCallingWorkSourceUid(100); Parcel data, reply; status_t ret; data.writeInterfaceToken(binderLibTestServiceName); ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply); Parcel data2, reply2; status_t ret2; data2.writeInterfaceToken(binderLibTestServiceName); ret2 = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data2, &reply2); EXPECT_EQ(100, reply2.readInt32()); EXPECT_EQ(NO_ERROR, ret2); } class BinderLibTestService : public BBinder { public: Loading