diff --git a/.gitmodules b/.gitmodules index d6e93f4..50d8b70 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "uSockets"] path = uSockets url = https://github.com/uNetworking/uSockets.git +[submodule "fuzzing/libEpollFuzzer"] + path = fuzzing/libEpollFuzzer + url = https://github.com/uNetworking/libEpollFuzzer diff --git a/fuzzing/EpollHelloWorld.cpp b/fuzzing/EpollHelloWorld.cpp new file mode 100644 index 0000000..dcb78b1 --- /dev/null +++ b/fuzzing/EpollHelloWorld.cpp @@ -0,0 +1,69 @@ +/* We rely on wrapped syscalls */ +#include "libEpollFuzzer/epoll_fuzzer.h" + +#include "App.h" + +/* We keep this one for teardown later on */ +struct us_listen_socket_t *listen_socket; + +/* This test is run by libEpollFuzzer */ +void test() { + /* ws->getUserData returns one of these */ + struct PerSocketData { + /* Fill with user data */ + }; + + /* Keep in mind that uWS::SSLApp({options}) is the same as uWS::App() when compiled without SSL support. + * You may swap to using uWS:App() if you don't need SSL */ + uWS::App({ + /* There are example certificates in uWebSockets.js repo */ + .key_file_name = "../misc/key.pem", + .cert_file_name = "../misc/cert.pem", + .passphrase = "1234" + }).ws("/*", { + /* Settings */ + .compression = uWS::SHARED_COMPRESSOR, + .maxPayloadLength = 16 * 1024, + .idleTimeout = 10, + .maxBackpressure = 1 * 1024 * 1024, + /* Handlers */ + .open = [](auto *ws) { + /* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */ + }, + .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { + ws->send(message, opCode, true); + }, + .drain = [](auto *ws) { + /* Check ws->getBufferedAmount() here */ + }, + .ping = [](auto *ws) { + /* Not implemented yet */ + }, + .pong = [](auto *ws) { + /* Not implemented yet */ + }, + .close = [](auto *ws, int code, std::string_view message) { + /* You may access ws->getUserData() here */ + } + }).listen(9001, [](auto *listenSocket) { + listen_socket = listenSocket; + }).run(); + + uWS::Loop::get()->free(); +} + +/* Thus function should shutdown the event-loop and let the test fall through */ +void teardown() { + /* If we are called twice there's a bug (it potentially could if + * all open sockets cannot be error-closed in one epoll_wait call). + * But we only allow 1k FDs and we have a buffer of 1024 from epoll_wait */ + if (!listen_socket) { + exit(-1); + } + + /* We might have open sockets still, and these will be error-closed by epoll_wait */ + // us_socket_context_close - close all open sockets created with this socket context + + us_listen_socket_close(0, listen_socket); + listen_socket = NULL; +} \ No newline at end of file diff --git a/fuzzing/Makefile b/fuzzing/Makefile index c6c331b..d8fbd9d 100644 --- a/fuzzing/Makefile +++ b/fuzzing/Makefile @@ -5,7 +5,16 @@ CXXFLAGS ?= -DLIBUS_NO_SSL -fsanitize=$(SANITIZER),fuzzer CFLAGS ?= -DLIBUS_NO_SSL OUT ?= . +# These are fetched from libEpollFuzzer +WRAPPED_SYSCALLS = -Wl,--wrap=recv,--wrap=read,--wrap=listen,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=setsockopt,--wrap=fcntl,--wrap=bind,--wrap=socket,--wrap=epoll_wait,--wrap=epoll_create1,--wrap=timerfd_settime,--wrap=close,--wrap=accept4,--wrap=eventfd,--wrap=timerfd_create,--wrap=epoll_ctl,--wrap=shutdown + oss-fuzz: +# libEpollFuzzer cases + # Compile uSockets without -flto + rm -rf *.o + $(CC) -DLIBUS_NO_SSL -std=c11 -I../uSockets/src -O3 -c ../uSockets/src/*.c ../uSockets/src/eventing/*.c ../uSockets/src/crypto/*.c + # Link against object files + $(CXX) $(CXXFLAGS) $(WRAPPED_SYSCALLS) -std=c++17 -O2 -DUWS_NO_ZLIB -I../src -I../uSockets/src EpollHelloWorld.cpp -o $(OUT)/EpollHelloWorld $(LIB_FUZZING_ENGINE) *.o # "Unit tests" $(CXX) $(CXXFLAGS) -std=c++17 -O3 WebSocket.cpp -o $(OUT)/WebSocket $(LIB_FUZZING_ENGINE) $(CXX) $(CXXFLAGS) -std=c++17 -O3 Http.cpp -o $(OUT)/Http $(LIB_FUZZING_ENGINE) diff --git a/fuzzing/libEpollFuzzer b/fuzzing/libEpollFuzzer new file mode 160000 index 0000000..6b5c31a --- /dev/null +++ b/fuzzing/libEpollFuzzer @@ -0,0 +1 @@ +Subproject commit 6b5c31a6575c80f8ea7ae9e15161eb71542c8cf3 diff --git a/uSockets b/uSockets index 577c822..716c51b 160000 --- a/uSockets +++ b/uSockets @@ -1 +1 @@ -Subproject commit 577c822ac2e27d297eb6ea8712c84db5bbfe3b44 +Subproject commit 716c51be4447196d6818b212189bcf31698179c4