diff options
| -rw-r--r-- | libs/binder/Binder.cpp | 62 | ||||
| -rw-r--r-- | libs/binder/IPCThreadState.cpp | 34 | ||||
| -rw-r--r-- | libs/binder/Parcel.cpp | 5 | ||||
| -rw-r--r-- | libs/binder/ProcessState.cpp | 16 | ||||
| -rw-r--r-- | libs/binder/include/binder/Binder.h | 6 | ||||
| -rw-r--r-- | libs/binder/include/binder/IPCThreadState.h | 7 | ||||
| -rw-r--r-- | libs/binder/include/binder/Parcel.h | 3 | 
7 files changed, 110 insertions, 23 deletions
| 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<IBinder>& 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<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; @@ -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 : "<N/A>"), 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<ProcessState>& /*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<ProcessState>& /*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<uintptr_t>(local->getWeakRefs());              obj.cookie = reinterpret_cast<uintptr_t>(local); diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 1c74e7b077..63f49ddba7 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<Extras*> 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..f6560a7f09 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -20,6 +20,8 @@  #include <string>  #include <vector> +#include <linux/android/binder.h> +  #include <android-base/unique_fd.h>  #include <cutils/native_handle.h>  #include <utils/Errors.h> @@ -27,7 +29,6 @@  #include <utils/String16.h>  #include <utils/Vector.h>  #include <utils/Flattenable.h> -#include <linux/android/binder.h>  #include <binder/IInterface.h>  #include <binder/Parcelable.h> |