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

Commit 64e3ec21 authored by Chris Weir's avatar Chris Weir
Browse files

Add clearPollErr to Socket

nlproxy gets stuck if a POLLERR is encountered, and I found a CL that
suggests the only way to clear the error is to recv (which should return
zero bytes in theory) on that socket.

Bug: 224850481
Test: nlproxy works
Change-Id: Ib1420ce542deeb35977223baf787bdee1b125110
parent 5cf9f6a0
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -47,6 +47,17 @@ Socket::Socket(int protocol, unsigned pid, uint32_t groups) : mProtocol(protocol
    }
}

void Socket::clearPollErr() {
    sockaddr_nl sa = {};
    socklen_t saLen = sizeof(sa);
    const auto bytesReceived = recvfrom(mFd.get(), mReceiveBuffer.data(), mReceiveBuffer.size(), 0,
                                        reinterpret_cast<sockaddr*>(&sa), &saLen);
    if (errno != EINVAL) {
        PLOG(WARNING) << "clearPollError() caught unexpected error: ";
    }
    CHECK_EQ(bytesReceived, 0) << "clearPollError() recvd " << bytesReceived << " instead of zero!";
}

bool Socket::send(const Buffer<nlmsghdr>& msg, const sockaddr_nl& sa) {
    if constexpr (kSuperVerbose) {
        LOG(VERBOSE) << (mFailed ? "(not) " : "") << "sending to " << sa.nl_pid << ": "
@@ -110,6 +121,13 @@ std::pair<std::optional<Buffer<nlmsghdr>>, sockaddr_nl> Socket::receiveFrom(size
    if constexpr (kSuperVerbose) {
        LOG(VERBOSE) << "received from " << sa.nl_pid << ": " << toString(msg, mProtocol);
    }
    long headerByteTotal = 0;
    for (const auto hdr : msg) {
        headerByteTotal += hdr->nlmsg_len;
    }
    if (bytesReceived != headerByteTotal) {
        LOG(ERROR) << "received " << bytesReceived << " bytes, header claims " << headerByteTotal;
    }
    return {msg, sa};
}

@@ -159,6 +177,7 @@ std::optional<unsigned> Socket::getPid() {
}

pollfd Socket::preparePoll(short events) {
    CHECK(mFd.get() > 0) << "Netlink socket fd is invalid!";
    return {mFd.get(), events, 0};
}

+6 −0
Original line number Diff line number Diff line
@@ -54,6 +54,12 @@ class Socket {
     */
    Socket(int protocol, unsigned pid = 0, uint32_t groups = 0);

    /**
     * Attempt to clear POLLERR by recv-ing.
     * TODO(224850481): determine if this is necessary, or if the socket is locked up anyway.
     */
    void clearPollErr();

    /**
     * Send Netlink message with incremented sequence number to the Kernel.
     *
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ bool FamilyTracker::track(const Buffer<nlmsghdr>& buffer) {
    const auto familyName = msg.attributes.get<std::string>(CTRL_ATTR_FAMILY_NAME);
    const auto familyId = msg.attributes.get<uint16_t>(CTRL_ATTR_FAMILY_ID);

    // TODO(224845900): NETLINK_GENERIC == 16, and (erroneously?) sets off this warning
    if (familyId < GENL_START_ALLOC) {
        LOG(WARNING) << "Invalid family ID: " << familyId;
        return true;
+5 −6
Original line number Diff line number Diff line
@@ -117,14 +117,13 @@ bool android_nlinterceptor_createSocket(
    int clientSocketFd, const char* clientName,
    struct android_nlinterceptor_InterceptedSocket* interceptedSocket);

void android_nlinterceptor_closeSocket(
    const struct android_nlinterceptor_InterceptedSocket* sock);
void android_nlinterceptor_closeSocket(struct android_nlinterceptor_InterceptedSocket sock);

bool android_nlinterceptor_subscribe(
    const struct android_nlinterceptor_InterceptedSocket* sock, uint32_t group);
bool android_nlinterceptor_subscribe(struct android_nlinterceptor_InterceptedSocket sock,
                                     uint32_t group);

bool android_nlinterceptor_unsubscribe(
    const struct android_nlinterceptor_InterceptedSocket* sock, uint32_t group);
bool android_nlinterceptor_unsubscribe(struct android_nlinterceptor_InterceptedSocket sock,
                                       uint32_t group);

#ifdef __cplusplus
}
+8 −15
Original line number Diff line number Diff line
@@ -150,25 +150,18 @@ extern "C" bool android_nlinterceptor_createSocket(
    return true;
}

extern "C" void android_nlinterceptor_closeSocket(
    const android_nlinterceptor_InterceptedSocket* sock) {
    if (!sock) {
        LOG(ERROR) << "Can't close socket identified by a null pointer!";
        return;
    }
    closeSocket({sock->nlFamily, sock->portId});
extern "C" void android_nlinterceptor_closeSocket(android_nlinterceptor_InterceptedSocket sock) {
    closeSocket({sock.nlFamily, sock.portId});
}

extern "C" bool android_nlinterceptor_subscribe(
    const android_nlinterceptor_InterceptedSocket* sock, uint32_t group) {
    if (!sock) return false;
    return subscribe({sock->nlFamily, sock->portId}, group);
extern "C" bool android_nlinterceptor_subscribe(android_nlinterceptor_InterceptedSocket sock,
                                                uint32_t group) {
    return subscribe({sock.nlFamily, sock.portId}, group);
}

extern "C" bool android_nlinterceptor_unsubscribe(
    const android_nlinterceptor_InterceptedSocket* sock, uint32_t group) {
    if (!sock) return false;
    return unsubscribe({sock->nlFamily, sock->portId}, group);
extern "C" bool android_nlinterceptor_unsubscribe(android_nlinterceptor_InterceptedSocket sock,
                                                  uint32_t group) {
    return unsubscribe({sock.nlFamily, sock.portId}, group);
}

}  // namespace android::nlinterceptor