Message ID | 20190725032321.12721-11-alxndr@bu.edu (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add virtual device fuzzing support | expand |
On 25/07/19 05:23, Oleinik, Alexander wrote: > Export normal qemu-system main so it can be called from tests/fuzz/fuzz.c > > Signed-off-by: Alexander Oleinik <alxndr@bu.edu> > --- > include/sysemu/sysemu.h | 4 ++++ > vl.c | 21 ++++++++++++++++++++- > 2 files changed, 24 insertions(+), 1 deletion(-) > > diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h > index 984c439ac9..1bb8cf184c 100644 > --- a/include/sysemu/sysemu.h > +++ b/include/sysemu/sysemu.h > @@ -184,6 +184,10 @@ QemuOpts *qemu_get_machine_opts(void); > > bool defaults_enabled(void); > > +#ifdef CONFIG_FUZZ > +int real_main(int argc, char **argv, char **envp); > +#endif > + > extern QemuOptsList qemu_legacy_drive_opts; > extern QemuOptsList qemu_common_drive_opts; > extern QemuOptsList qemu_drive_opts; > diff --git a/vl.c b/vl.c > index b426b32134..b71b99b6f8 100644 > --- a/vl.c > +++ b/vl.c > @@ -130,6 +130,10 @@ int main(int argc, char **argv) > #include "sysemu/iothread.h" > #include "qemu/guest-random.h" > > +#ifdef CONFIG_FUZZ > +#include "tests/libqtest.h" > +#endif > + > #define MAX_VIRTIO_CONSOLES 1 > > static const char *data_dir[16]; > @@ -2853,8 +2857,11 @@ static void user_register_global_props(void) > qemu_opts_foreach(qemu_find_opts("global"), > global_init_func, NULL, NULL); > } > - > +#ifdef CONFIG_FUZZ > +int real_main(int argc, char **argv, char **envp) > +#else > int main(int argc, char **argv, char **envp) > +#endif > { > int i; > int snapshot, linux_boot; > @@ -2903,7 +2910,9 @@ int main(int argc, char **argv, char **envp) > atexit(qemu_run_exit_notifiers); > qemu_init_exec_dir(argv[0]); > > +#ifndef CONFIG_FUZZ // QOM is already set up by the fuzzer. > module_call_init(MODULE_INIT_QOM); > +#endif You can modify module_call_init to record the modules that have been initialized, and skip the call (i.e. make it idempotent). > qemu_add_opts(&qemu_drive_opts); > qemu_add_drive_opts(&qemu_legacy_drive_opts); > @@ -4196,9 +4205,11 @@ int main(int argc, char **argv, char **envp) > */ > migration_object_init(); > > +#ifndef CONFIG_FUZZ // Already set up by the fuzzer > if (qtest_chrdev) { > qtest_init(qtest_chrdev, qtest_log, &error_fatal); > } > +#endif Here, I suspect the fuzzing target would have qtest_chrdev == NULL, therefore you can assert that qtest_init is only called once. For example, add an assert(!test_log_fp) in the function. > machine_opts = qemu_get_machine_opts(); > kernel_filename = qemu_opt_get(machine_opts, "kernel"); > @@ -4470,6 +4481,14 @@ int main(int argc, char **argv, char **envp) > accel_setup_post(current_machine); > os_setup_post(); > > +/* > + * Return to the fuzzer since it will run qtest programs and run the > + * main_loop > +*/ > +#ifdef CONFIG_FUZZ > + return 0; > +#endif Just place everything up to this point into a new function qemu_init(); for CONFIG_FUZZ that's what you call from LLVMFuzzerInitialize, while for !CONFIG_FUZZ you can call it from main(). All the functions below have no arguments, so the patch is trivial. Paolo > main_loop(); > > gdbserver_cleanup(); >
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 984c439ac9..1bb8cf184c 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -184,6 +184,10 @@ QemuOpts *qemu_get_machine_opts(void); bool defaults_enabled(void); +#ifdef CONFIG_FUZZ +int real_main(int argc, char **argv, char **envp); +#endif + extern QemuOptsList qemu_legacy_drive_opts; extern QemuOptsList qemu_common_drive_opts; extern QemuOptsList qemu_drive_opts; diff --git a/vl.c b/vl.c index b426b32134..b71b99b6f8 100644 --- a/vl.c +++ b/vl.c @@ -130,6 +130,10 @@ int main(int argc, char **argv) #include "sysemu/iothread.h" #include "qemu/guest-random.h" +#ifdef CONFIG_FUZZ +#include "tests/libqtest.h" +#endif + #define MAX_VIRTIO_CONSOLES 1 static const char *data_dir[16]; @@ -2853,8 +2857,11 @@ static void user_register_global_props(void) qemu_opts_foreach(qemu_find_opts("global"), global_init_func, NULL, NULL); } - +#ifdef CONFIG_FUZZ +int real_main(int argc, char **argv, char **envp) +#else int main(int argc, char **argv, char **envp) +#endif { int i; int snapshot, linux_boot; @@ -2903,7 +2910,9 @@ int main(int argc, char **argv, char **envp) atexit(qemu_run_exit_notifiers); qemu_init_exec_dir(argv[0]); +#ifndef CONFIG_FUZZ // QOM is already set up by the fuzzer. module_call_init(MODULE_INIT_QOM); +#endif qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); @@ -4196,9 +4205,11 @@ int main(int argc, char **argv, char **envp) */ migration_object_init(); +#ifndef CONFIG_FUZZ // Already set up by the fuzzer if (qtest_chrdev) { qtest_init(qtest_chrdev, qtest_log, &error_fatal); } +#endif machine_opts = qemu_get_machine_opts(); kernel_filename = qemu_opt_get(machine_opts, "kernel"); @@ -4470,6 +4481,14 @@ int main(int argc, char **argv, char **envp) accel_setup_post(current_machine); os_setup_post(); +/* + * Return to the fuzzer since it will run qtest programs and run the + * main_loop +*/ +#ifdef CONFIG_FUZZ + return 0; +#endif + main_loop(); gdbserver_cleanup();
Export normal qemu-system main so it can be called from tests/fuzz/fuzz.c Signed-off-by: Alexander Oleinik <alxndr@bu.edu> --- include/sysemu/sysemu.h | 4 ++++ vl.c | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-)