Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ViDeZZo fork mode bug on vbox #18

Open
blabla-my opened this issue Oct 30, 2024 · 0 comments
Open

ViDeZZo fork mode bug on vbox #18

blabla-my opened this issue Oct 30, 2024 · 0 comments

Comments

@blabla-my
Copy link

blabla-my commented Oct 30, 2024

Environment

Vbox version: 7.0.20 downloaded from https://download.virtualbox.org/virtualbox/7.0.20/VirtualBox-7.0.20.tar.bz2
ViDeZZo: docker container

Problem

A lot of segmentation fault while fuzzing with VIDEZZO_FORK=1, reported by UBSAN

SEGV on unknown address 0x7ffff7b340ab (pc 0x7ffff733b06e bp 0x7fffffffdcd0 sp 0x7fffffffdb50 T1547149)

The pc value 0x7ffff733b06e point to PGMPhysRead() in VBoxVMM.so. According to gdb, the machine code here is :

mov al, BYTE PTR [rip+0x7f9037]    #0x7ffff733b06e

GDB shows address 0x7ffff733b06e cannot be accessed.

Root Cause

In fork mode, ViDeZZo will fork a child to execute input.

In the parent process, VBoxVMM.so is mapped as follow:

7ffff68f9000-7ffff6c4c000 r--p 00000000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so
7ffff6c4c000-7ffff74b1000 r-xp 00353000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so
7ffff74b1000-7ffff7858000 r--p 00bb8000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so
7ffff7858000-7ffff78a8000 r--p 00f5e000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so
7ffff78a8000-7ffff7c1e000 rw-p 00fae000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so

However, in the child process, VBoxVMM.so is mapped as follow. We can see that 7ffff78a8000-7ffff7c1e000 disappears in the child process memory map. The segmentation fault is due to accessing this missing region.

7ffff68f9000-7ffff6c4c000 r--p 00000000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so
7ffff6c4c000-7ffff74b1000 r-xp 00353000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so
7ffff74b1000-7ffff7858000 r--p 00bb8000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so
7ffff7858000-7ffff78a8000 r--p 00f5e000 08:02 12451903                   /root/videzzo/videzzo_vbox-7.0.20/out-cov/VBoxVMM.so

I don't really know why this region is not inherited by the child. I guess while vbox loads VBoxVMM.so, it will invoke madvice() to make this region MADV_DONTFORK. (https://man7.org/linux/man-pages/man2/madvise.2.html).

Solution

As a workaround, I invoke madvice to set this region MADV_DOFORK in VBoxViDeZZo.cpp::LLVMFuzzerInitialize. Therefore, the segmentation fault disappears. The patch is below:

diff --git a/videzzo_vbox/VBoxViDeZZo.cpp b/videzzo_vbox/VBoxViDeZZo.cpp
index a49e7e0..f3442a8 100644
--- a/videzzo_vbox/VBoxViDeZZo.cpp
+++ b/videzzo_vbox/VBoxViDeZZo.cpp
@@ -1008,6 +1008,38 @@ static void cleanup(int sig) {
     exit(0);
 }

+void find_and_apply_madvise() {
+    FILE *maps_file = fopen("/proc/self/maps", "r");
+    if (!maps_file) {
+        perror("fopen");
+        return;
+    }
+
+    char line[256];
+    unsigned long start, end;
+    char permissions[5];
+    char path[256];
+
+    // Iterate through each line in /proc/self/maps
+    while (fgets(line, sizeof(line), maps_file)) {
+        // Parse the line to extract the memory region info
+        if (sscanf(line, "%lx-%lx %4s %*s %*s %*s %s", &start, &end, permissions, path) == 4) {
+            // Check if the path matches VBoxVMM.so and permissions include rw-
+            if (strstr(path, "VBoxVMM.so") && strcmp(permissions, "rw-p") == 0) {
+                // Apply madvise with MADV_DONTFORK on the found segment
+                if (madvise((void *)start, end - start, MADV_DOFORK) != 0) {
+                    perror("madvise");
+                } else {
+                    printf("Applied MADV_DONTFORK on segment: %lx-%lx\n", start, end);
+                }
+                break;
+            }
+        }
+    }
+
+    fclose(maps_file);
+}
+
 int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
 {
     char *target_name = nullptr;
@@ -1132,5 +1164,8 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
     // signal(SIGTERM, SIG_DFL);
     // signal(SIGUSR1, SIG_DFL);

+    // disable MADV_DONTFORK on VBoxVMM.so
+    find_and_apply_madvise();
+
     return 0;
 }
@blabla-my blabla-my changed the title ViDeZZo fork mode on vbox ViDeZZo fork mode bug on vbox Oct 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant