Loading libs/binder/Parcel.cpp +19 −3 Original line number Diff line number Diff line Loading @@ -254,8 +254,9 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) { if (binder) local = binder->localBinder(); if (local) local->setParceled(); if (const auto* rpcFields = maybeRpcFields()) { if (auto* rpcFields = maybeRpcFields()) { if (binder) { size_t dataPos = mDataPos; status_t status = writeInt32(RpcFields::TYPE_BINDER); // non-null if (status != OK) return status; uint64_t address; Loading @@ -265,6 +266,14 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) { if (status != OK) return status; status = writeUint64(address); if (status != OK) return status; if (rpcFields->mSession->getProtocolVersion() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS) { rpcFields->mObjectPositions .insert(std::upper_bound(rpcFields->mObjectPositions.begin(), rpcFields->mObjectPositions.end(), dataPos), dataPos); } } else { status_t status = writeInt32(RpcFields::TYPE_BINDER_NULL); // null if (status != OK) return status; Loading Loading @@ -1153,8 +1162,10 @@ size_t Parcel::objectsCount() const { if (const auto* kernelFields = maybeKernelFields()) { return kernelFields->mObjectsSize; } else if (auto* rpcFields = maybeRpcFields()) { return rpcFields->mObjectPositions.size(); } return 0; LOG_ALWAYS_FATAL("Must be for kernel or for RPC"); } status_t Parcel::errorCheck() const Loading Loading @@ -2915,7 +2926,12 @@ status_t Parcel::rpcSetDataReference( LOG_ALWAYS_FATAL_IF(session == nullptr); if (objectTableSize != ancillaryFds.size()) { bool sameSize = objectTableSize == ancillaryFds.size(); bool fitsIn = objectTableSize >= ancillaryFds.size(); // other positions are binders bool bindersInObjectPositions = session->getProtocolVersion() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS; if (!(bindersInObjectPositions ? fitsIn : sameSize)) { ALOGE("objectTableSize=%zu ancillaryFds.size=%zu", objectTableSize, ancillaryFds.size()); relFunc(data, dataSize, nullptr, 0); return BAD_VALUE; Loading libs/binder/include/binder/RpcSession.h +3 −2 Original line number Diff line number Diff line Loading @@ -38,15 +38,16 @@ class RpcState; class RpcTransport; class FdTrigger; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 2; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 3; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL = 0xF0000000; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = 1; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = 2; // Starting with this version: // // * RpcWireReply is larger (4 bytes -> 20). // * RpcWireTransaction and RpcWireReplyV1 include the parcel data size. constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE = 1; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS = 2; /** * This represents a session (group of connections) between a client Loading libs/binder/tests/binderRpcTest.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -1960,6 +1960,8 @@ static std::vector<SocketType> testSocketTypes(bool hasPreconnected = true) { static std::vector<BinderRpc::ParamType> getBinderRpcParams() { std::vector<BinderRpc::ParamType> ret; // IF YOU ARE MAKING MAJOR CHANGES TO RPC BINDER, SET THIS TO 'true' TO RUN ALL COMBINATIONS OF // TESTS constexpr bool full = false; for (const auto& type : testSocketTypes()) { Loading @@ -1969,6 +1971,14 @@ static std::vector<BinderRpc::ParamType> getBinderRpcParams() { for (const auto& serverVersion : testVersions()) { for (bool singleThreaded : {false, true}) { for (bool noKernel : noKernelValues()) { // SKIP combinatorial testing of old versions, since otherwise this // test takes way too long if (!full && (clientVersion != RPC_WIRE_PROTOCOL_VERSION && serverVersion != RPC_WIRE_PROTOCOL_VERSION) && security != RpcSecurity::RAW) continue; ret.push_back(BinderRpc::ParamType{ .type = type, .security = security, Loading libs/binder/tests/binderRpcUniversalTests.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,28 @@ TEST_P(BinderRpc, AppendSeparateFormats) { EXPECT_EQ(BAD_TYPE, p2.appendFrom(&p1, 0, p1.dataSize())); } TEST_P(BinderRpc, ObjectCountRight) { auto proc = createRpcTestSocketServerProcess({}); Parcel data; data.markForBinder(proc.rootBinder); data.writeStrongBinder(nullptr); // not considered an object EXPECT_EQ(0u, data.objectsCount()); data.writeStrongBinder(sp<BBinder>::make()); if (proc.proc->sessions.at(0).session->getProtocolVersion() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS) { EXPECT_EQ(1u, data.objectsCount()); } else { EXPECT_EQ(0u, data.objectsCount()); } // TODO(b/424526253#comment5): this should be deleted by Parcel unless // the Parcel is sent, but since it's not sent and processed currently, // we leak the binder. proc.forceShutdown(); } TEST_P(BinderRpc, UnknownTransaction) { auto proc = createRpcTestSocketServerProcess({}); Parcel data; Loading libs/binder/tests/binderRpcWireProtocolTest.cpp +5 −1 Original line number Diff line number Diff line Loading @@ -253,11 +253,15 @@ TEST(RpcWire, V1) { checkRepr(kCurrentRepr, 1); } TEST(RpcWire, V2) { checkRepr(kCurrentRepr, 2); } TEST(RpcWire, CurrentVersion) { checkRepr(kCurrentRepr, RPC_WIRE_PROTOCOL_VERSION); } static_assert(RPC_WIRE_PROTOCOL_VERSION == 1, static_assert(RPC_WIRE_PROTOCOL_VERSION == 2, "If the binder wire protocol is updated, this test should test additional versions. " "The binder wire protocol should only be updated on upstream AOSP."); Loading Loading
libs/binder/Parcel.cpp +19 −3 Original line number Diff line number Diff line Loading @@ -254,8 +254,9 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) { if (binder) local = binder->localBinder(); if (local) local->setParceled(); if (const auto* rpcFields = maybeRpcFields()) { if (auto* rpcFields = maybeRpcFields()) { if (binder) { size_t dataPos = mDataPos; status_t status = writeInt32(RpcFields::TYPE_BINDER); // non-null if (status != OK) return status; uint64_t address; Loading @@ -265,6 +266,14 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) { if (status != OK) return status; status = writeUint64(address); if (status != OK) return status; if (rpcFields->mSession->getProtocolVersion() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS) { rpcFields->mObjectPositions .insert(std::upper_bound(rpcFields->mObjectPositions.begin(), rpcFields->mObjectPositions.end(), dataPos), dataPos); } } else { status_t status = writeInt32(RpcFields::TYPE_BINDER_NULL); // null if (status != OK) return status; Loading Loading @@ -1153,8 +1162,10 @@ size_t Parcel::objectsCount() const { if (const auto* kernelFields = maybeKernelFields()) { return kernelFields->mObjectsSize; } else if (auto* rpcFields = maybeRpcFields()) { return rpcFields->mObjectPositions.size(); } return 0; LOG_ALWAYS_FATAL("Must be for kernel or for RPC"); } status_t Parcel::errorCheck() const Loading Loading @@ -2915,7 +2926,12 @@ status_t Parcel::rpcSetDataReference( LOG_ALWAYS_FATAL_IF(session == nullptr); if (objectTableSize != ancillaryFds.size()) { bool sameSize = objectTableSize == ancillaryFds.size(); bool fitsIn = objectTableSize >= ancillaryFds.size(); // other positions are binders bool bindersInObjectPositions = session->getProtocolVersion() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS; if (!(bindersInObjectPositions ? fitsIn : sameSize)) { ALOGE("objectTableSize=%zu ancillaryFds.size=%zu", objectTableSize, ancillaryFds.size()); relFunc(data, dataSize, nullptr, 0); return BAD_VALUE; Loading
libs/binder/include/binder/RpcSession.h +3 −2 Original line number Diff line number Diff line Loading @@ -38,15 +38,16 @@ class RpcState; class RpcTransport; class FdTrigger; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 2; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 3; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL = 0xF0000000; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = 1; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION = 2; // Starting with this version: // // * RpcWireReply is larger (4 bytes -> 20). // * RpcWireTransaction and RpcWireReplyV1 include the parcel data size. constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE = 1; constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS = 2; /** * This represents a session (group of connections) between a client Loading
libs/binder/tests/binderRpcTest.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -1960,6 +1960,8 @@ static std::vector<SocketType> testSocketTypes(bool hasPreconnected = true) { static std::vector<BinderRpc::ParamType> getBinderRpcParams() { std::vector<BinderRpc::ParamType> ret; // IF YOU ARE MAKING MAJOR CHANGES TO RPC BINDER, SET THIS TO 'true' TO RUN ALL COMBINATIONS OF // TESTS constexpr bool full = false; for (const auto& type : testSocketTypes()) { Loading @@ -1969,6 +1971,14 @@ static std::vector<BinderRpc::ParamType> getBinderRpcParams() { for (const auto& serverVersion : testVersions()) { for (bool singleThreaded : {false, true}) { for (bool noKernel : noKernelValues()) { // SKIP combinatorial testing of old versions, since otherwise this // test takes way too long if (!full && (clientVersion != RPC_WIRE_PROTOCOL_VERSION && serverVersion != RPC_WIRE_PROTOCOL_VERSION) && security != RpcSecurity::RAW) continue; ret.push_back(BinderRpc::ParamType{ .type = type, .security = security, Loading
libs/binder/tests/binderRpcUniversalTests.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,28 @@ TEST_P(BinderRpc, AppendSeparateFormats) { EXPECT_EQ(BAD_TYPE, p2.appendFrom(&p1, 0, p1.dataSize())); } TEST_P(BinderRpc, ObjectCountRight) { auto proc = createRpcTestSocketServerProcess({}); Parcel data; data.markForBinder(proc.rootBinder); data.writeStrongBinder(nullptr); // not considered an object EXPECT_EQ(0u, data.objectsCount()); data.writeStrongBinder(sp<BBinder>::make()); if (proc.proc->sessions.at(0).session->getProtocolVersion() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_INCLUDES_BINDER_POSITIONS) { EXPECT_EQ(1u, data.objectsCount()); } else { EXPECT_EQ(0u, data.objectsCount()); } // TODO(b/424526253#comment5): this should be deleted by Parcel unless // the Parcel is sent, but since it's not sent and processed currently, // we leak the binder. proc.forceShutdown(); } TEST_P(BinderRpc, UnknownTransaction) { auto proc = createRpcTestSocketServerProcess({}); Parcel data; Loading
libs/binder/tests/binderRpcWireProtocolTest.cpp +5 −1 Original line number Diff line number Diff line Loading @@ -253,11 +253,15 @@ TEST(RpcWire, V1) { checkRepr(kCurrentRepr, 1); } TEST(RpcWire, V2) { checkRepr(kCurrentRepr, 2); } TEST(RpcWire, CurrentVersion) { checkRepr(kCurrentRepr, RPC_WIRE_PROTOCOL_VERSION); } static_assert(RPC_WIRE_PROTOCOL_VERSION == 1, static_assert(RPC_WIRE_PROTOCOL_VERSION == 2, "If the binder wire protocol is updated, this test should test additional versions. " "The binder wire protocol should only be updated on upstream AOSP."); Loading