connman.cpp
1 // Copyright (c) 2020-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <addrman.h> 6 #include <chainparams.h> 7 #include <common/args.h> 8 #include <net.h> 9 #include <net_processing.h> 10 #include <netaddress.h> 11 #include <protocol.h> 12 #include <test/fuzz/FuzzedDataProvider.h> 13 #include <test/fuzz/fuzz.h> 14 #include <test/fuzz/util.h> 15 #include <test/fuzz/util/net.h> 16 #include <test/fuzz/util/threadinterrupt.h> 17 #include <test/util/setup_common.h> 18 #include <util/translation.h> 19 20 #include <cstdint> 21 #include <vector> 22 23 namespace { 24 const TestingSetup* g_setup; 25 26 int32_t GetCheckRatio() 27 { 28 return std::clamp<int32_t>(g_setup->m_node.args->GetIntArg("-checkaddrman", 0), 0, 1000000); 29 } 30 31 } // namespace 32 33 void initialize_connman() 34 { 35 static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); 36 g_setup = testing_setup.get(); 37 } 38 39 FUZZ_TARGET(connman, .init = initialize_connman) 40 { 41 SeedRandomStateForTest(SeedRand::ZEROS); 42 FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; 43 SetMockTime(ConsumeTime(fuzzed_data_provider)); 44 auto netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)}; 45 auto addr_man_ptr{std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio())}; 46 if (fuzzed_data_provider.ConsumeBool()) { 47 const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)}; 48 DataStream ds{serialized_data}; 49 try { 50 ds >> *addr_man_ptr; 51 } catch (const std::ios_base::failure&) { 52 addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio()); 53 } 54 } 55 AddrManDeterministic& addr_man{*addr_man_ptr}; 56 auto net_events{ConsumeNetEvents(fuzzed_data_provider)}; 57 58 // Mock CreateSock() to create FuzzedSock. 59 auto CreateSockOrig = CreateSock; 60 CreateSock = [&fuzzed_data_provider](int, int, int) { 61 return std::make_unique<FuzzedSock>(fuzzed_data_provider); 62 }; 63 64 // Mock g_dns_lookup() to return a fuzzed address. 65 auto g_dns_lookup_orig = g_dns_lookup; 66 g_dns_lookup = [&fuzzed_data_provider](const std::string&, bool) { 67 return std::vector<CNetAddr>{ConsumeNetAddr(fuzzed_data_provider)}; 68 }; 69 70 ConnmanTestMsg connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), 71 fuzzed_data_provider.ConsumeIntegral<uint64_t>(), 72 addr_man, 73 netgroupman, 74 Params(), 75 fuzzed_data_provider.ConsumeBool(), 76 ConsumeThreadInterrupt(fuzzed_data_provider)}; 77 78 const uint64_t max_outbound_limit{fuzzed_data_provider.ConsumeIntegral<uint64_t>()}; 79 CConnman::Options options; 80 options.m_msgproc = &net_events; 81 options.nMaxOutboundLimit = max_outbound_limit; 82 connman.Init(options); 83 84 CNetAddr random_netaddr; 85 CAddress random_address; 86 CNode random_node = ConsumeNode(fuzzed_data_provider); 87 CSubNet random_subnet; 88 std::string random_string; 89 90 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) { 91 CNode& p2p_node{*ConsumeNodeAsUniquePtr(fuzzed_data_provider).release()}; 92 connman.AddTestNode(p2p_node); 93 } 94 95 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) { 96 CallOneOf( 97 fuzzed_data_provider, 98 [&] { 99 random_netaddr = ConsumeNetAddr(fuzzed_data_provider); 100 }, 101 [&] { 102 random_address = ConsumeAddress(fuzzed_data_provider); 103 }, 104 [&] { 105 random_subnet = ConsumeSubNet(fuzzed_data_provider); 106 }, 107 [&] { 108 random_string = fuzzed_data_provider.ConsumeRandomLengthString(64); 109 }, 110 [&] { 111 connman.AddNode({random_string, fuzzed_data_provider.ConsumeBool()}); 112 }, 113 [&] { 114 connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); 115 }, 116 [&] { 117 connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>()); 118 }, 119 [&] { 120 connman.DisconnectNode(random_netaddr); 121 }, 122 [&] { 123 connman.DisconnectNode(random_string); 124 }, 125 [&] { 126 connman.DisconnectNode(random_subnet); 127 }, 128 [&] { 129 connman.ForEachNode([](auto) {}); 130 }, 131 [&] { 132 (void)connman.ForNode(fuzzed_data_provider.ConsumeIntegral<NodeId>(), [&](auto) { return fuzzed_data_provider.ConsumeBool(); }); 133 }, 134 [&] { 135 auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>(); 136 auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100); 137 auto filtered = fuzzed_data_provider.ConsumeBool(); 138 (void)connman.GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt, filtered); 139 }, 140 [&] { 141 auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>(); 142 auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100); 143 (void)connman.GetAddresses(/*requestor=*/random_node, max_addresses, max_pct); 144 }, 145 [&] { 146 (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); 147 }, 148 [&] { 149 (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({ConnectionDirection::None, ConnectionDirection::In, ConnectionDirection::Out, ConnectionDirection::Both})); 150 }, 151 [&] { 152 (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool()); 153 }, 154 [&] { 155 CSerializedNetMsg serialized_net_msg; 156 serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::MESSAGE_TYPE_SIZE); 157 serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider); 158 connman.PushMessage(&random_node, std::move(serialized_net_msg)); 159 }, 160 [&] { 161 connman.RemoveAddedNode(random_string); 162 }, 163 [&] { 164 connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool()); 165 }, 166 [&] { 167 connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool()); 168 }, 169 [&] { 170 ConnectionType conn_type{ 171 fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES)}; 172 if (conn_type == ConnectionType::INBOUND) { // INBOUND is not allowed 173 conn_type = ConnectionType::OUTBOUND_FULL_RELAY; 174 } 175 176 connman.OpenNetworkConnection( 177 /*addrConnect=*/random_address, 178 /*fCountFailure=*/fuzzed_data_provider.ConsumeBool(), 179 /*grant_outbound=*/{}, 180 /*pszDest=*/fuzzed_data_provider.ConsumeBool() ? nullptr : random_string.c_str(), 181 /*conn_type=*/conn_type, 182 /*use_v2transport=*/fuzzed_data_provider.ConsumeBool()); 183 }, 184 [&] { 185 connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool()); 186 const auto peer = ConsumeAddress(fuzzed_data_provider); 187 connman.CreateNodeFromAcceptedSocketPublic( 188 /*sock=*/CreateSock(AF_INET, SOCK_STREAM, IPPROTO_TCP), 189 /*permissions=*/ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS), 190 /*addr_bind=*/ConsumeAddress(fuzzed_data_provider), 191 /*addr_peer=*/peer); 192 }, 193 [&] { 194 CConnman::Options options; 195 196 options.vBinds = ConsumeServiceVector(fuzzed_data_provider); 197 198 options.vWhiteBinds = std::vector<NetWhitebindPermissions>{ 199 fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 5)}; 200 for (auto& wb : options.vWhiteBinds) { 201 wb.m_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS); 202 wb.m_service = ConsumeService(fuzzed_data_provider); 203 } 204 205 options.onion_binds = ConsumeServiceVector(fuzzed_data_provider); 206 207 options.bind_on_any = options.vBinds.empty() && options.vWhiteBinds.empty() && 208 options.onion_binds.empty(); 209 210 connman.InitBindsPublic(options); 211 }, 212 [&] { 213 connman.SocketHandlerPublic(); 214 }); 215 } 216 (void)connman.GetAddedNodeInfo(fuzzed_data_provider.ConsumeBool()); 217 (void)connman.GetExtraFullOutboundCount(); 218 (void)connman.GetLocalServices(); 219 assert(connman.GetMaxOutboundTarget() == max_outbound_limit); 220 (void)connman.GetMaxOutboundTimeframe(); 221 (void)connman.GetMaxOutboundTimeLeftInCycle(); 222 (void)connman.GetNetworkActive(); 223 std::vector<CNodeStats> stats; 224 connman.GetNodeStats(stats); 225 (void)connman.GetOutboundTargetBytesLeft(); 226 (void)connman.GetTotalBytesRecv(); 227 (void)connman.GetTotalBytesSent(); 228 (void)connman.GetTryNewOutboundPeer(); 229 (void)connman.GetUseAddrmanOutgoing(); 230 (void)connman.ASMapHealthCheck(); 231 232 connman.ClearTestNodes(); 233 g_dns_lookup = g_dns_lookup_orig; 234 CreateSock = CreateSockOrig; 235 }