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

Commit f551f7fe authored by Yifan Hong's avatar Yifan Hong Committed by Automerger Merge Worker
Browse files

Merge changes from topic "binder_rpc_test_ephermeral_port" am: 27f2ed69 am:...

Merge changes from topic "binder_rpc_test_ephermeral_port" am: 27f2ed69 am: 8f02b016 am: ad9814c4 am: 847ca5ad

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1687433

Change-Id: I76dd1f55bb9aedf21ed2df7d82b539608044dff0
parents 662ec846 847ca5ad
Loading
Loading
Loading
Loading
+62 −2
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <binder/RpcConnection.h>
#include <binder/RpcConnection.h>


#include <arpa/inet.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <netdb.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/socket.h>
@@ -45,9 +46,55 @@ extern "C" pid_t gettid();


namespace android {
namespace android {


using base::borrowed_fd;
using base::unique_fd;
using base::unique_fd;
using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>;
using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>;


namespace {
bool checkSockaddrSize(const char* name, size_t actual, size_t expected) {
    if (actual >= expected) return true;
    ALOGW("getSockaddrPort: family is %s but size is %zu < %zu", name, actual, expected);
    return false;
}

// Get the port number of |storage| for certain families. Requires storage->sa_family to be
// set to a known family; otherwise, return nullopt.
std::optional<unsigned int> getSockaddrPort(const sockaddr* storage, socklen_t len) {
    switch (storage->sa_family) {
        case AF_INET: {
            if (!checkSockaddrSize("INET", len, sizeof(sockaddr_in))) return std::nullopt;
            auto inetStorage = reinterpret_cast<const sockaddr_in*>(storage);
            return ntohs(inetStorage->sin_port);
        }
        default: {
            uint16_t family = storage->sa_family;
            ALOGW("Don't know how to infer port for family %" PRIu16, family);
            return std::nullopt;
        }
    }
}

std::optional<unsigned int> getSocketPort(borrowed_fd socketfd,
                                          const RpcConnection::SocketAddress& socketAddress) {
    sockaddr_storage storage{};
    socklen_t len = sizeof(storage);
    auto storagePtr = reinterpret_cast<sockaddr*>(&storage);
    if (0 != getsockname(socketfd.get(), storagePtr, &len)) {
        int savedErrno = errno;
        ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(),
              strerror(savedErrno));
        return std::nullopt;
    }

    // getsockname does not fill in family, but getSockaddrPort() needs it.
    if (storage.ss_family == AF_UNSPEC) {
        storage.ss_family = socketAddress.addr()->sa_family;
    }
    return getSockaddrPort(storagePtr, len);
}

} // namespace

RpcConnection::SocketAddress::~SocketAddress() {}
RpcConnection::SocketAddress::~SocketAddress() {}


RpcConnection::RpcConnection() {
RpcConnection::RpcConnection() {
@@ -166,14 +213,27 @@ AddrInfo GetAddrInfo(const char* addr, unsigned int port) {
    return AddrInfo(aiStart, &freeaddrinfo);
    return AddrInfo(aiStart, &freeaddrinfo);
}
}


bool RpcConnection::setupInetServer(unsigned int port) {
bool RpcConnection::setupInetServer(unsigned int port, unsigned int* assignedPort) {
    const char* kAddr = "127.0.0.1";
    const char* kAddr = "127.0.0.1";


    if (assignedPort != nullptr) *assignedPort = 0;
    auto aiStart = GetAddrInfo(kAddr, port);
    auto aiStart = GetAddrInfo(kAddr, port);
    if (aiStart == nullptr) return false;
    if (aiStart == nullptr) return false;
    for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
    for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
        InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port);
        InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port);
        if (setupSocketServer(socketAddress)) return true;
        if (!setupSocketServer(socketAddress)) {
            continue;
        }
        auto realPort = getSocketPort(mServer.get(), socketAddress);
        LOG_ALWAYS_FATAL_IF(!realPort.has_value(), "Unable to get port number after setting up %s",
                            socketAddress.toString().c_str());
        LOG_ALWAYS_FATAL_IF(port != 0 && *realPort != port,
                            "Requesting inet server on %s but it is set up on %u.",
                            socketAddress.toString().c_str(), *realPort);
        if (assignedPort != nullptr) {
            *assignedPort = *realPort;
        }
        return true;
    }
    }
    ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,
    ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,
          port);
          port);
+8 −2
Original line number Original line Diff line number Diff line
@@ -74,9 +74,15 @@ public:
#endif // __BIONIC__
#endif // __BIONIC__


    /**
    /**
     * Creates an RPC server at the current port.
     * Creates an RPC server at the current port using IPv4.
     *
     * TODO(b/182914638): IPv6 support
     *
     * Set |port| to 0 to pick an ephemeral port; see discussion of
     * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
     * will be set to the picked port number, if it is not null.
     */
     */
    [[nodiscard]] bool setupInetServer(unsigned int port);
    [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);


    /**
    /**
     * Connects to an RPC server at the given address and port.
     * Connects to an RPC server at the given address and port.
+41 −10
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#include <BnBinderRpcSession.h>
#include <BnBinderRpcSession.h>
#include <BnBinderRpcTest.h>
#include <BnBinderRpcTest.h>
#include <aidl/IBinderRpcTest.h>
#include <aidl/IBinderRpcTest.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/logging.h>
#include <android/binder_auto_utils.h>
#include <android/binder_auto_utils.h>
#include <android/binder_libbinder.h>
#include <android/binder_libbinder.h>
@@ -176,14 +177,27 @@ public:
};
};
sp<IBinder> MyBinderRpcTest::mHeldBinder;
sp<IBinder> MyBinderRpcTest::mHeldBinder;


class Pipe {
public:
    Pipe() { CHECK(android::base::Pipe(&mRead, &mWrite)); }
    Pipe(Pipe&&) = default;
    android::base::borrowed_fd readEnd() { return mRead; }
    android::base::borrowed_fd writeEnd() { return mWrite; }

private:
    android::base::unique_fd mRead;
    android::base::unique_fd mWrite;
};

class Process {
class Process {
public:
public:
    Process(const std::function<void()>& f) {
    Process(Process&&) = default;
    Process(const std::function<void(Pipe*)>& f) {
        if (0 == (mPid = fork())) {
        if (0 == (mPid = fork())) {
            // racey: assume parent doesn't crash before this is set
            // racey: assume parent doesn't crash before this is set
            prctl(PR_SET_PDEATHSIG, SIGHUP);
            prctl(PR_SET_PDEATHSIG, SIGHUP);


            f();
            f(&mPipe);
        }
        }
    }
    }
    ~Process() {
    ~Process() {
@@ -191,9 +205,11 @@ public:
            kill(mPid, SIGKILL);
            kill(mPid, SIGKILL);
        }
        }
    }
    }
    Pipe* getPipe() { return &mPipe; }


private:
private:
    pid_t mPid = 0;
    pid_t mPid = 0;
    Pipe mPipe;
};
};


static std::string allocateSocketAddress() {
static std::string allocateSocketAddress() {
@@ -215,6 +231,7 @@ struct ProcessConnection {
    // whether connection should be invalidated by end of run
    // whether connection should be invalidated by end of run
    bool expectInvalid = false;
    bool expectInvalid = false;


    ProcessConnection(ProcessConnection&&) = default;
    ~ProcessConnection() {
    ~ProcessConnection() {
        rootBinder = nullptr;
        rootBinder = nullptr;
        EXPECT_NE(nullptr, connection);
        EXPECT_NE(nullptr, connection);
@@ -238,6 +255,7 @@ struct BinderRpcTestProcessConnection {
    // pre-casted root object
    // pre-casted root object
    sp<IBinderRpcTest> rootIface;
    sp<IBinderRpcTest> rootIface;


    BinderRpcTestProcessConnection(BinderRpcTestProcessConnection&&) = default;
    ~BinderRpcTestProcessConnection() {
    ~BinderRpcTestProcessConnection() {
        if (!proc.expectInvalid) {
        if (!proc.expectInvalid) {
            int32_t remoteBinders = 0;
            int32_t remoteBinders = 0;
@@ -286,11 +304,11 @@ public:


        std::string addr = allocateSocketAddress();
        std::string addr = allocateSocketAddress();
        unlink(addr.c_str());
        unlink(addr.c_str());
        static unsigned int port = 3456;
        static unsigned int vsockPort = 3456;
        port++;
        vsockPort++;


        auto ret = ProcessConnection{
        auto ret = ProcessConnection{
                .host = Process([&] {
                .host = Process([&](Pipe* pipe) {
                    sp<RpcServer> server = RpcServer::make();
                    sp<RpcServer> server = RpcServer::make();


                    server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
                    server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
@@ -304,12 +322,17 @@ public:
                            break;
                            break;
#ifdef __BIONIC__
#ifdef __BIONIC__
                        case SocketType::VSOCK:
                        case SocketType::VSOCK:
                            CHECK(connection->setupVsockServer(port));
                            CHECK(connection->setupVsockServer(vsockPort));
                            break;
                            break;
#endif // __BIONIC__
#endif // __BIONIC__
                        case SocketType::INET:
                        case SocketType::INET: {
                            CHECK(connection->setupInetServer(port));
                            unsigned int outPort = 0;
                            CHECK(connection->setupInetServer(0, &outPort));
                            CHECK_NE(0, outPort);
                            CHECK(android::base::WriteFully(pipe->writeEnd(), &outPort,
                                                            sizeof(outPort)));
                            break;
                            break;
                        }
                        default:
                        default:
                            LOG_ALWAYS_FATAL("Unknown socket type");
                            LOG_ALWAYS_FATAL("Unknown socket type");
                    }
                    }
@@ -327,6 +350,13 @@ public:
                .connection = RpcConnection::make(),
                .connection = RpcConnection::make(),
        };
        };


        unsigned int inetPort = 0;
        if (socketType == SocketType::INET) {
            CHECK(android::base::ReadFully(ret.host.getPipe()->readEnd(), &inetPort,
                                           sizeof(inetPort)));
            CHECK_NE(0, inetPort);
        }

        // create remainder of connections
        // create remainder of connections
        for (size_t i = 0; i < numThreads; i++) {
        for (size_t i = 0; i < numThreads; i++) {
            for (size_t tries = 0; tries < 5; tries++) {
            for (size_t tries = 0; tries < 5; tries++) {
@@ -337,11 +367,12 @@ public:
                        break;
                        break;
#ifdef __BIONIC__
#ifdef __BIONIC__
                    case SocketType::VSOCK:
                    case SocketType::VSOCK:
                        if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success;
                        if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, vsockPort))
                            goto success;
                        break;
                        break;
#endif // __BIONIC__
#endif // __BIONIC__
                    case SocketType::INET:
                    case SocketType::INET:
                        if (ret.connection->addInetClient("127.0.0.1", port)) goto success;
                        if (ret.connection->addInetClient("127.0.0.1", inetPort)) goto success;
                        break;
                        break;
                    default:
                    default:
                        LOG_ALWAYS_FATAL("Unknown socket type");
                        LOG_ALWAYS_FATAL("Unknown socket type");