[PATCH v10 4/10] libs/guest: use Valgrind or sanitizers to detect various buffer overflows
Frediano Ziglio <[email protected]>
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <[email protected]> |
Previously this was done as buffers were allocated separately. Signed-off-by: Frediano Ziglio <[email protected]> --- Changes since v9: - add support for sanitizers also; - remove some unneeded check buffers. --- tools/config.h.in | 6 ++++ tools/configure | 12 +++++++ tools/configure.ac | 3 +- tools/libs/ctrl/xc_private.h | 61 +++++++++++++++++++++++++++++++-- tools/libs/guest/xg_sr_common.h | 6 ++++ tools/libs/guest/xg_sr_save.c | 11 ++++++ 6 files changed, 96 insertions(+), 3 deletions(-) diff --git a/tools/config.h.in b/tools/config.h.in index ed0042018d..d51816453b 100644 --- a/tools/config.h.in +++ b/tools/config.h.in @@ -48,6 +48,12 @@ /* ROMBIOS enabled */ #undef HAVE_ROMBIOS +/* Define to 1 if you have the <sanitizer/asan_interface.h> header file. */ +#undef HAVE_SANITIZER_ASAN_INTERFACE_H + +/* Define to 1 if you have the <sanitizer/msan_interface.h> header file. */ +#undef HAVE_SANITIZER_MSAN_INTERFACE_H + /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H diff --git a/tools/configure b/tools/configure index cd989925ed..94e630665f 100755 --- a/tools/configure +++ b/tools/configure @@ -10203,6 +10203,18 @@ then : printf "%s\n" "#define HAVE_UTMP_H 1" >>confdefs.h fi +ac_fn_c_check_header_compile "$LINENO" "sanitizer/asan_interface.h" "ac_cv_header_sanitizer_asan_interface_h" "$ac_includes_default" +if test "x$ac_cv_header_sanitizer_asan_interface_h" = xyes +then : + printf "%s\n" "#define HAVE_SANITIZER_ASAN_INTERFACE_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sanitizer/msan_interface.h" "ac_cv_header_sanitizer_msan_interface_h" "$ac_includes_default" +if test "x$ac_cv_header_sanitizer_msan_interface_h" = xyes +then : + printf "%s\n" "#define HAVE_SANITIZER_MSAN_INTERFACE_H 1" >>confdefs.h + +fi # Check for libnl3 >=3.2.8. If present enable remus network buffering. diff --git a/tools/configure.ac b/tools/configure.ac index 74b9f56025..5346ff6129 100644 --- a/tools/configure.ac +++ b/tools/configure.ac @@ -454,7 +454,8 @@ AC_CHECK_DECLS([fdt_property_u32],,,[#include <libfdt.h>]) esac # Checks for header files. -AC_CHECK_HEADERS([yajl/yajl_version.h sys/eventfd.h valgrind/memcheck.h utmp.h]) +AC_CHECK_HEADERS([yajl/yajl_version.h sys/eventfd.h valgrind/memcheck.h \ + utmp.h sanitizer/asan_interface.h sanitizer/msan_interface.h]) # Check for libnl3 >=3.2.8. If present enable remus network buffering. PKG_CHECK_MODULES(LIBNL3, [libnl-3.0 >= 3.2.8 libnl-route-3.0 >= 3.2.8], diff --git a/tools/libs/ctrl/xc_private.h b/tools/libs/ctrl/xc_private.h index 8a325c17b0..7803192599 100644 --- a/tools/libs/ctrl/xc_private.h +++ b/tools/libs/ctrl/xc_private.h @@ -42,13 +42,70 @@ #include <xen-tools/common-macros.h> -#if defined(HAVE_VALGRIND_MEMCHECK_H) && !defined(NDEBUG) && !defined(__MINIOS__) +#undef XEN_USE_MEM_NOACCESS +#if !defined(NDEBUG) && !defined(__MINIOS__) + +#if !defined(__has_feature) +#define __has_feature(x) 0 +#endif + +#if defined(HAVE_SANITIZER_ASAN_INTERFACE_H) && \ + (__has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)) +#include <sanitizer/asan_interface.h> +#define XEN_USE_MEM_NOACCESS 1 +#elif defined(HAVE_SANITIZER_MSAN_INTERFACE_H) && \ + __has_feature(memory_sanitizer) +#include <sanitizer/msan_interface.h> +#define XEN_USE_MEM_NOACCESS 1 +#endif +#if defined(HAVE_VALGRIND_MEMCHECK_H) /* Compile in Valgrind client requests? */ #include <valgrind/memcheck.h> -#else +#define XEN_USE_MEM_NOACCESS 1 +#endif + +#endif + +#if !defined(HAVE_VALGRIND_MEMCHECK_H) || defined(NDEBUG) || defined(__MINIOS__) #define VALGRIND_MAKE_MEM_UNDEFINED(addr, len) /* addr, len */ #endif +#if defined(XEN_USE_MEM_NOACCESS) +#define MEM_NOACCESS_BUFFER(name, size) uint8_t name[size]; +#if defined(HAVE_VALGRIND_MEMCHECK_H) +#define MEM_NOACCESS_INIT_VALGRIND(field) \ + VALGRIND_MAKE_MEM_NOACCESS(field, sizeof(field)) +#else +#define MEM_NOACCESS_INIT_VALGRIND(field) +#endif +#if defined(HAVE_SANITIZER_ASAN_INTERFACE_H) && \ + (__has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)) +#define MEM_NOACCESS_INIT_SANITIZER(field) \ + ASAN_POISON_MEMORY_REGION(field, sizeof(field)) +#else +#define MEM_NOACCESS_INIT_SANITIZER(field) +#endif +#if defined(HAVE_SANITIZER_MSAN_INTERFACE_H) && \ + __has_feature(memory_sanitizer) +#define MEM_UNDEFINED_INIT_SANITIZER(field) \ + __msan_poison(field, sizeof(field)) +#else +#define MEM_UNDEFINED_INIT_SANITIZER(field) +#endif +#define MEM_NOACCESS_INIT(field) do { \ + MEM_NOACCESS_INIT_VALGRIND(field); \ + MEM_NOACCESS_INIT_SANITIZER(field); \ +} while(0) +#define MEM_UNDEFINED_INIT(field) do { \ + VALGRIND_MAKE_MEM_UNDEFINED(field, sizeof(field)); \ + MEM_UNDEFINED_INIT_SANITIZER(field); \ +} while(0) +#else +#define MEM_NOACCESS_BUFFER(name, size) +#define MEM_NOACCESS_INIT(field) do {} while(0) +#define MEM_UNDEFINED_INIT(field) do {} while(0) +#endif + #if defined(__MINIOS__) /* * MiniOS's libc doesn't know about sys/uio.h or writev(). diff --git a/tools/libs/guest/xg_sr_common.h b/tools/libs/guest/xg_sr_common.h index c07c6db59e..020b1a5272 100644 --- a/tools/libs/guest/xg_sr_common.h +++ b/tools/libs/guest/xg_sr_common.h @@ -246,11 +246,17 @@ struct xc_sr_context struct xc_sr_context_save_buffers { xen_pfn_t batch_pfns[MAX_BATCH_SIZE]; + MEM_NOACCESS_BUFFER(na0, 64); xen_pfn_t mfns[MAX_BATCH_SIZE]; + MEM_NOACCESS_BUFFER(na1, 64); xen_pfn_t types[MAX_BATCH_SIZE]; + MEM_NOACCESS_BUFFER(na2, 64); void *local_pages[MAX_BATCH_SIZE]; + MEM_NOACCESS_BUFFER(na3, 64); struct iovec iov[MAX_BATCH_SIZE + 2]; /* Headers + data. */ + MEM_NOACCESS_BUFFER(na4, 64); uint64_t rec_pfns[MAX_BATCH_SIZE]; + MEM_NOACCESS_BUFFER(na5, 64); int errors[MAX_BATCH_SIZE]; } *buffers; } save; diff --git a/tools/libs/guest/xg_sr_save.c b/tools/libs/guest/xg_sr_save.c index 6a77e33a47..96d7e9e2f8 100644 --- a/tools/libs/guest/xg_sr_save.c +++ b/tools/libs/guest/xg_sr_save.c @@ -123,6 +123,11 @@ static int write_batch(struct xc_sr_context *ctx) assert(nr_pfns != 0); assert(nr_pfns <= MAX_BATCH_SIZE); + MEM_UNDEFINED_INIT(ctx->save.buffers->mfns); + MEM_UNDEFINED_INIT(ctx->save.buffers->types); + MEM_UNDEFINED_INIT(ctx->save.buffers->iov); + MEM_UNDEFINED_INIT(ctx->save.buffers->rec_pfns); + iov[0].iov_base = &hdrs; iov[0].iov_len = sizeof(hdrs); @@ -783,6 +788,12 @@ static int setup(struct xc_sr_context *ctx) errno = ENOMEM; goto err; } + MEM_NOACCESS_INIT(ctx->save.buffers->na0); + MEM_NOACCESS_INIT(ctx->save.buffers->na1); + MEM_NOACCESS_INIT(ctx->save.buffers->na2); + MEM_NOACCESS_INIT(ctx->save.buffers->na3); + MEM_NOACCESS_INIT(ctx->save.buffers->na4); + MEM_NOACCESS_INIT(ctx->save.buffers->na5); rc = 0; -- 2.43.0