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

Commit 08422a0d authored by Ken Chen's avatar Ken Chen
Browse files

Add a default ON flag for DNS fail-fast feature

This is an emergency stop button if any unexpected regression is
reported.

Bug: 309739930
Test: atest resolv_integration_test
Change-Id: Ib6aa5f619e34e3da33b82586d3e78b4fed5a666b
parent 921db2ae
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -708,6 +708,12 @@ bool isUidNetworkingBlocked(uid_t uid, unsigned netId) {
    // application's UID. Its DNS packets are not subject to certain network restriction features.
    if (resolv_is_enforceDnsUid_enabled_network(netId)) return false;

    // Feature flag that can disable the feature.
    if (!android::net::Experiments::getInstance()->getFlag("fail_fast_on_uid_network_blocking",
                                                           1)) {
        return false;
    }

    return (*ADnsHelper_isUidNetworkingBlocked)(uid, resolv_is_metered_network(netId)) == 1;
}

+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ class Experiments {
            "dot_validation_latency_factor",
            "dot_validation_latency_offset_ms",
            "dot_xport_unusable_threshold",
            "fail_fast_on_uid_network_blocking",
            "keep_listening_udp",
            "max_cache_entries",
            "max_queries_global",
+64 −0
Original line number Diff line number Diff line
@@ -603,6 +603,70 @@ TEST_P(TransportParameterizedTest, BlockDnsQuery) {
    }
}

// Verify whether the DNS fail-fast feature can be turned off by flag.
TEST_P(TransportParameterizedTest, BlockDnsQuery_FlaggedOff) {
    SKIP_IF_BEFORE_T;
    SKIP_IF_DEPENDENT_LIB_DOES_NOT_EXIST(DNS_HELPER);

    constexpr char ptr_name[] = "v4v6.example.com.";
    // PTR record for IPv6 address 2001:db8::102:304
    constexpr char ptr_addr_v6[] =
            "4.0.3.0.2.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.";
    const DnsRecord r = {ptr_addr_v6, ns_type::ns_t_ptr, ptr_name};
    dns.addMapping(r.host_name, r.type, r.addr);
    dot_backend.addMapping(r.host_name, r.type, r.addr);
    doh_backend.addMapping(r.host_name, r.type, r.addr);

    ScopedSystemProperties sp1(kFailFastOnUidNetworkBlockingFlag, "0");
    resetNetwork();

    auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel();
    ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));

    if (testParamHasDoh()) EXPECT_TRUE(WaitForDohValidationSuccess(test::kDefaultListenAddr));
    if (testParamHasDot()) EXPECT_TRUE(WaitForDotValidationSuccess(test::kDefaultListenAddr));

    // This waiting time is expected to avoid that the DoH validation event interferes other tests.
    if (!testParamHasDoh()) waitForDohValidationFailed();

    // Have the test independent of the number of sent queries in private DNS validation, because
    // the DnsResolver can send either 1 or 2 queries in DoT validation.
    if (testParamHasDoh()) {
        doh.clearQueries();
    }
    if (testParamHasDot()) {
        EXPECT_TRUE(dot.waitForQueries(1));
        dot.clearQueries();
    }
    dns.clearQueries();

    for (const bool testDataSaver : {false, true}) {
        SCOPED_TRACE(fmt::format("test {}", testDataSaver ? "data saver" : "UID firewall rules"));
        if (testDataSaver) {
            // Data Saver applies on metered networks only.
            parcel.meteredNetwork = true;
            ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel));

            // Block network access by enabling data saver.
            ScopedSetDataSaverByBPF scopedSetDataSaverByBPF(true);
            ScopedChangeUID scopedChangeUID(TEST_UID);
            EXPECT_NO_FAILURE(sendQueryAndCheckResult());
        } else {
            // Block network access by setting UID firewall rules.
            ScopeBlockedUIDRule scopeBlockUidRule(mDnsClient.netdService(), TEST_UID);
            EXPECT_NO_FAILURE(sendQueryAndCheckResult());
        }

        if (testParamHasDoh()) {
            EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */));
            dot.clearQueries();
        } else {
            EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 2 /* dot */, 0 /* doh */));
            doh.clearQueries();
        }
    }
}

class PrivateDnsDohTest : public BasePrivateDnsTest {
  protected:
    void SetUp() override {
+2 −0
Original line number Diff line number Diff line
@@ -184,6 +184,8 @@ const std::string kDotXportUnusableThresholdFlag(kFlagPrefix + "dot_xport_unusab
const std::string kDotValidationLatencyFactorFlag(kFlagPrefix + "dot_validation_latency_factor");
const std::string kDotValidationLatencyOffsetMsFlag(kFlagPrefix +
                                                    "dot_validation_latency_offset_ms");
const std::string kFailFastOnUidNetworkBlockingFlag(kFlagPrefix +
                                                    "fail_fast_on_uid_network_blocking");
const std::string kKeepListeningUdpFlag(kFlagPrefix + "keep_listening_udp");
const std::string kParallelLookupSleepTimeFlag(kFlagPrefix + "parallel_lookup_sleep_time");
const std::string kRetransIntervalFlag(kFlagPrefix + "retransmission_time_interval");