[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.