Loading libs/binder/RpcServer.cpp +15 −6 Original line number Original line Diff line number Diff line Loading @@ -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, Loading Loading @@ -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(); Loading Loading @@ -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); Loading libs/binder/include/binder/RpcServer.h +13 −2 Original line number Original line Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 */ */ Loading Loading @@ -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; Loading libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp +5 −1 Original line number Original line Diff line number Diff line Loading @@ -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. Loading libs/binder/libbinder_rpc_unstable.cpp +29 −7 Original line number Original line Diff line number Diff line Loading @@ -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(); Loading @@ -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); } } Loading libs/binder/rust/rpcbinder/src/server.rs +8 −3 Original line number Original line Diff line number Diff line Loading @@ -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 Loading
libs/binder/RpcServer.cpp +15 −6 Original line number Original line Diff line number Diff line Loading @@ -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, Loading Loading @@ -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(); Loading Loading @@ -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); Loading
libs/binder/include/binder/RpcServer.h +13 −2 Original line number Original line Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 */ */ Loading Loading @@ -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; Loading
libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp +5 −1 Original line number Original line Diff line number Diff line Loading @@ -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. Loading
libs/binder/libbinder_rpc_unstable.cpp +29 −7 Original line number Original line Diff line number Diff line Loading @@ -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(); Loading @@ -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); } } Loading
libs/binder/rust/rpcbinder/src/server.rs +8 −3 Original line number Original line Diff line number Diff line Loading @@ -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