using namespace isc::dhcp;
using namespace std;
-// Constants defined in the class definition
+// Constants defined in the Fuzz class definition.
constexpr size_t Fuzz::BUFFER_SIZE;
constexpr useconds_t Fuzz::SLEEP_INTERVAL;
constexpr long Fuzz::LOOP_COUNT;
-// Variables needed to synchronize between main and fuzzing threads.
-condition_variable Fuzz::fuzz_cond_;
-mutex Fuzz::fuzz_mutex_;
-thread Fuzz::fuzzing_thread_;
-condition_variable Fuzz::main_cond_;
-mutex Fuzz::main_mutex_;
+// Variables needed to synchronize between main and fuzzing threads. The
+// fuzz_sync_ condition is notified by the fuzzing thread and waited for by the
+// main thread. The main_sync_ condition is notified by the main thread and
+// waited for by the fuzzing thread.
+FuzzSynch Fuzz::fuzz_sync_;
+FuzzSynch Fuzz::main_sync_;
+std::thread Fuzz::fuzzing_thread_;
-// Address structure used to send data to address/port on which Kea listens
+// Address structure used to define the address/port used to send
+// fuzzing data to the Kea server.
struct sockaddr_in6 Fuzz::servaddr_;
// Pointer to the shutdown flag used by Kea. The fuzzing code will set this
// after the appropriate number of packets have been fuzzed.
volatile bool* Fuzz::shutdown_ptr_ = NULL;
-// Variable used in condition checks
-volatile bool Fuzz::fuzz_ready_ = false;
-volatile bool Fuzz::main_ready_ = false;
+// FuzzSynch methods. FuzSynch is the class that encapsulates the
+// synchronization process between the main and fuzzing threads.
-// Flag to state that the
+// init - just set the predicate as false.
+void FuzzSynch::init(const char* name) {
+ name_ = name;
+ ready_ = false;
+}
+// Wait to be notified when the predicate is true
+void
+FuzzSynch::wait(void) {
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_WAITING).arg(name_);
+ unique_lock<mutex> lock(mutex_);
+ cond_.wait(lock, [=]() { return this->ready_; });
+ ready_ = false;
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_WAITED).arg(name_);
+}
+
+// Set predicate and notify the waiting thread to continue
+void
+FuzzSynch::notify(void) {
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_SETTING).arg(name_);
+ unique_lock<mutex> lock(mutex_);
+ ready_ = true;
+ cond_.notify_all();
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_SET).arg(name_);
+}
+// Fuzz methods.
-// Fuzzer initialization: create the thread artifacts and start the
-// main thread.
+// Initialization: create the thread artifacts and start the fuzzing thread.
void
Fuzz::init(volatile bool* shutdown_flag) {
try {
- stringstream reason;
+ stringstream reason; // Used for exception messages
// Store reference to shutdown flag. When the fuzzing loop has read
- // the set number of packets from kea, it will set this flag to trigger
+ // the set number of packets from AFL, it will set this flag to trigger
// a Kea shutdown.
if (shutdown_flag) {
shutdown_ptr_ = shutdown_flag;
isc_throw(FuzzInitFail, "must pass shutdown flag to kea_fuzz_init");
}
- // Get the environment for the fuzzing. First the interface to use.
+ // Get the environment for the fuzzing: interface, address and port.
const char *iface_ptr = getenv("KEA_AFL_INTERFACE");
if (! iface_ptr) {
isc_throw(FuzzInitFail, "no fuzzing interface has been set");
}
-
+ // Interface obtained, convert to ID.
unsigned int iface_id = if_nametoindex(iface_ptr);
if (iface_id == 0) {
reason << "error retrieving interface ID for "
servaddr_.sin6_port = htons(port);
servaddr_.sin6_scope_id = iface_id;
- // Ensure that condition variables are initially clear.
- fuzz_ready_ = false;
- main_ready_ = false;
+ // Initialize synchronization variables.
+ fuzz_sync_.init("fuzz_synch");
+ main_sync_.init("main_synch");
// Initialization complete.
LOG_INFO(fuzz_logger, FUZZ_INTERFACE)
.arg(iface_ptr).arg(address_ptr).arg(port);
// Start the thread that reads the packets sent by AFL from stdin and
- // passes them to the port on which Kea is listening. We'll ensure
- // the the fuzzing thread has read its first packet from the fuzzer
- // before continuing.
- unique_lock<mutex> lock(fuzz_mutex_);
+ // passes them to the port on which Kea is listening.
fuzzing_thread_ = std::thread(Fuzz::run);
- LOG_DEBUG(fuzz_logger, 1, FUZZ_WAI).arg("fuzz_cond").arg("init");
- fuzz_cond_.wait(lock, []{return fuzz_ready_;});
- fuzz_ready_ = false;
- LOG_DEBUG(fuzz_logger, 1, FUZZ_CWT).arg("fuzz_cond").arg("init");
- lock.unlock();
+
+ // Wait for the fuzzing thread to read its first packet from AFL and
+ // send it to the port on which Kea is listening.
+ fuzz_sync_.wait();
} catch (const FuzzInitFail& e) {
// AFL tends to make it difficult to find out what exactly has failed:
// make sure that the error is logged.
- LOG_ERROR(fuzz_logger, FUZZ_INIT_FAIL).arg(e.what());
+ LOG_FATAL(fuzz_logger, FUZZ_INIT_FAIL).arg(e.what());
throw;
}
}
// This is the main fuzzing function. It receives data from fuzzing engine.
// That data is received to stdin and then sent over the configured UDP socket.
-// Then it wait for a conditional, which is called in kea_fuzz_notify() from
-// Kea main loop.
+// It then waits for the main thread to process the packet, the completion of
+// that task being signalled by the main thread calling Fuzz::packetProcessed().
void
Fuzz::run(void) {
// Create the socket throw which packets read from stdin will be send
// Kea will be terminated and AFL will restart it. The counting of loop
// iterations is done here with a separate variable (instead of inside
// inside the read loop in the server process using __AFL_LOOP) to ensure
- // that thread running this function shutdown down between each restart
- // of the fuzzing process.
+ // that thread running this function shuts down properly between each
+ // restart of Kea.
auto loop = Fuzz::LOOP_COUNT;
while (loop-- > 0) {
- // Prevent the main thread from reading until we have made a packet
- // available. Although the read in Kea itself is not protected by
- // a mutex, the condition variable used to control when the main
- // thread runs is.
- unique_lock<mutex> fuzz_lock(fuzz_mutex_);
-
// Read from stdin and continue reading (albeit after a pause) even
- // if there is an error. Do the same with end of files although, as
- // the fuzzer generates them in normal operation, don't log them.
+ // if there is an error. Do the same with end of files.
char buf[BUFFER_SIZE];
ssize_t length = read(0, buf, sizeof(buf));
if (length <= 0) {
LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_DATA_READ)
.arg(length);
- // Now send the data to the socket. This will be picked up by the main
- // loop and acted upon, after which kea_fuzz_notify will be called.
+ // Now send the data to the UDP port on which Kea is listening.
//
// The condition variables synchronize the operation: this thread
// will read from stdin and write to the socket. It then blocks until
// the main thread has processed the packet, at which point it can read
// more data from stdin.
//
- // Since the read() and sendto() calls are blocking, one would think
- // that the two threads would synchronize even without locks. However,
- // the problem seems to arise in the generation of SIGSTOP and the
- // tying it to a particular packet set to Kea by the fuzzer. But this
- // is speculation: the fact is that without the synchronization, the
- // code doesn't work.
-
- // Block the completion function until the data has been sent:
+ // Synchronization is required because although the read from stdin is
+ // blocking, there is no blocking on the sending of data to the port
+ // from which Kea is reading. It is quite possible to lose packets,
+ // and AFL seems to get confused in this case. At any rate, without
+ // some form of synchronization, this approach does not work.
// Send the data to the main Kea thread.
ssize_t sent = sendto(sockfd, buf, length, 0,
(struct sockaddr *) &servaddr_, sizeof(servaddr_));
if (sent < 0) {
LOG_ERROR(fuzz_logger, FUZZ_SEND_ERROR).arg(strerror(errno));
+ continue;
} else if (sent != length) {
LOG_WARN(fuzz_logger, FUZZ_SHORT_SEND).arg(length).arg(sent);
} else {
}
if (loop <= 0) {
- // If this is the last loop iteration, set the shutdown flag. This
- // is done under the protection of the mutex to avoid the following
- // scenario:
- //
- // a) This loop reaches its last iteration, then waits for
- // notify() to complete.
- // b) notify() completes and returns. The main processing loop
- // check the shutdown flag and finds that it is not set. It
- // enters the next iteration of the loop and waits to read
- // something from the configured interface.
- // c) This thread resumes execution, sets the shutdown flag and
- // exits.
- //
- // This would leave the main processing loop waiting for a packet
- // that will never arrive.
- //
- // By setting the shutdown flag under the protection of the mutex,
- // the notify() call will not take place until the flag is set, and
- // the main thread will see the flag being set and exit. We might
- // as well close the socket at the same time.
+ // If this is the last loop iteration, close everything down.
+ // This is done before giving permission for the main thread
+ // to run to avoid a race condition.
*shutdown_ptr_ = true;
close(sockfd);
- LOG_DEBUG(fuzz_logger, 1, FUZZ_SHUTDOWN_INITIATED);
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE, FUZZ_SHUTDOWN_INITIATED);
}
- LOG_DEBUG(fuzz_logger, 1, FUZZ_SET).arg("fuzz_cond-1").arg("main");
- fuzz_ready_ = true;
- fuzz_cond_.notify_all();
- LOG_DEBUG(fuzz_logger, 1, FUZZ_CST).arg("fumz_cond-1").arg("main");
- fuzz_lock.unlock();
+
+ // Tell the main thread to run.
+ fuzz_sync_.notify();
// We now need to synchronize with the main thread. In particular,
// we suspend processing until we know that the processing of the
// packet by Kea has finished and that the completion function has
// raised a SIGSTOP.
- unique_lock<std::mutex> main_lock(main_mutex_);
- LOG_DEBUG(fuzz_logger, 1, FUZZ_WAI).arg("main_cond").arg("main");
- main_cond_.wait(main_lock, [] {return main_ready_;});
- LOG_DEBUG(fuzz_logger, 1, FUZZ_CWT).arg("main_cond").arg("main");
- main_ready_ = false;
- main_lock.unlock();
+ main_sync_.wait();
}
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE, FUZZ_LOOP_EXIT);
// If the main thread is waiting, let it terminate as well.
- unique_lock<mutex> fuzz_lock(fuzz_mutex_);
- fuzz_ready_ = true;
- LOG_DEBUG(fuzz_logger, 1, FUZZ_SET).arg("fuzz_cond-2").arg("main");
- fuzz_cond_.notify_all();
- LOG_DEBUG(fuzz_logger, 1, FUZZ_CST).arg("fuzz_cond-2").arg("main");
- fuzz_lock.unlock();
-
- // Loop has exited, so we should shut down Kea.
- LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE, FUZZ_LOOP_EXIT);
+ fuzz_sync_.notify();
return;
}
-// Waits for the fuzzing thread to terminate.
-void
-Fuzz::wait(void) {
- unique_lock<mutex> main_lock(main_mutex_);
- main_ready_ = true;
- LOG_DEBUG(fuzz_logger, 1, FUZZ_SET).arg("main_cond").arg("wait");
- main_cond_.notify_all();
- LOG_DEBUG(fuzz_logger, 1, FUZZ_CST).arg("main_cond").arg("wait");
- main_lock.unlock();
- LOG_DEBUG(fuzz_logger, 1, FUZZ_THREAD_WAIT);
- fuzzing_thread_.join();
-}
-
// Called by the main thread, this notifies AFL that processing for the
-// // last packet has finished.
+// last packet has finished.
void
-Fuzz::notify(void) {
- LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_NOTIFY_CALLED);
+Fuzz::packetProcessed(void) {
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_PACKET_PROCESSED_CALLED);
+
+ // Tell AFL that the processing for this packet has finished.
raise(SIGSTOP);
- // Tell the fuzzing loop that it can continue.
- unique_lock<std::mutex> main_lock(main_mutex_);
- main_ready_ = true;
- LOG_DEBUG(fuzz_logger, 1, FUZZ_SET).arg("main_cond").arg("notify");
- main_cond_.notify_all();
- LOG_DEBUG(fuzz_logger, 1, FUZZ_CST).arg("main_cond").arg("notify");
- main_lock.unlock();
-
- // ... and wait until it tells us that it can continue.
- unique_lock<mutex> fuzz_lock(fuzz_mutex_);
- LOG_DEBUG(fuzz_logger, 1, FUZZ_WAI).arg("fuzz_cond").arg("notify");
- fuzz_cond_.wait(fuzz_lock, []{return fuzz_ready_;});
- LOG_DEBUG(fuzz_logger, 1, FUZZ_CWT).arg("fuzz_cond").arg("notify");
- fuzz_ready_ = false;
- fuzz_lock.unlock();
+ // Tell the fuzzing loop that it can continue and wait until it tells
+ // us that the main thread can continue.
+ main_sync_.notify();
+ fuzz_sync_.wait();
+
+ // If the fuzzing thread is shutting down, wait for it to terminate.
+ if (*shutdown_ptr_) {
+ // We shouldn't need to notify it to continue (the previous call in
+ // this method should have done that), but it does no harm to be sure.
+ main_sync_.notify();
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE, FUZZ_THREAD_WAIT);
+ fuzzing_thread_.join();
+ LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE, FUZZ_THREAD_TERMINATED);
+ }
}
#endif // ENABLE_AFL
#include <sys/socket.h>
#include <unistd.h>
-#include <mutex>
#include <condition_variable>
+#include <mutex>
+#include <string>
#include <thread>
namespace isc {
+/// @brief Helper class to manage synchronization between fuzzing threads
+///
+/// This contains the variables and encapsulates the primitives required
+/// to manage the condition variables between the two threads.
+
+class FuzzSynch {
+public:
+ /// @brief Initialization
+ ///
+ /// Objects of this type are declared static to allow them to be accessed
+ /// from mutiple thread. This function allows appropriate initialization.
+ ///
+ /// @param name Name for debug messages
+ void init(const char* name);
+
+ /// @brief Waits for condition notification
+ ///
+ /// Called by a thread, this function will wait for another thread to
+ /// notify it that it can proceed: in other words, this function calls
+ /// <condition_variable>.wait() and waits for the other to call
+ /// <condition_variable>.notify().
+ ///
+ /// As it is possible to miss a notification - if one thread reaches the
+ /// notification point before the other thread reaches the wait point -
+ /// the operation is mediated by a predicate (in this case, a boolean
+ /// variable). If this is set when the waiting thread reaches the wait
+ /// point, the thread does not wait. If it is not set, the thread will
+ /// wait until it is notified through the condition variable. At this
+ /// point, if the variable is still not set, the thread will re-enter the
+ /// wait state.
+ ///
+ /// In both cases, the predicate variable is cleared on exit.
+ void wait(void);
+
+ /// @brief Notifies other thread to continue
+ ///
+ /// Called by a thread, this function will notify another thread that is
+ /// waiting on the condition variable that it can continue. As noted
+ /// in the documentation for wait(), the operation is mediated by a
+ /// predicate variable; in this case, the variable is explicitly set
+ /// before the notification is sent.
+ void notify(void);
+
+private:
+ std::condition_variable cond_;
+ std::mutex mutex_;
+ volatile bool ready_;
+ std::string name_;
+};
+
+
/// @brief AFL Fuzzing Functions
class Fuzz {
public:
/// @brief Initializes Kea fuzzing
///
- /// This takes one parameter, which is a pointer to the shutdown flag,
- /// Dhcp6Srv::shutdown_. Kea runs until something sets this flag to true,
- /// which is an indication to shutdown Kea.
+ /// This takes one parameter, which is a pointer to the shutdown flag. Kea
+ /// runs until something sets this flag to true, at which point it shuts
+ /// down.
///
/// In the case of fuzzing, the shutdown flag is set when a fixed number of
- /// packets has been received from the fuzzer. At this point, the fuzzer
- /// shutdow down Kea and restarts it.
+ /// packets has been received from the fuzzer. After Kea exits, the fuzzer
+ /// will restart it.
///
/// @param shutdown Pointer to boolean flag that will be set to true to
/// trigger the shutdown procedure.
/// @brief Main Kea Fuzzing Function
///
- /// This is the main Kea fuzzing function. It is the entry point for the
- /// thread that handles the interface between AFL and Kea. The function
+ /// This is the main Kea fuzzing method. It is the entry point for the
+ /// thread that handles the interface between AFL and Kea. The method
/// receives data from the fuzzing engine via stdin, and then sends it to
- /// the configured UDP socket. Kea reads it from there, processes it and
- /// when processing is complete, calls the notification function.
+ /// the configured UDP socket. The main thread of Kea reads it from there,
+ /// processes it and when processing is complete, calls the
+ /// packetProcessed() method to notify the fuzzing thread that processing
+ /// of the packet is complete.
///
- /// After a given number of packets, this function will shut down Kea. This
- /// is recommended by AFL as it avoids any resource leaks (which are not
- /// caught by AFL) from getting too large and interfering with the fuzzing.
- /// AFL will automatically restart the program to continue fuzzing.
- ///
- /// Since this runs in a separate thread, errors are logged via the fuzzing
- /// logger. (Other than initialization - when the thread is not running -
- /// this is the only use of the fuzzing logger.) If the error is fatal, the
- /// thread will terminate, something that may cause the fuzzer to hang.
+ /// After a given number of packets, this method will set the flag shut
+ /// down Kea. This is recommended by the AFL documentation as it avoids
+ /// any resource leaks (which are not caught by AFL) from getting too large
+ /// and interfering with the fuzzing. AFL will automatically restart the
+ /// program to continue fuzzing.
static void run(void);
/// @brief Notify fuzzing thread that processing is complete
///
- /// This function is called by the main Kea processing loop when it has
- /// finished processing a packet. It raises a SIGSTOP signal, which tells
- /// the AFL fuzzer that processing for the data it has just sent has
- /// finished; this causes it to send another fuzzed packet to stdin. It
- /// also sets a condition variable, so releasing the fuzzing thread to
- /// read the next data from AFL.
- static void notify(void);
-
- /// @brief Wait for fuzzing thread to exit
+ /// This function is called by the Kea processing loop running in the main
+ /// thread when it has finished processing a packet. It raises a SIGSTOP
+ /// signal, which tells the AFL fuzzer that processing for the data it has
+ /// just sent has finished; this causes it to send another fuzzed packet
+ /// to stdin. It also sets a condition variable, so releasing the fuzzing
+ /// thread to read the next data from AFL.
///
- /// A short function, called after the fuzzing thread is supposed to have
- /// finished, to ensure that it really has finished.
- static void wait(void);
+ /// If a shutdown has been initiated, this method waits for the fuzzing
+ /// thread to exit before allowing the shutdown to continue.
+ static void packetProcessed(void);
/// @brief size of the buffer used to transfer data between AFL and Kea.
static constexpr size_t BUFFER_SIZE = 65536;
// Condition/mutext variables. The fuzz_XX_ variables are set by the
// fuzzing thread and waited on by the main thread. The main_XX_ variables
// are set by the main thread and waited on by the fuzzing thread.
- static std::condition_variable fuzz_cond_; //< Set by fuzzing thread
- static std::mutex fuzz_mutex_; //< Set by fuzzing thread
- static std::condition_variable main_cond_; //< Set by main thread
- static std::mutex main_mutex_; //< Set by main thread
-
- // The next two variables are used in the condition variables test. fuzz_ready_
- // i set by the fuzzing thread and cleared by the main thread. main_ready_
- // is set by the main thread and cleared by the fuzzing thread.
- static volatile bool fuzz_ready_; //< Set when data has been read from fuzzer
- static volatile bool main_ready_; //< Set when data has been read from fuzzer
+ static FuzzSynch fuzz_sync_; // Set by fuzzing thread
+ static FuzzSynch main_sync_; // Set by main thread
// Other member variables.
- static std::thread fuzzing_thread_;//< Holds the thread ID
- static struct sockaddr_in6 servaddr_; //< For sending data to main thread
- static volatile bool* shutdown_ptr_; //< Pointer to shutdown flag
+ static std::thread fuzzing_thread_;//< Holds the thread ID
+ static struct sockaddr_in6 servaddr_; //< Address information
+ static volatile bool* shutdown_ptr_; //< Pointer to shutdown flag
};
% FUZZ_DATA_READ read %1 byte(s) from AFL via stdin
A debug message output to indicate how much data has been received from
-the fuzzer.
+the fuzzer via stdin
% FUZZ_INTERFACE fuzzing will use interface %1 (address %2, port %3)
An informational message output during fuzzing initialization, this reports
the details of the interface to be used for fuzzing.
% FUZZ_INIT_FAIL fuzz initialization failure, reason: %1
-A generic message reported via standard Kea logging if the fuzzing
-initialization failed. The reason for the failure is given in the message.
+An error message reported if the fuzzing initialization failed. The reason
+for the failure is given in the message.
% FUZZ_LOOP_EXIT main loop has exited, shutting down Kea
This debug message is output when Kea has processed the number of packets
documentation as a way of avoiding issues if Kea gets itself into a funny
state after running for a long time.
-% FUZZ_NOTIFY_CALLED kea_fuzz_notify() has been called
+% FUZZ_PACKET_PROCESSED_CALLED packetProcessed has been called
A debug message indicating that the processing of a packet by Kea has
-finished and that the kea_fuzz_notify() function has been called (which
-raises a SIGSTOP informing AFL that Kea is ready to receive another packet).
+finished and that the Fuzz::packetProcessed() method has been called. This
+raises a SIGSTOP informing AFL that Kea is ready to receive another packet.
% FUZZ_READ_FAIL error reading input from fuzzer: %1
-This error is reported if the read of data from the fuzzer (which is received
-over stdin) fails. If this occurs, the thread will sleep for a short period
-before retrying the read. The message gives the reason for the failure.
+This error is reported if the read of data from the fuzzer (which is
+received over stdin) fails, or if a read returns zero bytes. If this
+occurs, the thread will sleep for a short period before retrying the read.
+The message includes the reason for the failure.
% FUZZ_SEND sent %1 byte(s) to the socket connected to the Kea interface
A debug message stating that the sendto() call in the main fuzzing function
-has successfully completed.
+has successfully completed and reporting the number of bytes sent. This
+call sends data received from AFL to the port on which Kea is listening.
% FUZZ_SEND_ERROR failed to send data to Kea input socket: %1
This error will be reported if the sendto() call in the fuzzing thread (which
The reason for the failure is given in the message. The fuzzing code will
attempt to continue from this, but it may cause the fuzzing process to fail.
+% FUZZ_SET successfully set %1 condition variable
+A debug message stating the named condition variable has been be set.
+
+% FUZZ_SETTING setting %1 condition variable
+A debug message stating the named condition variable is to be set.
+
% FUZZ_SHORT_SEND expected to send %d bytes to Kea input socket but only sent %2
A warning message that is output if the sendto() call (used to send data
from the fuzzing thread to the main Kea processing) did not send as much
data as that read from AFL. This may indicate a problem in the underlying
-communications between the fuzzing thread and the main Kea processing; the c
+communications between the fuzzing thread and the main Kea processing.
+
+% FUZZ_SHUTDOWN_INITIATED shutdown initated, shutdown flag is set
+A debug message output when the fuzzing thread has reached the maximum number
+of iterations. At this point, the shutdown flag is set, Kea will exit and
+the fuzzer will restart it. Periodic shutdowns of the program being fuzzed
+are recommended in the AFL documentation as a way of overcoming memory leaks
+of odd conditions that a program can get into after an extended period of
+running.
% FUZZ_SOCKET_CREATE_FAIL failed to crease socket for use by fuzzing thread: %1
An error message output when the fuzzing code has failed to create a socket
through which is will copy data received on stdin from the AFL fuzzer to
-the port on which Kea is listening.
+the port on which Kea is listening. The program will most likely hang if
+this occurs.
-% FUZZ_WAI %2: %1
-A debug message stating what is being waited for.
+% FUZZ_THREAD_TERMINATED fuzzing thread has terminated
+A debug message, output when the main thread has detected that the fuzzing
+thread has terminated.
-% FUZZ_SET %2: %1
-A debug message stating what is being set.
+% FUZZ_THREAD_WAIT waiting for fuzzing thread to terminate
+A debug message, output when the main thread is waiting for the fuzzing thread
+to terminate.
-% FUZZ_CWT %2: %1
-
-% FUZZ_CST %2: %1
-
-% FUZZ_THREAD_WAIT waiting for thread to die
-
-% FUZZ_SHUTDOWN_INITIATED shutdown initated, shutdown flag is set
+% FUZZ_WAITED successfully waited for for %1 condition variable to be set
+A debug message stating the the condition variable for which the originating
+thread was waiting has been set and that the wait has completed.
-% FUZZ_GENERAL %1
+% FUZZ_WAITING waiting for %1 condition variable to be set
+A debug message stating the condition variable for which the originating
+thread is waiting.