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

Commit 2f1edfa5 authored by Steven Moreland's avatar Steven Moreland
Browse files

libbinder: remove abstraction layer for get port

In preparation to move this code to another file. There were a few
bugs before:
- dead code
- getsockaddr error would lead to abort (but only inconsistent state in
  the old abstraction should have left for an abort)
- added check to ensure socklen_t when returned from getsockname is as
  expected

Bug: 185167543
Test: binderRpcTest
Change-Id: Ic79479b6a66226db309dfde134617af50c2365fe
parent a4c94756
Loading
Loading
Loading
Loading
+18 −52
Original line number Diff line number Diff line
@@ -46,55 +46,9 @@ extern "C" pid_t gettid();

namespace android {

using base::borrowed_fd;
using base::unique_fd;
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::RpcConnection() {
@@ -224,15 +178,27 @@ bool RpcConnection::setupInetServer(unsigned int port, unsigned int* assignedPor
        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,

        LOG_ALWAYS_FATAL_IF(socketAddress.addr()->sa_family != AF_INET, "expecting inet");
        sockaddr_in addr{};
        socklen_t len = sizeof(addr);
        if (0 != getsockname(mServer.get(), reinterpret_cast<sockaddr*>(&addr), &len)) {
            int savedErrno = errno;
            ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(),
                  strerror(savedErrno));
            return false;
        }
        LOG_ALWAYS_FATAL_IF(len != sizeof(addr), "Wrong socket type: len %zu vs len %zu",
                            static_cast<size_t>(len), sizeof(addr));
        unsigned int realPort = ntohs(addr.sin_port);
        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);
                            socketAddress.toString().c_str(), realPort);

        if (assignedPort != nullptr) {
            *assignedPort = *realPort;
            *assignedPort = realPort;
        }

        return true;
    }
    ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,