From 858976782639055c188a0e6081cbcdb68616f703 Mon Sep 17 00:00:00 2001 From: mattgilbride Date: Sat, 22 Oct 2022 17:42:44 +0000 Subject: IPCThreadState::hasExplicitIdentity() This new method will track whether the caller is within a Binder.clearCallingIdentity/restoreCallingIdentity block based on packing this state information into the token returned by clearCallingIdentity. Bug: b/252975769 Test: static_assert in IPCThreadState.cpp Change-Id: Ifa71fcf2f31b607fec39a51e3a8d16eb2987440a --- libs/binder/IPCThreadState.cpp | 95 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 6 deletions(-) (limited to 'libs/binder/IPCThreadState.cpp') diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 11c8e5dcea..77703749a1 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -45,11 +45,11 @@ #define IF_LOG_TRANSACTIONS() if (false) #define IF_LOG_COMMANDS() if (false) -#define LOG_REMOTEREFS(...) +#define LOG_REMOTEREFS(...) #define IF_LOG_REMOTEREFS() if (false) -#define LOG_THREADPOOL(...) -#define LOG_ONEWAY(...) +#define LOG_THREADPOOL(...) +#define LOG_ONEWAY(...) #else @@ -394,14 +394,92 @@ void IPCThreadState::checkContextIsBinderForUse(const char* use) const { // context, so we don't abort } +constexpr uint32_t encodeExplicitIdentity(bool hasExplicitIdentity, pid_t callingPid) { + uint32_t as_unsigned = static_cast(callingPid); + if (hasExplicitIdentity) { + return as_unsigned | (1 << 30); + } else { + return as_unsigned & ~(1 << 30); + } +} + +constexpr int64_t packCallingIdentity(bool hasExplicitIdentity, uid_t callingUid, + pid_t callingPid) { + // Calling PID is a 32-bit signed integer, but doesn't consume the entire 32 bit space. + // To future-proof this and because we have extra capacity, we decided to also support -1, + // since this constant is used to represent invalid UID in other places of the system. + // Thus, we pack hasExplicitIdentity into the 2nd bit from the left. This allows us to + // preserve the (left-most) bit for the sign while also encoding the value of + // hasExplicitIdentity. + // 32b | 1b | 1b | 30b + // token = [ calling uid | calling pid(sign) | has explicit identity | calling pid(rest) ] + uint64_t token = (static_cast(callingUid) << 32) | + encodeExplicitIdentity(hasExplicitIdentity, callingPid); + return static_cast(token); +} + +constexpr bool unpackHasExplicitIdentity(int64_t token) { + return static_cast(token) & (1 << 30); +} + +constexpr uid_t unpackCallingUid(int64_t token) { + return static_cast(token >> 32); +} + +constexpr pid_t unpackCallingPid(int64_t token) { + int32_t encodedPid = static_cast(token); + if (encodedPid & (1 << 31)) { + return encodedPid | (1 << 30); + } else { + return encodedPid & ~(1 << 30); + } +} + +static_assert(unpackHasExplicitIdentity(packCallingIdentity(true, 1000, 9999)) == true, + "pack true hasExplicit"); + +static_assert(unpackCallingUid(packCallingIdentity(true, 1000, 9999)) == 1000, "pack true uid"); + +static_assert(unpackCallingPid(packCallingIdentity(true, 1000, 9999)) == 9999, "pack true pid"); + +static_assert(unpackHasExplicitIdentity(packCallingIdentity(false, 1000, 9999)) == false, + "pack false hasExplicit"); + +static_assert(unpackCallingUid(packCallingIdentity(false, 1000, 9999)) == 1000, "pack false uid"); + +static_assert(unpackCallingPid(packCallingIdentity(false, 1000, 9999)) == 9999, "pack false pid"); + +static_assert(unpackHasExplicitIdentity(packCallingIdentity(true, 1000, -1)) == true, + "pack true (negative) hasExplicit"); + +static_assert(unpackCallingUid(packCallingIdentity(true, 1000, -1)) == 1000, + "pack true (negative) uid"); + +static_assert(unpackCallingPid(packCallingIdentity(true, 1000, -1)) == -1, + "pack true (negative) pid"); + +static_assert(unpackHasExplicitIdentity(packCallingIdentity(false, 1000, -1)) == false, + "pack false (negative) hasExplicit"); + +static_assert(unpackCallingUid(packCallingIdentity(false, 1000, -1)) == 1000, + "pack false (negative) uid"); + +static_assert(unpackCallingPid(packCallingIdentity(false, 1000, -1)) == -1, + "pack false (negative) pid"); + int64_t IPCThreadState::clearCallingIdentity() { // ignore mCallingSid for legacy reasons - int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid; + int64_t token = packCallingIdentity(mHasExplicitIdentity, mCallingUid, mCallingPid); clearCaller(); + mHasExplicitIdentity = true; return token; } +bool IPCThreadState::hasExplicitIdentity() { + return mHasExplicitIdentity; +} + void IPCThreadState::setStrictModePolicy(int32_t policy) { mStrictModePolicy = policy; @@ -474,9 +552,10 @@ ProcessState::CallRestriction IPCThreadState::getCallRestriction() const { void IPCThreadState::restoreCallingIdentity(int64_t token) { - mCallingUid = (int)(token>>32); + mCallingUid = unpackCallingUid(token); mCallingSid = nullptr; // not enough data to restore - mCallingPid = (int)token; + mCallingPid = unpackCallingPid(token); + mHasExplicitIdentity = unpackHasExplicitIdentity(token); } void IPCThreadState::clearCaller() @@ -889,6 +968,7 @@ IPCThreadState::IPCThreadState() mCallRestriction(mProcess->mCallRestriction) { pthread_setspecific(gTLS, this); clearCaller(); + mHasExplicitIdentity = false; mIn.setDataCapacity(256); mOut.setDataCapacity(256); } @@ -1279,6 +1359,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) const pid_t origPid = mCallingPid; const char* origSid = mCallingSid; const uid_t origUid = mCallingUid; + const bool origHasExplicitIdentity = mHasExplicitIdentity; const int32_t origStrictModePolicy = mStrictModePolicy; const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags; const int32_t origWorkSource = mWorkSource; @@ -1292,6 +1373,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = tr.sender_pid; mCallingSid = reinterpret_cast(tr_secctx.secctx); mCallingUid = tr.sender_euid; + mHasExplicitIdentity = false; mLastTransactionBinderFlags = tr.flags; // ALOGI(">>>> TRANSACT from pid %d sid %s uid %d\n", mCallingPid, @@ -1367,6 +1449,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) mCallingPid = origPid; mCallingSid = origSid; mCallingUid = origUid; + mHasExplicitIdentity = origHasExplicitIdentity; mStrictModePolicy = origStrictModePolicy; mLastTransactionBinderFlags = origTransactionBinderFlags; mWorkSource = origWorkSource; -- cgit v1.2.3-59-g8ed1b