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