fuzz: Add FUZZED_SOCKET_FAKE_LATENCY mode to FuzzedSock to allow for fuzzing timeout logic

pull/19203/head
practicalswift 4 years ago
parent b22d4c1607
commit 366e3e1f89

@ -39,7 +39,7 @@ int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
bool fNameLookup = DEFAULT_NAME_LOOKUP; bool fNameLookup = DEFAULT_NAME_LOOKUP;
// Need ample time for negotiation for very slow proxies such as Tor (milliseconds) // Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
static const int SOCKS5_RECV_TIMEOUT = 20 * 1000; int g_socks5_recv_timeout = 20 * 1000;
static std::atomic<bool> interruptSocks5Recv(false); static std::atomic<bool> interruptSocks5Recv(false);
enum Network ParseNetwork(const std::string& net_in) { enum Network ParseNetwork(const std::string& net_in) {
@ -455,7 +455,7 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
return error("Error sending to proxy"); return error("Error sending to proxy");
} }
uint8_t pchRet1[2]; uint8_t pchRet1[2];
if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, sock)) != IntrRecvError::OK) { if ((recvr = InterruptibleRecv(pchRet1, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port); LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
return false; return false;
} }
@ -478,7 +478,7 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
} }
LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
uint8_t pchRetA[2]; uint8_t pchRetA[2];
if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, sock)) != IntrRecvError::OK) { if ((recvr = InterruptibleRecv(pchRetA, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
return error("Error reading proxy authentication response"); return error("Error reading proxy authentication response");
} }
if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) { if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
@ -503,7 +503,7 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
return error("Error sending to proxy"); return error("Error sending to proxy");
} }
uint8_t pchRet2[4]; uint8_t pchRet2[4];
if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, sock)) != IntrRecvError::OK) { if ((recvr = InterruptibleRecv(pchRet2, 4, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
if (recvr == IntrRecvError::Timeout) { if (recvr == IntrRecvError::Timeout) {
/* If a timeout happens here, this effectively means we timed out while connecting /* If a timeout happens here, this effectively means we timed out while connecting
* to the remote node. This is very common for Tor, so do not print an * to the remote node. This is very common for Tor, so do not print an
@ -527,16 +527,16 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
uint8_t pchRet3[256]; uint8_t pchRet3[256];
switch (pchRet2[3]) switch (pchRet2[3])
{ {
case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, sock); break; case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, g_socks5_recv_timeout, sock); break;
case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, sock); break; case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, g_socks5_recv_timeout, sock); break;
case SOCKS5Atyp::DOMAINNAME: case SOCKS5Atyp::DOMAINNAME:
{ {
recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, sock); recvr = InterruptibleRecv(pchRet3, 1, g_socks5_recv_timeout, sock);
if (recvr != IntrRecvError::OK) { if (recvr != IntrRecvError::OK) {
return error("Error reading from proxy"); return error("Error reading from proxy");
} }
int nRecv = pchRet3[0]; int nRecv = pchRet3[0];
recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, sock); recvr = InterruptibleRecv(pchRet3, nRecv, g_socks5_recv_timeout, sock);
break; break;
} }
default: return error("Error: malformed proxy response"); default: return error("Error: malformed proxy response");
@ -544,7 +544,7 @@ bool Socks5(const std::string& strDest, int port, const ProxyCredentials* auth,
if (recvr != IntrRecvError::OK) { if (recvr != IntrRecvError::OK) {
return error("Error reading from proxy"); return error("Error reading from proxy");
} }
if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, sock)) != IntrRecvError::OK) { if ((recvr = InterruptibleRecv(pchRet3, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
return error("Error reading from proxy"); return error("Error reading from proxy");
} }
LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest); LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);

@ -11,9 +11,16 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace {
int default_socks5_recv_timeout;
};
extern int g_socks5_recv_timeout;
void initialize_socks5() void initialize_socks5()
{ {
static const auto testing_setup = MakeNoLogFileContext<const BasicTestingSetup>(); static const auto testing_setup = MakeNoLogFileContext<const BasicTestingSetup>();
default_socks5_recv_timeout = g_socks5_recv_timeout;
} }
FUZZ_TARGET_INIT(socks5, initialize_socks5) FUZZ_TARGET_INIT(socks5, initialize_socks5)
@ -23,6 +30,9 @@ FUZZ_TARGET_INIT(socks5, initialize_socks5)
proxy_credentials.username = fuzzed_data_provider.ConsumeRandomLengthString(512); proxy_credentials.username = fuzzed_data_provider.ConsumeRandomLengthString(512);
proxy_credentials.password = fuzzed_data_provider.ConsumeRandomLengthString(512); proxy_credentials.password = fuzzed_data_provider.ConsumeRandomLengthString(512);
InterruptSocks5(fuzzed_data_provider.ConsumeBool()); InterruptSocks5(fuzzed_data_provider.ConsumeBool());
// Set FUZZED_SOCKET_FAKE_LATENCY=1 to exercise recv timeout code paths. This
// will slow down fuzzing.
g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1 : default_socks5_recv_timeout;
FuzzedSock fuzzed_sock = ConsumeSock(fuzzed_data_provider); FuzzedSock fuzzed_sock = ConsumeSock(fuzzed_data_provider);
// This Socks5(...) fuzzing harness would have caught CVE-2017-18350 within // This Socks5(...) fuzzing harness would have caught CVE-2017-18350 within
// a few seconds of fuzzing. // a few seconds of fuzzing.

@ -642,6 +642,9 @@ public:
} }
return len; return len;
} }
if (m_fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) {
std::this_thread::sleep_for(std::chrono::milliseconds{2});
}
return random_bytes.size(); return random_bytes.size();
} }

Loading…
Cancel
Save