qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] fuzz: pass failures from child process into libfuzzer engine


From: Konstantin Khlebnikov
Subject: [PATCH] fuzz: pass failures from child process into libfuzzer engine
Date: Sun, 05 Dec 2021 19:17:56 +0300
User-agent: StGit/1.4.dev11+gd5bef96

Fuzzer is supposed to stop when first bug is found and report failure.
Present fuzzers fork new child at each iteration to isolate side-effects.
But child's exit code is ignored, i.e. libfuzzer does not see any crashes.

Right now virtio-net fuzzer instantly falls on assert in iov_copy and
dumps crash-*, but fuzzing continues and ends successfully if global
timeout is set.

Let's put required logic into helper function "fork_fuzzer_and_wait".

Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
---
 tests/qtest/fuzz/fork_fuzz.c        |   26 ++++++++++++++++++++++++++
 tests/qtest/fuzz/fork_fuzz.h        |    1 +
 tests/qtest/fuzz/generic_fuzz.c     |    3 +--
 tests/qtest/fuzz/i440fx_fuzz.c      |    3 +--
 tests/qtest/fuzz/virtio_blk_fuzz.c  |    6 ++----
 tests/qtest/fuzz/virtio_net_fuzz.c  |    6 ++----
 tests/qtest/fuzz/virtio_scsi_fuzz.c |    6 ++----
 7 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/tests/qtest/fuzz/fork_fuzz.c b/tests/qtest/fuzz/fork_fuzz.c
index 6ffb2a7937..6e3a3867bf 100644
--- a/tests/qtest/fuzz/fork_fuzz.c
+++ b/tests/qtest/fuzz/fork_fuzz.c
@@ -38,4 +38,30 @@ void counter_shm_init(void)
     free(copy);
 }
 
+/* Returns true in child process */
+bool fork_fuzzer_and_wait(void)
+{
+    pid_t pid;
+    int wstatus;
+
+    pid = fork();
+    if (pid < 0) {
+        perror("fork");
+        abort();
+    }
+
+    if (pid == 0) {
+        return true;
+    }
 
+    if (waitpid(pid, &wstatus, 0) < 0) {
+        perror("waitpid");
+        abort();
+    }
+
+    if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) {
+        abort();
+    }
+
+    return false;
+}
diff --git a/tests/qtest/fuzz/fork_fuzz.h b/tests/qtest/fuzz/fork_fuzz.h
index 9ecb8b58ef..792e922731 100644
--- a/tests/qtest/fuzz/fork_fuzz.h
+++ b/tests/qtest/fuzz/fork_fuzz.h
@@ -18,6 +18,7 @@ extern uint8_t __FUZZ_COUNTERS_START;
 extern uint8_t __FUZZ_COUNTERS_END;
 
 void counter_shm_init(void);
+bool fork_fuzzer_and_wait(void);
 
 #endif
 
diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c
index dd7e25851c..f0e25b39ea 100644
--- a/tests/qtest/fuzz/generic_fuzz.c
+++ b/tests/qtest/fuzz/generic_fuzz.c
@@ -667,7 +667,7 @@ static void generic_fuzz(QTestState *s, const unsigned char 
*Data, size_t Size)
     size_t cmd_len;
     uint8_t op;
 
-    if (fork() == 0) {
+    if (fork_fuzzer_and_wait()) {
         struct sigaction sact;
         struct itimerval timer;
         sigset_t set;
@@ -723,7 +723,6 @@ static void generic_fuzz(QTestState *s, const unsigned char 
*Data, size_t Size)
         _Exit(0);
     } else {
         flush_events(s);
-        wait(0);
     }
 }
 
diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c
index 86796bff2b..0b927f4b3a 100644
--- a/tests/qtest/fuzz/i440fx_fuzz.c
+++ b/tests/qtest/fuzz/i440fx_fuzz.c
@@ -147,12 +147,11 @@ static void i440fx_fuzz_qos(QTestState *s,
 
 static void i440fx_fuzz_qos_fork(QTestState *s,
         const unsigned char *Data, size_t Size) {
-    if (fork() == 0) {
+    if (fork_fuzzer_and_wait()) {
         i440fx_fuzz_qos(s, Data, Size);
         _Exit(0);
     } else {
         flush_events(s);
-        wait(NULL);
     }
 }
 
diff --git a/tests/qtest/fuzz/virtio_blk_fuzz.c 
b/tests/qtest/fuzz/virtio_blk_fuzz.c
index 623a756fd4..9532dc1fa7 100644
--- a/tests/qtest/fuzz/virtio_blk_fuzz.c
+++ b/tests/qtest/fuzz/virtio_blk_fuzz.c
@@ -136,13 +136,12 @@ static void virtio_blk_fork_fuzz(QTestState *s,
     if (!queues) {
         queues = qvirtio_blk_init(blk->vdev, 0);
     }
-    if (fork() == 0) {
+    if (fork_fuzzer_and_wait()) {
         virtio_blk_fuzz(s, queues, Data, Size);
         flush_events(s);
         _Exit(0);
     } else {
         flush_events(s);
-        wait(NULL);
     }
 }
 
@@ -152,7 +151,7 @@ static void virtio_blk_with_flag_fuzz(QTestState *s,
     QVirtioBlk *blk = fuzz_qos_obj;
     static QVirtioBlkQueues *queues;
 
-    if (fork() == 0) {
+    if (fork_fuzzer_and_wait()) {
         if (Size >= sizeof(uint64_t)) {
             queues = qvirtio_blk_init(blk->vdev, *(uint64_t *)Data);
             virtio_blk_fuzz(s, queues,
@@ -162,7 +161,6 @@ static void virtio_blk_with_flag_fuzz(QTestState *s,
         _Exit(0);
     } else {
         flush_events(s);
-        wait(NULL);
     }
 }
 
diff --git a/tests/qtest/fuzz/virtio_net_fuzz.c 
b/tests/qtest/fuzz/virtio_net_fuzz.c
index 0e873ab8e2..6b492ef9e7 100644
--- a/tests/qtest/fuzz/virtio_net_fuzz.c
+++ b/tests/qtest/fuzz/virtio_net_fuzz.c
@@ -118,26 +118,24 @@ static void virtio_net_fuzz_multi(QTestState *s,
 static void virtio_net_fork_fuzz(QTestState *s,
         const unsigned char *Data, size_t Size)
 {
-    if (fork() == 0) {
+    if (fork_fuzzer_and_wait()) {
         virtio_net_fuzz_multi(s, Data, Size, false);
         flush_events(s);
         _Exit(0);
     } else {
         flush_events(s);
-        wait(NULL);
     }
 }
 
 static void virtio_net_fork_fuzz_check_used(QTestState *s,
         const unsigned char *Data, size_t Size)
 {
-    if (fork() == 0) {
+    if (fork_fuzzer_and_wait()) {
         virtio_net_fuzz_multi(s, Data, Size, true);
         flush_events(s);
         _Exit(0);
     } else {
         flush_events(s);
-        wait(NULL);
     }
 }
 
diff --git a/tests/qtest/fuzz/virtio_scsi_fuzz.c 
b/tests/qtest/fuzz/virtio_scsi_fuzz.c
index 6ff6fabe4a..c7eaf3242b 100644
--- a/tests/qtest/fuzz/virtio_scsi_fuzz.c
+++ b/tests/qtest/fuzz/virtio_scsi_fuzz.c
@@ -140,13 +140,12 @@ static void virtio_scsi_fork_fuzz(QTestState *s,
     if (!queues) {
         queues = qvirtio_scsi_init(scsi->vdev, 0);
     }
-    if (fork() == 0) {
+    if (fork_fuzzer_and_wait()) {
         virtio_scsi_fuzz(s, queues, Data, Size);
         flush_events(s);
         _Exit(0);
     } else {
         flush_events(s);
-        wait(NULL);
     }
 }
 
@@ -156,7 +155,7 @@ static void virtio_scsi_with_flag_fuzz(QTestState *s,
     QVirtioSCSI *scsi = fuzz_qos_obj;
     static QVirtioSCSIQueues *queues;
 
-    if (fork() == 0) {
+    if (fork_fuzzer_and_wait()) {
         if (Size >= sizeof(uint64_t)) {
             queues = qvirtio_scsi_init(scsi->vdev, *(uint64_t *)Data);
             virtio_scsi_fuzz(s, queues,
@@ -166,7 +165,6 @@ static void virtio_scsi_with_flag_fuzz(QTestState *s,
         _Exit(0);
     } else {
         flush_events(s);
-        wait(NULL);
     }
 }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]