Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86296272 authored by Olivier Gaillard's avatar Olivier Gaillard Committed by Android (Google) Code Review
Browse files

Merge "Only propagates work source when explicitly set."

parents 535f063b 91a04809
Loading
Loading
Loading
Loading
+32 −6
Original line number Diff line number Diff line
@@ -109,9 +109,7 @@ static const char *kCommandStrings[] = {
    "BC_DEAD_BINDER_DONE"
};

// The work source represents the UID of the process we should attribute the transaction to.
// We use -1 to specify that the work source was not set using #setWorkSource.
static const int kUnsetWorkSource = -1;
static const int64_t kWorkSourcePropagatedBitIndex = 32;

static const char* getReturnString(uint32_t cmd)
{
@@ -389,12 +387,29 @@ int32_t IPCThreadState::getStrictModePolicy() const

int64_t IPCThreadState::setCallingWorkSourceUid(uid_t uid)
{
    // Note: we currently only use half of the int64. We return an int64 for extensibility.
    int64_t token = mWorkSource;
    int64_t token = setCallingWorkSourceUidWithoutPropagation(uid);
    mPropagateWorkSource = true;
    return token;
}

int64_t IPCThreadState::setCallingWorkSourceUidWithoutPropagation(uid_t uid)
{
    const int64_t propagatedBit = ((int64_t)mPropagateWorkSource) << kWorkSourcePropagatedBitIndex;
    int64_t token = propagatedBit | mWorkSource;
    mWorkSource = uid;
    return token;
}

void IPCThreadState::clearPropagateWorkSource()
{
    mPropagateWorkSource = false;
}

bool IPCThreadState::shouldPropagateWorkSource() const
{
    return mPropagateWorkSource;
}

uid_t IPCThreadState::getCallingWorkSourceUid() const
{
    return mWorkSource;
@@ -408,7 +423,8 @@ int64_t IPCThreadState::clearCallingWorkSource()
void IPCThreadState::restoreCallingWorkSource(int64_t token)
{
    uid_t uid = (int)token;
    setCallingWorkSourceUid(uid);
    setCallingWorkSourceUidWithoutPropagation(uid);
    mPropagateWorkSource = ((token >> kWorkSourcePropagatedBitIndex) & 1) == 1;
}

void IPCThreadState::setLastTransactionBinderFlags(int32_t flags)
@@ -765,6 +781,7 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy)
IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mWorkSource(kUnsetWorkSource),
      mPropagateWorkSource(false),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
@@ -1127,6 +1144,13 @@ status_t IPCThreadState::executeCommand(int32_t cmd)
            const uid_t origUid = mCallingUid;
            const int32_t origStrictModePolicy = mStrictModePolicy;
            const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;
            const int32_t origWorkSource = mWorkSource;
            const bool origPropagateWorkSet = mPropagateWorkSource;
            // Calling work source will be set by Parcel#enforceInterface. Parcel#enforceInterface
            // is only guaranteed to be called for AIDL-generated stubs so we reset the work source
            // here to never propagate it.
            clearCallingWorkSource();
            clearPropagateWorkSource();

            mCallingPid = tr.sender_pid;
            mCallingUid = tr.sender_euid;
@@ -1179,6 +1203,8 @@ status_t IPCThreadState::executeCommand(int32_t cmd)
            mCallingUid = origUid;
            mStrictModePolicy = origStrictModePolicy;
            mLastTransactionBinderFlags = origTransactionBinderFlags;
            mWorkSource = origWorkSource;
            mPropagateWorkSource = origPropagateWorkSet;

            IF_LOG_TRANSACTIONS() {
                TextOutput::Bundle _b(alog);
+5 −4
Original line number Diff line number Diff line
@@ -599,9 +599,10 @@ bool Parcel::hasFileDescriptors() const
// Write RPC headers.  (previously just the interface token)
status_t Parcel::writeInterfaceToken(const String16& interface)
{
    writeInt32(IPCThreadState::self()->getStrictModePolicy() |
               STRICT_MODE_PENALTY_GATHER);
    writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
    const IPCThreadState* threadState = IPCThreadState::self();
    writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
    writeInt32(threadState->shouldPropagateWorkSource() ?
            threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource);
    // currently the interface identification token is just its name as a string
    return writeString16(interface);
}
@@ -631,7 +632,7 @@ bool Parcel::enforceInterface(const String16& interface,
    }
    // WorkSource.
    int32_t workSource = readInt32();
    threadState->setCallingWorkSourceUid(workSource);
    threadState->setCallingWorkSourceUidWithoutPropagation(workSource);
    // Interface descriptor.
    const String16 str(readString16());
    if (str == interface) {
+11 −0
Original line number Diff line number Diff line
@@ -49,12 +49,16 @@ public:

            // See Binder#setCallingWorkSourceUid in Binder.java.
            int64_t             setCallingWorkSourceUid(uid_t uid);
            // Internal only. Use setCallingWorkSourceUid(uid) instead.
            int64_t             setCallingWorkSourceUidWithoutPropagation(uid_t uid);
            // See Binder#getCallingWorkSourceUid in Binder.java.
            uid_t               getCallingWorkSourceUid() const;
            // See Binder#clearCallingWorkSource in Binder.java.
            int64_t             clearCallingWorkSource();
            // See Binder#restoreCallingWorkSource in Binder.java.
            void                restoreCallingWorkSource(int64_t token);
            void                clearPropagateWorkSource();
            bool                shouldPropagateWorkSource() const;

            void                setLastTransactionBinderFlags(int32_t flags);
            int32_t             getLastTransactionBinderFlags() const;
@@ -127,6 +131,11 @@ public:
            // infer information about thread state.
            bool                isServingCall() const;

            // The work source represents the UID of the process we should attribute the transaction
            // to.
            // We use -1 to specify that the work source was not set using #setWorkSource.
            static const int32_t kUnsetWorkSource = -1;

private:
                                IPCThreadState();
                                ~IPCThreadState();
@@ -167,6 +176,8 @@ private:
            // The UID of the process who is responsible for this transaction.
            // This is used for resource attribution.
            int32_t             mWorkSource;
            // Whether the work source should be propagated.
            bool                mPropagateWorkSource;
            int32_t             mStrictModePolicy;
            int32_t             mLastTransactionBinderFlags;
            IPCThreadStateBase  *mIPCThreadStateBase;
+69 −1
Original line number Diff line number Diff line
@@ -180,6 +180,7 @@ class BinderLibTest : public ::testing::Test {
    public:
        virtual void SetUp() {
            m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer();
            IPCThreadState::self()->restoreCallingWorkSource(0); 
        }
        virtual void TearDown() {
        }
@@ -953,11 +954,28 @@ TEST_F(BinderLibTest, WorkSourceSet)
{
    status_t ret;
    Parcel data, reply;
    IPCThreadState::self()->clearCallingWorkSource();
    int64_t previousWorkSource = IPCThreadState::self()->setCallingWorkSourceUid(100);
    data.writeInterfaceToken(binderLibTestServiceName);
    ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
    EXPECT_EQ(100, reply.readInt32());
    EXPECT_EQ(-1, previousWorkSource);
    EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource());
    EXPECT_EQ(NO_ERROR, ret);
}

TEST_F(BinderLibTest, WorkSourceSetWithoutPropagation)
{
    status_t ret;
    Parcel data, reply;

    IPCThreadState::self()->setCallingWorkSourceUidWithoutPropagation(100);
    EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource());

    data.writeInterfaceToken(binderLibTestServiceName);
    ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);
    EXPECT_EQ(-1, reply.readInt32());
    EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource());
    EXPECT_EQ(NO_ERROR, ret);
}

@@ -967,7 +985,8 @@ TEST_F(BinderLibTest, WorkSourceCleared)
    Parcel data, reply;

    IPCThreadState::self()->setCallingWorkSourceUid(100);
    int64_t previousWorkSource = IPCThreadState::self()->clearCallingWorkSource();
    int64_t token = IPCThreadState::self()->clearCallingWorkSource();
    int32_t previousWorkSource = (int32_t)token;
    data.writeInterfaceToken(binderLibTestServiceName);
    ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);

@@ -989,9 +1008,58 @@ TEST_F(BinderLibTest, WorkSourceRestored)
    ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);

    EXPECT_EQ(100, reply.readInt32());
    EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource());
    EXPECT_EQ(NO_ERROR, ret);
}

TEST_F(BinderLibTest, PropagateFlagSet)
{
    status_t ret;
    Parcel data, reply;

    IPCThreadState::self()->clearPropagateWorkSource();
    IPCThreadState::self()->setCallingWorkSourceUid(100);
    EXPECT_EQ(true, IPCThreadState::self()->shouldPropagateWorkSource());
}

TEST_F(BinderLibTest, PropagateFlagCleared)
{
    status_t ret;
    Parcel data, reply;

    IPCThreadState::self()->setCallingWorkSourceUid(100);
    IPCThreadState::self()->clearPropagateWorkSource();
    EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource());
}

TEST_F(BinderLibTest, PropagateFlagRestored)
{
    status_t ret;
    Parcel data, reply;

    int token = IPCThreadState::self()->setCallingWorkSourceUid(100);
    IPCThreadState::self()->restoreCallingWorkSource(token);

    EXPECT_EQ(false, IPCThreadState::self()->shouldPropagateWorkSource());
}

TEST_F(BinderLibTest, WorkSourcePropagatedForAllFollowingBinderCalls)
{
    IPCThreadState::self()->setCallingWorkSourceUid(100);

    Parcel data, reply;
    status_t ret;
    data.writeInterfaceToken(binderLibTestServiceName);
    ret = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data, &reply);

    Parcel data2, reply2;
    status_t ret2;
    data2.writeInterfaceToken(binderLibTestServiceName);
    ret2 = m_server->transact(BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, data2, &reply2);
    EXPECT_EQ(100, reply2.readInt32());
    EXPECT_EQ(NO_ERROR, ret2);
}

class BinderLibTestService : public BBinder
{
    public: