summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Binder.cpp60
-rw-r--r--IPCThreadState.cpp35
-rw-r--r--Parcel.cpp3
-rw-r--r--ProcessState.cpp16
-rw-r--r--include/hwbinder/Binder.h9
-rw-r--r--include/hwbinder/IPCThreadState.h7
-rw-r--r--include/hwbinder/binder_kernel.h13
7 files changed, 121 insertions, 22 deletions
diff --git a/Binder.cpp b/Binder.cpp
index 8f576ae..72884f0 100644
--- a/Binder.cpp
+++ b/Binder.cpp
@@ -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;
diff --git a/Parcel.cpp b/Parcel.cpp
index b58cf9c..38d97eb 100644
--- a/Parcel.cpp
+++ b/Parcel.cpp
@@ -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