xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [GSoC] Fuzzing the Hypervisor
@ 2017-08-17  9:58 Felix Schmoll
  2017-08-17 10:15 ` [PATCH AFL] Fuzzing the hypervisor Felix Schmoll
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Felix Schmoll @ 2017-08-17  9:58 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu


[-- Attachment #1.1: Type: text/plain, Size: 7549 bytes --]

This email will be a technical description of what I, Felix Schmoll, as a
Google Summer of Code student, did over summer.

=== Introduction / What is the project? ===

Fuzzing is a recent trend for systematic testing of interfaces by trying
more or less random inputs and iterating over them. A subset of fuzzers
uses code-
coverage as feedback when permuting and choosing inputs. The goal of this
project was to test the hypercall interface of Xen that way.

While this was overall a very comprehensive problem, and a full-fledged
test suite similar to OSS-Test is a desirable overall goal, this was not
realistic for the scope of this project. Instead, a generic mechanism to
obtain feedback on code-coverage was implemented and the output processed
in order to actually run a particular fuzzer (AFL). This way, the project
helped to develop a better understanding of the problem space and will lay
the foundation for possible future endeavours in that direction.

==== Implementation ===

== Overview ==

It was clear from the beginning that the American Fuzzy Lop, in the
following referred to as AFL, was supposed to be run on the hypervisor.
Being a user-space coverage-based fuzzer, it had to be ported in some way
to the kernel. The first step of this was to allow it to somehow obtain
feedback on the coverage from Xen by implementing a hypercall. Further, a
mechanism was needed to actually execute the hypercalls from a domain other
than dom0 (there are many ways to stop the hypervisor from dom0, and this
was not what was supposed to be tested). This was done by what will be
referred to as the executor.

== Implementation of the hypercall ==

The implementation of the hypercall to obtain code-coverage feedback was
realised using the fsanitize-coverage=trace_pc feature of gcc-6. It inserts
a customisable function at every basic block of the binary. This function
was instrumented to write the current program counter to a particular
domain-specific location, allowing tracing of individual domains.

Slowing down the hypervisor in normal operation, this was added as a
compile-option and the hypercall returns an error code in case the edge's
are disabled.

== Executor ==

As mentioned, there are many ways to stop the hypervisor from the
control-domain (dom0), such that the hypercalls were supposed to be
executed from a different domain. Being very lean and not making any
hypercalls in the background (this would make the tracing indeterministic),
XTF was chosen for this purpose. While one could have used an isolated
domain for every test case, this would have required recompiling the test
case for every run, thus being extremely slow, and adding little value
overall. Instead, a server was programmed, running in an endless loop,
taking binary information (test cases) from AFL, parsing them into
hypercalls and executing them. The server also does some sanity checks,
ignoring hypercalls that would kill the domain but not the hypervisor. It
also informs the fuzzer once a hypercall ended and it is ready to receive a
new test case.

== Fuzzer (American Fuzzy Lop) ==

The fuzzer is executed in dom0 as this allows an easier communication with
XTF via xenconsole. For this purpose, the domain of the xtf-server needs to
be passed to AFL on startup and it needs to run with super-user rights.
Changes were made to AFL to pass the test cases to the xtf-server via
xenconsole instead of to a user-space program via the command line, as it
normally does. This is a quite fundamental change to the functioning of
AFL, but the overall philosophy behind the design here was to keep the keep
the changes to as few functions as possible.

=== Discussion of the fork-server ===

In testing it is desirable to have the exact same conditions for every
iteration, which is why AFL in user-space mode starts a new process for
every test case, speeding it up by using fork(). The equivalent in this
scenario would be to fork a complete machine running a hypervisor. This
would however require VM-forking and nested virtualization, both of which
are currently not supported by Xen. In this scenario, a machine (the host)
would be running Xen and AFL in a domain on top of it. Another domain would
run a nested version of Xen and would execute a series of hypercalls as a
test. This VM could be forked before the tests in order to always have an
identical environment of Xen.

Instead, the setup developed in this project just runs a single hypervisor
and executes all hypercalls consecutively as one single large test-case,
while still passing the information to AFL as if these were completely
isolated. This is weird to some extent, but the best currently supported
compromise.

=== Deliverables ===

There were a minor patch for Xen [1] and a minor patch for XTF [2].

The actual hypercall meanwhile has not been merged, even though it conforms
to the requirements as layed out initially. The build system should be
updated to allow a better specification of what to trace before the
hypercall becomes useful. It is instead, together with the changes to AFL
and XTF, attached to this email.

The main patches are based on the following versions:
* Xen, commit 6c9abf0e8022807bb7d677570d0775659950ff1a
* AFL 2.43b
* XTF, commit 8956f82ce1321b89deda6895d58e5788d2198477

=== How to fuzz the hypercall interface ===

* Run the XTF-server [sudo xtf_dir/xtf-runner xtf-server] and detach from
console [Ctrl-C] after the initialisation log ended (three lines of
"Executing ...")
* Create (empty) directories for findings and testcases
* Disable AFL-forkserver [export AFL_NO_FORKSRV=1]
* Start AFL [sudo ./afl-fuzz -i ~/testcase_dir -o ~/findings_dir -r [DOMID
of XTF-server] /some/unused/path]

You can find the domain-id of the xtf-server using [sudo xl list].

The test case also is configured such that it only tests as a pv64 (this
was the only setup my hardware supports). It is possible that adjustments
have to be made to run other modes.

=== Future work ===

No bugs were found so far, and it is quite possible that there aren't any
without using more sophisticated fuzzing (i.e. valid buffers). Possible
areas of improvement are the following:

* Minor usability improvements, like starting the XTF-server from within AFL
* Increase coverage
* Solve remaining problems with determinism
* Make XTF server more sophisticated, encode more information about
hypercalls (e.g. pass valid buffers into hypercalls)
* Improve speed
* Improve stability (there still seem to be some files that shouldn't be
compiled with tracing, although the stability is 100% for most hypercalls)
* Do the more complicated approach with complete hypervisor cloning

The patches for the hypercall, XTF and AFL will be sent in reply to this
document.

=== References ===

Links to other documents:
* [1] xenconsole: Add option to xenconsole to always forward console input (
https://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=32e5bd5dcf6f45c2fc39d8d62b52b53d3e79ada7
)
* [2] Implement pv_read_some (
https://xenbits.xen.org/gitweb/?p=xtf.git;a=commit;h=34f052d41415cbd424f37c1a63a47464ce8f63e9
)
* [3] The GSoC page of this project (
https://summerofcode.withgoogle.com/projects/#5585891117498368)
* [4] Summary of the design session at the Xen summit (
https://lists.xen.org/archives/html/xen-devel/2017-07/msg02138.html)
* [5] Design proposal for the hypercall (
https://lists.xen.org/archives/html/xen-devel/2017-05/msg02210.html)
* [6] Design proposal for fuzzing the hypervisor (
https://lists.xen.org/archives/html/xen-devel/2017-06/msg02924.html)

[-- Attachment #1.2: Type: text/html, Size: 9063 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH AFL] Fuzzing the hypervisor
  2017-08-17  9:58 [GSoC] Fuzzing the Hypervisor Felix Schmoll
@ 2017-08-17 10:15 ` Felix Schmoll
  2017-08-17 10:21 ` [PATCH XTF] " Felix Schmoll
  2017-08-17 10:25 ` [PATCH XEN] " Felix Schmoll
  2 siblings, 0 replies; 5+ messages in thread
From: Felix Schmoll @ 2017-08-17 10:15 UTC (permalink / raw)
  To: xen-devel; +Cc: wei.liu2, Felix Schmoll

Changes based on version 2.43b of AFL
---
 Makefile   |   2 +-
 afl-fuzz.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 hash_map.h |  82 ++++++++++++++++++++++
 3 files changed, 306 insertions(+), 11 deletions(-)
 create mode 100644 hash_map.h

diff --git a/Makefile b/Makefile
index 44d1ffa..3a75c8c 100644
--- a/Makefile
+++ b/Makefile
@@ -70,7 +70,7 @@ afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86
 	ln -sf afl-as as
 
 afl-fuzz: afl-fuzz.c $(COMM_HDR) | test_x86
-	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
+	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) -lxenctrl
 
 afl-showmap: afl-showmap.c $(COMM_HDR) | test_x86
 	$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
diff --git a/afl-fuzz.c b/afl-fuzz.c
index 562fd50..08fa346 100644
--- a/afl-fuzz.c
+++ b/afl-fuzz.c
@@ -56,6 +56,10 @@
 #include <sys/ioctl.h>
 #include <sys/file.h>
 
+#include <xenctrl.h>
+#include <xen/public/trace_pc.h>
+#include "hash_map.h"
+
 #if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__)
 #  include <sys/sysctl.h>
 #endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */
@@ -80,6 +84,25 @@
    really makes no sense to haul them around as function parameters. */
 
 
+/* number of buckets in the hash map */
+#define NUM_BUCKETS 1000
+/* number of bytes written to xtf */
+#define SIZE_MEM_WRITE_TO_TESTCASE 80
+/* path for the file containing the last test case */
+#define TEST_CASE_LOG_PATH "/var/log/testcase"
+/* path for the file containing all test cases */
+#define OVERALL_LOG_PATH "/var/log/afl.log"
+#define XENCONSOLE_PATH "/usr/local/lib/xen/bin/xenconsole"
+
+int pipefd_to_xtf[2];
+int pipefd_from_xtf[2];
+char* domain;
+hash_map* map;
+
+long mem_write_to_testcase[SIZE_MEM_WRITE_TO_TESTCASE];
+
+FILE* log_file;
+
 EXP_ST u8 *in_dir,                    /* Input directory with test cases  */
           *out_file,                  /* File to fuzz, if any             */
           *out_dir,                   /* Working & output directory       */
@@ -2253,6 +2276,107 @@ EXP_ST void init_forkserver(char** argv) {
 }
 
 
+/** Process program counters into format expected by AFL and
+    insert into trace_bits.
+
+    cur_location = <COMPILE_TIME_RANDOM>;
+    shared_mem[cur_location ^ prev_location]++;
+    prev_location = cur_location >> 1;
+*/
+void process_program_counters(uint64_t* pc_buffer, long pc_num) {
+
+  u32 cur_location = 0, prev_location = 0;
+  hash_bucket* bucket;
+
+  for(int i = 0; i < pc_num; ++i) {
+    bucket = _hash_map_lookup(map, pc_buffer[i]);
+
+    if( !bucket ) {
+       cur_location = UR(MAP_SIZE);
+       if(!_hash_map_insert(map, pc_buffer[i], cur_location))
+         FATAL("process_program_counters: Could not insert into hash map\n");
+    } else {
+      cur_location = bucket->val;
+    }
+
+    trace_bits[(cur_location ^ prev_location) % MAP_SIZE]++;
+    prev_location = cur_location >> 1;
+  }
+
+}
+
+/* Send test case to XTF-server. */
+
+static u8 send_test_to_xtf(char** argv, u32 timeout) {
+
+  size_t buf_size = 100;
+  char buffer[buf_size];
+
+  int pc_buffer_size = 100000;
+  uint64_t pc_buffer[pc_buffer_size];
+  long ret;
+
+  /* log the test case that is about to be send */
+  if( fprintf(log_file, "get_cur_time %ld %li %li %ld %ld %ld\n",
+                         (long) get_cur_time(),
+                         mem_write_to_testcase[0] % 41,
+                         mem_write_to_testcase[1],
+                         mem_write_to_testcase[2],
+                         mem_write_to_testcase[3],
+                         mem_write_to_testcase[4]) < 0 )
+    FATAL("send_test_to_xtf: Couldn't write to file\n");
+
+  fflush(log_file);
+  memset(trace_bits, 0, MAP_SIZE);
+
+  xc_interface *xch = xc_interface_open(NULL, NULL, 0);
+  if( xch == NULL ) {
+    fclose(log_file);
+    FATAL("send_test_to_xtf: Couldn't open xen interface\n");
+  }
+
+  if( xc_trace_pc(xch, atoi(domain), XEN_TRACE_PC_START,
+                  pc_buffer_size, pc_buffer) < 0 ) {
+    fclose(log_file);
+    xc_interface_close(xch);
+    FATAL("send_test_to_xtf: Start edge_trace failed\n");
+  }
+
+  /* send tet case to XTF */
+  if( write(pipefd_to_xtf[1], (char*) mem_write_to_testcase,
+              SIZE_MEM_WRITE_TO_TESTCASE) <= 0 ) {
+     fclose(log_file);
+     xc_interface_close(xch);
+     FATAL("send_test_to_xtf: Couldn't write to XTF\n");
+  }
+
+  /* XTF will message us when it's hypercall returned */
+  if( read(pipefd_from_xtf[0], buffer, buf_size) < 0 ) {
+     fclose(log_file);
+     xc_interface_close(xch);
+     FATAL("send_test_to_xtf: Couldn't read from XTF\n");
+  }
+
+  ret = xc_trace_pc(xch, atoi(domain), 1, pc_buffer_size, pc_buffer);
+  xc_interface_close(xch);
+
+  if( ret < 0 ) {
+     fclose(log_file);
+     FATAL("send_test_to_xtf: Stop edge_trace failed\n");
+  }
+
+  process_program_counters(pc_buffer, ret);
+
+#ifdef __x86_64__
+  classify_counts((u64*)trace_bits);
+#else
+  classify_counts((u32*)trace_bits);
+#endif /* ^__x86_64__ */
+
+  return FAULT_NONE;
+}
+
+
 /* Execute target application, monitoring for timeouts. Return status
    information. The called program will update trace_bits[]. */
 
@@ -2455,13 +2579,21 @@ static u8 run_target(char** argv, u32 timeout) {
 
 }
 
-
 /* Write modified data to file for testing. If out_file is set, the old file
    is unlinked and a new one is created. Otherwise, out_fd is rewound and
    truncated. */
 
 static void write_to_testcase(void* mem, u32 len) {
 
+  memset((char*) mem_write_to_testcase, 0, SIZE_MEM_WRITE_TO_TESTCASE);
+  memcpy((char*) mem_write_to_testcase, mem, (len < SIZE_MEM_WRITE_TO_TESTCASE)?len:SIZE_MEM_WRITE_TO_TESTCASE);
+
+  remove(TEST_CASE_LOG_PATH);
+  s32 my_file = open(TEST_CASE_LOG_PATH, O_WRONLY | O_CREAT | O_EXCL , 0600);
+  ck_write(my_file, mem, SIZE_MEM_WRITE_TO_TESTCASE, TEST_CASE_LOG_PATH);
+  fsync(my_file);
+  close(my_file);
+
   s32 fd = out_fd;
 
   if (out_file) {
@@ -2490,6 +2622,15 @@ static void write_to_testcase(void* mem, u32 len) {
 
 static void write_with_gap(void* mem, u32 len, u32 skip_at, u32 skip_len) {
 
+  memset((char*) mem_write_to_testcase, 0, SIZE_MEM_WRITE_TO_TESTCASE);
+  memcpy((char*) mem_write_to_testcase, mem, (len < SIZE_MEM_WRITE_TO_TESTCASE)?len:SIZE_MEM_WRITE_TO_TESTCASE);
+
+  remove(TEST_CASE_LOG_PATH);
+  s32 my_file = open(TEST_CASE_LOG_PATH, O_WRONLY | O_CREAT | O_EXCL , 0600);
+  ck_write(my_file, mem, SIZE_MEM_WRITE_TO_TESTCASE, TEST_CASE_LOG_PATH);
+  fsync(my_file);
+  close(my_file);
+
   s32 fd = out_fd;
   u32 tail_len = len - skip_at - skip_len;
 
@@ -2568,7 +2709,7 @@ static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem,
 
     write_to_testcase(use_mem, q->len);
 
-    fault = run_target(argv, use_tmout);
+    fault = send_test_to_xtf(argv, use_tmout);
 
     /* stop_soon is set by the handler for Ctrl+C. When it's pressed,
        we want to bail out quickly. */
@@ -3198,7 +3339,7 @@ static u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) {
 
         u8 new_fault;
         write_to_testcase(mem, len);
-        new_fault = run_target(argv, hang_tmout);
+        new_fault = send_test_to_xtf(argv, hang_tmout);
 
         if (stop_soon || new_fault != FAULT_TMOUT) return keeping;
 
@@ -4479,7 +4620,7 @@ static u8 trim_case(char** argv, struct queue_entry* q, u8* in_buf) {
 
       write_with_gap(in_buf, q->len, remove_pos, trim_avail);
 
-      fault = run_target(argv, exec_tmout);
+      fault = send_test_to_xtf(argv, exec_tmout);
       trim_execs++;
 
       if (stop_soon || fault == FAULT_ERROR) goto abort_trimming;
@@ -4572,7 +4713,7 @@ EXP_ST u8 common_fuzz_stuff(char** argv, u8* out_buf, u32 len) {
 
   write_to_testcase(out_buf, len);
 
-  fault = run_target(argv, exec_tmout);
+  fault = send_test_to_xtf(argv, exec_tmout);
 
   if (stop_soon) return 1;
 
@@ -6701,7 +6842,7 @@ static void sync_fuzzers(char** argv) {
 
         write_to_testcase(mem, st.st_size);
 
-        fault = run_target(argv, exec_tmout);
+        fault = send_test_to_xtf(argv, exec_tmout);
 
         if (stop_soon) return;
 
@@ -7665,6 +7806,73 @@ static void save_cmdline(u32 argc, char** argv) {
 
 }
 
+/**
+  * @param domid_s Point to domid of XTF
+  *
+  * This function does initial setup needed for the fuzzing. It also
+  * sets up pipes such that stdout and stdin can be used to communicate
+  * with the XTF-server.
+  *
+  * TODO      make this two separate functions
+  */
+static void setup_pipe_and_fork(char *domid_s) {
+  map = _hash_map_create(NUM_BUCKETS);
+
+  if(!map) {
+    FATAL("setup_pipe_and_fork: Hash map could not be created\n");
+  }
+
+  log_file = fopen(OVERALL_LOG_PATH, "w");
+
+  if(log_file < 0)
+    goto FAIL;
+
+  pid_t childpid;
+  int ret;
+
+  if( (ret = pipe(pipefd_to_xtf)) < 0)
+    goto FAIL;
+
+  if( (ret = pipe(pipefd_from_xtf)) < 0)
+    goto FAIL;
+
+  if((childpid = fork()) == -1)
+    FATAL("setup_pipe_and_fork: fork failed");
+
+  if (childpid == 0) { /* child */
+
+    /* close unnecessary pipe ends */
+    close(pipefd_to_xtf[1]);
+    close(pipefd_from_xtf[0]);
+
+    /* stdin */
+    close(0);
+    if( (ret = dup(pipefd_to_xtf[0])) < 0 )
+      goto FAIL;
+
+    /* stdout */
+    close(1);
+    if( (ret = dup(pipefd_from_xtf[1])) < 0 )
+      goto FAIL;
+
+    if( execl(XENCONSOLE_PATH, XENCONSOLE_PATH, domid_s, "--num", "0",
+              "--type", "pv", "--interactive", (void *)NULL) < 0 )
+      FATAL("setup_pipe_and_fork: execl");
+
+  } else { /* parent */
+
+    /* close unnecessary pipe ends */
+    close(pipefd_to_xtf[0]);
+    close(pipefd_from_xtf[1]);
+
+  }
+
+  return;
+
+  FAIL:
+    FATAL("setup_pipe_and_fork: Failed to setup pipes\n");
+}
+
 
 #ifndef AFL_LIB
 
@@ -7690,7 +7898,7 @@ int main(int argc, char** argv) {
   gettimeofday(&tv, &tz);
   srandom(tv.tv_sec ^ tv.tv_usec ^ getpid());
 
-  while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Q")) > 0)
+  while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Qr:")) > 0)
 
     switch (opt) {
 
@@ -7858,6 +8066,12 @@ int main(int argc, char** argv) {
 
         break;
 
+      case 'r': /* domain id for XTF server */
+
+        domain = optarg;
+        printf("domain set: %s\n", domain);
+        break;
+
       default:
 
         usage(argv[0]);
@@ -7935,8 +8149,6 @@ int main(int argc, char** argv) {
 
   if (!out_file) setup_stdio_file();
 
-  check_binary(argv[optind]);
-
   start_time = get_cur_time();
 
   if (qemu_mode)
@@ -7944,6 +8156,8 @@ int main(int argc, char** argv) {
   else
     use_argv = argv + optind;
 
+  setup_pipe_and_fork(domain);
+
   perform_dry_run(use_argv);
 
   cull_queue();
@@ -7966,7 +8180,6 @@ int main(int argc, char** argv) {
   }
 
   while (1) {
-
     u8 skipped_fuzz;
 
     cull_queue();
diff --git a/hash_map.h b/hash_map.h
new file mode 100644
index 0000000..e5e6602
--- /dev/null
+++ b/hash_map.h
@@ -0,0 +1,82 @@
+/* @file hash_map.h
+ *
+ */
+
+typedef struct hash_bucket {
+    struct hash_bucket* next;
+    uint64_t key;
+    uint64_t val;
+} hash_bucket;
+
+typedef struct hash_map {
+    hash_bucket** buckets;
+    int num_buckets;
+} hash_map;
+
+uint64_t _hash_function(hash_map* map, uint64_t key) {
+    return (key % map->num_buckets);
+}
+
+hash_map* _hash_map_create(int num_buckets) {
+    hash_map* map = (hash_map*) malloc(sizeof(hash_map));
+
+    if( map ) {
+      map->num_buckets = num_buckets;
+      map->buckets = (hash_bucket**) malloc(sizeof(hash_bucket*) * num_buckets);
+
+       if( !map->buckets ) {
+         free(map);
+         return NULL;
+       }
+
+       for(int i = 0; i < num_buckets; ++i)
+         map->buckets[i] = NULL;
+    }
+
+    return map;
+}
+
+void _hash_map_destroy(hash_map* map) {
+  //not implemented
+}
+
+hash_bucket* _hash_map_lookup(hash_map* map, uint64_t key) {
+    uint64_t hash = _hash_function(map, key);
+
+    if(map->buckets[hash] == NULL) {
+      return NULL;
+    } else {
+      hash_bucket* cur = map->buckets[hash];
+
+      while(cur->key != key && cur->next)
+        cur = cur->next;
+
+      return cur;
+    }
+}
+
+bool _hash_map_insert(hash_map* map, uint64_t key, uint64_t val) {
+    uint64_t hash = _hash_function(map, key);
+
+    hash_bucket* bucket = (hash_bucket*) malloc(sizeof(hash_bucket));
+
+    if(!bucket)
+      return false;
+
+    bucket->next = NULL;
+    bucket->key = key;
+    bucket->val = val;
+
+    if(map->buckets[hash] == NULL) {
+      map->buckets[hash] = bucket;
+    } else {
+      hash_bucket* cur = map->buckets[hash];
+      while(cur->next) {
+        cur = cur->next;
+      }
+
+      cur->next = bucket;
+    }
+
+    return true;
+}
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH XTF] Fuzzing the hypervisor
  2017-08-17  9:58 [GSoC] Fuzzing the Hypervisor Felix Schmoll
  2017-08-17 10:15 ` [PATCH AFL] Fuzzing the hypervisor Felix Schmoll
@ 2017-08-17 10:21 ` Felix Schmoll
  2017-08-17 12:41   ` Wei Liu
  2017-08-17 10:25 ` [PATCH XEN] " Felix Schmoll
  2 siblings, 1 reply; 5+ messages in thread
From: Felix Schmoll @ 2017-08-17 10:21 UTC (permalink / raw)
  To: xen-devel; +Cc: wei.liu2, Felix Schmoll

Changes based on commit 8956f82ce1321b89deda6895d58e5788d2198477
---
 include/xen/xen.h          |   1 +
 include/xtf/hypercall.h    |   8 +-
 tests/mk_hcall/.main.c.swo | Bin 0 -> 12288 bytes
 tests/mk_hcall/Makefile    |   9 +++
 tests/mk_hcall/main.c      |  51 +++++++++++++
 tests/xtf-server/Makefile  |   9 +++
 tests/xtf-server/main.c    | 183 +++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 257 insertions(+), 4 deletions(-)
 create mode 100644 tests/mk_hcall/.main.c.swo
 create mode 100644 tests/mk_hcall/Makefile
 create mode 100644 tests/mk_hcall/main.c
 create mode 100644 tests/xtf-server/Makefile
 create mode 100644 tests/xtf-server/main.c

diff --git a/include/xen/xen.h b/include/xen/xen.h
index 85aaba8..33eb23d 100644
--- a/include/xen/xen.h
+++ b/include/xen/xen.h
@@ -51,6 +51,7 @@
 #define __HYPERVISOR_tmem_op              38
 #define __HYPERVISOR_xc_reserved_op       39 /* reserved for XenClient */
 #define __HYPERVISOR_xenpmu_op            40
+#define __HYPERVISOR_trace_pc             42
 
 /* Architecture-specific hypercall definitions. */
 #define __HYPERVISOR_arch_0               48
diff --git a/include/xtf/hypercall.h b/include/xtf/hypercall.h
index be4a01e..3fa9b3c 100644
--- a/include/xtf/hypercall.h
+++ b/include/xtf/hypercall.h
@@ -151,16 +151,16 @@ static inline long hypercall_shutdown(unsigned int reason)
     return hypercall_sched_op(SCHEDOP_shutdown, &reason);
 }
 
+/* hypercall_yield and hypercall_poll are dummies so that printing to
+   console doesn't interfere with tracing determinism */
 static inline void hypercall_yield(void)
 {
-    hypercall_sched_op(SCHEDOP_yield, NULL);
+    return;
 }
 
 static inline long hypercall_poll(evtchn_port_t port)
 {
-    struct sched_poll poll = { .ports = &port, .nr_ports = 1 };
-
-    return hypercall_sched_op(SCHEDOP_poll, &poll);
+    return 0;
 }
 
 static inline int hypercall_register_callback(const xen_callback_register_t *arg)
diff --git a/tests/mk_hcall/.main.c.swo b/tests/mk_hcall/.main.c.swo
new file mode 100644
index 0000000000000000000000000000000000000000..153f8f050b2ad8647ad69fc2bf398e0309a2145d
GIT binary patch
literal 12288
zcmeI2&2Jk;7{(_E4nPA4PQYc@D3$Hn*^fB3<CHdOVi&7v5}c%vrqMFqolRER>{`3)
zuqbK}M-CuFFI<s;1405JIDz1Tgy4VR1UI<QD+uw-`lBCC8!B;$G!y-_@yt8VJM-+j
zD_NeFcBOHdmM4k??I}VIe|vjlbnIdB&7*`k+;bDre@wG^%VqvCK^Q(v1=UyA>V=D|
z!MqytD2~*<U314`o~Q0H*PpPCmyr?D0qMYlI?#!oLS>Xp8oDN?jwvtDXP#bvP!$<3
z9gq%42c!ei0qKBrKsq2DkPe(+2jcb!c@yh@sJDl?-gV@zYwx4HNC%_?(gEp!bU->F
z9gq%42c!ei0qKBrKss;&9bh&gr|?^U{xK{bzyJ5Y|Ns3YA-{kh!4Kdg@F92$9D>)t
zHE;<S;5qOt`0EKmz6ald8{mBqgC<x4mp~3Y0!F|;qlEklz6GCxPr%3EJ@77Y!7Jb*
zsDqoQ2>BD-0At|m#|ilgTm>88Ja``5#D4w&zk{E_PvA@N1^66%20j4qfPKKg%b)@@
zkos`~@26a{bU->F9gq%42c!eif&bG1no|kQ(VA~p#nts~?#G3gwW7jaVDl>VT~7?4
zr|`OK$2(P86rZg^i$$(g2plKk@u1UjJzj|7H$2Q#F03vnBDO0uFaBK&a4eMWv(RNN
zk4IIa<_Nh?C|VLbX4J7P9z~g@^~J^P3`zUjq3g%H86}E?c9o8MHofL6dCL5#AJLsJ
zH2SgQ3SDV7l2VZ>-QY0Xbhi*Mf}9}Cc!9r7UHT%`W^g$x)Mn_JGj5h1q%i{_&%Qew
zLNV{9jg?w+er|EGm}=#zX{KFQ8mr4qGY*->&9;@N3(J=q3+8HVv7V=To~||L=4<AK
z^?JS5G*=r}YuHE__BS#lswEo7A9FO(bY_(4I4wd418Ktm*D;{8TYcRTO*2HC=yuR5
zhOJdJqga|WT0I|B^@w~%S!Y53!c62I<P$k`Wa}<PONDXn@Q&8YXS9%|SkaKt5V?o*
z8Aq9hIx=zWxU(Jd?K~}2%EqK#(saF4o;J#*%JkHrv#3v(^s-TzoSvMb_cZT6+!5^J
z{&ys^AGmflEswM=(z@wZfYz<14yv<MG-GieH;2TwX2<~%8dMyNHpOx1t|TF<dL4*@
z6qU~tH_l)yw|X4rdYzDG6uyr~(iF$3Tg=);Ii_K$DEDo%9R}MW+v~0L01CHB_v=`Q
zMa<#!NSXfVAj$p3(ghu@bmv+JGQ<k}D5lm93%f?dZtU^REj&od8jPX+1LF!F`Z1e3
zuFvVpa${+&*32YXn#m;e93IxBUaxB!J$;%ccxbgmPYW<h&r^+7X_6hx9l8;8O2Zjh
zRULDE%j?*jDt#v=b`&z`J)3Y}-REKC2L8m(x!VU~M|AYwm$MP)=}v~vy3?F^(apwz
t9ngiqip2XS4K4IHiSaa~&9=KDgOPy`{g9A5Lv!h@c+1`+yPC_9e*rg5=j{Lh

literal 0
HcmV?d00001

diff --git a/tests/mk_hcall/Makefile b/tests/mk_hcall/Makefile
new file mode 100644
index 0000000..7e0eda2
--- /dev/null
+++ b/tests/mk_hcall/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := mk_hcall
+CATEGORY  := utility
+TEST-ENVS := pv64
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/mk_hcall/main.c b/tests/mk_hcall/main.c
new file mode 100644
index 0000000..87f52d7
--- /dev/null
+++ b/tests/mk_hcall/main.c
@@ -0,0 +1,51 @@
+/**
+ * @file tests/mk_hcall/main.c
+ * @ref test-mk_hcall
+ *
+ * @page test-mk_hcall mk_hcall
+ *
+ * This test case is a helper to debug tracing and
+ * fuzzing. It executes a particular hypercall and
+ * prints the information obtained from tracing to
+ * the console..
+ *
+ * @see tests/mk_hcall/main.c
+ */
+#include <xtf.h>
+#include <xen/version.h>
+
+#define TRACE_BUFFER_SIZE 500
+#define POINTER(x) ((x >= 0xFFF00 && x < 0x110000) ? 0 : x)
+
+const char test_title[] = "Test mk_hcall";
+
+void test_main(void)
+{
+    uint64_t arr[TRACE_BUFFER_SIZE];
+    long ans;
+
+    HYPERCALL4(long, __HYPERVISOR_trace_pc, DOMID_SELF, 0, TRACE_BUFFER_SIZE, arr);
+
+    /* the actual hypercall that should be traced */
+    HYPERCALL3(long, __HYPERVISOR_grant_table_op, 0, POINTER(63974), 7);
+
+    ans = HYPERCALL4(long, __HYPERVISOR_trace_pc, DOMID_SELF, 1, TRACE_BUFFER_SIZE, arr);
+
+    for(long i = 0; i < ans; ++i) {
+        printk("%" PRIx64 "\n", arr[i]);
+    }
+
+    printk("stop: %ld \n", ans);
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/xtf-server/Makefile b/tests/xtf-server/Makefile
new file mode 100644
index 0000000..d0ff533
--- /dev/null
+++ b/tests/xtf-server/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := xtf-server
+CATEGORY  := utility
+TEST-ENVS := pv64
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/xtf-server/main.c b/tests/xtf-server/main.c
new file mode 100644
index 0000000..8742e11
--- /dev/null
+++ b/tests/xtf-server/main.c
@@ -0,0 +1,183 @@
+/**
+ * @file tests/xtf-server/main.c
+ * @ref test-xtf-server
+ *
+ * @page test-xtf-server xtf-server
+ *
+ * This is the XTF-server for fuzzing
+ * the hypervisor. It waits for input
+ * via the console (thus in form of a
+ * string) and parses it into a test case.
+ *
+ * There are some information encoded about
+ * the hypercalls, i.e. some are excluded as
+ * they might not return for certain arguments
+ * or as they might stop the domain. Also, the
+ * pointer macro is used to prevent the overwriting
+ * of the code segments when passing buffers into Xen.
+ *
+ * Further improvements here would be to provide valid
+ * buffers, etc. and encode more information about hypercalls.
+ *
+ * Hypercalls annotated mostly according to xen/xen/include/xen/hypercall.h
+ *
+ * @see tests/xtf-server/main.c
+ */
+#include <xtf.h>
+
+#define TEST_CASE_STR_SIZE 1000
+
+/* avoid overwriting the code section in XTF when passing
+   buffers to Xen */
+#define POINTER(x) ((x >= 0xFFF00 && x < 0x110000) ? 0 : x)
+
+const char test_title[] = "Test xtf-server";
+
+char test_case_str[TEST_CASE_STR_SIZE];
+
+void test_main(void)
+{
+    int ret;
+
+    while( 1 )
+    {
+        /* receive test case */
+        memset(test_case_str, 0, TEST_CASE_STR_SIZE);
+        ret = pv_console_read_some(test_case_str, TEST_CASE_STR_SIZE);
+
+        if(ret <= 0)
+            xtf_failure("Couldn't read from AFL");
+
+        long hypercall_num, arg1, arg2, arg3, arg4;
+        hypercall_num = (*(long*) test_case_str) % 41;
+        arg1 = *(((long*) test_case_str) + 1);
+        arg2 = *(((long*) test_case_str) + 2);
+        arg3 = *(((long*) test_case_str) + 3);
+        arg4 = *(((long*) test_case_str) + 4);
+
+        /* execute test case */
+        switch(hypercall_num)
+        {
+            case __HYPERVISOR_set_trap_table:
+                (void) HYPERCALL1(long, __HYPERVISOR_set_trap_table, POINTER(arg1));
+                break;
+            case __HYPERVISOR_mmu_update:
+                break;
+            case __HYPERVISOR_set_gdt:
+                (void) HYPERCALL2(long, __HYPERVISOR_set_gdt, POINTER(arg1), arg2);
+                break;
+            case __HYPERVISOR_stack_switch:
+                (void) HYPERCALL2(long, __HYPERVISOR_stack_switch, arg1, arg2);
+                break;
+            case __HYPERVISOR_set_callbacks:
+                (void) HYPERCALL4(long, __HYPERVISOR_set_callbacks, arg1, arg2, arg3, arg4);
+                break;
+            case __HYPERVISOR_fpu_taskswitch:
+                (void) HYPERCALL1(long, __HYPERVISOR_fpu_taskswitch, arg1);
+                break;
+            case __HYPERVISOR_sched_op_compat:
+                break;
+            case __HYPERVISOR_platform_op:
+                (void) HYPERCALL4(long, __HYPERVISOR_platform_op, arg1, arg2, arg3, arg4);
+                break;
+            case __HYPERVISOR_set_debugreg:
+                (void) HYPERCALL2(long, __HYPERVISOR_set_debugreg, arg1, arg2);
+                break;
+            case __HYPERVISOR_get_debugreg:
+                (void) HYPERCALL1(long, __HYPERVISOR_get_debugreg, arg1);
+                break;
+            case __HYPERVISOR_update_descriptor:
+                (void) HYPERCALL1(long, __HYPERVISOR_update_descriptor, arg1);
+                break;
+            case __HYPERVISOR_memory_op:
+                break;
+            case __HYPERVISOR_multicall:
+                break;
+            case __HYPERVISOR_update_va_mapping:
+                break;
+            case __HYPERVISOR_set_timer_op:
+                break;
+            case __HYPERVISOR_event_channel_op_compat:
+                break;
+            case __HYPERVISOR_xen_version:
+                (void) HYPERCALL2(long, __HYPERVISOR_xen_version, arg1, POINTER(arg2));
+                break;
+            case __HYPERVISOR_console_io:
+                break;
+            case __HYPERVISOR_physdev_op_compat:
+                break;
+            case __HYPERVISOR_grant_table_op:
+                break;
+            case __HYPERVISOR_vm_assist:
+                (void) HYPERCALL2(long, __HYPERVISOR_vm_assist, arg1, arg2);
+                break;
+            case __HYPERVISOR_update_va_mapping_otherdomain:
+                (void) HYPERCALL4(long, __HYPERVISOR_update_va_mapping_otherdomain, arg1, arg2, arg3, arg4);
+                break;
+            case __HYPERVISOR_iret:
+                break;
+            case __HYPERVISOR_vcpu_op:
+                break;
+            case __HYPERVISOR_set_segment_base:
+                break;
+            case __HYPERVISOR_mmuext_op:
+                 (void) HYPERCALL4(long, __HYPERVISOR_mmuext_op, arg1, arg2, arg3, arg4);
+                break;
+           case __HYPERVISOR_xsm_op:
+                (void) HYPERCALL1(long, __HYPERVISOR_xsm_op, POINTER(arg1));
+                break;
+            case __HYPERVISOR_nmi_op:
+                (void) HYPERCALL2(long, __HYPERVISOR_nmi_op, arg1, POINTER(arg2));
+                break;
+            case __HYPERVISOR_sched_op:
+                break;
+            case __HYPERVISOR_callback_op:
+                (void) HYPERCALL4(long, __HYPERVISOR_callback_op, arg1, arg2, arg3, arg4);
+                break;
+            case __HYPERVISOR_xenoprof_op:
+                (void) HYPERCALL2(long, __HYPERVISOR_xenoprof_op, arg1, POINTER(arg2));
+                break;
+            case __HYPERVISOR_event_channel_op:
+                break;
+            case __HYPERVISOR_physdev_op:
+                break;
+            case __HYPERVISOR_hvm_op:
+                (void) HYPERCALL2(long, __HYPERVISOR_hvm_op, arg1, POINTER(arg2));
+                break;
+            case __HYPERVISOR_sysctl:
+                break;
+            case __HYPERVISOR_domctl:
+                break;
+            case __HYPERVISOR_kexec_op:
+                (void) HYPERCALL2(long, __HYPERVISOR_kexec_op, arg1, POINTER(arg2));
+                break;
+            case __HYPERVISOR_tmem_op:
+                (void) HYPERCALL1(long, __HYPERVISOR_tmem_op, arg1);
+                break;
+            case __HYPERVISOR_xc_reserved_op:
+                (void) HYPERCALL4(long, __HYPERVISOR_xc_reserved_op, arg1, arg2, arg3, arg4);
+                break;
+            case __HYPERVISOR_xenpmu_op:
+                break;
+            default:
+                break;
+        }
+
+        /* A string to inform AFL that the hypercall has finished. Has
+           to be shorter than 80 characters inorder to guarantee reading
+           with a single read() call in AFL. */
+        printk("Executed\n");
+    }
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH XEN] Fuzzing the hypervisor
  2017-08-17  9:58 [GSoC] Fuzzing the Hypervisor Felix Schmoll
  2017-08-17 10:15 ` [PATCH AFL] Fuzzing the hypervisor Felix Schmoll
  2017-08-17 10:21 ` [PATCH XTF] " Felix Schmoll
@ 2017-08-17 10:25 ` Felix Schmoll
  2 siblings, 0 replies; 5+ messages in thread
From: Felix Schmoll @ 2017-08-17 10:25 UTC (permalink / raw)
  To: xen-devel; +Cc: wei.liu2, Felix Schmoll

Based on commit 6c9abf0e8022807bb7d677570d0775659950ff1a
---
 xen/Kconfig.debug             |  7 +++-
 xen/Rules.mk                  |  4 ++
 xen/arch/arm/traps.c          |  1 +
 xen/arch/x86/Makefile         |  2 +
 xen/arch/x86/hvm/hypercall.c  |  1 +
 xen/arch/x86/hypercall.c      |  1 +
 xen/arch/x86/pv/Makefile      |  2 +
 xen/arch/x86/pv/hypercall.c   |  1 +
 xen/common/Makefile           | 13 ++++++
 xen/common/domain.c           |  4 ++
 xen/common/trace_pc.c         | 96 +++++++++++++++++++++++++++++++++++++++++++
 xen/common/trace_pc_stub.c    | 39 ++++++++++++++++++
 xen/include/public/trace_pc.h | 38 +++++++++++++++++
 xen/include/public/xen.h      |  1 +
 xen/include/xen/hypercall.h   |  7 ++++
 xen/include/xen/sched.h       |  6 +++
 xen/include/xen/trace_pc.h    | 31 ++++++++++++++
 17 files changed, 253 insertions(+), 1 deletion(-)
 create mode 100644 xen/common/trace_pc.c
 create mode 100644 xen/common/trace_pc_stub.c
 create mode 100644 xen/include/public/trace_pc.h
 create mode 100644 xen/include/xen/trace_pc.h

diff --git a/xen/Kconfig.debug b/xen/Kconfig.debug
index 689f2974c0..d87dcd78f4 100644
--- a/xen/Kconfig.debug
+++ b/xen/Kconfig.debug
@@ -98,7 +98,6 @@ config PERF_ARRAYS
 	---help---
 	  Enables software performance counter array histograms.
 
-
 config VERBOSE_DEBUG
 	bool "Verbose debug messages"
 	default DEBUG
@@ -114,6 +113,12 @@ config DEVICE_TREE_DEBUG
 	  logged in the Xen ring buffer.
 	  If unsure, say N here.
 
+config TRACE_PC
+    bool "Enable pc-tracing"
+    default false
+    ---help---
+	  Adds tracing support to the hypervisor (needed for the trace_pc hypercall).
+
 endif # DEBUG || EXPERT
 
 endmenu
diff --git a/xen/Rules.mk b/xen/Rules.mk
index 77bcd44922..dde14e3228 100644
--- a/xen/Rules.mk
+++ b/xen/Rules.mk
@@ -170,6 +170,10 @@ clean:: $(addprefix _clean_, $(subdir-all))
 _clean_%/: FORCE
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C $* clean
 
+ifeq ($(CONFIG_TRACE_PC),y)
+$(objs-need-tracing): CFLAGS += -fsanitize-coverage=trace-pc
+endif
+
 %.o: %.c Makefile
 	$(CC) $(CFLAGS) -c $< -o $@
 
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index c07999b518..247a68c964 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1419,6 +1419,7 @@ static arm_hypercall_t arm_hypercall_table[] = {
     HYPERCALL(platform_op, 1),
     HYPERCALL_ARM(vcpu_op, 3),
     HYPERCALL(vm_assist, 2),
+    HYPERCALL(trace_pc, 4),
 };
 
 #ifndef NDEBUG
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 93ead6e5dd..b283c3e22c 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -74,6 +74,8 @@ efi-y := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \
                       -O $(BASEDIR)/include/xen/compile.h ]; then \
                          echo '$(TARGET).efi'; fi)
 
+objs-need-tracing := cpuid.o hypercall.o
+
 ifneq ($(build_id_linker),)
 notes_phdrs = --notes
 else
diff --git a/xen/arch/x86/hvm/hypercall.c b/xen/arch/x86/hvm/hypercall.c
index e7238ce293..b59d7d481e 100644
--- a/xen/arch/x86/hvm/hypercall.c
+++ b/xen/arch/x86/hvm/hypercall.c
@@ -132,6 +132,7 @@ static const hypercall_table_t hvm_hypercall_table[] = {
     COMPAT_CALL(mmuext_op),
     HYPERCALL(xenpmu_op),
     COMPAT_CALL(dm_op),
+    HYPERCALL(trace_pc),
     HYPERCALL(arch_1)
 };
 
diff --git a/xen/arch/x86/hypercall.c b/xen/arch/x86/hypercall.c
index e30181817a..672ffe7ef5 100644
--- a/xen/arch/x86/hypercall.c
+++ b/xen/arch/x86/hypercall.c
@@ -68,6 +68,7 @@ const hypercall_args_t hypercall_args_table[NR_hypercalls] =
     ARGS(xenpmu_op, 2),
     ARGS(dm_op, 3),
     ARGS(mca, 1),
+    ARGS(trace_pc, 4),
     ARGS(arch_1, 1),
 };
 
diff --git a/xen/arch/x86/pv/Makefile b/xen/arch/x86/pv/Makefile
index 4e15484471..8c3eccdfd7 100644
--- a/xen/arch/x86/pv/Makefile
+++ b/xen/arch/x86/pv/Makefile
@@ -11,3 +11,5 @@ obj-y += traps.o
 
 obj-bin-y += dom0_build.init.o
 obj-bin-y += gpr_switch.o
+
+objs-need-tracing += hypercall.o
diff --git a/xen/arch/x86/pv/hypercall.c b/xen/arch/x86/pv/hypercall.c
index f79f7eef62..13eb2e86a2 100644
--- a/xen/arch/x86/pv/hypercall.c
+++ b/xen/arch/x86/pv/hypercall.c
@@ -80,6 +80,7 @@ static const hypercall_table_t pv_hypercall_table[] = {
     HYPERCALL(xenpmu_op),
     COMPAT_CALL(dm_op),
     HYPERCALL(mca),
+    HYPERCALL(trace_pc),
     HYPERCALL(arch_1),
 };
 
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 26c5a64337..4e39dc66e0 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -55,6 +55,8 @@ obj-y += tasklet.o
 obj-y += time.o
 obj-y += timer.o
 obj-y += trace.o
+obj-y += trace_pc.o
+obj-$(CONFIG_TRACE_PC) += trace_pc_stub.o
 obj-y += version.o
 obj-y += virtual_region.o
 obj-y += vm_event.o
@@ -80,3 +82,14 @@ subdir-$(CONFIG_GCOV) += gcov
 
 subdir-y += libelf
 subdir-$(CONFIG_HAS_DEVICE_TREE) += libfdt
+
+objs-need-tracing := bsearch.o \
+    decompress.o device_tree.o domain.o domctl.o earlycpio.o grant_table.o \
+    guestcopy.o gunzip.o inflate.o kernel.o kexec.o keyhandler.o kimage.o \
+    lib.o livepatch.o lzo.o mem_access.o memory.o multicall.o notifier.o \
+    page_alloc.o pdx.o perfc.o radix_tree.o rangeset.o \
+    rbtree.o shutdown.o sort.o stop_machine.o \
+    symbols.o symbols-dummy.o sysctl.o time.o tmem.o \
+    tmem_control.o tmem_xen.o trace.o unlz4.o unlzo.o unxz.o version.o \
+    virtual_region.o vmap.o vm_event.o warning.o xenoprof.o \
+    xmalloc_tlsf.o
diff --git a/xen/common/domain.c b/xen/common/domain.c
index b22aacc57e..c98a0a94ec 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -874,6 +874,10 @@ void domain_destroy(struct domain *d)
     rcu_assign_pointer(*pd, d->next_in_hashbucket);
     spin_unlock(&domlist_update_lock);
 
+#ifdef CONFIG_TRACE_PC
+    xfree(d->tracing_buffer);
+#endif
+
     /* Schedule RCU asynchronous completion of domain destroy. */
     call_rcu(&d->rcu, complete_domain_destroy);
 }
diff --git a/xen/common/trace_pc.c b/xen/common/trace_pc.c
new file mode 100644
index 0000000000..722572c500
--- /dev/null
+++ b/xen/common/trace_pc.c
@@ -0,0 +1,96 @@
+/******************************************************************************
+ * trace_pc.c
+ *
+ * Implementation of the program counter tracing hypercall.
+ *
+ * Copyright (c) 2017 Felix Schmoll <eggi.innovations@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms and conditions of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/guest_access.h>
+#include <xen/sched.h>
+#include <xen/xmalloc.h>
+#include <public/trace_pc.h>
+
+long do_trace_pc(domid_t dom, int mode, unsigned int size,
+                 XEN_GUEST_HANDLE_PARAM(uint64_t) buf)
+{
+#ifdef CONFIG_TRACE_PC
+    int ret = 0;
+    struct domain *d;
+
+    if ( dom == DOMID_SELF )
+        d = current->domain;
+    else
+        d = get_domain_by_id(dom);
+
+    if ( !d )
+        return -ESRCH; /* invalid domain */
+
+    switch ( mode )
+    {
+    case XEN_TRACE_PC_START:
+    {
+        if ( d->tracing_buffer )
+        {
+            ret = -EBUSY; /* domain already being traced */
+            break;
+        }
+
+        d->tracing_buffer_pos = 0;
+        d->tracing_buffer_size = size;
+        d->tracing_buffer = xmalloc_array(uint64_t, size);
+
+        if ( !d->tracing_buffer )
+            ret = -ENOMEM;
+        break;
+    }
+
+    case XEN_TRACE_PC_STOP:
+    {
+        uint64_t *temp = d->tracing_buffer;
+        d->tracing_buffer = NULL;
+
+        if ( copy_to_guest(buf, temp, d->tracing_buffer_pos) )
+            ret = -EFAULT;
+        else
+            ret = d->tracing_buffer_pos;
+
+        xfree(temp);
+
+        break;
+    }
+
+    default:
+        ret = -ENOSYS;
+    }
+
+    if ( dom != DOMID_SELF )
+        put_domain(d);
+
+    return ret;
+#else
+    return -EOPNOTSUPP;
+#endif
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/trace_pc_stub.c b/xen/common/trace_pc_stub.c
new file mode 100644
index 0000000000..4aba7dba9f
--- /dev/null
+++ b/xen/common/trace_pc_stub.c
@@ -0,0 +1,39 @@
+/******************************************************************************
+ * trace_pc_stub.c
+ *
+ * Edge function/stub for the program counter tracing hypercall.
+ *
+ * Copyright (c) 2017 Felix Schmoll <eggi.innovations@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms and conditions of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/trace_pc.h>
+#include <xen/kernel.h>
+
+void __sanitizer_cov_trace_pc(void)
+{
+    struct domain *d;
+
+    if ( system_state < SYS_STATE_active )
+        return;
+
+    d = current->domain;
+
+    if ( d->tracing_buffer &&
+        (d->tracing_buffer_pos < d->tracing_buffer_size) )
+    {
+        d->tracing_buffer[d->tracing_buffer_pos++] =
+            (uint64_t) __builtin_return_address(0);
+    }
+}
diff --git a/xen/include/public/trace_pc.h b/xen/include/public/trace_pc.h
new file mode 100644
index 0000000000..54e430a561
--- /dev/null
+++ b/xen/include/public/trace_pc.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ * trace_pc.h
+ *
+ * Macros for program counter tracing hypercall.
+ *
+ * Copyright (C) 2017 Felix Schmoll <eggi.innovations@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_TRACE_PC_H__
+#define __XEN_PUBLIC_TRACE_PC_H__
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+
+#define XEN_TRACE_PC_START 0
+#define XEN_TRACE_PC_STOP 1
+
+#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
+
+#endif /* __XEN_PUBLIC_TRACE_PC_H__ */
diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index 2ac6b1e24d..95d83c21ce 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -121,6 +121,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
 #define __HYPERVISOR_xc_reserved_op       39 /* reserved for XenClient */
 #define __HYPERVISOR_xenpmu_op            40
 #define __HYPERVISOR_dm_op                41
+#define __HYPERVISOR_trace_pc             42
 
 /* Architecture-specific hypercall definitions. */
 #define __HYPERVISOR_arch_0               48
diff --git a/xen/include/xen/hypercall.h b/xen/include/xen/hypercall.h
index cc99aea57d..aa6269e7b7 100644
--- a/xen/include/xen/hypercall.h
+++ b/xen/include/xen/hypercall.h
@@ -83,6 +83,13 @@ do_xen_version(
     XEN_GUEST_HANDLE_PARAM(void) arg);
 
 extern long
+do_trace_pc(
+    domid_t dom_id,
+    int mode,
+    unsigned int size,
+    XEN_GUEST_HANDLE_PARAM(uint64_t) buf);
+
+extern long
 do_console_io(
     int cmd,
     int count,
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 6673b27d88..4bd3fe2417 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -483,6 +483,12 @@ struct domain
         unsigned int guest_request_enabled       : 1;
         unsigned int guest_request_sync          : 1;
     } monitor;
+
+#ifdef CONFIG_TRACE_PC
+    uint64_t* tracing_buffer;
+    unsigned int tracing_buffer_pos;
+    unsigned int tracing_buffer_size;
+#endif
 };
 
 /* Protect updates/reads (resp.) of domain_list and domain_hash. */
diff --git a/xen/include/xen/trace_pc.h b/xen/include/xen/trace_pc.h
new file mode 100644
index 0000000000..631815de30
--- /dev/null
+++ b/xen/include/xen/trace_pc.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * trace_pc.h
+ *
+ * Declarations for the program counter tracing hypercall
+ *
+ * Copyright (C) 2017 Felix Schmoll <eggi.innovations@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms and conditions of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TRACE_PC_H__
+#define __TRACE_PC_H__
+
+#include <xen/sched.h>
+#include <xen/types.h>
+
+#include <asm/current.h>
+
+void __sanitizer_cov_trace_pc(void);
+
+#endif /* __TRACE_PC_H__ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH XTF] Fuzzing the hypervisor
  2017-08-17 10:21 ` [PATCH XTF] " Felix Schmoll
@ 2017-08-17 12:41   ` Wei Liu
  0 siblings, 0 replies; 5+ messages in thread
From: Wei Liu @ 2017-08-17 12:41 UTC (permalink / raw)
  To: Felix Schmoll; +Cc: xen-devel, wei.liu2

On Thu, Aug 17, 2017 at 12:21:49PM +0200, Felix Schmoll wrote:
> Changes based on commit 8956f82ce1321b89deda6895d58e5788d2198477
> ---
>  include/xen/xen.h          |   1 +
>  include/xtf/hypercall.h    |   8 +-
>  tests/mk_hcall/.main.c.swo | Bin 0 -> 12288 bytes

This should not be included.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-08-17 12:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-17  9:58 [GSoC] Fuzzing the Hypervisor Felix Schmoll
2017-08-17 10:15 ` [PATCH AFL] Fuzzing the hypervisor Felix Schmoll
2017-08-17 10:21 ` [PATCH XTF] " Felix Schmoll
2017-08-17 12:41   ` Wei Liu
2017-08-17 10:25 ` [PATCH XEN] " Felix Schmoll

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).