diff mbox series

[1/4] fuzz: add datadir for oss-fuzz compatability

Message ID 20200512030133.29896-2-alxndr@bu.edu (mailing list archive)
State New, archived
Headers show
Series fuzz: misc changes for oss-fuzz compatability | expand

Commit Message

Alexander Bulekov May 12, 2020, 3:01 a.m. UTC
This allows us to keep pc-bios in executable_dir/pc-bios, rather than
executable_dir/../pc-bios, which is incompatible with oss-fuzz' file
structure.

Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
---
 include/sysemu/sysemu.h |  2 ++
 softmmu/vl.c            |  2 +-
 tests/qtest/fuzz/fuzz.c | 15 +++++++++++++++
 3 files changed, 18 insertions(+), 1 deletion(-)

Comments

Darren Kenny May 12, 2020, 7:59 a.m. UTC | #1
On Monday, 2020-05-11 at 23:01:30 -04, Alexander Bulekov wrote:
> This allows us to keep pc-bios in executable_dir/pc-bios, rather than
> executable_dir/../pc-bios, which is incompatible with oss-fuzz' file
> structure.
>
> Signed-off-by: Alexander Bulekov <alxndr@bu.edu>

Reviewed-by: Darren Kenny <darren.kenny@oracle.com>

> ---
>  include/sysemu/sysemu.h |  2 ++
>  softmmu/vl.c            |  2 +-
>  tests/qtest/fuzz/fuzz.c | 15 +++++++++++++++
>  3 files changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index ef81302e1a..cc96b66fc9 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -15,6 +15,8 @@ extern const char *qemu_name;
>  extern QemuUUID qemu_uuid;
>  extern bool qemu_uuid_set;
>  
> +void qemu_add_data_dir(const char *path);
> +
>  void qemu_add_exit_notifier(Notifier *notify);
>  void qemu_remove_exit_notifier(Notifier *notify);
>  
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index afd2615fb3..c71485a965 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -1993,7 +1993,7 @@ char *qemu_find_file(int type, const char *name)
>      return NULL;
>  }
>  
> -static void qemu_add_data_dir(const char *path)
> +void qemu_add_data_dir(const char *path)
>  {
>      int i;
>  
> diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
> index f5c923852e..33365c3782 100644
> --- a/tests/qtest/fuzz/fuzz.c
> +++ b/tests/qtest/fuzz/fuzz.c
> @@ -137,6 +137,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
>  {
>  
>      char *target_name;
> +    char *dir;
>  
>      /* Initialize qgraph and modules */
>      qos_graph_init();
> @@ -147,6 +148,20 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
>      target_name = strstr(**argv, "-target-");
>      if (target_name) {        /* The binary name specifies the target */
>          target_name += strlen("-target-");
> +        /*
> +         * With oss-fuzz, the executable is kept in the root of a directory (we
> +         * cannot assume the path). All data (including bios binaries) must be
> +         * in the same dir, or a subdir. Thus, we cannot place the pc-bios so
> +         * that it would be in exec_dir/../pc-bios.
> +         * As a workaround, oss-fuzz allows us to use argv[0] to get the
> +         * location of the executable. Using this we add exec_dir/pc-bios to
> +         * the datadirs.
> +         */
> +        dir = g_build_filename(g_path_get_dirname(**argv), "pc-bios", NULL);
> +        if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
> +            qemu_add_data_dir(dir);
> +        }
> +        g_free(dir);
>      } else if (*argc > 1) {  /* The target is specified as an argument */
>          target_name = (*argv)[1];
>          if (!strstr(target_name, "--fuzz-target=")) {
> -- 
> 2.26.2
Philippe Mathieu-Daudé May 20, 2020, 4:51 p.m. UTC | #2
On 5/12/20 5:01 AM, Alexander Bulekov wrote:
> This allows us to keep pc-bios in executable_dir/pc-bios, rather than
> executable_dir/../pc-bios, which is incompatible with oss-fuzz' file
> structure.
> 
> Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
> ---
>   include/sysemu/sysemu.h |  2 ++
>   softmmu/vl.c            |  2 +-
>   tests/qtest/fuzz/fuzz.c | 15 +++++++++++++++
>   3 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index ef81302e1a..cc96b66fc9 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -15,6 +15,8 @@ extern const char *qemu_name;
>   extern QemuUUID qemu_uuid;
>   extern bool qemu_uuid_set;
>   
> +void qemu_add_data_dir(const char *path);
> +
>   void qemu_add_exit_notifier(Notifier *notify);
>   void qemu_remove_exit_notifier(Notifier *notify);
>   
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index afd2615fb3..c71485a965 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -1993,7 +1993,7 @@ char *qemu_find_file(int type, const char *name)
>       return NULL;
>   }
>   
> -static void qemu_add_data_dir(const char *path)
> +void qemu_add_data_dir(const char *path)
>   {
>       int i;
>   
> diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
> index f5c923852e..33365c3782 100644
> --- a/tests/qtest/fuzz/fuzz.c
> +++ b/tests/qtest/fuzz/fuzz.c
> @@ -137,6 +137,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
>   {
>   
>       char *target_name;
> +    char *dir;
>   
>       /* Initialize qgraph and modules */
>       qos_graph_init();
> @@ -147,6 +148,20 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
>       target_name = strstr(**argv, "-target-");
>       if (target_name) {        /* The binary name specifies the target */
>           target_name += strlen("-target-");
> +        /*
> +         * With oss-fuzz, the executable is kept in the root of a directory (we
> +         * cannot assume the path). All data (including bios binaries) must be
> +         * in the same dir, or a subdir. Thus, we cannot place the pc-bios so
> +         * that it would be in exec_dir/../pc-bios.
> +         * As a workaround, oss-fuzz allows us to use argv[0] to get the
> +         * location of the executable. Using this we add exec_dir/pc-bios to
> +         * the datadirs.

I don't understand well the problem. How do you run it?

> +         */
> +        dir = g_build_filename(g_path_get_dirname(**argv), "pc-bios", NULL);
> +        if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
> +            qemu_add_data_dir(dir);
> +        }
> +        g_free(dir);
>       } else if (*argc > 1) {  /* The target is specified as an argument */
>           target_name = (*argv)[1];
>           if (!strstr(target_name, "--fuzz-target=")) {
>
Alexander Bulekov May 20, 2020, 6:07 p.m. UTC | #3
On 200520 1851, Philippe Mathieu-Daudé wrote:
> On 5/12/20 5:01 AM, Alexander Bulekov wrote:

-snip-
> > +        /*
> > +         * With oss-fuzz, the executable is kept in the root of a directory (we
> > +         * cannot assume the path). All data (including bios binaries) must be
> > +         * in the same dir, or a subdir. Thus, we cannot place the pc-bios so
> > +         * that it would be in exec_dir/../pc-bios.
> > +         * As a workaround, oss-fuzz allows us to use argv[0] to get the
> > +         * location of the executable. Using this we add exec_dir/pc-bios to
> > +         * the datadirs.
> 
> I don't understand well the problem. How do you run it?

On oss-fuzz, the build and execution happens in two separate containers.

1.) In the build container, we can do whatever we want, but we must
place the executable(s) we produce at the root of a directory /out/.
e.g. one output executable is /out/qemu-system-target-i440fx-fuzz

2.) In the runner, this "build artifact" directory is mounted at
some location(we can't assume the location). This runner container
automatically identifies the executable within the root of the  "build
artifact" dir and runs it. The path to the executable could now be 
/somedir/qemu-system-target-i440fx-fuzz

In the runner container we only have control over the files in /somedir/
(which was /out/ in the builder). Thus, in addition to copying over
shared-libs to /out/ we need to copy any data (pc-bios) that the binary
relies on. The problem is that we have to point qemu towards the
location of the bios. Normally qemu checks the /usr/share/... dir. For
local builds, qemu also examines the executable path and looks in
$executable_path/../pc-bios/. On the oss-fuzz runner we dont control
/somedir/../pc-bios, so we can't rely on this. This patch allows us to
specify /somedir/pc-bios as the datadir.

Hopefully that is not too confusing.

For reference, here is a draft of the build-script that I expect to
deploy to oss-fuzz:

# build project
# e.g.
# ./autogen.sh
# ./configure
# make -j$(nproc) all

# build fuzzers
# e.g.
# $CXX $CXXFLAGS -std=c++11 -Iinclude \
#     /path/to/name_of_fuzzer.cc -o $OUT/name_of_fuzzer \
#     $LIB_FUZZING_ENGINE /path/to/library.a

# make a dir for the shared libs
mkdir -p $OUT/lib/

#Build once to copy over the list of dynamic libs
./configure --datadir="./data/" --disable-werror --cc="$CC" --cxx="$CXX" --extra-cflags="$CFLAGS -U __OPTIMIZE__ "
make CONFIG_FUZZ=y CFLAGS="$LIB_FUZZING_ENGINE" -j$(nproc) i386-softmmu/fuzz

# copy over the shared libs
for i in $(ldd ./i386-softmmu/qemu-fuzz-i386  | cut -f3 -d' '); do
    cp $i $OUT/lib/
done
rm ./i386-softmmu/qemu-fuzz-i386

# Build second time to build the final binary with correct rpath
./configure --datadir="./data/" --disable-werror --cc="$CC" --cxx="$CXX" --extra-cflags="$CFLAGS -U __OPTIMIZE__" --extra-ldflags="-Wl,-rpath,'\$\$ORIGIN/lib'"
make CONFIG_FUZZ=y CFLAGS="$LIB_FUZZING_ENGINE" -j$(nproc) i386-softmmu/fuzz

# copy over bios data
cp  -r ./pc-bios/ $OUT/pc-bios
for target in $(./i386-softmmu/qemu-fuzz-i386 | awk '$1 ~ /\*/  {print $2}');
do
    cp ./i386-softmmu/qemu-fuzz-i386 $OUT/qemu-fuzz-i386-target-$target
done

-Alex
> 
> > +         */
> > +        dir = g_build_filename(g_path_get_dirname(**argv), "pc-bios", NULL);
> > +        if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
> > +            qemu_add_data_dir(dir);
> > +        }
> > +        g_free(dir);
> >       } else if (*argc > 1) {  /* The target is specified as an argument */
> >           target_name = (*argv)[1];
> >           if (!strstr(target_name, "--fuzz-target=")) {
> > 
>
diff mbox series

Patch

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index ef81302e1a..cc96b66fc9 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -15,6 +15,8 @@  extern const char *qemu_name;
 extern QemuUUID qemu_uuid;
 extern bool qemu_uuid_set;
 
+void qemu_add_data_dir(const char *path);
+
 void qemu_add_exit_notifier(Notifier *notify);
 void qemu_remove_exit_notifier(Notifier *notify);
 
diff --git a/softmmu/vl.c b/softmmu/vl.c
index afd2615fb3..c71485a965 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -1993,7 +1993,7 @@  char *qemu_find_file(int type, const char *name)
     return NULL;
 }
 
-static void qemu_add_data_dir(const char *path)
+void qemu_add_data_dir(const char *path)
 {
     int i;
 
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
index f5c923852e..33365c3782 100644
--- a/tests/qtest/fuzz/fuzz.c
+++ b/tests/qtest/fuzz/fuzz.c
@@ -137,6 +137,7 @@  int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
 {
 
     char *target_name;
+    char *dir;
 
     /* Initialize qgraph and modules */
     qos_graph_init();
@@ -147,6 +148,20 @@  int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
     target_name = strstr(**argv, "-target-");
     if (target_name) {        /* The binary name specifies the target */
         target_name += strlen("-target-");
+        /*
+         * With oss-fuzz, the executable is kept in the root of a directory (we
+         * cannot assume the path). All data (including bios binaries) must be
+         * in the same dir, or a subdir. Thus, we cannot place the pc-bios so
+         * that it would be in exec_dir/../pc-bios.
+         * As a workaround, oss-fuzz allows us to use argv[0] to get the
+         * location of the executable. Using this we add exec_dir/pc-bios to
+         * the datadirs.
+         */
+        dir = g_build_filename(g_path_get_dirname(**argv), "pc-bios", NULL);
+        if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
+            qemu_add_data_dir(dir);
+        }
+        g_free(dir);
     } else if (*argc > 1) {  /* The target is specified as an argument */
         target_name = (*argv)[1];
         if (!strstr(target_name, "--fuzz-target=")) {