summaryrefslogtreecommitdiff
path: root/dbus
diff options
context:
space:
mode:
authorAlex Richardson <arichardson@FreeBSD.org>2022-09-15 18:53:30 +0000
committerSimon McVittie <smcv@collabora.com>2022-09-21 11:35:05 +0000
commit33dbeb5ebe28aadcde9f6f6bf22eb86fa7023dfa (patch)
tree2bedf05f445f0ac071f835076882647284e80c90 /dbus
parentc4a8c2d920002a961d13dab4247f91e9f2c18df6 (diff)
downloaddbus-33dbeb5ebe28aadcde9f6f6bf22eb86fa7023dfa.tar.gz
dbus-mempool.c: ensure that all alignments are aligned to max_align_t
This is required e.g. for CHERI-enabled targets such as Arm Morello where aligning to sizeof(long) is not sufficient to load/store pointers (which need 16 byte alignment instead of 8 bytes). As we can't depend on C11 yet, this commit adds a max_align_t emulation to dbus-internals.h.
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-internals.h15
-rw-r--r--dbus/dbus-mempool.c32
2 files changed, 41 insertions, 6 deletions
diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
index deee366f..4643053b 100644
--- a/dbus/dbus-internals.h
+++ b/dbus/dbus-internals.h
@@ -283,6 +283,21 @@ _dbus_assert_error_xor_bool (const DBusError *error,
#define _DBUS_ALIGN_ADDRESS(this, boundary) \
((void*)_DBUS_ALIGN_VALUE(this, boundary))
+#define _DBUS_IS_ALIGNED(this, boundary) \
+ ((((size_t) (uintptr_t) (this)) & ((size_t) (boundary) - 1)) == 0)
+
+/**
+ * Aligning a pointer to _DBUS_ALIGNOF(dbus_max_align_t) guarantees that all
+ * scalar types can be loaded/stored from/to such an address without incurring
+ * an alignment fault (or a slow misaligned access).
+ * This is based on C11 max_align_t, but falls back to DBusBasicValue for
+ * older C standards.
+ */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+typedef max_align_t dbus_max_align_t;
+#else
+typedef DBusBasicValue dbus_max_align_t;
+#endif
DBUS_PRIVATE_EXPORT
char* _dbus_strdup (const char *str);
diff --git a/dbus/dbus-mempool.c b/dbus/dbus-mempool.c
index c6565351..dc0b4467 100644
--- a/dbus/dbus-mempool.c
+++ b/dbus/dbus-mempool.c
@@ -82,12 +82,24 @@ struct DBusMemBlock
* when we free the mem pool.
*/
- /* this is a size_t so that "elements" is aligned */
size_t used_so_far; /**< bytes of this block already allocated as elements. */
-
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+ /*
+ * Ensure that elements is aligned correctly. For all supported pre-C11
+ * targets, the size_t above should ensure that the elements array is
+ * sufficiently aligned (this is checked in the static assert below).
+ */
+ _Alignas (dbus_max_align_t)
+#endif
unsigned char elements[]; /**< the block data, actually allocated to required size */
};
+_DBUS_STATIC_ASSERT (_DBUS_IS_ALIGNED (sizeof (struct DBusMemBlock),
+ _DBUS_ALIGNOF (dbus_max_align_t)));
+_DBUS_STATIC_ASSERT (_DBUS_IS_ALIGNED (offsetof (struct DBusMemBlock,
+ elements),
+ _DBUS_ALIGNOF (dbus_max_align_t)));
+
/**
* Internals fields of DBusMemPool
*/
@@ -152,10 +164,11 @@ _dbus_mem_pool_new (int element_size,
_dbus_assert (element_size >= (int) sizeof (void*));
_dbus_assert (element_size >= (int) sizeof (DBusFreedElement));
- /* align the element size to a pointer boundary so we won't get bus
- * errors under other architectures.
+ /* align the element size to be suitable for the most-aligned type
+ * that we care about (in practice usually a pointer).
*/
- pool->element_size = _DBUS_ALIGN_VALUE (element_size, sizeof (void *));
+ pool->element_size =
+ _DBUS_ALIGN_VALUE (element_size, _DBUS_ALIGNOF (dbus_max_align_t));
pool->zero_elements = zero_elements != FALSE;
@@ -239,6 +252,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
VALGRIND_MEMPOOL_ALLOC (pool, (void *) &block->elements[0],
pool->element_size);
+ _dbus_assert (_DBUS_IS_ALIGNED (&block->elements[0],
+ _DBUS_ALIGNOF (dbus_max_align_t)));
return (void*) &block->elements[0];
}
else
@@ -264,7 +279,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
memset (element, '\0', pool->element_size);
pool->allocated_elements += 1;
-
+ _dbus_assert (
+ _DBUS_IS_ALIGNED (element, _DBUS_ALIGNOF (dbus_max_align_t)));
return element;
}
else
@@ -306,6 +322,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
block = dbus_malloc0 (alloc_size);
else
block = dbus_malloc (alloc_size);
+ _dbus_assert (
+ _DBUS_IS_ALIGNED (block, _DBUS_ALIGNOF (dbus_max_align_t)));
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
_dbus_set_fail_alloc_counter (saved_counter);
@@ -327,6 +345,8 @@ _dbus_mem_pool_alloc (DBusMemPool *pool)
pool->allocated_elements += 1;
VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size);
+ _dbus_assert (
+ _DBUS_IS_ALIGNED (element, _DBUS_ALIGNOF (dbus_max_align_t)));
return element;
}
}