fuzzed_host_resolver_util.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/dns/fuzzed_host_resolver_util.h"
  5. #include <stdint.h>
  6. #include <fuzzer/FuzzedDataProvider.h>
  7. #include <algorithm>
  8. #include <limits>
  9. #include <memory>
  10. #include <string>
  11. #include <utility>
  12. #include <vector>
  13. #include "base/bind.h"
  14. #include "base/check.h"
  15. #include "base/memory/ref_counted.h"
  16. #include "base/memory/weak_ptr.h"
  17. #include "base/notreached.h"
  18. #include "base/task/single_thread_task_runner.h"
  19. #include "base/threading/thread_task_runner_handle.h"
  20. #include "net/base/address_list.h"
  21. #include "net/base/completion_once_callback.h"
  22. #include "net/base/io_buffer.h"
  23. #include "net/base/ip_address.h"
  24. #include "net/base/ip_endpoint.h"
  25. #include "net/base/net_errors.h"
  26. #include "net/dns/context_host_resolver.h"
  27. #include "net/dns/dns_client.h"
  28. #include "net/dns/dns_config.h"
  29. #include "net/dns/dns_hosts.h"
  30. #include "net/dns/host_cache.h"
  31. #include "net/dns/host_resolver_manager.h"
  32. #include "net/dns/host_resolver_proc.h"
  33. #include "net/dns/mdns_client.h"
  34. #include "net/dns/public/util.h"
  35. #include "net/dns/resolve_context.h"
  36. #include "net/log/net_log.h"
  37. #include "net/log/net_log_with_source.h"
  38. #include "net/socket/datagram_server_socket.h"
  39. #include "net/socket/fuzzed_socket_factory.h"
  40. namespace net {
  41. namespace {
  42. // Returns a fuzzed non-zero port number.
  43. uint16_t FuzzPort(FuzzedDataProvider* data_provider) {
  44. return data_provider->ConsumeIntegral<uint16_t>();
  45. }
  46. // Returns a fuzzed IPv4 address. Can return invalid / reserved addresses.
  47. IPAddress FuzzIPv4Address(FuzzedDataProvider* data_provider) {
  48. return IPAddress(data_provider->ConsumeIntegral<uint8_t>(),
  49. data_provider->ConsumeIntegral<uint8_t>(),
  50. data_provider->ConsumeIntegral<uint8_t>(),
  51. data_provider->ConsumeIntegral<uint8_t>());
  52. }
  53. // Returns a fuzzed IPv6 address. Can return invalid / reserved addresses.
  54. IPAddress FuzzIPv6Address(FuzzedDataProvider* data_provider) {
  55. return IPAddress(data_provider->ConsumeIntegral<uint8_t>(),
  56. data_provider->ConsumeIntegral<uint8_t>(),
  57. data_provider->ConsumeIntegral<uint8_t>(),
  58. data_provider->ConsumeIntegral<uint8_t>(),
  59. data_provider->ConsumeIntegral<uint8_t>(),
  60. data_provider->ConsumeIntegral<uint8_t>(),
  61. data_provider->ConsumeIntegral<uint8_t>(),
  62. data_provider->ConsumeIntegral<uint8_t>(),
  63. data_provider->ConsumeIntegral<uint8_t>(),
  64. data_provider->ConsumeIntegral<uint8_t>(),
  65. data_provider->ConsumeIntegral<uint8_t>(),
  66. data_provider->ConsumeIntegral<uint8_t>(),
  67. data_provider->ConsumeIntegral<uint8_t>(),
  68. data_provider->ConsumeIntegral<uint8_t>(),
  69. data_provider->ConsumeIntegral<uint8_t>(),
  70. data_provider->ConsumeIntegral<uint8_t>());
  71. }
  72. // Returns a fuzzed address, which can be either IPv4 or IPv6. Can return
  73. // invalid / reserved addresses.
  74. IPAddress FuzzIPAddress(FuzzedDataProvider* data_provider) {
  75. if (data_provider->ConsumeBool())
  76. return FuzzIPv4Address(data_provider);
  77. return FuzzIPv6Address(data_provider);
  78. }
  79. DnsConfig GetFuzzedDnsConfig(FuzzedDataProvider* data_provider) {
  80. // Fuzz DNS configuration.
  81. DnsConfig config;
  82. // Fuzz name servers.
  83. uint32_t num_nameservers = data_provider->ConsumeIntegralInRange(0, 4);
  84. for (uint32_t i = 0; i < num_nameservers; ++i) {
  85. config.nameservers.push_back(
  86. IPEndPoint(FuzzIPAddress(data_provider), FuzzPort(data_provider)));
  87. }
  88. // Fuzz suffix search list.
  89. switch (data_provider->ConsumeIntegralInRange(0, 3)) {
  90. case 3:
  91. config.search.push_back("foo.com");
  92. [[fallthrough]];
  93. case 2:
  94. config.search.push_back("bar");
  95. [[fallthrough]];
  96. case 1:
  97. config.search.push_back("com");
  98. [[fallthrough]];
  99. default:
  100. break;
  101. }
  102. net::DnsHosts hosts;
  103. // Fuzz hosts file.
  104. uint8_t num_hosts_entries = data_provider->ConsumeIntegral<uint8_t>();
  105. for (uint8_t i = 0; i < num_hosts_entries; ++i) {
  106. const char* kHostnames[] = {"foo", "foo.com", "a.foo.com",
  107. "bar", "localhost", "localhost6"};
  108. const char* hostname = data_provider->PickValueInArray(kHostnames);
  109. net::IPAddress address = FuzzIPAddress(data_provider);
  110. config.hosts[net::DnsHostsKey(hostname, net::GetAddressFamily(address))] =
  111. address;
  112. }
  113. config.unhandled_options = data_provider->ConsumeBool();
  114. config.append_to_multi_label_name = data_provider->ConsumeBool();
  115. config.ndots = data_provider->ConsumeIntegralInRange(0, 3);
  116. config.attempts = data_provider->ConsumeIntegralInRange(1, 3);
  117. // Fallback periods don't really work for fuzzing. Even a period of 0
  118. // milliseconds will be increased after the first expiration, resulting in
  119. // inconsistent behavior.
  120. config.fallback_period = base::Days(10);
  121. config.rotate = data_provider->ConsumeBool();
  122. config.use_local_ipv6 = data_provider->ConsumeBool();
  123. return config;
  124. }
  125. // HostResolverProc that returns a random set of results, and can succeed or
  126. // fail. Must only be run on the thread it's created on.
  127. class FuzzedHostResolverProc : public HostResolverProc {
  128. public:
  129. // Can safely be used after the destruction of |data_provider|. This can
  130. // happen if a request is issued but the code never waits for the result
  131. // before the test ends.
  132. explicit FuzzedHostResolverProc(
  133. base::WeakPtr<FuzzedDataProvider> data_provider)
  134. : HostResolverProc(nullptr),
  135. data_provider_(data_provider),
  136. network_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
  137. FuzzedHostResolverProc(const FuzzedHostResolverProc&) = delete;
  138. FuzzedHostResolverProc& operator=(const FuzzedHostResolverProc&) = delete;
  139. int Resolve(const std::string& host,
  140. AddressFamily address_family,
  141. HostResolverFlags host_resolver_flags,
  142. AddressList* addrlist,
  143. int* os_error) override {
  144. DCHECK(network_task_runner_->BelongsToCurrentThread());
  145. if (os_error)
  146. *os_error = 0;
  147. // If the data provider is no longer avaiable, just fail. The HostResolver
  148. // has already been deleted by this point, anyways.
  149. if (!data_provider_)
  150. return ERR_FAILED;
  151. AddressList result;
  152. // Put IPv6 addresses before IPv4 ones. This code doesn't sort addresses
  153. // correctly, but when sorted according to spec, IPv6 addresses are
  154. // generally before IPv4 ones.
  155. if (address_family == ADDRESS_FAMILY_UNSPECIFIED ||
  156. address_family == ADDRESS_FAMILY_IPV6) {
  157. uint8_t num_ipv6_addresses = data_provider_->ConsumeIntegral<uint8_t>();
  158. for (uint8_t i = 0; i < num_ipv6_addresses; ++i) {
  159. result.push_back(
  160. net::IPEndPoint(FuzzIPv6Address(data_provider_.get()), 0));
  161. }
  162. }
  163. if (address_family == ADDRESS_FAMILY_UNSPECIFIED ||
  164. address_family == ADDRESS_FAMILY_IPV4) {
  165. uint8_t num_ipv4_addresses = data_provider_->ConsumeIntegral<uint8_t>();
  166. for (uint8_t i = 0; i < num_ipv4_addresses; ++i) {
  167. result.push_back(
  168. net::IPEndPoint(FuzzIPv4Address(data_provider_.get()), 0));
  169. }
  170. }
  171. if (result.empty())
  172. return ERR_NAME_NOT_RESOLVED;
  173. if (host_resolver_flags & HOST_RESOLVER_CANONNAME) {
  174. // Don't bother to fuzz this - almost nothing cares.
  175. std::vector<std::string> aliases({"foo.com"});
  176. result.SetDnsAliases(std::move(aliases));
  177. }
  178. *addrlist = result;
  179. return OK;
  180. }
  181. private:
  182. ~FuzzedHostResolverProc() override = default;
  183. base::WeakPtr<FuzzedDataProvider> data_provider_;
  184. // Just used for thread-safety checks.
  185. scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
  186. };
  187. const Error kMdnsErrors[] = {ERR_FAILED,
  188. ERR_ACCESS_DENIED,
  189. ERR_INTERNET_DISCONNECTED,
  190. ERR_TIMED_OUT,
  191. ERR_CONNECTION_RESET,
  192. ERR_CONNECTION_ABORTED,
  193. ERR_CONNECTION_REFUSED,
  194. ERR_ADDRESS_UNREACHABLE};
  195. // Fuzzed socket implementation to handle the limited functionality used by
  196. // MDnsClientImpl. Uses a FuzzedDataProvider to generate errors or responses for
  197. // RecvFrom calls.
  198. class FuzzedMdnsSocket : public DatagramServerSocket {
  199. public:
  200. explicit FuzzedMdnsSocket(FuzzedDataProvider* data_provider)
  201. : data_provider_(data_provider),
  202. local_address_(FuzzIPAddress(data_provider_), 5353) {}
  203. int Listen(const IPEndPoint& address) override { return OK; }
  204. int RecvFrom(IOBuffer* buffer,
  205. int buffer_length,
  206. IPEndPoint* out_address,
  207. CompletionOnceCallback callback) override {
  208. if (data_provider_->ConsumeBool())
  209. return GenerateResponse(buffer, buffer_length, out_address);
  210. // Maybe never receive any responses.
  211. if (data_provider_->ConsumeBool()) {
  212. base::ThreadTaskRunnerHandle::Get()->PostTask(
  213. FROM_HERE,
  214. base::BindOnce(&FuzzedMdnsSocket::CompleteRecv,
  215. weak_factory_.GetWeakPtr(), std::move(callback),
  216. base::RetainedRef(buffer), buffer_length,
  217. out_address));
  218. }
  219. return ERR_IO_PENDING;
  220. }
  221. int SendTo(IOBuffer* buf,
  222. int buf_len,
  223. const IPEndPoint& address,
  224. CompletionOnceCallback callback) override {
  225. if (data_provider_->ConsumeBool()) {
  226. return data_provider_->ConsumeBool()
  227. ? OK
  228. : data_provider_->PickValueInArray(kMdnsErrors);
  229. }
  230. base::ThreadTaskRunnerHandle::Get()->PostTask(
  231. FROM_HERE,
  232. base::BindOnce(&FuzzedMdnsSocket::CompleteSend,
  233. weak_factory_.GetWeakPtr(), std::move(callback)));
  234. return ERR_IO_PENDING;
  235. }
  236. int SetReceiveBufferSize(int32_t size) override { return OK; }
  237. int SetSendBufferSize(int32_t size) override { return OK; }
  238. void AllowAddressReuse() override {}
  239. void AllowBroadcast() override {}
  240. void AllowAddressSharingForMulticast() override {}
  241. int JoinGroup(const IPAddress& group_address) const override { return OK; }
  242. int LeaveGroup(const IPAddress& group_address) const override { return OK; }
  243. int SetMulticastInterface(uint32_t interface_index) override { return OK; }
  244. int SetMulticastTimeToLive(int time_to_live) override { return OK; }
  245. int SetMulticastLoopbackMode(bool loopback) override { return OK; }
  246. int SetDiffServCodePoint(DiffServCodePoint dscp) override { return OK; }
  247. void DetachFromThread() override {}
  248. void Close() override {}
  249. int GetPeerAddress(IPEndPoint* address) const override {
  250. return ERR_SOCKET_NOT_CONNECTED;
  251. }
  252. int GetLocalAddress(IPEndPoint* address) const override {
  253. *address = local_address_;
  254. return OK;
  255. }
  256. void UseNonBlockingIO() override {}
  257. int SetDoNotFragment() override { return OK; }
  258. void SetMsgConfirm(bool confirm) override {}
  259. const NetLogWithSource& NetLog() const override { return net_log_; }
  260. private:
  261. void CompleteRecv(CompletionOnceCallback callback,
  262. IOBuffer* buffer,
  263. int buffer_length,
  264. IPEndPoint* out_address) {
  265. int rv = GenerateResponse(buffer, buffer_length, out_address);
  266. std::move(callback).Run(rv);
  267. }
  268. int GenerateResponse(IOBuffer* buffer,
  269. int buffer_length,
  270. IPEndPoint* out_address) {
  271. if (data_provider_->ConsumeBool()) {
  272. std::string data =
  273. data_provider_->ConsumeRandomLengthString(buffer_length);
  274. std::copy(data.begin(), data.end(), buffer->data());
  275. *out_address =
  276. IPEndPoint(FuzzIPAddress(data_provider_), FuzzPort(data_provider_));
  277. return data.size();
  278. }
  279. return data_provider_->PickValueInArray(kMdnsErrors);
  280. }
  281. void CompleteSend(CompletionOnceCallback callback) {
  282. if (data_provider_->ConsumeBool())
  283. std::move(callback).Run(OK);
  284. else
  285. std::move(callback).Run(data_provider_->PickValueInArray(kMdnsErrors));
  286. }
  287. FuzzedDataProvider* const data_provider_;
  288. const IPEndPoint local_address_;
  289. const NetLogWithSource net_log_;
  290. base::WeakPtrFactory<FuzzedMdnsSocket> weak_factory_{this};
  291. };
  292. class FuzzedMdnsSocketFactory : public MDnsSocketFactory {
  293. public:
  294. explicit FuzzedMdnsSocketFactory(FuzzedDataProvider* data_provider)
  295. : data_provider_(data_provider) {}
  296. void CreateSockets(
  297. std::vector<std::unique_ptr<DatagramServerSocket>>* sockets) override {
  298. int num_sockets = data_provider_->ConsumeIntegralInRange(1, 4);
  299. for (int i = 0; i < num_sockets; ++i)
  300. sockets->push_back(std::make_unique<FuzzedMdnsSocket>(data_provider_));
  301. }
  302. private:
  303. FuzzedDataProvider* const data_provider_;
  304. };
  305. class FuzzedHostResolverManager : public HostResolverManager {
  306. public:
  307. // |data_provider| and |net_log| must outlive the FuzzedHostResolver.
  308. // TODO(crbug.com/971411): Fuzz system DNS config changes through a non-null
  309. // SystemDnsConfigChangeNotifier.
  310. FuzzedHostResolverManager(const HostResolver::ManagerOptions& options,
  311. NetLog* net_log,
  312. FuzzedDataProvider* data_provider)
  313. : HostResolverManager(options,
  314. nullptr /* system_dns_config_notifier */,
  315. net_log),
  316. data_provider_(data_provider),
  317. is_ipv6_reachable_(data_provider->ConsumeBool()),
  318. socket_factory_(data_provider_),
  319. net_log_(net_log),
  320. data_provider_weak_factory_(data_provider) {
  321. ProcTaskParams proc_task_params(
  322. base::MakeRefCounted<FuzzedHostResolverProc>(
  323. data_provider_weak_factory_.GetWeakPtr()),
  324. // Retries are only used when the original request hangs, which this
  325. // class currently can't simulate.
  326. 0 /* max_retry_attempts */);
  327. set_proc_params_for_test(proc_task_params);
  328. SetTaskRunnerForTesting(base::SequencedTaskRunnerHandle::Get());
  329. SetMdnsSocketFactoryForTesting(
  330. std::make_unique<FuzzedMdnsSocketFactory>(data_provider_));
  331. std::unique_ptr<DnsClient> dns_client = DnsClient::CreateClientForTesting(
  332. net_log_, base::BindRepeating(
  333. &FuzzedDataProvider::ConsumeIntegralInRange<int32_t>,
  334. base::Unretained(data_provider_)));
  335. dns_client->SetSystemConfig(GetFuzzedDnsConfig(data_provider_));
  336. HostResolverManager::SetDnsClientForTesting(std::move(dns_client));
  337. }
  338. FuzzedHostResolverManager(const FuzzedHostResolverManager&) = delete;
  339. FuzzedHostResolverManager& operator=(const FuzzedHostResolverManager&) =
  340. delete;
  341. ~FuzzedHostResolverManager() override = default;
  342. void SetDnsClientForTesting(std::unique_ptr<DnsClient> dns_client) {
  343. // The only DnsClient that is supported is the one created by the
  344. // FuzzedHostResolverManager since that DnsClient contains the necessary
  345. // fuzzing logic.
  346. NOTREACHED();
  347. }
  348. private:
  349. // HostResolverManager implementation:
  350. bool IsGloballyReachable(const IPAddress& dest,
  351. const NetLogWithSource& net_log) override {
  352. return is_ipv6_reachable_;
  353. }
  354. void RunLoopbackProbeJob() override {
  355. SetHaveOnlyLoopbackAddresses(data_provider_->ConsumeBool());
  356. }
  357. FuzzedDataProvider* const data_provider_;
  358. // Fixed value to be returned by IsIPv6Reachable.
  359. const bool is_ipv6_reachable_;
  360. // Used for UDP and TCP sockets if the async resolver is enabled.
  361. FuzzedSocketFactory socket_factory_;
  362. NetLog* const net_log_;
  363. base::WeakPtrFactory<FuzzedDataProvider> data_provider_weak_factory_;
  364. };
  365. } // namespace
  366. std::unique_ptr<ContextHostResolver> CreateFuzzedContextHostResolver(
  367. const HostResolver::ManagerOptions& options,
  368. NetLog* net_log,
  369. FuzzedDataProvider* data_provider,
  370. bool enable_caching) {
  371. auto manager = std::make_unique<FuzzedHostResolverManager>(options, net_log,
  372. data_provider);
  373. auto resolve_context = std::make_unique<ResolveContext>(
  374. nullptr /* url_request_context */, enable_caching);
  375. return std::make_unique<ContextHostResolver>(std::move(manager),
  376. std::move(resolve_context));
  377. }
  378. } // namespace net