From 8ec6d68a35ec801055eec7bed50981d122744ac0 Mon Sep 17 00:00:00 2001 From: iphydf Date: Sun, 10 Apr 2022 19:29:09 +0000 Subject: [PATCH] test: Enable fuzzing for TCP. If the `recvbuf` network function returns 0 all the time, that means there is never any data available on the TCP socket. This change makes it so there is a random amount of data available on the TCP socket. This invalidates the bootstrap fuzzer corpus. --- .github/workflows/ci.yml | 3 ++ .../docker/tox-bootstrapd.sha256 | 2 +- other/proxy/go.mod | 5 +++ other/proxy/go.sum | 14 +++++++ testing/fuzzing/bootstrap_harness.cc | 38 ++++++++++++++----- testing/fuzzing/fuzz_support.cc | 18 +++++---- toxcore/TCP_client.c | 24 ++++++++---- toxcore/network.c | 2 +- 8 files changed, 80 insertions(+), 26 deletions(-) create mode 100644 other/proxy/go.mod create mode 100644 other/proxy/go.sum diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fa4792e2a4..372ae721270 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,6 +122,9 @@ jobs: - uses: actions/checkout@v2 with: submodules: recursive + - uses: actions/setup-go@v3 + with: + go-version: "1.16.15" - name: Build, test, and upload coverage run: .github/scripts/coverage-linux diff --git a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 index 396bc2c29ea..4eb883f2dfd 100644 --- a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 +++ b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 @@ -1 +1 @@ -f20ba5a6917e5faee9a2a6439b448d3ced7cd177ba666ff1804882f494ea7b90 /usr/local/bin/tox-bootstrapd +4302ebfb454cfd087a919ac41ea513e04a9cdddfd9518c9c1959058bc244c06f /usr/local/bin/tox-bootstrapd diff --git a/other/proxy/go.mod b/other/proxy/go.mod new file mode 100644 index 00000000000..1f7b3964c41 --- /dev/null +++ b/other/proxy/go.mod @@ -0,0 +1,5 @@ +module github.com/TokTok/c-toxcore/other/proxy + +go 1.16 + +require github.com/things-go/go-socks5 v0.0.2 diff --git a/other/proxy/go.sum b/other/proxy/go.sum new file mode 100644 index 00000000000..35434d40cd0 --- /dev/null +++ b/other/proxy/go.sum @@ -0,0 +1,14 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/things-go/go-socks5 v0.0.2 h1:dFi5iZ/LqgHRTQ6n3XlipTLDWHAQsejvJ300bH2VFWo= +github.com/things-go/go-socks5 v0.0.2/go.mod h1:dhnDTBbIg31cbJdROP4/Zz6Iw7JPEpiMvOl2LdHSSjE= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/testing/fuzzing/bootstrap_harness.cc b/testing/fuzzing/bootstrap_harness.cc index 7564c0d46b7..b315eaed81b 100644 --- a/testing/fuzzing/bootstrap_harness.cc +++ b/testing/fuzzing/bootstrap_harness.cc @@ -108,13 +108,8 @@ void setup_callbacks(Tox_Dispatch *dispatch) }); } -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +void TestBootstrap(Fuzz_Data &input) { - Fuzz_Data input{data, size}; - Fuzz_System sys(input); assert(sys.rng != nullptr); @@ -122,6 +117,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) assert(opts != nullptr); tox_options_set_operating_system(opts, sys.sys.get()); + CONSUME1_OR_RETURN(const uint8_t proxy_type, input); + if (proxy_type == 0) { + tox_options_set_proxy_type(opts, TOX_PROXY_TYPE_NONE); + } else if (proxy_type == 1) { + tox_options_set_proxy_type(opts, TOX_PROXY_TYPE_SOCKS5); + tox_options_set_proxy_host(opts, "127.0.0.1"); + tox_options_set_proxy_port(opts, 8080); + } else if (proxy_type == 2) { + tox_options_set_proxy_type(opts, TOX_PROXY_TYPE_HTTP); + tox_options_set_proxy_host(opts, "127.0.0.1"); + tox_options_set_proxy_port(opts, 8080); + } + Tox_Err_New error_new; Tox *tox = tox_new(opts, &error_new); tox_options_free(opts); @@ -129,15 +137,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (tox == nullptr) { // It might fail, because some I/O happens in tox_new, and the fuzzer // might do things that make that I/O fail. - return 0; + return; } assert(error_new == TOX_ERR_NEW_OK); uint8_t pub_key[TOX_PUBLIC_KEY_SIZE] = {0}; - const bool success = tox_bootstrap(tox, "127.0.0.1", 12345, pub_key, nullptr); - assert(success); + const bool udp_success = tox_bootstrap(tox, "127.0.0.1", 12345, pub_key, nullptr); + assert(udp_success); + + const bool tcp_success = tox_add_tcp_relay(tox, "127.0.0.1", 12345, pub_key, nullptr); + assert(tcp_success); tox_events_init(tox); @@ -158,5 +169,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) tox_dispatch_free(dispatch); tox_kill(tox); +} + +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + Fuzz_Data input{data, size}; + TestBootstrap(input); return 0; // Non-zero return values are reserved for future use. } diff --git a/testing/fuzzing/fuzz_support.cc b/testing/fuzzing/fuzz_support.cc index b34921353c7..a96ccd5b382 100644 --- a/testing/fuzzing/fuzz_support.cc +++ b/testing/fuzzing/fuzz_support.cc @@ -47,10 +47,9 @@ static constexpr Network_Funcs fuzz_network_funcs = { /* .bind = */ [](void *obj, int sock, const Network_Addr *addr) { return 0; }, /* .listen = */ [](void *obj, int sock, int backlog) { return 0; }, /* .recvbuf = */ - [](void *obj, int sock) { - // TODO(iphydf): Return something sensible here (from the fuzzer): number of - // bytes to be read from the socket. - return 0; + ![](Fuzz_System *self, int sock) { + const size_t count = random_u16(self->rng.get()); + return static_cast(std::min(count, self->data.size)); }, /* .recv = */ ![](Fuzz_System *self, int sock, uint8_t *buf, size_t len) { @@ -107,10 +106,13 @@ static constexpr Random_Funcs fuzz_random_funcs = { }, /* .random_uniform = */ ![](Fuzz_System *self, uint32_t upper_bound) { - uint32_t randnum; - self->rng->funcs->random_bytes( - self, reinterpret_cast(&randnum), sizeof(randnum)); - return randnum % upper_bound; + uint32_t randnum = 0; + if (upper_bound > 0) { + self->rng->funcs->random_bytes( + self, reinterpret_cast(&randnum), sizeof(randnum)); + randnum %= upper_bound; + } + return randnum; }, }; diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 53866c854e3..1bc09640047 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -151,7 +151,8 @@ static int proxy_http_read_connection_response(const Logger *logger, const TCP_C char success[] = "200"; uint8_t data[16]; // draining works the best if the length is a power of 2 - const int ret = read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, data, sizeof(data) - 1, &tcp_conn->con.ip_port); + const int ret = read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, data, sizeof(data) - 1, + &tcp_conn->con.ip_port); if (ret == -1) { return 0; @@ -161,14 +162,19 @@ static int proxy_http_read_connection_response(const Logger *logger, const TCP_C if (strstr((const char *)data, success) != nullptr) { // drain all data - const uint16_t data_left = net_socket_data_recv_buffer(tcp_conn->con.ns, tcp_conn->con.sock); + uint16_t data_left = net_socket_data_recv_buffer(tcp_conn->con.ns, tcp_conn->con.sock); - if (data_left > 0) { - VLA(uint8_t, temp_data, data_left); - if (read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, temp_data, data_left, &tcp_conn->con.ip_port) == -1) { + while (data_left > 0) { + uint8_t temp_data[16]; + const uint16_t temp_data_size = min_u16(data_left, sizeof(temp_data)); + + if (read_TCP_packet(logger, tcp_conn->con.ns, tcp_conn->con.sock, temp_data, temp_data_size, + &tcp_conn->con.ip_port) == -1) { LOGGER_ERROR(logger, "failed to drain TCP data (but ignoring failure)"); return 1; } + + data_left -= temp_data_size; } return 1; @@ -812,12 +818,16 @@ static int handle_TCP_client_packet(const Logger *logger, TCP_Client_Connection return handle_TCP_client_oob_recv(conn, data, length, userdata); case TCP_PACKET_ONION_RESPONSE: { - conn->onion_callback(conn->onion_callback_object, data + 1, length - 1, userdata); + if (conn->onion_callback != nullptr) { + conn->onion_callback(conn->onion_callback_object, data + 1, length - 1, userdata); + } return 0; } case TCP_PACKET_FORWARDING: { - conn->forwarded_response_callback(conn->forwarded_response_callback_object, data + 1, length - 1, userdata); + if (conn->forwarded_response_callback != nullptr) { + conn->forwarded_response_callback(conn->forwarded_response_callback_object, data + 1, length - 1, userdata); + } return 0; } diff --git a/toxcore/network.c b/toxcore/network.c index f9986f2e98e..ce3d03e5625 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -648,7 +648,7 @@ static uint32_t data_1(uint16_t buflen, const uint8_t *buffer) { uint32_t data = 0; - if (buflen > 7) { + if (buflen > 8) { net_unpack_u32(buffer + 5, &data); }