Loading libs/binder/RpcServer.cpp +15 −6 Original line number Diff line number Diff line Loading @@ -70,11 +70,8 @@ status_t RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); } status_t RpcServer::setupVsockServer(unsigned int port) { // realizing value w/ this type at compile time to avoid ubsan abort constexpr unsigned int kAnyCid = VMADDR_CID_ANY; return setupSocketServer(VsockSocketAddress(kAnyCid, port)); status_t RpcServer::setupVsockServer(unsigned int bindCid, unsigned int port) { return setupSocketServer(VsockSocketAddress(bindCid, port)); } status_t RpcServer::setupInetServer(const char* address, unsigned int port, Loading Loading @@ -157,6 +154,12 @@ void RpcServer::setPerSessionRootObject( 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() { RpcMutexLockGuard _l(mLock); bool hasWeak = mRootObjectWeak.unsafe_get(); Loading Loading @@ -242,13 +245,19 @@ void RpcServer::join() { if (mAcceptFn(*this, &clientSocket) != OK) { 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()), &addrLen)) { ALOGE("Could not getpeername socket: %s", strerror(errno)); 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); Loading libs/binder/include/binder/RpcServer.h +13 −2 Original line number Diff line number Diff line Loading @@ -81,9 +81,9 @@ public: [[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. Loading Loading @@ -170,6 +170,16 @@ public: void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object); 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 */ Loading Loading @@ -253,6 +263,7 @@ private: sp<IBinder> mRootObject; wp<IBinder> mRootObjectWeak; 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::unique_ptr<FdTrigger> mShutdownTrigger; RpcConditionVariable mShutdownCv; Loading libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp +5 −1 Original line number Diff line number Diff line Loading @@ -25,9 +25,13 @@ struct AIBinder; struct ARpcServer; // 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 // 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` // and a given root IBinder object. Loading libs/binder/libbinder_rpc_unstable.cpp +29 −7 Original line number Diff line number Diff line Loading @@ -51,21 +51,26 @@ static void freeRpcServerHandle(ARpcServer* handle) { 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" { bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context), void* factoryContext, unsigned int port) { 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 << " error: " << statusToString(status).c_str(); return false; } server->setPerSessionRootObject([=](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 AIBinder_toPlatformBinder(factory(vaddr->svm_cid, factoryContext)); unsigned int cid = cidFromStructAddr(addr, addrlen); return AIBinder_toPlatformBinder(factory(cid, factoryContext)); }); server->join(); Loading @@ -75,13 +80,30 @@ bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* c 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(); 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 << " error: " << statusToString(status).c_str(); 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)); return createRpcServerHandle(server); } Loading libs/binder/rust/rpcbinder/src/server.rs +8 −3 Original line number Diff line number Diff line Loading @@ -41,14 +41,19 @@ unsafe impl Sync for RpcServer {} impl RpcServer { /// Creates a binder RPC server, serving the supplied binder service implementation on the given /// vsock port. pub fn new_vsock(mut service: SpIBinder, port: u32) -> Result<RpcServer, Error> { /// vsock port. Only connections from the given CID are accepted. /// // 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(); // SAFETY: Service ownership is transferring to the server and won't be valid afterward. // Plus the binder objects are threadsafe. 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 Loading
libs/binder/RpcServer.cpp +15 −6 Original line number Diff line number Diff line Loading @@ -70,11 +70,8 @@ status_t RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); } status_t RpcServer::setupVsockServer(unsigned int port) { // realizing value w/ this type at compile time to avoid ubsan abort constexpr unsigned int kAnyCid = VMADDR_CID_ANY; return setupSocketServer(VsockSocketAddress(kAnyCid, port)); status_t RpcServer::setupVsockServer(unsigned int bindCid, unsigned int port) { return setupSocketServer(VsockSocketAddress(bindCid, port)); } status_t RpcServer::setupInetServer(const char* address, unsigned int port, Loading Loading @@ -157,6 +154,12 @@ void RpcServer::setPerSessionRootObject( 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() { RpcMutexLockGuard _l(mLock); bool hasWeak = mRootObjectWeak.unsafe_get(); Loading Loading @@ -242,13 +245,19 @@ void RpcServer::join() { if (mAcceptFn(*this, &clientSocket) != OK) { 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()), &addrLen)) { ALOGE("Could not getpeername socket: %s", strerror(errno)); 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); Loading
libs/binder/include/binder/RpcServer.h +13 −2 Original line number Diff line number Diff line Loading @@ -81,9 +81,9 @@ public: [[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. Loading Loading @@ -170,6 +170,16 @@ public: void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object); 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 */ Loading Loading @@ -253,6 +263,7 @@ private: sp<IBinder> mRootObject; wp<IBinder> mRootObjectWeak; 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::unique_ptr<FdTrigger> mShutdownTrigger; RpcConditionVariable mShutdownCv; Loading
libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp +5 −1 Original line number Diff line number Diff line Loading @@ -25,9 +25,13 @@ struct AIBinder; struct ARpcServer; // 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 // 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` // and a given root IBinder object. Loading
libs/binder/libbinder_rpc_unstable.cpp +29 −7 Original line number Diff line number Diff line Loading @@ -51,21 +51,26 @@ static void freeRpcServerHandle(ARpcServer* handle) { 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" { bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context), void* factoryContext, unsigned int port) { 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 << " error: " << statusToString(status).c_str(); return false; } server->setPerSessionRootObject([=](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 AIBinder_toPlatformBinder(factory(vaddr->svm_cid, factoryContext)); unsigned int cid = cidFromStructAddr(addr, addrlen); return AIBinder_toPlatformBinder(factory(cid, factoryContext)); }); server->join(); Loading @@ -75,13 +80,30 @@ bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* c 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(); 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 << " error: " << statusToString(status).c_str(); 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)); return createRpcServerHandle(server); } Loading
libs/binder/rust/rpcbinder/src/server.rs +8 −3 Original line number Diff line number Diff line Loading @@ -41,14 +41,19 @@ unsafe impl Sync for RpcServer {} impl RpcServer { /// Creates a binder RPC server, serving the supplied binder service implementation on the given /// vsock port. pub fn new_vsock(mut service: SpIBinder, port: u32) -> Result<RpcServer, Error> { /// vsock port. Only connections from the given CID are accepted. /// // 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(); // SAFETY: Service ownership is transferring to the server and won't be valid afterward. // Plus the binder objects are threadsafe. 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