From 3085a47ebb695dd95271a7db2aa0d181d69c1f4d Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Wed, 26 Dec 2018 13:59:23 -0800 Subject: getCallingSid: get calling security context This call gets the security context of the calling process when requested. Bug: 121035042 Test: boot Change-Id: Ia8a4c0cb4a9c86dcc0d3b7583014237f879a3074 Merged-In: Ia8a4c0cb4a9c86dcc0d3b7583014237f879a3074 --- libs/binder/Binder.cpp | 62 +++++++++++++++++++++++------ libs/binder/IPCThreadState.cpp | 34 +++++++++++++--- libs/binder/Parcel.cpp | 5 ++- libs/binder/ProcessState.cpp | 16 +++++++- libs/binder/include/binder/Binder.h | 6 +++ libs/binder/include/binder/IPCThreadState.h | 7 ++++ libs/binder/include/binder/Parcel.h | 2 +- libs/binder/include/binder/binder_kernel.h | 45 +++++++++++++++++++++ 8 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 libs/binder/include/binder/binder_kernel.h (limited to 'libs') diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index f6cc3afc97..96ee29556c 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -86,6 +86,10 @@ status_t IBinder::shellCommand(const sp& target, int in, int out, int e class BBinder::Extras { public: + // unlocked objects + bool mRequestingSid = false; + + // for below objects Mutex mLock; BpBinder::ObjectManager mObjects; }; @@ -163,19 +167,8 @@ void BBinder::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); @@ -204,6 +197,30 @@ BBinder* BBinder::localBinder() return this; } +bool BBinder::isRequestingSid() +{ + Extras* e = mExtras.load(std::memory_order_acquire); + + return e && e->mRequestingSid; +} + +void BBinder::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; +} + BBinder::~BBinder() { Extras* e = mExtras.load(std::memory_order_relaxed); @@ -267,6 +284,25 @@ status_t BBinder::onTransact( } } +BBinder::Extras* BBinder::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/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 22f6f54e28..e60f03ae54 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -88,7 +88,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[] = { @@ -363,6 +364,11 @@ pid_t IPCThreadState::getCallingPid() const return mCallingPid; } +const char* IPCThreadState::getCallingSid() const +{ + return mCallingSid; +} + uid_t IPCThreadState::getCallingUid() const { return mCallingUid; @@ -370,6 +376,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; @@ -398,12 +405,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(); } @@ -1089,10 +1098,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 == (int) 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; @@ -1108,15 +1126,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(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 : ""), mCallingUid); Parcel reply; status_t error; @@ -1148,8 +1169,8 @@ status_t IPCThreadState::executeCommand(int32_t cmd) } mIPCThreadStateBase->popCurrentState(); - //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 : ""), origUid); if ((tr.flags & TF_ONE_WAY) == 0) { LOG_ONEWAY("Sending reply to %d!", mCallingPid); @@ -1160,6 +1181,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd) } mCallingPid = origPid; + mCallingSid = origSid; mCallingUid = origUid; mStrictModePolicy = origStrictModePolicy; mLastTransactionBinderFlags = origTransactionBinderFlags; diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index ca6a97debb..9f8c40876e 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -215,7 +215,7 @@ status_t flatten_binder(const sp& /*proc*/, } if (binder != nullptr) { - IBinder *local = binder->localBinder(); + BBinder *local = binder->localBinder(); if (!local) { BpBinder *proxy = binder->remoteBinder(); if (proxy == nullptr) { @@ -227,6 +227,9 @@ status_t flatten_binder(const sp& /*proc*/, obj.handle = handle; obj.cookie = 0; } else { + if (local->isRequestingSid()) { + obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX; + } obj.hdr.type = BINDER_TYPE_BINDER; obj.binder = reinterpret_cast(local->getWeakRefs()); obj.cookie = reinterpret_cast(local); diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 3798b61ab9..79db0cb71e 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -181,8 +181,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/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h index c251468bdb..cf3ef84caa 100644 --- a/libs/binder/include/binder/Binder.h +++ b/libs/binder/include/binder/Binder.h @@ -60,6 +60,10 @@ public: virtual BBinder* localBinder(); + bool isRequestingSid(); + // This must be called before the object is sent to another process. Not thread safe. + void setRequestingSid(bool requestSid); + protected: virtual ~BBinder(); @@ -75,6 +79,8 @@ private: class Extras; + Extras* getOrCreateExtras(); + std::atomic mExtras; void* mReserved0; }; diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h index 745f6182f6..a20ef7c410 100644 --- a/libs/binder/include/binder/IPCThreadState.h +++ b/libs/binder/include/binder/IPCThreadState.h @@ -42,6 +42,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); @@ -51,6 +56,7 @@ public: int32_t getLastTransactionBinderFlags() const; int64_t clearCallingIdentity(); + // Restores PID/UID (not SID) void restoreCallingIdentity(int64_t token); int setupPolling(int* fd); @@ -154,6 +160,7 @@ private: Parcel mOut; status_t mLastError; pid_t mCallingPid; + const char* mCallingSid; uid_t mCallingUid; int32_t mStrictModePolicy; int32_t mLastTransactionBinderFlags; diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index c9c273acd8..8db50e7409 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -27,8 +27,8 @@ #include #include #include -#include +#include #include #include #include diff --git a/libs/binder/include/binder/binder_kernel.h b/libs/binder/include/binder/binder_kernel.h new file mode 100644 index 0000000000..c7f6b4b4e6 --- /dev/null +++ b/libs/binder/include/binder/binder_kernel.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BINDER_KERNEL_H +#define ANDROID_BINDER_KERNEL_H + +#include + +/** + * This file exists because the uapi kernel headers in bionic are built + * from upstream kernel headers only, and not all of the hwbinder kernel changes + * have made it upstream yet. Therefore, the modifications to the + * binder header are added locally in this file. + */ + +enum { + FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000, +}; + +#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_BINDER_KERNEL_H -- cgit v1.2.3-59-g8ed1b From be5ee85e032bd6992e1acdfaca12ce9415c64d83 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Wed, 20 Mar 2019 17:18:58 -0700 Subject: Update for kernel headers v5.0.3. All of the structures in binder_kernel.h are now in the upstream kernel. Test: Builds. Bug: 129785390 Change-Id: Iab9a918edcef1550877c0e81920abde7aea1dbf9 Merged-In: I3719b1ca48515170eca5834b1a29f15086441b50 --- libs/binder/include/binder/Parcel.h | 3 +- libs/binder/include/binder/binder_kernel.h | 45 ------------------------------ 2 files changed, 2 insertions(+), 46 deletions(-) delete mode 100644 libs/binder/include/binder/binder_kernel.h (limited to 'libs') diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index 8db50e7409..f6560a7f09 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -20,6 +20,8 @@ #include #include +#include + #include #include #include @@ -28,7 +30,6 @@ #include #include -#include #include #include #include diff --git a/libs/binder/include/binder/binder_kernel.h b/libs/binder/include/binder/binder_kernel.h deleted file mode 100644 index c7f6b4b4e6..0000000000 --- a/libs/binder/include/binder/binder_kernel.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_BINDER_KERNEL_H -#define ANDROID_BINDER_KERNEL_H - -#include - -/** - * This file exists because the uapi kernel headers in bionic are built - * from upstream kernel headers only, and not all of the hwbinder kernel changes - * have made it upstream yet. Therefore, the modifications to the - * binder header are added locally in this file. - */ - -enum { - FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000, -}; - -#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_BINDER_KERNEL_H -- cgit v1.2.3-59-g8ed1b