From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: "Oleinik, Alexander" <alxndr@bu.edu>,
"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Cc: "pbonzini@redhat.com" <pbonzini@redhat.com>,
"bsd@redhat.com" <bsd@redhat.com>,
"superirishdonkey@gmail.com" <superirishdonkey@gmail.com>,
"stefanha@redhat.com" <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [RFC 16/19] fuzz: add general fuzzer entrypoints
Date: Thu, 25 Jul 2019 19:53:19 +0200 [thread overview]
Message-ID: <139e1ca9-0da3-277b-baa6-94aa5372baac@redhat.com> (raw)
In-Reply-To: <20190725032321.12721-17-alxndr@bu.edu>
Hi Aleksander,
On 7/25/19 5:23 AM, Oleinik, Alexander wrote:
> Defines LLVMFuzzerInitialize and LLVMFuzzerTestOneInput
>
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
> tests/fuzz/fuzz.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++
> tests/fuzz/fuzz.h | 96 +++++++++++++++++
> 2 files changed, 358 insertions(+)
> create mode 100644 tests/fuzz/fuzz.c
> create mode 100644 tests/fuzz/fuzz.h
>
> diff --git a/tests/fuzz/fuzz.c b/tests/fuzz/fuzz.c
> new file mode 100644
> index 0000000000..0421b9402c
> --- /dev/null
> +++ b/tests/fuzz/fuzz.c
> @@ -0,0 +1,262 @@
> +#include "tests/fuzz/ramfile.h"
> +#include "migration/qemu-file.h"
> +#include "migration/global_state.h"
> +#include "migration/savevm.h"
> +#include "tests/libqtest.h"
> +#include "exec/memory.h"
> +#include "migration/migration.h"
> +#include "fuzz.h"
> +#include "tests/libqos/qgraph.h"
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <linux/userfaultfd.h>
> +#include <poll.h>
> +#include <pthread.h>
> +#include <sys/syscall.h>
> +#include <sys/types.h>
> +#include <sys/ioctl.h>
> +
> +QTestState *s;
> +
> +QEMUFile *ramfile;
> +QEMUFile *writefile;
> +ram_disk *rd;
> +typedef QSLIST_HEAD(, FuzzTarget) FuzzTargetList;
> +
> +FuzzTargetList* fuzz_target_list;
> +
> +uint64_t total_mr_size = 0;
> +uint64_t mr_index = 0;
> +
> +const MemoryRegion* mrs[1000];
> +
> +
> +// Save just the VMStateDescriptors
> +void save_device_state(void)
> +{
> + writefile = qemu_fopen_ram(&rd);
> + global_state_store();
> + qemu_save_device_state(writefile);
> + qemu_fflush(writefile);
> + ramfile = qemu_fopen_ro_ram(rd);
> +}
> +
> +// Save the entire vm state including RAM
> +void save_vm_state(void)
> +{
> + writefile = qemu_fopen_ram(&rd);
> + vm_stop(RUN_STATE_SAVE_VM);
> + global_state_store();
> + qemu_savevm_state(writefile, NULL);
> + qemu_fflush(writefile);
> + ramfile = qemu_fopen_ro_ram(rd);
> +}
> +
> +/* Reset state by rebooting */
> +void reboot()
> +{
> + qemu_system_reset(SHUTDOWN_CAUSE_NONE);
> +}
> +
> +/* Restore device state */
> +void load_device_state()
> +{
> + qemu_freopen_ro_ram(ramfile);
> +
> + int ret = qemu_load_device_state(ramfile);
> + if (ret < 0){
> + printf("reset error\n");
> + exit(-1);
> + }
> +}
> +
> +/* Restore full vm state */
> +void load_vm_state()
> +{
> + qemu_freopen_ro_ram(ramfile);
> +
> + vm_stop(RUN_STATE_RESTORE_VM);
> + /* qemu_system_reset(SHUTDOWN_CAUSE_NONE); */
> +
> + int ret = qemu_loadvm_state(ramfile);
> + if (ret < 0){
> + printf("reset error\n");
> + exit(-1);
> + }
> + migration_incoming_state_destroy();
> + vm_start();
> +}
> +
> +void qtest_setup()
> +{
> + s = qtest_init_fuzz(NULL, NULL);
> + global_qtest = s;
> +}
> +
> +void fuzz_add_target(const char* name,
> + const char* description,
> + void(*init_pre_main)(void),
> + void(*init_pre_save)(void),
> + void(*save_state)(void),
> + void(*reset)(void),
> + void(*pre_fuzz)(void),
> + void(*fuzz)(const unsigned char*, size_t),
> + void(*post_fuzz)(void),
> + int* main_argc,
> + char*** main_argv)
> +{
> +
> + FuzzTarget *target;
> + FuzzTarget *tmp;
> + if(!fuzz_target_list)
> + fuzz_target_list = g_new0(FuzzTargetList, 1);
> +
> + QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
> + if (g_strcmp0(tmp->name->str, name) == 0) {
> + fprintf(stderr, "Error: Fuzz target name %s already in use\n", name);
> + abort();
> + }
> + }
> + target = g_new0(FuzzTarget, 1);
> + target->name = g_string_new(name);
> + target->description = g_string_new(description);
> + target->init_pre_main = init_pre_main;
> + target->init_pre_save = init_pre_save;
> + target->save_state = save_state;
> + target->reset = reset;
> + target->pre_fuzz = pre_fuzz;
> + target->fuzz = fuzz;
> + target->post_fuzz = post_fuzz;
> + target->main_argc = main_argc;
> + target->main_argv = main_argv;
> + QSLIST_INSERT_HEAD(fuzz_target_list, target, target_list);
> +}
> +
> +
> +FuzzTarget* fuzz_get_target(char* name)
> +{
> + FuzzTarget* tmp;
> + if(!fuzz_target_list){
> + fprintf(stderr, "Fuzz target list not initialized");
> + abort();
> + }
> +
> + QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
> + if (g_strcmp0(tmp->name->str, name) == 0) {
> + break;
> + }
> + }
> + return tmp;
> +}
> +
> +FuzzTarget* fuzz_target;
> +
> +
> +
> +static void usage(void)
> +{
> + printf("Usage: ./fuzz --FUZZ_TARGET [LIBFUZZER ARGUMENTS]\n");
> + printf("where --FUZZ_TARGET is one of:\n");
> + FuzzTarget* tmp;
> + if(!fuzz_target_list){
> + fprintf(stderr, "Fuzz target list not initialized");
> + abort();
> + }
> + QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
> + QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
> + printf(" --%s : %s\n", tmp->name->str, tmp->description->str);
> + }
> + exit(0);
> + }
> +}
> +
> +// TODO: Replace this with QEMU's built-in linked list
> +static void enum_memory(void)
> +{
> + mtree_info(true, true, true);
> + fuzz_memory_region *fmr = g_new0(fuzz_memory_region, 1);
> +
> + fmr->io = false;
> + fmr->start = 0x100000;
> + fmr->length = 0x10000;
> + fmr->next = fuzz_memory_region_head;
> + fuzz_memory_region_tail->next = fmr;
> + fuzz_memory_region_tail = fmr;
> + fmr = fuzz_memory_region_head;
> +
> + while(true){
> + fmr = fmr->next;
> + if(fmr == fuzz_memory_region_head)
> + break;
> + }
> +}
> +
> +/* Executed for each fuzzing-input */
> +int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size)
> +{
> + /* e.g. Device bootstrapping */
> + if(fuzz_target->pre_fuzz)
> + fuzz_target->pre_fuzz();
> +
> + if(fuzz_target->fuzz)
> + fuzz_target->fuzz(Data, Size);
> +
> + /* e.g. Copy counter bitmap to shm*/
> + if(fuzz_target->post_fuzz)
> + fuzz_target->post_fuzz();
> +
> + /* e.g. Reboot the machine or vmload */
> + if(fuzz_target->reset)
> + fuzz_target->reset();
> +
> + return 0;
> +}
> +
> +/* Executed once, prior to fuzzing */
> +int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
> +{
> +
> + char *target_name;
> +
> + // Initialize qgraph and modules
> + qos_graph_init();
> + module_call_init(MODULE_INIT_FUZZ_TARGET);
> + module_call_init(MODULE_INIT_QOM);
> + module_call_init(MODULE_INIT_LIBQOS);
> +
> + if(*argc <= 1)
> + usage();
> +
> +
> + /* Identify the fuzz target */
> + target_name = (*argv)[1];
> + target_name+=2;
> + fuzz_target = fuzz_get_target(target_name);
> +
> + if(!fuzz_target)
> + {
> + fprintf(stderr, "Error: Fuzz fuzz_target name %s not found\n", target_name);
> + usage();
> + }
> +
> + if(fuzz_target->init_pre_main)
> + fuzz_target->init_pre_main();
> +
> + /* Run QEMU's regular vl.c:main */
> + real_main(*(fuzz_target->main_argc), *(fuzz_target->main_argv), NULL);
> +
> +
> + /* Enumerate memory to identify mapped MMIO and I/O regions */
> + enum_memory();
> +
> + /* Good place to do any one-time device initialization (such as QOS init) */
> + if(fuzz_target->init_pre_save)
> + fuzz_target->init_pre_save();
> +
> + /* If configured, this is where we save vm or device state to ramdisk */
> + if(fuzz_target->save_state)
> + fuzz_target->save_state();
> +
> + return 0;
> +}
> diff --git a/tests/fuzz/fuzz.h b/tests/fuzz/fuzz.h
> new file mode 100644
> index 0000000000..02f26752eb
> --- /dev/null
> +++ b/tests/fuzz/fuzz.h
> @@ -0,0 +1,96 @@
> +#ifndef FUZZER_H_
> +#define FUZZER_H_
> +
> +#include "qemu/osdep.h"
> +#include "qemu/units.h"
> +#include "qapi/error.h"
> +#include "exec/memory.h"
> +#include "tests/libqtest.h"
> +#include "migration/qemu-file.h"
> +#include "ramfile.h"
> +
> +#include <linux/userfaultfd.h>
> +
> +
> +extern QTestState *s;
> +extern QEMUFile *writefile;
> +extern QEMUFile *ramfile;
> +extern ram_disk *rd;
> +
> +typedef struct FuzzTarget {
> + GString* name;
> + GString* description;
> + void(*init_pre_main)(void);
> + void(*init_pre_save)(void);
> + void(*save_state)(void);
> + void(*reset)(void);
> + void(*pre_fuzz)(void);
> + void(*fuzz)(const unsigned char*, size_t);
> + void(*post_fuzz)(void);
> + int* main_argc;
> + char*** main_argv;
> + QSLIST_ENTRY(FuzzTarget) target_list;
> +
> +} FuzzTarget;
> +
> +extern void* _ZN6fuzzer3TPCE;
> +/* extern uint8_t __sancov_trace_pc_guard_8bit_counters; */
> +/* extern uint8_t __sancov_trace_pc_pcs; */
> +extern void* __prof_nms_sect_data;
> +extern void* __prof_vnodes_sect_data;
> +
> +#define TPC_SIZE 0x0443c00
> +#define PROFILE_SIZE ( &__prof_vnodes_sect_data - &__prof_nms_sect_data)
> +
> +#define NUMPCS (1 << 21)
> +/* #define TPC_SIZE 0x33c00 */
> +
> +extern uint8_t *TPCCopy;
> +extern uint8_t *ARGCopy;
> +
> +void save_device_state(void);
> +void save_vm_state(void);
> +void reboot(void);
> +
> +void load_device_state(void);
> +void load_vm_state(void);
> +
> +
> +void save_device_state(void);
> +void qtest_setup(void);
> +void fuzz_register_mr(const MemoryRegion *mr);
> +
> +FuzzTarget* fuzz_get_target(char* name);
> +
> +extern FuzzTarget* fuzz_target;
> +
> +typedef struct fuzz_memory_region {
> + bool io;
> + uint64_t start;
> + uint64_t length;
> + struct fuzz_memory_region* next;
> +} fuzz_memory_region;
> +
> +extern fuzz_memory_region *fuzz_memory_region_head;
> +extern fuzz_memory_region *fuzz_memory_region_tail;
> +
> +extern uint64_t total_io_mem;
> +extern uint64_t total_ram_mem;
> +
> +void fuzz_add_target(const char* name,
> + const char* description,
> + void(*init_pre_main)(void),
> + void(*init_pre_save)(void),
> + void(*save_state)(void),
> + void(*reset)(void),
> + void(*pre_fuzz)(void),
> + void(*fuzz)(const unsigned char*, size_t),
> + void(*post_fuzz)(void),
> + int* main_argc,
> + char*** main_argv);
What about having in tests/fuzz/fuzz.h:
typedef struct FuzzTarget {
GString* name;
GString* description;
void(*init_pre_main)(void);
void(*init_pre_save)(void);
void(*save_state)(void);
void(*reset)(void);
void(*pre_fuzz)(void);
void(*fuzz)(const unsigned char*, size_t);
void(*post_fuzz)(void);
int* main_argc;
char*** main_argv;
} FuzzTarget;
void fuzz_add_target(FuzzTarget *target);
And in tests/fuzz/fuzz.c:
typedef struct FuzzTargetState {
FuzzTarget *target;
QSLIST_ENTRY(FuzzTarget) target_list;
} FuzzTargetState;
> +
> +int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size);
> +int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp);
> +
> +#endif
> +
>
next prev parent reply other threads:[~2019-07-25 17:53 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-25 3:23 [Qemu-devel] [RFC 00/19] Add virtual device fuzzing support Oleinik, Alexander
2019-07-25 3:23 ` [Qemu-devel] [RFC 01/19] fuzz: add configure option and linker objects Oleinik, Alexander
2019-07-25 9:39 ` Paolo Bonzini
2019-07-25 3:23 ` [Qemu-devel] [RFC 02/19] fuzz: add FUZZ_TARGET type to qemu module system Oleinik, Alexander
2019-07-26 12:32 ` Stefan Hajnoczi
2019-07-25 3:23 ` [Qemu-devel] [RFC 03/19] fuzz: add fuzz accelerator Oleinik, Alexander
2019-07-26 10:33 ` Paolo Bonzini
2019-07-26 12:35 ` Stefan Hajnoczi
2019-07-25 3:23 ` [Qemu-devel] [RFC 04/19] fuzz: Add qos support to fuzz targets Oleinik, Alexander
2019-07-26 10:39 ` Paolo Bonzini
2019-07-25 3:23 ` [Qemu-devel] [RFC 05/19] fuzz: expose qemu_savevm_state & skip state header Oleinik, Alexander
2019-07-25 13:22 ` Dr. David Alan Gilbert
2019-07-25 3:23 ` [Qemu-devel] [RFC 07/19] fuzz: Modify libqtest to directly invoke qtest.c Oleinik, Alexander
2019-07-25 9:04 ` Thomas Huth
2019-07-25 9:33 ` Paolo Bonzini
2019-07-26 12:49 ` Stefan Hajnoczi
2019-07-26 12:56 ` Stefan Hajnoczi
2019-07-26 21:50 ` Paolo Bonzini
2019-07-25 3:23 ` [Qemu-devel] [RFC 06/19] fuzz: Add ramfile for fast vmstate/vmload Oleinik, Alexander
2019-07-26 12:47 ` Stefan Hajnoczi
2019-07-26 19:36 ` Oleinik, Alexander
2019-07-26 19:54 ` Paolo Bonzini
2019-07-25 3:23 ` [Qemu-devel] [RFC 08/19] fuzz: add shims to intercept libfuzzer init Oleinik, Alexander
2019-07-25 8:21 ` Paolo Bonzini
2019-07-26 12:59 ` Stefan Hajnoczi
2019-07-25 3:23 ` [Qemu-devel] [RFC 09/19] fuzz: use mtree_info to find mapped addresses Oleinik, Alexander
2019-07-26 13:04 ` Stefan Hajnoczi
2019-07-26 21:51 ` Paolo Bonzini
2019-07-25 3:23 ` [Qemu-devel] [RFC 10/19] fuzz: expose real_main (aka regular vl.c:main) Oleinik, Alexander
2019-07-25 9:38 ` Paolo Bonzini
2019-07-25 3:23 ` [Qemu-devel] [RFC 11/19] fuzz: add direct send/receive in qtest client Oleinik, Alexander
2019-07-25 9:10 ` Thomas Huth
2019-07-25 3:23 ` [Qemu-devel] [RFC 12/19] fuzz: hard-code all of the needed files for build Oleinik, Alexander
2019-07-25 3:23 ` [Qemu-devel] [RFC 13/19] fuzz: add ctrl vq support to virtio-net in libqos Oleinik, Alexander
2019-07-25 16:25 ` John Snow
2019-07-25 17:05 ` Oleinik, Alexander
2019-07-26 13:09 ` Stefan Hajnoczi
2019-07-25 3:23 ` [Qemu-devel] [RFC 14/19] fuzz: hard-code a main-loop timeout Oleinik, Alexander
2019-07-25 9:40 ` Paolo Bonzini
2019-07-25 3:23 ` [Qemu-devel] [RFC 15/19] fuzz: add fuzz accelerator type Oleinik, Alexander
2019-07-25 3:23 ` [Qemu-devel] [RFC 16/19] fuzz: add general fuzzer entrypoints Oleinik, Alexander
2019-07-25 17:53 ` Philippe Mathieu-Daudé [this message]
2019-07-25 3:23 ` [Qemu-devel] [RFC 17/19] fuzz: add general qtest fuzz target Oleinik, Alexander
2019-07-25 3:24 ` [Qemu-devel] [RFC 19/19] fuzz: Add documentation about the fuzzer to docs/ Oleinik, Alexander
2019-07-26 13:19 ` Stefan Hajnoczi
2019-07-25 3:24 ` [Qemu-devel] [RFC 18/19] fuzz: Add virtio-net tx and ctrl fuzz targets Oleinik, Alexander
2019-07-25 3:41 ` [Qemu-devel] [RFC 00/19] Add virtual device fuzzing support no-reply
2019-07-26 13:24 ` Stefan Hajnoczi
2019-08-06 9:59 ` jiade zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=139e1ca9-0da3-277b-baa6-94aa5372baac@redhat.com \
--to=philmd@redhat.com \
--cc=alxndr@bu.edu \
--cc=bsd@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=superirishdonkey@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).