]> xenbits.xensource.com Git - xen.git/commitdiff
x86emul: rework wrapping of libc functions in test and fuzzing harnesses
authorJan Beulich <jbeulich@suse.com>
Fri, 18 Aug 2023 13:04:28 +0000 (15:04 +0200)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 22 Aug 2023 12:43:05 +0000 (13:43 +0100)
Our present approach is working fully behind the compiler's back. This
was found to not work with LTO. Employ ld's --wrap= option instead. Note
that while this makes the build work at least with new enough gcc (it
doesn't with gcc7, for example, due to tool chain side issues afaict),
according to my testing things still won't work when building the
fuzzing harness with afl-cc: While with the gcc7 tool chain I see afl-as
getting invoked, this does not happen with gcc13. Yet without using that
assembler wrapper the resulting binary will look uninstrumented to
afl-fuzz.

While checking the resulting binaries I noticed that we've gained uses
of snprintf() and strstr(), which only just so happen to not cause any
problems. Add a wrappers for them as well.

Since we don't have any actual uses of v{,sn}printf(), no definitions of
their wrappers appear (just yet). But I think we want
__wrap_{,sn}printf() to properly use __real_v{,sn}printf() right away,
which means we need delarations of the latter.

Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Tested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
(cherry picked from commit 6fba45ca3be1c5d46cddb1eaf371d9e69550b244)

tools/fuzz/x86_instruction_emulator/Makefile
tools/tests/x86_emulator/Makefile
tools/tests/x86_emulator/wrappers.c
tools/tests/x86_emulator/x86-emulate.h

index 13aa238503359750b8a44db89b3f028b12d972e9..c83959c847bfb13a41f8d842192934c7a4997c0d 100644 (file)
@@ -29,6 +29,8 @@ GCOV_FLAGS := --coverage
 %-cov.o: %.c
        $(CC) -c $(CFLAGS) $(GCOV_FLAGS) $< -o $@
 
+WRAPPED = $(shell sed -n 's,^ *WRAP(\([[:alnum:]_]*\));,\1,p' x86-emulate.h)
+
 x86-emulate.h: x86_emulate/x86_emulate.h
 x86-emulate.o x86-emulate-cov.o: x86-emulate.h x86_emulate/x86_emulate.c
 fuzz-emul.o fuzz-emul-cov.o wrappers.o: x86-emulate.h
@@ -37,10 +39,10 @@ x86-insn-fuzzer.a: fuzz-emul.o x86-emulate.o cpuid.o
        $(AR) rc $@ $^
 
 afl-harness: afl-harness.o fuzz-emul.o x86-emulate.o cpuid.o wrappers.o
-       $(CC) $(CFLAGS) $^ -o $@
+       $(CC) $(CFLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
 
 afl-harness-cov: afl-harness-cov.o fuzz-emul-cov.o x86-emulate-cov.o cpuid.o wrappers.o
-       $(CC) $(CFLAGS) $(GCOV_FLAGS) $^ -o $@
+       $(CC) $(CFLAGS) $(GCOV_FLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) $^ -o $@
 
 # Common targets
 .PHONY: all
index bd82598f976657aea5ce2e684227f2d81618993f..a2fd6607c6388f76671f1589cc704fa7b420cee6 100644 (file)
@@ -250,8 +250,10 @@ xop.h avx512f.h: simd-fma.c
 
 endif # 32-bit override
 
+WRAPPED := $(shell sed -n 's,^ *WRAP(\([[:alnum:]_]*\));,\1,p' x86-emulate.h)
+
 $(TARGET): x86-emulate.o cpuid.o test_x86_emulator.o evex-disp8.o predicates.o wrappers.o
-       $(HOSTCC) $(HOSTCFLAGS) -o $@ $^
+       $(HOSTCC) $(HOSTCFLAGS) $(addprefix -Wl$(comma)--wrap=,$(WRAPPED)) -o $@ $^
 
 .PHONY: clean
 clean:
index eba7cc93c5153349b41fd220ba00c4f8c7d4305d..3829a6f416130d56a2a5e0d588428e8ede5efbdf 100644 (file)
 #include <stdarg.h>
 
-#define WRAP(x) typeof(x) emul_##x
+#define WRAP(x) typeof(x) __wrap_ ## x, __real_ ## x
 #include "x86-emulate.h"
 
-size_t emul_fwrite(const void *src, size_t sz, size_t n, FILE *f)
+size_t __wrap_fwrite(const void *src, size_t sz, size_t n, FILE *f)
 {
     emul_save_fpu_state();
-    sz = fwrite(src, sz, n, f);
+    sz = __real_fwrite(src, sz, n, f);
     emul_restore_fpu_state();
 
     return sz;
 }
 
-int emul_memcmp(const void *p1, const void *p2, size_t sz)
+int __wrap_memcmp(const void *p1, const void *p2, size_t sz)
 {
     int rc;
 
     emul_save_fpu_state();
-    rc = memcmp(p1, p2, sz);
+    rc = __real_memcmp(p1, p2, sz);
     emul_restore_fpu_state();
 
     return rc;
 }
 
-void *emul_memcpy(void *dst, const void *src, size_t sz)
+void *__wrap_memcpy(void *dst, const void *src, size_t sz)
 {
     emul_save_fpu_state();
-    memcpy(dst, src, sz);
+    __real_memcpy(dst, src, sz);
     emul_restore_fpu_state();
 
     return dst;
 }
 
-void *emul_memset(void *dst, int c, size_t sz)
+void *__wrap_memset(void *dst, int c, size_t sz)
 {
     emul_save_fpu_state();
-    memset(dst, c, sz);
+    __real_memset(dst, c, sz);
     emul_restore_fpu_state();
 
     return dst;
 }
 
-int emul_printf(const char *fmt, ...)
+int __wrap_printf(const char *fmt, ...)
 {
     va_list varg;
     int rc;
 
     emul_save_fpu_state();
     va_start(varg, fmt);
-    rc = vprintf(fmt, varg);
+    rc = __real_vprintf(fmt, varg);
     va_end(varg);
     emul_restore_fpu_state();
 
     return rc;
 }
 
-int emul_putchar(int c)
+int __wrap_putchar(int c)
 {
     int rc;
 
     emul_save_fpu_state();
-    rc = putchar(c);
+    rc = __real_putchar(c);
     emul_restore_fpu_state();
 
     return rc;
 }
 
-int emul_puts(const char *str)
+int __wrap_puts(const char *str)
 {
     int rc;
 
     emul_save_fpu_state();
-    rc = puts(str);
+    rc = __real_puts(str);
     emul_restore_fpu_state();
 
     return rc;
 }
+
+int __wrap_snprintf(char *buf, size_t n, const char *fmt, ...)
+{
+    va_list varg;
+    int rc;
+
+    emul_save_fpu_state();
+    va_start(varg, fmt);
+    rc = __real_vsnprintf(buf, n, fmt, varg);
+    va_end(varg);
+    emul_restore_fpu_state();
+
+    return rc;
+}
+
+char *__wrap_strstr(const char *s1, const char *s2)
+{
+    char *s;
+
+    emul_save_fpu_state();
+    s = __real_strstr(s1, s2);
+    emul_restore_fpu_state();
+
+    return s;
+}
index 19bea9c38d589f45eeb715458de07b15be3194d9..58760f096d3e8328ed738b6e9d822ae8f56d6d20 100644 (file)
@@ -29,9 +29,7 @@
 #ifdef EOF
 # error "Must not include <stdio.h> before x86-emulate.h"
 #endif
-#ifdef WRAP
-# include <stdio.h>
-#endif
+#include <stdio.h>
 
 #include <xen/xen.h>
 
@@ -85,11 +83,7 @@ void emul_restore_fpu_state(void);
  * around the actual function.
  */
 #ifndef WRAP
-# if 0 /* This only works for explicit calls, not for compiler generated ones. */
-#  define WRAP(x) typeof(x) x asm("emul_" #x)
-# else
-# define WRAP(x) asm(".equ " #x ", emul_" #x)
-# endif
+# define WRAP(x) typeof(x) __wrap_ ## x
 #endif
 
 WRAP(fwrite);
@@ -99,6 +93,10 @@ WRAP(memset);
 WRAP(printf);
 WRAP(putchar);
 WRAP(puts);
+WRAP(snprintf);
+WRAP(strstr);
+WRAP(vprintf);
+WRAP(vsnprintf);
 
 #undef WRAP