Bug 1636411 - Allow disabling DNS resolution via pref r=dragana,necko-reviewers
authorAlex Catarineu <acat@torproject.org>
Fri, 08 May 2020 13:12:03 +0000
changeset 528843 6bbed9a7eb4b514db53bee202241e1d13e8ae4a2
parent 528842 ab928e23885577b559a6c7f6296cabb9fe70dc09
child 528844 59a45d8c0fbbb218874b8a80b4b4e47c58322a38
push id37397
push usernbeleuzu@mozilla.com
push dateFri, 08 May 2020 21:54:59 +0000
treeherdermozilla-central@5d4199425f57 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana, necko-reviewers
bugs1636411
milestone78.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1636411 - Allow disabling DNS resolution via pref r=dragana,necko-reviewers If `network.dns.disabled=true`, only resolve IP literals or cached entries. Differential Revision: https://phabricator.services.mozilla.com/D74387
modules/libpref/init/StaticPrefList.yaml
netwerk/dns/nsHostResolver.cpp
netwerk/test/unit/test_dns_disabled.js
netwerk/test/unit/xpcshell.ini
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -7704,16 +7704,22 @@
   mirror: always
 
 # Telemetry of traffic categories. Whether or not to enable HttpTrafficAnalyzer.
 - name: network.traffic_analyzer.enabled
   type: RelaxedAtomicBool
   value: true
   mirror: always
 
+# Whether DNS resolution is limited to literals and cached entries.
+- name: network.dns.disabled
+  type: RelaxedAtomicBool
+  value: false
+  mirror: always
+
 - name: network.dns.disablePrefetchFromHTTPS
   type: bool
   value: true
   mirror: always
 
 # Max time to shutdown the resolver threads
 - name: network.dns.resolver_shutdown_timeout_ms
   type: uint32_t
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -990,16 +990,22 @@ nsresult nsHostResolver::ResolveHost(con
              "host [%s].\n",
              IsMediumPriority(flags) ? "medium" : "low", host.get()));
         if (IS_ADDR_TYPE(type)) {
           Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2, METHOD_OVERFLOW);
         }
         // This is a lower priority request and we are swamped, so refuse it.
         rv = NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
 
+        // Check if DNS resolution is disabled.
+      } else if (StaticPrefs::network_dns_disabled()) {
+        LOG(("  DNS resolution disabled: dropping request for host [%s].\n",
+             host.get()));
+        rv = NS_ERROR_UNKNOWN_HOST;
+
         // Check if the offline flag is set.
       } else if (flags & RES_OFFLINE) {
         LOG(("  Offline request for host [%s]; ignoring.\n", host.get()));
         rv = NS_ERROR_OFFLINE;
 
         // We do not have a valid result till here.
         // A/AAAA request can check for an alternative entry like AF_UNSPEC.
         // Otherwise we need to start a new query.
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_dns_disabled.js
@@ -0,0 +1,117 @@
+"use strict";
+
+var dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService);
+var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(
+  Ci.nsIThreadManager
+);
+var mainThread = threadManager.currentThread;
+
+var disabledPref;
+var localdomainPref;
+var prefs = Cc["@mozilla.org/preferences-service;1"].getService(
+  Ci.nsIPrefBranch
+);
+var defaultOriginAttributes = {};
+
+function makeListenerBlock(next) {
+  return {
+    onLookupComplete(inRequest, inRecord, inStatus) {
+      Assert.ok(!Components.isSuccessCode(inStatus));
+      next();
+    },
+    QueryInterface: ChromeUtils.generateQI(["nsIDNSListener"]),
+  };
+}
+
+function makeListenerDontBlock(next, expectedAnswer) {
+  return {
+    onLookupComplete(inRequest, inRecord, inStatus) {
+      var answer = inRecord.getNextAddrAsString();
+      if (expectedAnswer) {
+        Assert.equal(answer, expectedAnswer);
+      } else {
+        Assert.ok(answer == "127.0.0.1" || answer == "::1");
+      }
+      next();
+    },
+    QueryInterface: ChromeUtils.generateQI(["nsIDNSListener"]),
+  };
+}
+
+function do_test({
+  dnsDisabled,
+  mustBlock,
+  testDomain,
+  nextCallback,
+  expectedAnswer,
+}) {
+  prefs.setBoolPref("network.dns.disabled", dnsDisabled);
+  try {
+    dns.asyncResolve(
+      testDomain,
+      0,
+      mustBlock
+        ? makeListenerBlock(nextCallback)
+        : makeListenerDontBlock(nextCallback, expectedAnswer),
+      mainThread,
+      defaultOriginAttributes
+    );
+  } catch (e) {
+    Assert.ok(mustBlock === true);
+    nextCallback();
+  }
+}
+
+function all_done() {
+  // Reset locally modified prefs
+  prefs.setCharPref("network.dns.localDomains", localdomainPref);
+  prefs.setBoolPref("network.dns.disabled", disabledPref);
+  do_test_finished();
+}
+
+// Cached hostnames should be resolved even if dns is disabled
+function testCached() {
+  do_test({
+    dnsDisabled: true,
+    mustBlock: false,
+    testDomain: "foo.bar",
+    nextCallback: all_done,
+  });
+}
+
+function testNotBlocked() {
+  do_test({
+    dnsDisabled: false,
+    mustBlock: false,
+    testDomain: "foo.bar",
+    nextCallback: testCached,
+  });
+}
+
+function testBlocked() {
+  do_test({
+    dnsDisabled: true,
+    mustBlock: true,
+    testDomain: "foo.bar",
+    nextCallback: testNotBlocked,
+  });
+}
+
+// IP literals should be resolved even if dns is disabled
+function testIPLiteral() {
+  do_test({
+    dnsDisabled: true,
+    mustBlock: false,
+    testDomain: "0x01010101",
+    nextCallback: testBlocked,
+    expectedAnswer: "1.1.1.1",
+  });
+}
+
+function run_test() {
+  do_test_pending();
+  disabledPref = prefs.getBoolPref("network.dns.disabled");
+  localdomainPref = prefs.getCharPref("network.dns.localDomains");
+  prefs.setCharPref("network.dns.localDomains", "foo.bar");
+  testIPLiteral();
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -198,16 +198,17 @@ skip-if = true # Bug 863738
 [test_dns_cancel.js]
 [test_data_protocol.js]
 [test_dns_service.js]
 [test_dns_offline.js]
 [test_dns_onion.js]
 [test_dns_originAttributes.js]
 [test_dns_localredirect.js]
 [test_dns_proxy_bypass.js]
+[test_dns_disabled.js]
 [test_domain_eviction.js]
 [test_duplicate_headers.js]
 [test_chunked_responses.js]
 [test_content_length_underrun.js]
 [test_event_sink.js]
 [test_eviction.js]
 [test_extract_charset_from_content_type.js]
 [test_fallback_no-cache-entry_canceled.js]