diff options
author | Luca Boccassi <luca.boccassi@gmail.com> | 2020-04-26 04:27:48 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-25 20:27:48 -0700 |
commit | e003502f26fab3cd9083b583ecd6b5a43f7e6c21 (patch) | |
tree | d9389966cef1b17b3a0f37bd1f67d15ff6d300e1 /projects | |
parent | 24cb3468e1d7954848546a7baeccea0bf0ca5dcc (diff) |
libzmq: update maintainers, add network tests (#3710)
* libzmq: add alternative mail address and other maintainer's address
* libzmq: adjust zmq_z85_decode test
The output buffer is not fixed in size, it depends on input size and the
caller allocates it
* libzmq: add tests for handshake engine on connect/bind
Create localhost ipv4 TCP sockets to exercise libzmq's processing
of data over the network.
This connections should be rejected in the first part of the handshake
(greeting) only, so more tests should be added to further mock the
greeting and exercise deeper parts of the engine.
https://rfc.zeromq.org/spec/37/
* libzmq: fix coverage build
The combination of clang, coverage and automake is not happy at the
moment, and binaries fail to link. We don't need to build any of
the tools for these tests, so simply disable them.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21872
Diffstat (limited to 'projects')
-rwxr-xr-x | projects/libzmq/build.sh | 4 | ||||
-rw-r--r-- | projects/libzmq/decode_fuzzer.cc | 9 | ||||
-rw-r--r-- | projects/libzmq/project.yaml | 3 | ||||
-rw-r--r-- | projects/libzmq/socket_bind_fuzzer.cc | 74 | ||||
-rw-r--r-- | projects/libzmq/socket_connect_fuzzer.cc | 77 |
5 files changed, 164 insertions, 3 deletions
diff --git a/projects/libzmq/build.sh b/projects/libzmq/build.sh index be98e338..db574888 100755 --- a/projects/libzmq/build.sh +++ b/projects/libzmq/build.sh @@ -17,8 +17,8 @@ # build project cd $SRC/libzmq -./autogen.sh --disable-shared -./configure +./autogen.sh +./configure --disable-shared --disable-perf --disable-curve-keygen make -j$(nproc) V=1 # build fuzzers diff --git a/projects/libzmq/decode_fuzzer.cc b/projects/libzmq/decode_fuzzer.cc index cedf8ee6..ef3f86a6 100644 --- a/projects/libzmq/decode_fuzzer.cc +++ b/projects/libzmq/decode_fuzzer.cc @@ -21,8 +21,15 @@ #include "include/zmq.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - uint8_t secret_key[32]; + uint8_t *secret_key; + // As per API definition, input must be divisible by 5, so truncate it if it's not + size -= size % 5; + // As per API definition, the destination must be at least 0.8 times the input data + secret_key = (uint8_t *)malloc(size * 4 / 5); + if (!secret_key) + return -1; std::string z85_secret_key(reinterpret_cast<const char *>(data), size); zmq_z85_decode(secret_key, z85_secret_key.c_str()); + free(secret_key); return 0; } diff --git a/projects/libzmq/project.yaml b/projects/libzmq/project.yaml index 42dad7fb..59b178c3 100644 --- a/projects/libzmq/project.yaml +++ b/projects/libzmq/project.yaml @@ -1,6 +1,9 @@ homepage: "https://github.com/zeromq/libzmq" language: c++ primary_contact: "bluca@debian.org" +auto_ccs: + - "luca.boccassi@gmail.com" + - "somdoron@gmail.com" sanitizers: - address - memory diff --git a/projects/libzmq/socket_bind_fuzzer.cc b/projects/libzmq/socket_bind_fuzzer.cc new file mode 100644 index 00000000..c47ba17d --- /dev/null +++ b/projects/libzmq/socket_bind_fuzzer.cc @@ -0,0 +1,74 @@ +// Copyright 2020 Luca Boccassi <bluca@debian.org> +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <fuzzer/FuzzedDataProvider.h> + +#include <cstddef> +#include <cstdint> +#include <string> +#include <assert.h> +#include <arpa/inet.h> +#include <unistd.h> + +#include "include/zmq.h" + +// Test that the ZMTP engine handles invalid handshake when binding +// https://rfc.zeromq.org/spec/37/ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + void *server, *ctx; + struct sockaddr_in ip4addr; + char endpoint[32]; + size_t endpoint_len = 32, sent_bytes; + unsigned short port; + int client, rc, linger = 0; + + ctx = zmq_ctx_new (); + assert(ctx); + server = zmq_socket(ctx, ZMQ_PUB); + assert(server); + rc = zmq_setsockopt (server, ZMQ_LINGER, &linger, sizeof(linger)); + assert(rc == 0); + rc = zmq_bind(server, "tcp://127.0.0.1:*"); + assert(rc == 0); + rc = zmq_getsockopt(server, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_len); + assert(rc == 0); + rc = sscanf(endpoint, "tcp://127.0.0.1:%hu", &port); + assert(rc == 1); + + ip4addr.sin_family = AF_INET; + ip4addr.sin_port = htons(port); + inet_pton(AF_INET, "127.0.0.1", &ip4addr.sin_addr); + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + assert(client >= 0); + rc = connect(client, reinterpret_cast<struct sockaddr *> (&ip4addr), sizeof(ip4addr)); + assert(rc >= 0); + + // Send as many bytes as possible, and then let the background I/O thread + // have some time to handle them. + // We should at least be able to send 33 bytes, which is the very first + // part of the ZMTP 3.x handshake. Otherwise something is not quite right + // in the localhost connection we set up. + sent_bytes = write(client, (const char *)data, size); + assert(size < 33 || sent_bytes >= 33); + usleep (static_cast<useconds_t> (250) * 1000); + + close(client); + + rc = zmq_close(server); + assert(rc == 0); + rc = zmq_ctx_term(ctx); + assert(rc == 0); + + return 0; +} diff --git a/projects/libzmq/socket_connect_fuzzer.cc b/projects/libzmq/socket_connect_fuzzer.cc new file mode 100644 index 00000000..ee586fb3 --- /dev/null +++ b/projects/libzmq/socket_connect_fuzzer.cc @@ -0,0 +1,77 @@ +// Copyright 2020 Luca Boccassi <bluca@debian.org> +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <fuzzer/FuzzedDataProvider.h> + +#include <cstddef> +#include <cstdint> +#include <string> +#include <assert.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "include/zmq.h" + +// Test that the ZMTP engine handles invalid handshake when connecting +// https://rfc.zeromq.org/spec/37/ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + void *client, *ctx; + struct sockaddr_in ip4addr; + socklen_t ip4addr_len = sizeof(ip4addr); + char endpoint[32]; + size_t sent_bytes; + int server, server_accept, rc; + + ip4addr.sin_family = AF_INET; + ip4addr.sin_port = 0; + inet_pton(AF_INET, "127.0.0.1", &ip4addr.sin_addr); + server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + assert(server >= 0); + rc = bind(server, reinterpret_cast<struct sockaddr *> (&ip4addr), sizeof(ip4addr)); + assert(rc >= 0); + rc = listen (server, SOMAXCONN); + assert(rc == 0); + rc = getsockname (server, (struct sockaddr *) &ip4addr, &ip4addr_len); + assert(rc == 0); + sprintf(endpoint, "tcp://127.0.0.1:%u", ntohs(ip4addr.sin_port)); + + ctx = zmq_ctx_new (); + assert(ctx); + client = zmq_socket(ctx, ZMQ_SUB); + assert(client); + rc = zmq_connect(client, endpoint); + assert(rc == 0); + + // Send as many bytes as possible, and then let the background I/O thread + // have some time to handle them. + // We should at least be able to send 33 bytes, which is the very first + // part of the ZMTP 3.x handshake. Otherwise something is not quite right + // in the localhost connection we set up. + server_accept = accept(server, NULL, NULL); + sent_bytes = write(server_accept, (const char *)data, size); + assert(size < 33 || sent_bytes >= 33); + usleep (static_cast<useconds_t> (250) * 1000); + + close(server_accept); + close(server); + + rc = zmq_close(client); + assert(rc == 0); + rc = zmq_ctx_term(ctx); + assert(rc == 0); + + return 0; +} |