diff options
-rw-r--r-- | Binder.cpp | 60 | ||||
-rw-r--r-- | IPCThreadState.cpp | 35 | ||||
-rw-r--r-- | Parcel.cpp | 3 | ||||
-rw-r--r-- | ProcessState.cpp | 16 | ||||
-rw-r--r-- | include/hwbinder/Binder.h | 9 | ||||
-rw-r--r-- | include/hwbinder/IPCThreadState.h | 7 | ||||
-rw-r--r-- | include/hwbinder/binder_kernel.h | 13 |
7 files changed, 121 insertions, 22 deletions
@@ -61,6 +61,10 @@ bool IBinder::checkSubclass(const void* /*subclassID*/) const class BHwBinder::Extras { public: + // unlocked objects + bool mRequestingSid = false; + + // for below objects Mutex mLock; BpHwBinder::ObjectManager mObjects; }; @@ -79,6 +83,28 @@ int BHwBinder::getMinSchedulingPriority() { return mSchedPriority; } +bool BHwBinder::isRequestingSid() { + Extras* e = mExtras.load(std::memory_order_acquire); + + return e && e->mRequestingSid; +} + +void BHwBinder::setRequestingSid(bool requestingSid) { + Extras* e = mExtras.load(std::memory_order_acquire); + + if (!e) { + // default is false. Most things don't need sids, so avoiding allocations when possible. + if (!requestingSid) { + return; + } + + e = getOrCreateExtras(); + if (!e) return; // out of memory + } + + e->mRequestingSid = true; +} + status_t BHwBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback callback) { @@ -118,19 +144,8 @@ void BHwBinder::attachObject( const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) { - Extras* e = mExtras.load(std::memory_order_acquire); - - if (!e) { - e = new Extras; - Extras* expected = nullptr; - if (!mExtras.compare_exchange_strong(expected, e, - std::memory_order_release, - std::memory_order_acquire)) { - delete e; - e = expected; // Filled in by CAS - } - if (e == nullptr) return; // out of memory - } + Extras* e = getOrCreateExtras(); + if (!e) return; // out of memory AutoMutex _l(e->mLock); e->mObjects.attach(objectID, object, cleanupCookie, func); @@ -173,6 +188,25 @@ status_t BHwBinder::onTransact( return UNKNOWN_TRANSACTION; } +BHwBinder::Extras* BHwBinder::getOrCreateExtras() +{ + Extras* e = mExtras.load(std::memory_order_acquire); + + if (!e) { + e = new Extras; + Extras* expected = nullptr; + if (!mExtras.compare_exchange_strong(expected, e, + std::memory_order_release, + std::memory_order_acquire)) { + delete e; + e = expected; // Filled in by CAS + } + if (e == nullptr) return nullptr; // out of memory + } + + return e; +} + // --------------------------------------------------------------------------- enum { diff --git a/IPCThreadState.cpp b/IPCThreadState.cpp index c7c71be..89fc35b 100644 --- a/IPCThreadState.cpp +++ b/IPCThreadState.cpp @@ -87,7 +87,8 @@ static const char *kReturnStrings[] = { "BR_FINISHED", "BR_DEAD_BINDER", "BR_CLEAR_DEATH_NOTIFICATION_DONE", - "BR_FAILED_REPLY" + "BR_FAILED_REPLY", + "BR_TRANSACTION_SEC_CTX", }; static const char *kCommandStrings[] = { @@ -353,6 +354,11 @@ pid_t IPCThreadState::getCallingPid() const return mCallingPid; } +const char* IPCThreadState::getCallingSid() const +{ + return mCallingSid; +} + uid_t IPCThreadState::getCallingUid() const { return mCallingUid; @@ -360,6 +366,7 @@ uid_t IPCThreadState::getCallingUid() const int64_t IPCThreadState::clearCallingIdentity() { + // ignore mCallingSid for legacy reasons int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid; clearCaller(); return token; @@ -388,12 +395,14 @@ int32_t IPCThreadState::getLastTransactionBinderFlags() const void IPCThreadState::restoreCallingIdentity(int64_t token) { mCallingUid = (int)(token>>32); + mCallingSid = nullptr; // not enough data to restore mCallingPid = (int)token; } void IPCThreadState::clearCaller() { mCallingPid = getpid(); + mCallingSid = nullptr; // expensive to lookup mCallingUid = getuid(); } @@ -1108,10 +1117,19 @@ status_t IPCThreadState::executeCommand(int32_t cmd) } break; + case BR_TRANSACTION_SEC_CTX: case BR_TRANSACTION: { - binder_transaction_data tr; - result = mIn.read(&tr, sizeof(tr)); + binder_transaction_data_secctx tr_secctx; + binder_transaction_data& tr = tr_secctx.transaction_data; + + if (cmd == BR_TRANSACTION_SEC_CTX) { + result = mIn.read(&tr_secctx, sizeof(tr_secctx)); + } else { + result = mIn.read(&tr, sizeof(tr)); + tr_secctx.secctx = 0; + } + ALOG_ASSERT(result == NO_ERROR, "Not enough command data for brTRANSACTION"); if (result != NO_ERROR) break; @@ -1127,15 +1145,18 @@ status_t IPCThreadState::executeCommand(int32_t cmd) tr.offsets_size/sizeof(binder_size_t), freeBuffer, this); const pid_t origPid = mCallingPid; + const char* origSid = mCallingSid; const uid_t origUid = mCallingUid; const int32_t origStrictModePolicy = mStrictModePolicy; const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags; mCallingPid = tr.sender_pid; + mCallingSid = reinterpret_cast<const char*>(tr_secctx.secctx); mCallingUid = tr.sender_euid; mLastTransactionBinderFlags = tr.flags; - //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); + // ALOGI(">>>> TRANSACT from pid %d sid %s uid %d\n", mCallingPid, + // (mCallingSid ? mCallingSid : "<N/A>"), mCallingUid); Parcel reply; status_t error; @@ -1200,11 +1221,11 @@ status_t IPCThreadState::executeCommand(int32_t cmd) // One-way transaction, don't care about return value or reply. } - //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n", - // mCallingPid, origPid, origUid); - + //ALOGI("<<<< TRANSACT from pid %d restore pid %d sid %s uid %d\n", + // mCallingPid, origPid, (origSid ? origSid : "<N/A>"), origUid); mCallingPid = origPid; + mCallingSid = origSid; mCallingUid = origUid; mStrictModePolicy = origStrictModePolicy; mLastTransactionBinderFlags = origTransactionBinderFlags; @@ -219,6 +219,9 @@ status_t flatten_binder(const sp<ProcessState>& /*proc*/, obj.flags = priority & FLAT_BINDER_FLAG_PRIORITY_MASK; obj.flags |= FLAT_BINDER_FLAG_ACCEPTS_FDS | FLAT_BINDER_FLAG_INHERIT_RT; obj.flags |= (policy & 3) << FLAT_BINDER_FLAG_SCHEDPOLICY_SHIFT; + if (local->isRequestingSid()) { + obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX; + } obj.hdr.type = BINDER_TYPE_BINDER; obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); obj.cookie = reinterpret_cast<uintptr_t>(local); diff --git a/ProcessState.cpp b/ProcessState.cpp index 84fb8f7..5e6642e 100644 --- a/ProcessState.cpp +++ b/ProcessState.cpp @@ -167,8 +167,20 @@ bool ProcessState::becomeContextManager(context_check_func checkFunc, void* user mBinderContextCheckFunc = checkFunc; mBinderContextUserData = userData; - int dummy = 0; - status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy); + flat_binder_object obj { + .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX, + }; + + status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj); + + // fallback to original method + if (result != 0) { + android_errorWriteLog(0x534e4554, "121035042"); + + int dummy = 0; + result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy); + } + if (result == 0) { mManagesContexts = true; } else if (result == -1) { diff --git a/include/hwbinder/Binder.h b/include/hwbinder/Binder.h index 11ca331..4289f2d 100644 --- a/include/hwbinder/Binder.h +++ b/include/hwbinder/Binder.h @@ -56,6 +56,9 @@ public: int getMinSchedulingPolicy(); int getMinSchedulingPriority(); + + bool isRequestingSid(); + protected: virtual ~BHwBinder(); @@ -64,6 +67,10 @@ protected: Parcel* reply, uint32_t flags = 0, TransactCallback callback = nullptr); + + // This must be called before the object is sent to another process. Not thread safe. + void setRequestingSid(bool requestSid); + int mSchedPolicy; // policy to run transaction from this node at // priority [-20..19] for SCHED_NORMAL, [1..99] for SCHED_FIFO/RT int mSchedPriority; @@ -73,6 +80,8 @@ private: class Extras; + Extras* getOrCreateExtras(); + std::atomic<Extras*> mExtras; void* mReserved0; }; diff --git a/include/hwbinder/IPCThreadState.h b/include/hwbinder/IPCThreadState.h index f2112c0..579c331 100644 --- a/include/hwbinder/IPCThreadState.h +++ b/include/hwbinder/IPCThreadState.h @@ -46,6 +46,11 @@ public: status_t clearLastError(); pid_t getCallingPid() const; + // nullptr if unavailable + // + // this can't be restored once it's cleared, and it does not return the + // context of the current process when not in a binder call. + const char* getCallingSid() const; uid_t getCallingUid() const; void setStrictModePolicy(int32_t policy); @@ -55,6 +60,7 @@ public: int32_t getLastTransactionBinderFlags() const; int64_t clearCallingIdentity(); + // Restores PID/UID (not SID) void restoreCallingIdentity(int64_t token); int setupPolling(int* fd); @@ -165,6 +171,7 @@ public: Parcel mOut; status_t mLastError; pid_t mCallingPid; + const char* mCallingSid; uid_t mCallingUid; int32_t mStrictModePolicy; int32_t mLastTransactionBinderFlags; diff --git a/include/hwbinder/binder_kernel.h b/include/hwbinder/binder_kernel.h index f78b294..08483ae 100644 --- a/include/hwbinder/binder_kernel.h +++ b/include/hwbinder/binder_kernel.h @@ -34,6 +34,7 @@ enum { FLAT_BINDER_FLAG_SCHEDPOLICY_MASK = 0x600, FLAT_BINDER_FLAG_SCHEDPOLICY_SHIFT = 9, FLAT_BINDER_FLAG_INHERIT_RT = 0x800, + FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000, }; struct binder_node_info_for_ref { @@ -46,5 +47,17 @@ struct binder_node_info_for_ref { }; #define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref) +#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) + +struct binder_transaction_data_secctx { + struct binder_transaction_data transaction_data; + binder_uintptr_t secctx; +}; + +enum { + BR_TRANSACTION_SEC_CTX = _IOR('r', 2, + struct binder_transaction_data_secctx), +}; + #endif // ANDROID_HARDWARE_BINDER_KERNEL_H |