|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen staging] tools/fuzz: Add a cpu-policy fuzzing harness
commit a08243eb4a2626851e2e2c77465b49781710b490
Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Thu Jan 3 18:03:25 2019 +0000
Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Thu Jun 6 15:28:20 2019 +0100
tools/fuzz: Add a cpu-policy fuzzing harness
There is now enough complexity that a fuzzing harness is a good idea, and
enough supporting logic to implement one which AFL seems happy with.
Take the existing recalculate_synth() helper and export it as
x86_cpuid_policy_recalc_synth(), as it is needed by the fuzzing harness.
While editing the MAINTAINERS file, insert a related entry which was
accidentally missed from c/s 919ddc3c0 "tools/cpu-policy: Add unit tests",
and
sort the lines.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Acked-by: Jan Beulich <jbeulich@xxxxxxxx>
---
MAINTAINERS | 4 +-
tools/fuzz/cpu-policy/.gitignore | 1 +
tools/fuzz/cpu-policy/Makefile | 28 +++++
tools/fuzz/cpu-policy/afl-policy-fuzzer.c | 189 ++++++++++++++++++++++++++++++
xen/include/xen/lib/x86/cpuid.h | 5 +
xen/lib/x86/cpuid.c | 7 +-
6 files changed, 229 insertions(+), 5 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 3c4326de48..6fbdc2bdcb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -449,8 +449,10 @@ F: xen/lib/x86
F: tools/firmware/hvmloader/
F: tools/firmware/rombios/
F: tools/firmware/vgabios/
-F: tools/tests/x86_emulator/
+F: tools/fuzz/cpu-policy/
F: tools/fuzz/x86_instruction_emulator/
+F: tools/tests/cpu-policy/
+F: tools/tests/x86_emulator/
X86 I/O EMULATION
M: Paul Durrant <paul.durrant@xxxxxxxxxx>
diff --git a/tools/fuzz/cpu-policy/.gitignore b/tools/fuzz/cpu-policy/.gitignore
new file mode 100644
index 0000000000..b0e0bdf811
--- /dev/null
+++ b/tools/fuzz/cpu-policy/.gitignore
@@ -0,0 +1 @@
+afl-policy-fuzzer
diff --git a/tools/fuzz/cpu-policy/Makefile b/tools/fuzz/cpu-policy/Makefile
new file mode 100644
index 0000000000..41a2230408
--- /dev/null
+++ b/tools/fuzz/cpu-policy/Makefile
@@ -0,0 +1,28 @@
+XEN_ROOT = $(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+.PHONY: all
+all: afl-policy-fuzzer
+
+.PHONY: clean
+clean:
+ $(RM) -f -- *.o .*.d .*.d2 afl-policy-fuzzer
+
+.PHONY: distclean
+distclean: clean
+ $(RM) -f -- *~
+
+.PHONY: install
+install: all
+
+.PHONY: uninstall
+
+CFLAGS += -Werror $(CFLAGS_xeninclude) -D__XEN_TOOLS__
+CFLAGS += $(APPEND_CFLAGS) -Og
+
+vpath %.c ../../../xen/lib/x86
+
+afl-policy-fuzzer: afl-policy-fuzzer.o msr.o cpuid.o
+ $(CC) $(CFLAGS) $^ -o $@
+
+-include $(DEPS_INCLUDE)
diff --git a/tools/fuzz/cpu-policy/afl-policy-fuzzer.c
b/tools/fuzz/cpu-policy/afl-policy-fuzzer.c
new file mode 100644
index 0000000000..79a849a044
--- /dev/null
+++ b/tools/fuzz/cpu-policy/afl-policy-fuzzer.c
@@ -0,0 +1,189 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include <xen-tools/libs.h>
+#include <xen/lib/x86/cpuid.h>
+#include <xen/lib/x86/msr.h>
+#include <xen/domctl.h>
+
+static bool debug;
+
+#define EMPTY_LEAF ((struct cpuid_leaf){})
+
+static void check_cpuid(struct cpuid_policy *cp)
+{
+ struct cpuid_policy new = {};
+ size_t data_end;
+ xen_cpuid_leaf_t *leaves = malloc(CPUID_MAX_SERIALISED_LEAVES *
+ sizeof(xen_cpuid_leaf_t));
+ unsigned int nr = CPUID_MAX_SERIALISED_LEAVES;
+ int rc;
+
+ if ( !leaves )
+ return;
+
+ /*
+ * Clean unusable leaves. These can't be accessed via architectural
+ * means, but may be filled by the fread() across the entire structure.
+ * Also zero the trailing padding (if any).
+ */
+ cp->basic.raw[4] = EMPTY_LEAF;
+ cp->basic.raw[7] = EMPTY_LEAF;
+ cp->basic.raw[0xb] = EMPTY_LEAF;
+ cp->basic.raw[0xd] = EMPTY_LEAF;
+ data_end = offsetof(typeof(*cp), x86_vendor) + sizeof(cp->x86_vendor);
+ if ( data_end < sizeof(*cp) )
+ memset((void *)cp + data_end, 0, sizeof(*cp) - data_end);
+
+ /*
+ * Fix up the data in the source policy which isn't expected to survive
+ * serialisation.
+ */
+ x86_cpuid_policy_clear_out_of_range_leaves(cp);
+ x86_cpuid_policy_recalc_synth(cp);
+
+ /* Serialise... */
+ rc = x86_cpuid_copy_to_buffer(cp, leaves, &nr);
+ assert(rc == 0);
+ assert(nr <= CPUID_MAX_SERIALISED_LEAVES);
+
+ /* ... and deserialise. */
+ rc = x86_cpuid_copy_from_buffer(&new, leaves, nr, NULL, NULL);
+ assert(rc == 0);
+
+ /* The result after serialisation/deserialisaion should be identical... */
+ if ( memcmp(cp, &new, sizeof(*cp)) != 0 )
+ {
+ if ( debug )
+ {
+ unsigned char *l = (void *)cp, *r = (void *)&new;
+
+ for ( size_t i = 0; i < sizeof(*cp); ++i )
+ if ( l[i] != r[i] )
+ printf("Differ at offset %zu: %u vs %u\n",
+ i, l[i], r[i]);
+ }
+
+ abort();
+ }
+
+ free(leaves);
+}
+
+static void check_msr(struct msr_policy *mp)
+{
+ struct msr_policy new = {};
+ xen_msr_entry_t *msrs = malloc(MSR_MAX_SERIALISED_ENTRIES *
+ sizeof(xen_msr_entry_t));
+ unsigned int nr = MSR_MAX_SERIALISED_ENTRIES;
+ int rc;
+
+ if ( !msrs )
+ return;
+
+ rc = x86_msr_copy_to_buffer(mp, msrs, &nr);
+ assert(rc == 0);
+ assert(nr <= MSR_MAX_SERIALISED_ENTRIES);
+
+ rc = x86_msr_copy_from_buffer(&new, msrs, nr, NULL);
+ assert(rc == 0);
+ assert(memcmp(mp, &new, sizeof(*mp)) == 0);
+
+ free(msrs);
+}
+
+int main(int argc, char **argv)
+{
+ FILE *fp = NULL;
+
+ setbuf(stdin, NULL);
+ setbuf(stdout, NULL);
+
+ while ( true )
+ {
+ static const struct option opts[] = {
+ { "debug", no_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ {},
+ };
+ int c = getopt_long(argc, argv, "hd", opts, NULL);
+
+ if ( c == -1 )
+ break;
+
+ switch ( c )
+ {
+ case 'd':
+ printf("Enabling debug\n");
+ debug = true;
+ break;
+
+ case '?':
+ case 'h':
+ printf("Usage: %s [--debug] <FILE>\n", argv[0]);
+ default:
+ exit(-(c != 'h'));
+ break;
+ }
+ }
+
+ if ( optind == argc ) /* No positional parameters. Use stdin. */
+ {
+ printf("Using stdin\n");
+ fp = stdin;
+ }
+
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+ __AFL_INIT();
+ while ( __AFL_LOOP(1000) )
+#endif
+ {
+ struct cpuid_policy *cp = NULL;
+ struct msr_policy *mp = NULL;
+
+ if ( fp != stdin )
+ {
+ printf("Opening file '%s'\n", argv[optind]);
+ fp = fopen(argv[optind], "rb");
+
+ if ( !fp )
+ {
+ perror("fopen");
+ exit(-1);
+ }
+ }
+
+ cp = calloc(1, sizeof(*cp));
+ mp = calloc(1, sizeof(*mp));
+ if ( !cp || !mp )
+ goto skip;
+
+ fread(cp, sizeof(*cp), 1, fp);
+ fread(mp, sizeof(*mp), 1, fp);
+
+ if ( !feof(fp) )
+ goto skip;
+
+ check_cpuid(cp);
+ check_msr(mp);
+
+ skip:
+ free(cp);
+ free(mp);
+
+ if ( fp != stdin )
+ {
+ fclose(fp);
+ fp = NULL;
+ }
+ }
+
+ return 0;
+}
diff --git a/xen/include/xen/lib/x86/cpuid.h b/xen/include/xen/lib/x86/cpuid.h
index 2618598319..df5946b6b1 100644
--- a/xen/include/xen/lib/x86/cpuid.h
+++ b/xen/include/xen/lib/x86/cpuid.h
@@ -323,6 +323,11 @@ static inline uint64_t cpuid_policy_xstates(const struct
cpuid_policy *p)
const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature);
/**
+ * Recalculate the content in a CPUID policy which is derived from raw data.
+ */
+void x86_cpuid_policy_recalc_synth(struct cpuid_policy *p);
+
+/**
* Fill a CPUID policy using the native CPUID instruction.
*
* No sanitisation is performed, but synthesised values are calculated.
diff --git a/xen/lib/x86/cpuid.c b/xen/lib/x86/cpuid.c
index 24f425eed5..ea6e476a4f 100644
--- a/xen/lib/x86/cpuid.c
+++ b/xen/lib/x86/cpuid.c
@@ -53,8 +53,7 @@ const char *x86_cpuid_vendor_to_str(unsigned int vendor)
}
}
-/* Recalculate the content in a CPUID policy which is derived from raw data. */
-static void recalculate_synth(struct cpuid_policy *p)
+void x86_cpuid_policy_recalc_synth(struct cpuid_policy *p)
{
p->x86_vendor = x86_cpuid_lookup_vendor(
p->basic.vendor_ebx, p->basic.vendor_ecx, p->basic.vendor_edx);
@@ -170,7 +169,7 @@ void x86_cpuid_policy_fill_native(struct cpuid_policy *p)
p->extd.max_leaf + 1 - 0x80000000); ++i )
cpuid_leaf(0x80000000 + i, &p->extd.raw[i]);
- recalculate_synth(p);
+ x86_cpuid_policy_recalc_synth(p);
}
void x86_cpuid_policy_clear_out_of_range_leaves(struct cpuid_policy *p)
@@ -465,7 +464,7 @@ int x86_cpuid_copy_from_buffer(struct cpuid_policy *p,
}
}
- recalculate_synth(p);
+ x86_cpuid_policy_recalc_synth(p);
return 0;
--
generated by git-patchbot for /home/xen/git/xen.git#staging
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |