summaryrefslogtreecommitdiffstats
path: root/src/server/net.c
diff options
context:
space:
mode:
authorSimon Rettberg2017-10-30 21:39:56 +0100
committerSimon Rettberg2017-10-30 21:39:56 +0100
commit46c3e0e276e62b6be76e69b68de56432692efcf3 (patch)
tree194ab981ea90f1227cfb94509b9d17b25bb29354 /src/server/net.c
parent[SERVER] Missed occurence of AF_INET(6) -> HOST_IP[46] (diff)
downloaddnbd3-46c3e0e276e62b6be76e69b68de56432692efcf3.tar.gz
dnbd3-46c3e0e276e62b6be76e69b68de56432692efcf3.tar.xz
dnbd3-46c3e0e276e62b6be76e69b68de56432692efcf3.zip
[SERVER] Add AFL support
AFL is an instrumenting fuzzer. It expects to pass input to the program to be tested via command line (file name) or via stdin. This adds support for reading messages that normally would arrive via network directly from stdin. In this mode, the server is pretty useless otherwise. http://lcamtuf.coredump.cx/afl/
Diffstat (limited to 'src/server/net.c')
-rw-r--r--src/server/net.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/src/server/net.c b/src/server/net.c
index c7d34de..c11a78a 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -69,6 +69,9 @@ void net_updateGlobalSentStatsFromClient(dnbd3_client_t * const client)
static inline bool recv_request_header(int sock, dnbd3_request_t *request)
{
ssize_t ret, fails = 0;
+#ifdef AFL_MODE
+ sock = 0;
+#endif
// Read request header from socket
while ( ( ret = recv( sock, request, sizeof(*request), MSG_WAITALL ) ) != sizeof(*request) ) {
if ( errno == EINTR && ++fails < 10 ) continue;
@@ -93,6 +96,9 @@ static inline bool recv_request_header(int sock, dnbd3_request_t *request)
static inline bool recv_request_payload(int sock, uint32_t size, serialized_buffer_t *payload)
{
+#ifdef AFL_MODE
+ sock = 0;
+#endif
if ( size == 0 ) {
logadd( LOG_ERROR, "Called recv_request_payload() to receive 0 bytes" );
return false;
@@ -169,7 +175,11 @@ void* net_handleNewConnection(void *clientPtr)
// Await data from client. Since this is a fresh connection, we expect data right away
sock_setTimeout( client->sock, _clientTimeout );
do {
+#ifdef AFL_MODE
+ const int ret = (int)recv( 0, &request, sizeof(request), MSG_WAITALL );
+#else
const int ret = (int)recv( client->sock, &request, sizeof(request), MSG_WAITALL );
+#endif
// It's expected to be a real dnbd3 client
// Check request for validity. This implicitly dictates that all HTTP requests are more than 16 bytes...
if ( ret != (int)sizeof(request) ) {
@@ -408,7 +418,32 @@ void* net_handleNewConnection(void *clientPtr)
realBytes = image->realFilesize - offset;
}
while ( done < realBytes ) {
-#ifdef __linux__
+#ifdef AFL_MODE
+ char buf[1000];
+ size_t cnt = realBytes - done;
+ if ( cnt > 1000 ) {
+ cnt = 1000;
+ }
+ const ssize_t ret = pread( image_file, buf, cnt, offset );
+ if ( ret <= 0 ) {
+ const int err = errno;
+ if ( lock ) pthread_mutex_unlock( &client->sendMutex );
+ if ( ret == -1 ) {
+ if ( err != EPIPE && err != ECONNRESET && err != ESHUTDOWN
+ && err != EAGAIN && err != EWOULDBLOCK ) {
+ logadd( LOG_DEBUG1, "sendfile to %s failed (image to net. sent %d/%d, errno=%d)",
+ client->hostName, (int)done, (int)realBytes, err );
+ }
+ if ( err == EBADF || err == EFAULT || err == EINVAL || err == EIO ) {
+ logadd( LOG_INFO, "Disabling %s:%d", image->name, image->rid );
+ image->working = false;
+ }
+ }
+ goto exit_client_cleanup;
+ }
+ write( client->sock, buf, ret );
+ done += ret;
+#elif defined(__linux__)
const ssize_t ret = sendfile( client->sock, image_file, &foffset, realBytes - done );
if ( ret <= 0 ) {
const int err = errno;