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

Commit 80170d5f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "rpc_binder: Specify CID for vsock RpcServer"

parents a1cf02cf a47dfdaf
Loading
Loading
Loading
Loading
+15 −6
Original line number Original line Diff line number Diff line
@@ -70,11 +70,8 @@ status_t RpcServer::setupUnixDomainServer(const char* path) {
    return setupSocketServer(UnixSocketAddress(path));
    return setupSocketServer(UnixSocketAddress(path));
}
}


status_t RpcServer::setupVsockServer(unsigned int port) {
status_t RpcServer::setupVsockServer(unsigned int bindCid, unsigned int port) {
    // realizing value w/ this type at compile time to avoid ubsan abort
    return setupSocketServer(VsockSocketAddress(bindCid, port));
    constexpr unsigned int kAnyCid = VMADDR_CID_ANY;

    return setupSocketServer(VsockSocketAddress(kAnyCid, port));
}
}


status_t RpcServer::setupInetServer(const char* address, unsigned int port,
status_t RpcServer::setupInetServer(const char* address, unsigned int port,
@@ -157,6 +154,12 @@ void RpcServer::setPerSessionRootObject(
    mRootObjectFactory = std::move(makeObject);
    mRootObjectFactory = std::move(makeObject);
}
}


void RpcServer::setConnectionFilter(std::function<bool(const void*, size_t)>&& filter) {
    RpcMutexLockGuard _l(mLock);
    LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
    mConnectionFilter = std::move(filter);
}

sp<IBinder> RpcServer::getRootObject() {
sp<IBinder> RpcServer::getRootObject() {
    RpcMutexLockGuard _l(mLock);
    RpcMutexLockGuard _l(mLock);
    bool hasWeak = mRootObjectWeak.unsafe_get();
    bool hasWeak = mRootObjectWeak.unsafe_get();
@@ -242,13 +245,19 @@ void RpcServer::join() {
        if (mAcceptFn(*this, &clientSocket) != OK) {
        if (mAcceptFn(*this, &clientSocket) != OK) {
            continue;
            continue;
        }
        }

        LOG_RPC_DETAIL("accept on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get());

        if (getpeername(clientSocket.fd.get(), reinterpret_cast<sockaddr*>(addr.data()),
        if (getpeername(clientSocket.fd.get(), reinterpret_cast<sockaddr*>(addr.data()),
                        &addrLen)) {
                        &addrLen)) {
            ALOGE("Could not getpeername socket: %s", strerror(errno));
            ALOGE("Could not getpeername socket: %s", strerror(errno));
            continue;
            continue;
        }
        }


        LOG_RPC_DETAIL("accept on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get());
        if (mConnectionFilter != nullptr && !mConnectionFilter(addr.data(), addrLen)) {
            ALOGE("Dropped client connection fd %d", clientSocket.fd.get());
            continue;
        }


        {
        {
            RpcMutexLockGuard _l(mLock);
            RpcMutexLockGuard _l(mLock);
+13 −2
Original line number Original line Diff line number Diff line
@@ -81,9 +81,9 @@ public:
    [[nodiscard]] status_t setupRawSocketServer(base::unique_fd socket_fd);
    [[nodiscard]] status_t setupRawSocketServer(base::unique_fd socket_fd);


    /**
    /**
     * Creates an RPC server at the current port.
     * Creates an RPC server binding to the given CID at the given port.
     */
     */
    [[nodiscard]] status_t setupVsockServer(unsigned int port);
    [[nodiscard]] status_t setupVsockServer(unsigned int bindCid, unsigned int port);


    /**
    /**
     * Creates an RPC server at the current port using IPv4.
     * Creates an RPC server at the current port using IPv4.
@@ -170,6 +170,16 @@ public:
    void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object);
    void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object);
    sp<IBinder> getRootObject();
    sp<IBinder> getRootObject();


    /**
     * Set optional filter of incoming connections based on the peer's address.
     *
     * Takes one argument: a callable that is invoked on each accept()-ed
     * connection and returns false if the connection should be dropped.
     * See the description of setPerSessionRootObject() for details about
     * the callable's arguments.
     */
    void setConnectionFilter(std::function<bool(const void*, size_t)>&& filter);

    /**
    /**
     * See RpcTransportCtx::getCertificate
     * See RpcTransportCtx::getCertificate
     */
     */
@@ -253,6 +263,7 @@ private:
    sp<IBinder> mRootObject;
    sp<IBinder> mRootObject;
    wp<IBinder> mRootObjectWeak;
    wp<IBinder> mRootObjectWeak;
    std::function<sp<IBinder>(const void*, size_t)> mRootObjectFactory;
    std::function<sp<IBinder>(const void*, size_t)> mRootObjectFactory;
    std::function<bool(const void*, size_t)> mConnectionFilter;
    std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
    std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
    std::unique_ptr<FdTrigger> mShutdownTrigger;
    std::unique_ptr<FdTrigger> mShutdownTrigger;
    RpcConditionVariable mShutdownCv;
    RpcConditionVariable mShutdownCv;
+5 −1
Original line number Original line Diff line number Diff line
@@ -25,9 +25,13 @@ struct AIBinder;
struct ARpcServer;
struct ARpcServer;


// Starts an RPC server on a given port and a given root IBinder object.
// Starts an RPC server on a given port and a given root IBinder object.
// The server will only accept connections from the given CID.
// Set `cid` to VMADDR_CID_ANY to accept connections from any client.
// Set `cid` to VMADDR_CID_LOCAL to only bind to the local vsock interface.
// Returns an opaque handle to the running server instance, or null if the server
// Returns an opaque handle to the running server instance, or null if the server
// could not be started.
// could not be started.
[[nodiscard]] ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int port);
[[nodiscard]] ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid,
                                              unsigned int port);


// Starts a Unix domain RPC server with a given init-managed Unix domain `name`
// Starts a Unix domain RPC server with a given init-managed Unix domain `name`
// and a given root IBinder object.
// and a given root IBinder object.
+29 −7
Original line number Original line Diff line number Diff line
@@ -51,21 +51,26 @@ static void freeRpcServerHandle(ARpcServer* handle) {
    ref->decStrong(ref);
    ref->decStrong(ref);
}
}


static unsigned int cidFromStructAddr(const void* addr, size_t addrlen) {
    LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated");
    const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr);
    LOG_ALWAYS_FATAL_IF(vaddr->svm_family != AF_VSOCK, "address is not a vsock");
    return vaddr->svm_cid;
}

extern "C" {
extern "C" {


bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
                                  void* factoryContext, unsigned int port) {
                                  void* factoryContext, unsigned int port) {
    auto server = RpcServer::make();
    auto server = RpcServer::make();
    if (status_t status = server->setupVsockServer(port); status != OK) {
    if (status_t status = server->setupVsockServer(VMADDR_CID_ANY, port); status != OK) {
        LOG(ERROR) << "Failed to set up vsock server with port " << port
        LOG(ERROR) << "Failed to set up vsock server with port " << port
                   << " error: " << statusToString(status).c_str();
                   << " error: " << statusToString(status).c_str();
        return false;
        return false;
    }
    }
    server->setPerSessionRootObject([=](const void* addr, size_t addrlen) {
    server->setPerSessionRootObject([=](const void* addr, size_t addrlen) {
        LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated");
        unsigned int cid = cidFromStructAddr(addr, addrlen);
        const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr);
        return AIBinder_toPlatformBinder(factory(cid, factoryContext));
        LOG_ALWAYS_FATAL_IF(vaddr->svm_family != AF_VSOCK, "address is not a vsock");
        return AIBinder_toPlatformBinder(factory(vaddr->svm_cid, factoryContext));
    });
    });


    server->join();
    server->join();
@@ -75,13 +80,30 @@ bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* c
    return true;
    return true;
}
}


ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int port) {
ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid, unsigned int port) {
    auto server = RpcServer::make();
    auto server = RpcServer::make();
    if (status_t status = server->setupVsockServer(port); status != OK) {

    unsigned int bindCid = VMADDR_CID_ANY; // bind to the remote interface
    if (cid == VMADDR_CID_LOCAL) {
        bindCid = VMADDR_CID_LOCAL; // bind to the local interface
        cid = VMADDR_CID_ANY;       // no need for a connection filter
    }

    if (status_t status = server->setupVsockServer(bindCid, port); status != OK) {
        LOG(ERROR) << "Failed to set up vsock server with port " << port
        LOG(ERROR) << "Failed to set up vsock server with port " << port
                   << " error: " << statusToString(status).c_str();
                   << " error: " << statusToString(status).c_str();
        return nullptr;
        return nullptr;
    }
    }
    if (cid != VMADDR_CID_ANY) {
        server->setConnectionFilter([=](const void* addr, size_t addrlen) {
            unsigned int remoteCid = cidFromStructAddr(addr, addrlen);
            if (cid != remoteCid) {
                LOG(ERROR) << "Rejected vsock connection from CID " << remoteCid;
                return false;
            }
            return true;
        });
    }
    server->setRootObject(AIBinder_toPlatformBinder(service));
    server->setRootObject(AIBinder_toPlatformBinder(service));
    return createRpcServerHandle(server);
    return createRpcServerHandle(server);
}
}
+8 −3
Original line number Original line Diff line number Diff line
@@ -41,14 +41,19 @@ unsafe impl Sync for RpcServer {}


impl RpcServer {
impl RpcServer {
    /// Creates a binder RPC server, serving the supplied binder service implementation on the given
    /// Creates a binder RPC server, serving the supplied binder service implementation on the given
    /// vsock port.
    /// vsock port. Only connections from the given CID are accepted.
    pub fn new_vsock(mut service: SpIBinder, port: u32) -> Result<RpcServer, Error> {
    ///
    // Set `cid` to libc::VMADDR_CID_ANY to accept connections from any client.
    // Set `cid` to libc::VMADDR_CID_LOCAL to only bind to the local vsock interface.
    pub fn new_vsock(mut service: SpIBinder, cid: u32, port: u32) -> Result<RpcServer, Error> {
        let service = service.as_native_mut();
        let service = service.as_native_mut();


        // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
        // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
        // Plus the binder objects are threadsafe.
        // Plus the binder objects are threadsafe.
        unsafe {
        unsafe {
            Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newVsock(service, port))
            Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newVsock(
                service, cid, port,
            ))
        }
        }
    }
    }


Loading