Skip to content

Commit

Permalink
Merge pull request #61 from KTH/feature/handle-crashed-server
Browse files Browse the repository at this point in the history
Feature/handle crashed server
  • Loading branch information
olapiv authored Aug 28, 2020
2 parents b3ce3f9 + a61e646 commit 6cf5590
Show file tree
Hide file tree
Showing 14 changed files with 203 additions and 76 deletions.
7 changes: 5 additions & 2 deletions wasm-fuzzer/.env
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Whether we are using AFL with Swam or just using dummy data
DUMMY_TESTING_AFL=False

# (Not being used yet..) Error, Warn, Info, Debug
LOG_LEVEL=Error
# Enum: ERROR, WARNING, INFO, DEBUG
LOG_LEVEL=INFO

# Set True if AFL should always continue where it left off (and not delete old findings). Useful if AFL/SWAM may crash and auto-restart.
REUSE_DATA_AFL=True

# Path to the parent directory of our local .wasm/.wat executable
LOCAL_WASM=/tmp/fuzzer-wat_files
Expand Down
31 changes: 22 additions & 9 deletions wasm-fuzzer/fuzzing-client-afl/entrypoint_afl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,41 @@ PREPARED_INPUT_PATH="$DOCKER_AFL_INPUT/prepared_input.dat"
REQUIRED_BYTES=$(./getFileSize.out $PREPARED_INPUT_PATH)

# Parallel fuzzing: https://github.com/mirrorer/afl/blob/master/docs/parallel_fuzzing.txt
if [[ ! -z "$MASTER_AFL_NODE" ]]
then
if [[ ! -z "$MASTER_AFL_NODE" ]]; then
DOCKER_CONTAINER_ID=$(</etc/hostname)
if [[ $MASTER_AFL_NODE == "True" ]]
then
if [[ $MASTER_AFL_NODE == "True" ]]; then
RANK="-M $DOCKER_CONTAINER_ID"
elif [[ $MASTER_AFL_NODE == "False" ]]
then
elif [[ $MASTER_AFL_NODE == "False" ]]; then
RANK="-S $DOCKER_CONTAINER_ID"
fi
fi

# AFL Docs on re-starting:
# If you need to stop and re-start the fuzzing, use the same command line
# options (or even change them by selecting a different power schedule
# or another mutation mode!) and switch the input directory with a
# dash (-): afl-fuzz -i - -o output -- bin/target -d @@

# Check if AFL has already produced results
if ! [ "$(ls -A $DOCKER_AFL_OUTPUT)" ]; then
echo "$DOCKER_AFL_OUTPUT is empty - starting fresh run!"
elif [ $REUSE_DATA_AFL ]; then
echo "$DOCKER_AFL_OUTPUT is not empty & REUSE_DATA_AFL=$REUSE_DATA_AFL, so continuing where we left off!"
DOCKER_AFL_INPUT="-"
else
echo "$DOCKER_AFL_OUTPUT is not empty & REUSE_DATA_AFL=$REUSE_DATA_AFL, so deleting old data!"
fi

./wait_for_server.out

if [ $? != 0 ]; then
exit 1
fi

# AFL Docs:
# afl-fuzz starts by performing an array of deterministic fuzzing steps,
# which can take several days, but tend to produce neat test cases.
# If you want quick & dirty results right away - akin to zzuf and other
# afl-fuzz starts by performing an array of deterministic fuzzing steps,
# which can take several days, but tend to produce neat test cases.
# If you want quick & dirty results right away - akin to zzuf and other
# traditional fuzzers - add the -d option to the command line.

echo "afl-fuzz -i $DOCKER_AFL_INPUT -o $DOCKER_AFL_OUTPUT $RANK -d -- ${DOCKER_INTERFACE_SRC}/interface.out @@ $REQUIRED_BYTES"
Expand Down
77 changes: 52 additions & 25 deletions wasm-fuzzer/fuzzing-client-afl/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@

#define AFL_SHM_SIZE 65536

void LOG(std::string some_string)
{
std::string DOCKER_LOGS = parseEnvVariables((char *)"DOCKER_LOGS");
log(DOCKER_LOGS + "/interface.log", some_string);
}

std::vector<std::string> readFileToVector(const std::string &filename)
{
std::ifstream source;
Expand All @@ -26,24 +20,24 @@ void log_file(char *filename)
std::vector<std::string> vector = readFileToVector(filename);
for (int i = 0; i < vector.size(); ++i)
{
LOG(vector[i]);
log_default(vector[i], DEBUG);
}
}

uint8_t *getShm()
{
std::string shmStr = parseEnvVariables((char *)"__AFL_SHM_ID");
LOG("shmStr: " + shmStr);
log_default("shmStr: " + shmStr, INFO);

key_t key = std::stoi(shmStr);

uint8_t *trace_bits = (uint8_t *)shmat(key, 0, 0);
if (trace_bits == (uint8_t *)-1)
{
LOG("Failed to access shared memory");
log_default("Failed to access shared memory", ERROR);
exit(1);
}
LOG("Shared memory attached.");
log_default("Shared memory attached.", INFO);
return trace_bits;
}

Expand All @@ -69,7 +63,8 @@ void pass_data_to_afl(int sizeReadBuffer, char *readBuffer, uint8_t *trace_bits)
void main_fuzz(
char *fuzzed_input_path,
uint8_t *trace_bits,
int requiredBytes)
int requiredBytes,
pid_t aflPID)
{

std::string DUMMY_TESTING_AFL = parseEnvVariables((char *)"DUMMY_TESTING_AFL");
Expand All @@ -79,17 +74,36 @@ void main_fuzz(
exit(0);
}

// TODO: Replace sendBuffer by
char sendBuffer[requiredBytes];
readBinaryToBuffer(sendBuffer, sizeof(sendBuffer), (std::string)fuzzed_input_path);
// std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of tempBuffer

char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code

std::string SWAM_SOCKET_HOST = parseEnvVariables((char *)"SWAM_SOCKET_HOST");
std::string SWAM_SOCKET_PORT = parseEnvVariables((char *)"SWAM_SOCKET_PORT");

runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_SOCKET_HOST[0], std::stoi(SWAM_SOCKET_PORT));
int num_tries = 0;
while (true)
{
try
{
runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, &SWAM_SOCKET_HOST[0], std::stoi(SWAM_SOCKET_PORT));
break;
}
catch (...)
{
num_tries += 1;
if (num_tries > 1)
{
// Failing twice probably means SWAM server is down. Therefore, kill
// AFL before AFL kills us due to timeout. Would run here endlessly
// otherwise.
kill(aflPID, 6);
log_default("Killed AFL because server not responding.", WARNING);
exit(1);
}
}
}

pass_data_to_afl(sizeof(readBuffer), readBuffer, trace_bits);

Expand All @@ -109,14 +123,27 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
hard-coded by AFL and thereby accessible here.
*/

// Just for logging:
pid_t aflPID = getppid();
char aflPIDChar[6];
sprintf(aflPIDChar, "%d", aflPID);
std::string aflPIDString = aflPIDChar;
log_default("AFL's PID: " + aflPIDString, INFO);

pid_t forkServerPID = getpid();
char forkServerPIDChar[6];
sprintf(forkServerPIDChar, "%d", forkServerPID);
std::string forkServerPIDString = forkServerPIDChar;
log_default("Forkserver's PID: " + forkServerPIDString, INFO);

int status = 0;

// Starting the 'Fork server handshake'

// Phone home and tell AFL that we're OK
if (write(199, &status, 4) != 4)
{
LOG("Write failed");
log_default("Write failed", ERROR);
close(199);
exit(1);
}
Expand All @@ -125,11 +152,12 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
// and is creating forks of itself is called the "fork server".
while (true)
{

// Wait for AFL by reading from the pipe.
// This will block until AFL sends us something. Abort if read fails.
if (read(198, &status, 4) != 4)
{
LOG("Read failed");
log_default("Read failed", ERROR);
close(198);
close(199);
exit(1);
Expand All @@ -143,7 +171,7 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
int pid = fork();
if (pid < 0)
{
LOG("Fork failed");
log_default("Fork failed", ERROR);
close(198);
close(199);
exit(1);
Expand All @@ -153,7 +181,7 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
// This is the child process
close(198);
close(199);
main_fuzz(fuzzed_input_path, trace_bits, requiredBytes);
main_fuzz(fuzzed_input_path, trace_bits, requiredBytes, aflPID);
exit(0);
}

Expand All @@ -171,7 +199,7 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
// Waiting for child
if (waitpid(pid, &status, 0) <= 0) // Technically only fails at -1; 0 means still running
{
LOG("waitpid() failed.");
log_default("waitpid() failed.", ERROR);
close(198);
close(199);
exit(1);
Expand All @@ -186,14 +214,14 @@ void fork_server(char *fuzzed_input_path, uint8_t *trace_bits, int requiredBytes
else if (WIFSIGNALED(status)) // Process was stopped/terminated by signal;
{
// TODO: Find out why this branch gets triggered
LOG("Signal status: " + std::to_string(status));
LOG("WTERMSIG(status): " + std::to_string(WTERMSIG(status)));
LOG("WSTOPSIG(status): " + std::to_string(WSTOPSIG(status)));
log_default("Signal status: " + std::to_string(status), ERROR);
log_default("WTERMSIG(status): " + std::to_string(WTERMSIG(status)), ERROR);
log_default("WSTOPSIG(status): " + std::to_string(WSTOPSIG(status)), ERROR);
write(199, &status, 4);
}
else
{
LOG("Weird status: " + std::to_string(status));
log_default("Weird status: " + std::to_string(status), ERROR);
close(198);
close(199);
exit(1);
Expand All @@ -205,13 +233,12 @@ void log_args(int argc, char *argv[])
{
for (int i = 0; i < argc; ++i)
{
LOG("argv[" + std::to_string(i) + "]: " + std::string(argv[i]));
log_default("argv[" + std::to_string(i) + "]: " + std::string(argv[i]), INFO);
}
}

int main(int argc, char *argv[])
{
// TODO: Remove everything related to requiredBytes; not necessary anymore
log_args(argc, argv);

char *fuzzed_input_path = argv[1];
Expand Down
1 change: 1 addition & 0 deletions wasm-fuzzer/fuzzing-client-afl/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
#include <sys/wait.h>
#include <stdlib.h>
#include <algorithm>
#include <signal.h>

#endif
1 change: 0 additions & 1 deletion wasm-fuzzer/fuzzing-client-afl/prepare_wasm_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ void printResult(std::string filepath)
printf("Total bytes written: %i\n", fileSize);
char buffer[fileSize];
readBinaryToBuffer(buffer, fileSize, filepath);
// std::reverse(buffer, &buffer[sizeof(buffer)]);

printBuffer(sizeof(buffer), buffer);
printf("-----------------\n");
Expand Down
5 changes: 2 additions & 3 deletions wasm-fuzzer/fuzzing-client-afl/run_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
// data sent by the client properly
int main(int argc, char *argv[])
{
std::string inputFile = (std::string) argv[1];
std::string inputFile = (std::string)argv[1];

char readBuffer[AFL_SHM_SIZE + 1]; // + 1 for exit code

int fileSize = (int)getFileSize(inputFile);
char sendBuffer[fileSize];
readBinaryToBuffer(sendBuffer, fileSize, inputFile);
// std::reverse(sendBuffer, &sendBuffer[sizeof(sendBuffer)]); // Reverse order of sendBuffer

runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, "localhost", 9999);
runClient(sizeof(sendBuffer), sendBuffer, sizeof(readBuffer), readBuffer, (char *)"localhost", 9999);
exit(0);
};
2 changes: 2 additions & 0 deletions wasm-fuzzer/fuzzing-client-afl/run_test.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash

# TODO: Since now all logging is to a file (using env var DOCKER_LOGS), this script cannot be run locally anymore. Fix this.

# For testing the integration of prepare_wasm_input.cpp and socket_client.cpp.

# Run server in Swam first (example with fibo.wat):
Expand Down
Loading

0 comments on commit 6cf5590

Please sign in to comment.