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

Commit 5e74d2db authored by Andrei Homescu's avatar Andrei Homescu
Browse files

libbinder: keep track of multiple connections in RpcServerTrusty

Correctly keep track of each individual RpcConnection made
to RpcServerTrusty and close the correct one on cleanup.
The code previously assumed that each session would only
have one connection, which is not necessarily the case
in practice with multi-threaded Android clients.

Bug: 224644083
Test: Trusty tests
Change-Id: I12d04de803e0c5df5c658cdbaf3dd0d45e10ef20
parent 62bb50a6
Loading
Loading
Loading
Loading
+28 −7
Original line number Diff line number Diff line
@@ -104,8 +104,17 @@ int RpcServerTrusty::handleConnect(const tipc_port* port, handle_t chan, const u
            return;
        }

        /* Save the session for easy access */
        *ctx_p = session.get();
        /* Save the session and connection for the other callbacks */
        auto* channelContext = new (std::nothrow) ChannelContext;
        if (channelContext == nullptr) {
            rc = ERR_NO_MEMORY;
            return;
        }

        channelContext->session = std::move(session);
        channelContext->connection = std::move(result.connection);

        *ctx_p = channelContext;
    };

    base::unique_fd clientFd(chan);
@@ -119,9 +128,14 @@ int RpcServerTrusty::handleConnect(const tipc_port* port, handle_t chan, const u
}

int RpcServerTrusty::handleMessage(const tipc_port* port, handle_t chan, void* ctx) {
    auto* session = reinterpret_cast<RpcSession*>(ctx);
    status_t status = session->state()->drainCommands(session->mConnections.mIncoming[0], session,
                                                      RpcState::CommandType::ANY);
    auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
    LOG_ALWAYS_FATAL_IF(channelContext == nullptr,
                        "bad state: message received on uninitialized channel");

    auto& session = channelContext->session;
    auto& connection = channelContext->connection;
    status_t status =
            session->state()->drainCommands(connection, session, RpcState::CommandType::ANY);
    if (status != OK) {
        LOG_RPC_DETAIL("Binder connection thread closing w/ status %s",
                       statusToString(status).c_str());
@@ -133,10 +147,17 @@ int RpcServerTrusty::handleMessage(const tipc_port* port, handle_t chan, void* c
void RpcServerTrusty::handleDisconnect(const tipc_port* port, handle_t chan, void* ctx) {}

void RpcServerTrusty::handleChannelCleanup(void* ctx) {
    auto* session = reinterpret_cast<RpcSession*>(ctx);
    auto& connection = session->mConnections.mIncoming.at(0);
    auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
    if (channelContext == nullptr) {
        return;
    }

    auto& session = channelContext->session;
    auto& connection = channelContext->connection;
    LOG_ALWAYS_FATAL_IF(!session->removeIncomingConnection(connection),
                        "bad state: connection object guaranteed to be in list");

    delete channelContext;
}

} // namespace android
+6 −0
Original line number Diff line number Diff line
@@ -77,6 +77,12 @@ private:
    explicit RpcServerTrusty(std::unique_ptr<RpcTransportCtx> ctx, std::string&& portName,
                             std::shared_ptr<const PortAcl>&& portAcl, size_t msgMaxSize);

    // The Rpc-specific context maintained for every open TIPC channel.
    struct ChannelContext {
        sp<RpcSession> session;
        sp<RpcSession::RpcConnection> connection;
    };

    static int handleConnect(const tipc_port* port, handle_t chan, const uuid* peer, void** ctx_p);
    static int handleMessage(const tipc_port* port, handle_t chan, void* ctx);
    static void handleDisconnect(const tipc_port* port, handle_t chan, void* ctx);