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

Commit 1f94a5f4 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 5968874 from 09b3d066 to rvc-release

Change-Id: Ia19cec4009ea2c27e01d30e6f15a96aba5ca6077
parents 5279bf4b 09b3d066
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ cc_library {
        "res_query.cpp",
        "res_send.cpp",
        "res_stats.cpp",
        "util.cpp",
        "Dns64Configuration.cpp",
        "DnsProxyListener.cpp",
        "DnsResolver.cpp",
+6 −9
Original line number Diff line number Diff line
@@ -74,10 +74,6 @@ namespace {
// Limits the number of outstanding DNS queries by client UID.
constexpr int MAX_QUERIES_PER_UID = 256;

// Max packet size for answer, sync with getaddrinfo.c
// TODO: switch to dynamically allocated buffers with std::vector
constexpr int MAXPACKET = 8 * 1024;

android::netdutils::OperationLimiter<uid_t> queryLimiter(MAX_QUERIES_PER_UID);

void logArguments(int argc, char** argv) {
@@ -886,12 +882,13 @@ void DnsProxyListener::ResNSendHandler::run() {

    // Send DNS query
    std::vector<uint8_t> ansBuf(MAXPACKET, 0);
    int arcode, nsendAns = -1;
    int rcode = ns_r_noerror;
    int nsendAns = -1;
    NetworkDnsEventReported event;
    initDnsEvent(&event);
    if (queryLimiter.start(uid)) {
        nsendAns = resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET,
                                    &arcode, static_cast<ResNsendFlags>(mFlags), &event);
                                    &rcode, static_cast<ResNsendFlags>(mFlags), &event);
        queryLimiter.finish(uid);
    } else {
        LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid
@@ -909,13 +906,13 @@ void DnsProxyListener::ResNSendHandler::run() {
        sendBE32(mClient, nsendAns);
        if (rr_type == ns_t_a || rr_type == ns_t_aaaa) {
            reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
                           resNSendToAiError(nsendAns, arcode), event, rr_name);
                           resNSendToAiError(nsendAns, rcode), event, rr_name);
        }
        return;
    }

    // Send rcode
    if (!sendBE32(mClient, arcode)) {
    if (!sendBE32(mClient, rcode)) {
        PLOG(WARNING) << "ResNSendHandler::run: resnsend: failed to send rcode to uid " << uid;
        return;
    }
@@ -932,7 +929,7 @@ void DnsProxyListener::ResNSendHandler::run() {
        const int total_ip_addr_count =
                extractResNsendAnswers((uint8_t*) ansBuf.data(), nsendAns, rr_type, &ip_addrs);
        reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
                       resNSendToAiError(nsendAns, arcode), event, rr_name, ip_addrs,
                       resNSendToAiError(nsendAns, rcode), event, rr_name, ip_addrs,
                       total_ip_addr_count);
    }
}
+21 −45
Original line number Diff line number Diff line
@@ -108,20 +108,13 @@ const Explore explore_options[] = {
};

#define PTON_MAX 16
#define MAXPACKET (8 * 1024)

typedef union {
    HEADER hdr;
    uint8_t buf[MAXPACKET];
} querybuf;

struct res_target {
    struct res_target* next;
    const char* name;  /* domain name */
    int qclass, qtype; /* class and type of query */
    uint8_t* answer;   /* buffer to put answer */
    int anslen;        /* size of answer buffer */
    int n;             /* result length */
    const char* name;                                                  // domain name
    int qclass, qtype;                                                 // class and type of query
    std::vector<uint8_t> answer = std::vector<uint8_t>(MAXPACKET, 0);  // buffer to put answer
    int n = 0;                                                         // result length
};

static int str2number(const char*);
@@ -139,8 +132,8 @@ static int get_port(const struct addrinfo*, const char*, int);
static const struct afd* find_afd(int);
static int ip6_str2scopeid(const char*, struct sockaddr_in6*, uint32_t*);

static struct addrinfo* getanswer(const querybuf*, int, const char*, int, const struct addrinfo*,
                                  int* herrno);
static struct addrinfo* getanswer(const std::vector<uint8_t>&, int, const char*, int,
                                  const struct addrinfo*, int* herrno);
static int dns_getaddrinfo(const char* name, const addrinfo* pai,
                           const android_net_context* netcontext, addrinfo** rv,
                           NetworkDnsEventReported* event);
@@ -838,8 +831,8 @@ static int ip6_str2scopeid(const char* scope, struct sockaddr_in6* sin6, uint32_
        }                            \
    } while (0)

static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype,
                                  const struct addrinfo* pai, int* herrno) {
static struct addrinfo* getanswer(const std::vector<uint8_t>& answer, int anslen, const char* qname,
                                  int qtype, const struct addrinfo* pai, int* herrno) {
    struct addrinfo sentinel = {};
    struct addrinfo *cur;
    struct addrinfo ai;
@@ -856,14 +849,13 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char
    int (*name_ok)(const char*);
    char hostbuf[8 * 1024];

    assert(answer != NULL);
    assert(qname != NULL);
    assert(pai != NULL);

    cur = &sentinel;

    canonname = NULL;
    eom = answer->buf + anslen;
    eom = answer.data() + anslen;
    switch (qtype) {
        case T_A:
        case T_AAAA:
@@ -876,18 +868,18 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char
    /*
     * find first satisfactory answer
     */
    hp = &answer->hdr;
    hp = reinterpret_cast<const HEADER*>(answer.data());
    ancount = ntohs(hp->ancount);
    qdcount = ntohs(hp->qdcount);
    bp = hostbuf;
    ep = hostbuf + sizeof hostbuf;
    cp = answer->buf;
    cp = answer.data();
    BOUNDED_INCR(HFIXEDSZ);
    if (qdcount != 1) {
        *herrno = NO_RECOVERY;
        return (NULL);
    }
    n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
    n = dn_expand(answer.data(), eom, cp, bp, ep - bp);
    if ((n < 0) || !(*name_ok)(bp)) {
        *herrno = NO_RECOVERY;
        return (NULL);
@@ -911,7 +903,7 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char
    haveanswer = 0;
    had_error = 0;
    while (ancount-- > 0 && cp < eom && !had_error) {
        n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
        n = dn_expand(answer.data(), eom, cp, bp, ep - bp);
        if ((n < 0) || !(*name_ok)(bp)) {
            had_error++;
            continue;
@@ -931,7 +923,7 @@ static struct addrinfo* getanswer(const querybuf* answer, int anslen, const char
            continue; /* XXX - had_error++ ? */
        }
        if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && type == T_CNAME) {
            n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
            n = dn_expand(answer.data(), eom, cp, tbuf, sizeof tbuf);
            if ((n < 0) || !(*name_ok)(tbuf)) {
                had_error++;
                continue;
@@ -1397,16 +1389,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
    res_target q = {};
    res_target q2 = {};

    auto buf = std::make_unique<querybuf>();
    auto buf2 = std::make_unique<querybuf>();

    switch (pai->ai_family) {
        case AF_UNSPEC: {
            /* prefer IPv6 */
            q.name = name;
            q.qclass = C_IN;
            q.answer = buf->buf;
            q.anslen = sizeof(buf->buf);
            int query_ipv6 = 1, query_ipv4 = 1;
            if (pai->ai_flags & AI_ADDRCONFIG) {
                query_ipv6 = have_ipv6(netcontext->app_mark, netcontext->uid);
@@ -1419,8 +1406,6 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
                    q2.name = name;
                    q2.qclass = C_IN;
                    q2.qtype = T_A;
                    q2.answer = buf2->buf;
                    q2.anslen = sizeof(buf2->buf);
                }
            } else if (query_ipv4) {
                q.qtype = T_A;
@@ -1433,15 +1418,11 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,
            q.name = name;
            q.qclass = C_IN;
            q.qtype = T_A;
            q.answer = buf->buf;
            q.anslen = sizeof(buf->buf);
            break;
        case AF_INET6:
            q.name = name;
            q.qclass = C_IN;
            q.qtype = T_AAAA;
            q.answer = buf->buf;
            q.anslen = sizeof(buf->buf);
            break;
        default:
            return EAI_FAMILY;
@@ -1460,13 +1441,13 @@ static int dns_getaddrinfo(const char* name, const addrinfo* pai,

    addrinfo sentinel = {};
    addrinfo* cur = &sentinel;
    addrinfo* ai = getanswer(buf.get(), q.n, q.name, q.qtype, pai, &he);
    addrinfo* ai = getanswer(q.answer, q.n, q.name, q.qtype, pai, &he);
    if (ai) {
        cur->ai_next = ai;
        while (cur && cur->ai_next) cur = cur->ai_next;
    }
    if (q.next) {
        ai = getanswer(buf2.get(), q2.n, q2.name, q2.qtype, pai, &he);
        ai = getanswer(q2.answer, q2.n, q2.name, q2.qtype, pai, &he);
        if (ai) cur->ai_next = ai;
    }
    if (sentinel.ai_next == NULL) {
@@ -1578,7 +1559,6 @@ static bool files_getaddrinfo(const char* name, const addrinfo* pai, addrinfo**
 */
static int res_queryN(const char* name, res_target* target, res_state res, int* herrno) {
    uint8_t buf[MAXPACKET];
    HEADER* hp;
    int n;
    struct res_target* t;
    int rcode;
@@ -1591,10 +1571,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int*
    ancount = 0;

    for (t = target; t; t = t->next) {
        uint8_t* answer;
        int anslen;

        hp = (HEADER*) (void*) t->answer;
        HEADER* hp = (HEADER*)(void*)t->answer.data();
        bool retried = false;
    again:
        hp->rcode = NOERROR; /* default */
@@ -1602,8 +1579,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int*
        /* make it easier... */
        int cl = t->qclass;
        int type = t->qtype;
        answer = t->answer;
        anslen = t->anslen;
        const int anslen = t->answer.size();

        LOG(DEBUG) << __func__ << ": (" << cl << ", " << type << ")";

@@ -1620,7 +1596,7 @@ static int res_queryN(const char* name, res_target* target, res_state res, int*
            return n;
        }

        n = res_nsend(res, buf, n, answer, anslen, &rcode, 0);
        n = res_nsend(res, buf, n, t->answer.data(), anslen, &rcode, 0);
        if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
            // Record rcode from DNS response header only if no timeout.
            // Keep rcode timeout for reporting later if any.
@@ -1689,7 +1665,7 @@ static int res_searchN(const char* name, res_target* target, res_state res, int*
    assert(name != NULL);
    assert(target != NULL);

    hp = (HEADER*) (void*) target->answer; /*XXX*/
    hp = (HEADER*)(void*)target->answer.data();

    errno = 0;
    *herrno = HOST_NOT_FOUND; /* default, if we never query */
@@ -1721,7 +1697,7 @@ static int res_searchN(const char* name, res_target* target, res_state res, int*
         * the domain stuff is tried.  Will have a better
         * fix after thread pools are used.
         */
        _resolv_populate_res_for_net(res);
        resolv_populate_res_for_net(res);

        for (const auto& domain : res->search_domains) {
            ret = res_querydomainN(name, domain.c_str(), target, res, herrno);
+0 −2
Original line number Diff line number Diff line
@@ -95,8 +95,6 @@ using android::net::NetworkDnsEventReported;
#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)

#define MAXPACKET (8 * 1024)

constexpr int MAXADDRS = 35;

typedef union {
+58 −79
Original line number Diff line number Diff line
@@ -61,10 +61,14 @@
#include "DnsStats.h"
#include "res_debug.h"
#include "resolv_private.h"
#include "util.h"

using android::base::StringAppendF;
using android::net::DnsQueryEvent;
using android::net::DnsStats;
using android::net::PROTO_DOT;
using android::net::PROTO_TCP;
using android::net::PROTO_UDP;
using android::netdutils::DumpWriter;
using android::netdutils::IPSockAddr;

@@ -936,7 +940,7 @@ struct resolv_cache_info {
    struct resolv_cache_info* next;
    int nscount;
    std::vector<std::string> nameservers;
    struct addrinfo* nsaddrinfo[MAXNS];  // TODO: Use struct sockaddr_storage.
    std::vector<IPSockAddr> nameserverSockAddrs;
    int revision_id;  // # times the nameservers have been replaced
    res_params params;
    struct res_stats nsstats[MAXNS];
@@ -1563,6 +1567,21 @@ std::vector<std::string> filter_nameservers(const std::vector<std::string>& serv
    return res;
}

bool isValidServer(const std::string& server) {
    const addrinfo hints = {
            .ai_family = AF_UNSPEC,
            .ai_socktype = SOCK_DGRAM,
    };
    addrinfo* result = nullptr;
    if (int err = getaddrinfo_numeric(server.c_str(), "53", hints, &result); err != 0) {
        LOG(WARNING) << __func__ << ": getaddrinfo_numeric(" << server
                     << ") = " << gai_strerror(err);
        return false;
    }
    freeaddrinfo(result);
    return true;
}

}  // namespace

int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& servers,
@@ -1574,24 +1593,11 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve

    // Parse the addresses before actually locking or changing any state, in case there is an error.
    // As a side effect this also reduces the time the lock is kept.
    // TODO: find a better way to replace addrinfo*, something like std::vector<SafeAddrinfo>
    addrinfo* nsaddrinfo[MAXNS];
    for (int i = 0; i < numservers; i++) {
        // The addrinfo structures allocated here are freed in free_nameservers_locked().
        const addrinfo hints = {
                .ai_flags = AI_NUMERICHOST,
                .ai_family = AF_UNSPEC,
                .ai_socktype = SOCK_DGRAM,
        };
        const int rt = getaddrinfo_numeric(nameservers[i].c_str(), "53", hints, &nsaddrinfo[i]);
        if (rt != 0) {
            for (int j = 0; j < i; j++) {
                freeaddrinfo(nsaddrinfo[j]);
            }
            LOG(INFO) << __func__ << ": getaddrinfo_numeric(" << nameservers[i]
                      << ") = " << gai_strerror(rt);
            return -EINVAL;
        }
    std::vector<IPSockAddr> ipSockAddrs;
    ipSockAddrs.reserve(nameservers.size());
    for (const auto& server : nameservers) {
        if (!isValidServer(server)) return -EINVAL;
        ipSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53));
    }

    std::lock_guard guard(cache_mutex);
@@ -1607,10 +1613,10 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve
        free_nameservers_locked(cache_info);
        cache_info->nameservers = std::move(nameservers);
        for (int i = 0; i < numservers; i++) {
            cache_info->nsaddrinfo[i] = nsaddrinfo[i];
            LOG(INFO) << __func__ << ": netid = " << netid
                      << ", addr = " << cache_info->nameservers[i];
        }
        cache_info->nameserverSockAddrs = std::move(ipSockAddrs);
        cache_info->nscount = numservers;
    } else {
        if (cache_info->params.max_samples != old_max_samples) {
@@ -1621,23 +1627,15 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve
            // under which servers are considered usable.
            res_cache_clear_stats_locked(cache_info);
        }
        for (int j = 0; j < numservers; j++) {
            freeaddrinfo(nsaddrinfo[j]);
        }
    }

    // Always update the search paths. Cache-flushing however is not necessary,
    // since the stored cache entries do contain the domain, not just the host name.
    cache_info->search_domains = filter_domains(domains);

    std::vector<IPSockAddr> serverSockAddrs;
    serverSockAddrs.reserve(cache_info->nameservers.size());
    for (const auto& server : cache_info->nameservers) {
        serverSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53));
    }

    if (!cache_info->dnsStats->setServers(serverSockAddrs, android::net::PROTO_TCP) ||
        !cache_info->dnsStats->setServers(serverSockAddrs, android::net::PROTO_UDP)) {
    // Setup stats for cleartext dns servers.
    if (!cache_info->dnsStats->setServers(cache_info->nameserverSockAddrs, PROTO_TCP) ||
        !cache_info->dnsStats->setServers(cache_info->nameserverSockAddrs, PROTO_UDP)) {
        LOG(WARNING) << __func__ << ": netid = " << netid << ", failed to set dns stats";
        return -EINVAL;
    }
@@ -1659,45 +1657,39 @@ static bool resolv_is_nameservers_equal(const std::vector<std::string>& oldServe
}

static void free_nameservers_locked(resolv_cache_info* cache_info) {
    int i;
    for (i = 0; i < cache_info->nscount; i++) {
        cache_info->nameservers.clear();
        if (cache_info->nsaddrinfo[i] != nullptr) {
            freeaddrinfo(cache_info->nsaddrinfo[i]);
            cache_info->nsaddrinfo[i] = nullptr;
        }
    }
    cache_info->nscount = 0;
    cache_info->nameservers.clear();
    cache_info->nameserverSockAddrs.clear();
    res_cache_clear_stats_locked(cache_info);
}

void _resolv_populate_res_for_net(res_state statp) {
    if (statp == NULL) {
void resolv_populate_res_for_net(ResState* statp) {
    if (statp == nullptr) {
        return;
    }
    LOG(INFO) << __func__ << ": netid=" << statp->netid;

    std::lock_guard guard(cache_mutex);
    resolv_cache_info* info = find_cache_info_locked(statp->netid);
    if (info != NULL) {
        int nserv;
        struct addrinfo* ai;
        for (nserv = 0; nserv < MAXNS; nserv++) {
            ai = info->nsaddrinfo[nserv];
            if (ai == NULL) {
                break;
            }
    if (info == nullptr) return;

    // TODO: Convert nsaddrs[] to c++ container and remove the size-checking.
    const int serverNum = std::min(MAXNS, static_cast<int>(info->nameserverSockAddrs.size()));

    for (int nserv = 0; nserv < serverNum; nserv++) {
        sockaddr_storage ss = info->nameserverSockAddrs.at(nserv);

            if ((size_t)ai->ai_addrlen <= sizeof(statp->nsaddrs[0])) {
                memcpy(&statp->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen);
        if (auto sockaddr_len = sockaddrSize(ss); sockaddr_len != 0) {
            memcpy(&statp->nsaddrs[nserv], &ss, sockaddr_len);
        } else {
                LOG(INFO) << __func__ << ": found too long addrlen";
            LOG(WARNING) << __func__ << ": can't get sa_len from "
                         << info->nameserverSockAddrs.at(nserv);
        }
    }
        statp->nscount = nserv;

    statp->nscount = serverNum;
    statp->search_domains = info->search_domains;
}
}

/* Resolver reachability statistics. */

@@ -1745,31 +1737,18 @@ int android_net_res_stats_get_info_for_net(unsigned netid, int* nscount,
            return -1;
        }
        int i;
        for (i = 0; i < info->nscount; i++) {
            // Verify that the following assumptions are held, failure indicates corruption:
            //  - getaddrinfo() may never return a sockaddr > sockaddr_storage
            //  - all addresses are valid
            //  - there is only one address per addrinfo thanks to numeric resolution
            int addrlen = info->nsaddrinfo[i]->ai_addrlen;
            if (addrlen < (int) sizeof(struct sockaddr) || addrlen > (int) sizeof(servers[0])) {
                LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_addrlen == " << addrlen;
                errno = EMSGSIZE;
                return -1;
            }
            if (info->nsaddrinfo[i]->ai_addr == NULL) {
                LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_addr == NULL";
                errno = ENOENT;
                return -1;
            }
            if (info->nsaddrinfo[i]->ai_next != NULL) {
                LOG(INFO) << __func__ << ": nsaddrinfo[" << i << "].ai_next != NULL";
                errno = ENOTUNIQ;
        *nscount = info->nscount;

        // It shouldn't happen, but just in case of buffer overflow.
        if (info->nscount != static_cast<int>(info->nameserverSockAddrs.size())) {
            LOG(INFO) << __func__ << ": nscount " << info->nscount
                      << " != " << info->nameserverSockAddrs.size();
            errno = EFAULT;
            return -1;
        }
        }
        *nscount = info->nscount;

        for (i = 0; i < info->nscount; i++) {
            memcpy(&servers[i], info->nsaddrinfo[i]->ai_addr, info->nsaddrinfo[i]->ai_addrlen);
            servers[i] = info->nameserverSockAddrs.at(i);
            stats[i] = info->nsstats[i];
        }

Loading