[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 05/05: Refactored user-poison: minimized scope of non-sa
From: |
gnunet |
Subject: |
[libmicrohttpd] 05/05: Refactored user-poison: minimized scope of non-sanitized code |
Date: |
Sat, 26 Nov 2022 18:08:19 +0100 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit 3444792f14d96a58648add92b8f3b70e4babf772
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Thu Nov 24 11:59:38 2022 +0300
Refactored user-poison: minimized scope of non-sanitized code
---
configure.ac | 246 +++++++++++++++++++++++++++++++++++++-------
src/include/mhd_options.h | 7 +-
src/microhttpd/memorypool.c | 120 ++++++++++++++++-----
3 files changed, 308 insertions(+), 65 deletions(-)
diff --git a/configure.ac b/configure.ac
index cf261ead..b032badc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3995,39 +3995,167 @@ AS_VAR_IF([enable_sanitizers], ["no"], [:],
AS_VAR_IF([enable_san_upoison], ["no"], [:],
[
AC_CHECK_HEADERS([sanitizer/asan_interface.h], [], [],
[AC_INCLUDES_DEFAULT])
- AS_IF([test "x${mhd_cv_cc_sanitizer_pointer_compare}" =
"xyes" && test "x${ac_cv_header_sanitizer_asan_interface_h}" = "xyes"],
+ AS_VAR_IF([ac_cv_header_sanitizer_asan_interface_h],["yes"],
[
- AC_CACHE_CHECK([whether
'__attribute__((no_sanitize("pointer-compare","pointer-subtract")))' works],
[mhd_cv_func_attribute_nosanitize_ptr],
+ AC_CACHE_CHECK([whether special function attribute is
needed for user-poison], [mhd_cv_func_u_p_attribute_needed],
[
ASAN_OPTIONS="exitcode=88:detect_invalid_pointer_pairs=3:halt_on_error=1"
export ASAN_OPTIONS
CFLAGS="${CFLAGS_ac} ${san_CFLAGS} ${san_FLAGS}
${errattr_CFLAGS} ${user_CFLAGS}"
AC_RUN_IFELSE(
[
- AC_LANG_PROGRAM(
+ AC_LANG_SOURCE(
[[
+#include <stdint.h>
#include <stdlib.h>
+#include <sanitizer/asan_interface.h>
-__attribute__((no_sanitize("pointer-compare","pointer-subtract")))
-int ptr_process(void *ptr1, void *ptr2)
+static const size_t first_pos = 0;
+static const size_t mid_pos = 64;
+static const size_t last_pos = 128;
+static const size_t zone_size = 16;
+static const size_t buf_size = 128 + 16;
+
+static int ptr_compare(void *ptr1, uint8_t *ptr2)
{
- if ((char*)ptr1 <= (char*)ptr2)
- return (int) ((char*)ptr2 - (char*)ptr1);
- return (int) ((char*)ptr1 - (char*)ptr2);
+ if ((((uintptr_t) (uint8_t *)ptr1) >= ((uintptr_t)ptr2)))
+ return ((char *) ptr1)[0] < ((char *) ptr2)[0];
+ return ((char *) ptr1)[0] > ((char *) ptr2)[0];
}
- ]],
+
+static int ptr_subtract(void *ptr1, uint8_t *ptr2)
+{
+ return ((size_t)(((uintptr_t)(uint8_t*)ptr1) - ((uintptr_t)ptr2))) <=
last_pos;
+}
+
+int main(int argc, char *argv[])
+{
+ char *buf = (char*) malloc (buf_size);
+ char *a;
+ char *b;
+ int ret;
+
+ (void) argv;
+ if (NULL == buf)
+ return 10;
+ ASAN_POISON_MEMORY_REGION (buf + first_pos + zone_size, mid_pos - first_pos
- zone_size);
+ ASAN_POISON_MEMORY_REGION (buf + mid_pos + zone_size, last_pos - mid_pos -
zone_size);
+
+ if (0 < argc)
+ a = buf + last_pos;
+ else
+ a = buf + first_pos;
+ b = buf + mid_pos;
+
+ *a = '0';
+ *b = '9';
+
+ if (ptr_compare((void *)a, (uint8_t*) b))
+ {
+ if (ptr_subtract((void *)a, (uint8_t*) b))
+ ret = 0;
+ else
+ ret = 10;
+ }
+ else
+ ret = 5;
+ ASAN_UNPOISON_MEMORY_REGION (buf, buf_size);
+ free (buf);
+
+ return ret;
+}
+ ]]
+ )
+ ],
+ [mhd_cv_func_u_p_attribute_needed="no"],
[mhd_cv_func_u_p_attribute_needed="yes"],
+ [
+ # Cross-compiling with sanitizers??
+ mhd_cv_func_up_attribute_needed='assuming no'
+ ]
+ )
+ AS_UNSET([ASAN_OPTIONS])
+ ]
+ )
+ ]
+ )
+ AS_VAR_IF([mhd_cv_func_u_p_attribute_needed],["yes"],[:],
+ [
+
AC_DEFINE([FUNC_PTRCOMPARE_CAST_WORKAROUND_WORKS],[1],[Define to '1' if cast to
'uintptr_t' works for safely processing user-poisoned pointer])
+ ]
+ )
+ AS_IF([test "x${mhd_cv_func_u_p_attribute_needed}" = "xyes"
&& test "x${ac_cv_header_sanitizer_asan_interface_h}" = "xyes"],
+ [
+ AC_CACHE_CHECK([whether
'__attribute__((no_sanitize("pointer-compare")))' and
'__attribute__((no_sanitize("pointer-subtract")))' work],
+ [mhd_cv_func_attribute_nosanitize_ptr],
+ [
+
ASAN_OPTIONS="exitcode=88:detect_invalid_pointer_pairs=3:halt_on_error=1"
+ export ASAN_OPTIONS
+ CFLAGS="${CFLAGS_ac} ${san_CFLAGS} ${san_FLAGS}
${errattr_CFLAGS} ${user_CFLAGS}"
+ AC_RUN_IFELSE(
+ [
+ AC_LANG_SOURCE(
[[
- int *a = (int*) malloc (sizeof(int)*4);
- int *b = (int*) malloc (sizeof(long)*6);
- int c = ptr_process(a, b);
- if (c)
+#include <stdint.h>
+#include <stdlib.h>
+#include <sanitizer/asan_interface.h>
+
+static const size_t first_pos = 0;
+static const size_t mid_pos = 64;
+static const size_t last_pos = 128;
+static const size_t zone_size = 16;
+static const size_t buf_size = 128 + 16;
+
+__attribute__((no_sanitize("pointer-compare")))
+static int ptr_compare(void *ptr1, uint8_t *ptr2)
+{
+ if ((((const uint8_t*)ptr1) >= ((const uint8_t*)ptr2)))
+ return ((char *) ptr1)[0] < ((char *) ptr2)[0];
+ return ((char *) ptr1)[0] > ((char *) ptr2)[0];
+}
+
+__attribute__((no_sanitize("pointer-subtract")))
+static int ptr_subtract(void *ptr1, uint8_t *ptr2)
+{
+ return ((size_t)(((const uint8_t*)ptr1) - \
+ ((const uint8_t*)ptr2))) <= last_pos;
+}
+
+int main(int argc, char *argv[])
+{
+ char *buf = (char*) malloc (buf_size);
+ char *a;
+ char *b;
+ int ret;
+
+ (void) argv;
+ if (NULL == buf)
+ return 10;
+ ASAN_POISON_MEMORY_REGION (buf + first_pos + zone_size, mid_pos - first_pos
- zone_size);
+ ASAN_POISON_MEMORY_REGION (buf + mid_pos + zone_size, last_pos - mid_pos -
zone_size);
+
+ if (0 < argc)
+ a = buf + last_pos;
+ else
+ a = buf + first_pos;
+ b = buf + mid_pos;
+
+ *a = '0';
+ *b = '9';
+
+ if (ptr_compare((void *)a, (uint8_t*) b))
{
- free (b);
- free (a);
- return 0;
+ if (ptr_subtract((void *)a, (uint8_t*) b))
+ ret = 0;
+ else
+ ret = 10;
}
- free (a);
- free (b);
+ else
+ ret = 5;
+ ASAN_UNPOISON_MEMORY_REGION (buf, buf_size);
+ free (buf);
+
+ return ret;
+}
]]
)
],
@@ -4041,7 +4169,10 @@ int ptr_process(void *ptr1, void *ptr2)
]
)
AS_VAR_IF([mhd_cv_func_attribute_nosanitize_ptr],
["yes"],
- [AC_DEFINE([FUNC_ATTR_PTRCOMPARE_WORKS],[1],[Define
to '1' if '__attribute__((no_sanitize("pointer-compare","pointer-subtract")))'
works])],
+ [
+ AC_DEFINE([FUNC_ATTR_PTRCOMPARE_WORKS],[1],[Define
to '1' if '__attribute__((no_sanitize("pointer-compare")))' works])
+ AC_DEFINE([FUNC_ATTR_PTRSUBTRACT_WORKS],[1],[Define
to '1' if '__attribute__((no_sanitize("pointer-subtract")))' works])
+ ],
[
AC_CACHE_CHECK([whether
'__attribute__((no_sanitize("address")))' works for pointers compare],
[mhd_cv_func_attribute_nosanitize_addr],
[
@@ -4050,30 +4181,69 @@ int ptr_process(void *ptr1, void *ptr2)
CFLAGS="${CFLAGS_ac} ${san_CFLAGS} ${san_FLAGS}
${errattr_CFLAGS} ${user_CFLAGS}"
AC_RUN_IFELSE(
[
- AC_LANG_PROGRAM(
+ AC_LANG_SOURCE(
[[
+#include <stdint.h>
#include <stdlib.h>
+#include <sanitizer/asan_interface.h>
+
+static const size_t first_pos = 0;
+static const size_t mid_pos = 64;
+static const size_t last_pos = 128;
+static const size_t zone_size = 16;
+static const size_t buf_size = 128 + 16;
__attribute__((no_sanitize("address")))
-int ptr_process(void *ptr1, void *ptr2)
+static int ptr_compare(void *ptr1, uint8_t *ptr2)
{
- if ((char*)ptr1 <= (char*)ptr2)
- return (int) ((char*)ptr2 - (char*)ptr1);
- return (int) ((char*)ptr1 - (char*)ptr2);
+ if ((((const uint8_t*)ptr1) >= ((const uint8_t*)ptr2)))
+ return ((char *) ptr1)[0] < ((char *) ptr2)[0];
+ return ((char *) ptr1)[0] > ((char *) ptr2)[0];
}
- ]],
- [[
- int *a = (int*) malloc (sizeof(int)*4);
- int *b = (int*) malloc (sizeof(long)*6);
- int c = ptr_process(a, b);
- if (c)
+
+__attribute__((no_sanitize("address")))
+static int ptr_subtract(void *ptr1, uint8_t *ptr2)
+{
+ return ((size_t)(((const uint8_t*)ptr1) - \
+ ((const uint8_t*)ptr2))) <= last_pos;
+}
+
+int main(int argc, char *argv[])
+{
+ char *buf = (char*) malloc (buf_size);
+ char *a;
+ char *b;
+ int ret;
+
+ (void) argv;
+ if (NULL == buf)
+ return 10;
+ ASAN_POISON_MEMORY_REGION (buf + first_pos + zone_size, mid_pos - first_pos
- zone_size);
+ ASAN_POISON_MEMORY_REGION (buf + mid_pos + zone_size, last_pos - mid_pos -
zone_size);
+
+ if (0 < argc)
+ a = buf + last_pos;
+ else
+ a = buf + first_pos;
+ b = buf + mid_pos;
+
+ *a = '0';
+ *b = '9';
+
+ if (ptr_compare((void *)a, (uint8_t*) b))
{
- free (b);
- free (a);
- return 0;
+ if (ptr_subtract((void *)a, (uint8_t*) b))
+ ret = 0;
+ else
+ ret = 10;
}
- free (a);
- free (b);
+ else
+ ret = 5;
+ ASAN_UNPOISON_MEMORY_REGION (buf, buf_size);
+ free (buf);
+
+ return ret;
+}
]]
)
],
@@ -4263,9 +4433,9 @@ int main(void)
AS_VAR_IF([enable_san_upoison], ["no"], [:],
[
AC_MSG_CHECKING([whether to enable user memory poisoning])
- AS_IF([test "x${mhd_cv_cc_sanitizer_address}" = "xyes" && test
"x${mhd_cv_cc_sanitizer_pointer_compare}" = "xyes" && \
- test "x${ac_cv_header_sanitizer_asan_interface_h}" = "xyes"
&& \
- (test "x${mhd_cv_func_attribute_nosanitize_ptr}" = "xyes" ||
test "x${mhd_cv_func_attribute_nosanitize_addr}" = "xyes")],
+ AS_IF([test "x${mhd_cv_cc_sanitizer_address}" = "xyes" && test
"x${ac_cv_header_sanitizer_asan_interface_h}" = "xyes" && \
+ (test "x${mhd_cv_func_u_p_attribute_needed}" != "xyes" ||
test "x${mhd_cv_func_attribute_nosanitize_ptr}" = "xyes" || \
+ test "x${mhd_cv_func_attribute_nosanitize_addr}" = "xyes")],
[
AC_DEFINE([MHD_ASAN_POISON_ACTIVE], [1], [Define to '1' if
user memory poison is used])
enabled_sanitizers="${enabled_sanitizers}${enabled_sanitizers:+, }user-poison"
diff --git a/src/include/mhd_options.h b/src/include/mhd_options.h
index 85ad6555..5a5b7fee 100644
--- a/src/include/mhd_options.h
+++ b/src/include/mhd_options.h
@@ -156,9 +156,12 @@
#endif /* MHD_ASAN_ACTIVE */
#if defined(MHD_ASAN_ACTIVE) && defined(HAVE_SANITIZER_ASAN_INTERFACE_H) && \
- (defined(FUNC_ATTR_PTRCOMPARE_WORKS) || defined(FUNC_ATTR_NOSANITIZE_WORKS))
+ (defined(FUNC_PTRCOMPARE_CAST_WORKAROUND_WORKS) || \
+ (defined(FUNC_ATTR_PTRCOMPARE_WORKS) && \
+ defined(FUNC_ATTR_PTRSUBTRACT_WORKS)) || \
+ defined(FUNC_ATTR_NOSANITIZE_WORKS))
#ifndef MHD_ASAN_POISON_ACTIVE
-/* Manual ASAN poisoning could be used */
+/* User ASAN poisoning could be used */
#warning User memory poisoning is not active
#endif /* ! MHD_ASAN_POISON_ACTIVE */
#else /* ! (MHD_ASAN_ACTIVE && HAVE_SANITIZER_ASAN_INTERFACE_H &&
diff --git a/src/microhttpd/memorypool.c b/src/microhttpd/memorypool.c
index 5d656b47..92ec6edc 100644
--- a/src/microhttpd/memorypool.c
+++ b/src/microhttpd/memorypool.c
@@ -102,19 +102,92 @@
#define ROUND_TO_ALIGN_PLUS_RED_ZONE(n) ROUND_TO_ALIGN(n)
#define _MHD_POISON_MEMORY(pointer, size) (void)0
#define _MHD_UNPOISON_MEMORY(pointer, size) (void)0
+/**
+ * Boolean 'true' if the first pointer is less or equal the second pointer
+ */
+#define mp_ptr_le_(p1,p2) \
+ (((const uint8_t*)p1) <= ((const uint8_t*)p2))
+/**
+ * The difference in bytes between positions of the first and
+ * the second pointers
+ */
+#define mp_ptr_diff_(p1,p2) \
+ ((size_t)(((const uint8_t*)p1) - ((const uint8_t*)p2)))
#else /* MHD_ASAN_POISON_ACTIVE */
-#if defined(FUNC_ATTR_PTRCOMPARE_WORKS)
-#define _MHD_NOSANITIZE_PTRS \
- __attribute__((no_sanitize("pointer-compare","pointer-subtract")))
-#elif defined(FUNC_ATTR_NOSANITIZE_WORKS)
-#define _MHD_NOSANITIZE_PTRS __attribute__((no_sanitize("address")))
-#endif
#define _MHD_RED_ZONE_SIZE (ALIGN_SIZE)
#define ROUND_TO_ALIGN_PLUS_RED_ZONE(n) (ROUND_TO_ALIGN(n) +
_MHD_RED_ZONE_SIZE)
#define _MHD_POISON_MEMORY(pointer, size) \
ASAN_POISON_MEMORY_REGION ((pointer), (size))
#define _MHD_UNPOISON_MEMORY(pointer, size) \
ASAN_UNPOISON_MEMORY_REGION ((pointer), (size))
+#if defined(FUNC_PTRCOMPARE_CAST_WORKAROUND_WORKS)
+/**
+ * Boolean 'true' if the first pointer is less or equal the second pointer
+ */
+#define mp_ptr_le_(p1,p2) \
+ (((uintptr_t)((const void*)(p1))) <= ((uintptr_t)((const void*)(p1))))
+/**
+ * The difference in bytes between positions of the first and
+ * the second pointers
+ */
+#define mp_ptr_diff_(p1,p2) \
+ ((size_t)(((uintptr_t)((const uint8_t*)p1)) - \
+ ((uintptr_t)((const uint8_t*)p2))))
+#elif defined(FUNC_ATTR_PTRCOMPARE_WORKS) && \
+ defined(FUNC_ATTR_PTRSUBTRACT_WORKS)
+#ifdef _DEBUG
+/**
+ * Boolean 'true' if the first pointer is less or equal the second pointer
+ */
+__attribute__((no_sanitize ("pointer-compare"))) static bool
+mp_ptr_le_ (const void *p1, const void *p2)
+{
+ return (((const uint8_t *) p1) <= ((const uint8_t *) p2));
+}
+
+
+#endif /* _DEBUG */
+
+
+/**
+ * The difference in bytes between positions of the first and
+ * the second pointers
+ */
+__attribute__((no_sanitize ("pointer-subtract"))) static size_t
+mp_ptr_diff_ (const void *p1, const void *p2)
+{
+ return (size_t) (((const uint8_t *) p1) - ((const uint8_t *) p2));
+}
+
+
+#elif defined(FUNC_ATTR_NOSANITIZE_WORKS)
+#ifdef _DEBUG
+/**
+ * Boolean 'true' if the first pointer is less or equal the second pointer
+ */
+__attribute__((no_sanitize ("address"))) static bool
+mp_ptr_le_ (const void *p1, const void *p2)
+{
+ return (((const uint8_t *) p1) <= ((const uint8_t *) p2));
+}
+
+
+#endif /* _DEBUG */
+
+/**
+ * The difference in bytes between positions of the first and
+ * the second pointers
+ */
+__attribute__((no_sanitize ("address"))) static size_t
+mp_ptr_diff_ (const void *p1, const void *p2)
+{
+ return (size_t) (((const uint8_t *) p1) - ((const uint8_t *) p2));
+}
+
+
+#else /* ! FUNC_ATTR_NOSANITIZE_WORKS */
+#error User-poisoning cannot be used
+#endif /* ! FUNC_ATTR_NOSANITIZE_WORKS */
#endif /* MHD_ASAN_POISON_ACTIVE */
/**
@@ -419,7 +492,7 @@ MHD_pool_try_alloc (struct MemoryPool *pool,
* NULL if the pool cannot support @a new_size
* bytes (old continues to be valid for @a old_size)
*/
-_MHD_NOSANITIZE_PTRS void *
+void *
MHD_pool_reallocate (struct MemoryPool *pool,
void *old,
size_t old_size,
@@ -432,23 +505,21 @@ MHD_pool_reallocate (struct MemoryPool *pool,
mhd_assert (pool->size >= pool->end - pool->pos);
mhd_assert (old != NULL || old_size == 0);
mhd_assert (pool->size >= old_size);
- mhd_assert (old == NULL || pool->memory <= (uint8_t *) old);
- /* (old == NULL || pool->memory + pool->size >= (uint8_t*) old + old_size) */
- mhd_assert (old == NULL || \
- (pool->size - _MHD_RED_ZONE_SIZE) >= \
- (((size_t) (((uint8_t *) old) - pool->memory)) + old_size));
- /* Blocks "from the end" must not be reallocated */
- /* (old == NULL || old_size == 0 || pool->memory + pool->pos > (uint8_t*)
old) */
- mhd_assert (old == NULL || old_size == 0 || \
- pool->pos > (size_t) ((uint8_t *) old - pool->memory));
- mhd_assert (old == NULL || old_size == 0 || \
- (size_t) (((uint8_t *) old) - pool->memory) + old_size <= \
- pool->end - _MHD_RED_ZONE_SIZE);
if (NULL != old)
{ /* Have previously allocated data */
- const size_t old_offset = (size_t) (((uint8_t *) old) - pool->memory);
+ const size_t old_offset = mp_ptr_diff_ (old, pool->memory);
const bool shrinking = (old_size > new_size);
+
+ mhd_assert (mp_ptr_le_ (pool->memory, old));
+ /* (pool->memory + pool->size >= (uint8_t*) old + old_size) */
+ mhd_assert ((pool->size - _MHD_RED_ZONE_SIZE) >= (old_offset + old_size));
+ /* Blocks "from the end" must not be reallocated */
+ /* (old_size == 0 || pool->memory + pool->pos > (uint8_t*) old) */
+ mhd_assert ((old_size == 0) || \
+ (pool->pos > old_offset));
+ mhd_assert ((old_size == 0) || \
+ ((pool->end - _MHD_RED_ZONE_SIZE) >= (old_offset + old_size)));
/* Try resizing in-place */
if (shrinking)
{ /* Shrinking in-place, zero-out freed part */
@@ -510,7 +581,7 @@ MHD_pool_reallocate (struct MemoryPool *pool,
* (should be larger or equal to @a copy_bytes)
* @return addr new address of @a keep (if it had to change)
*/
-_MHD_NOSANITIZE_PTRS void *
+void *
MHD_pool_reset (struct MemoryPool *pool,
void *keep,
size_t copy_bytes,
@@ -521,11 +592,10 @@ MHD_pool_reset (struct MemoryPool *pool,
mhd_assert (copy_bytes <= new_size);
mhd_assert (copy_bytes <= pool->size);
mhd_assert (keep != NULL || copy_bytes == 0);
- mhd_assert (keep == NULL || pool->memory <= (uint8_t *) keep);
+ mhd_assert (keep == NULL || mp_ptr_le_ (pool->memory, keep));
/* (keep == NULL || pool->memory + pool->size >= (uint8_t*) keep +
copy_bytes) */
- mhd_assert (keep == NULL || \
- pool->size >= \
- ((size_t) ((uint8_t *) keep - pool->memory)) + copy_bytes);
+ mhd_assert ((keep == NULL) || \
+ (pool->size >= mp_ptr_diff_ (keep, pool->memory) + copy_bytes));
_MHD_UNPOISON_MEMORY (pool->memory, new_size);
if ( (NULL != keep) &&
(keep != pool->memory) )
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libmicrohttpd] branch master updated (1ffe7932 -> 3444792f), gnunet, 2022/11/26
- [libmicrohttpd] 02/05: test_upgrade{,_large}: fixed HTTP/1.1 compatibility, gnunet, 2022/11/26
- [libmicrohttpd] 01/05: testcurl: fixed checking response headers as null-terminated string, gnunet, 2022/11/26
- [libmicrohttpd] 03/05: test_get_iovec: fixed missing include headers, gnunet, 2022/11/26
- [libmicrohttpd] 04/05: configure: fixed detection of eventfd() with new compilers builds, gnunet, 2022/11/26
- [libmicrohttpd] 05/05: Refactored user-poison: minimized scope of non-sanitized code,
gnunet <=