From 9c36990eb48d41907357a159a88c4cf5eb018271 Mon Sep 17 00:00:00 2001
From: Ilya Verbin <iverbin@tarantool.org>
Date: Thu, 10 Oct 2024 21:36:43 +0300
Subject: [PATCH] box: fix SIGSEGV on unaligned access to a struct with
 extended alignment

All structures with a non-default alignment (set by `alignas()`) must be
allocated by `aligned_alloc()`, otherwise an access to such a structure
member fill crash, e.g. if compiled with AVX-512 support.

Closes #10215
Part of #10631

NO_DOC=bugfix
NO_TEST=tested by debug_asan_clang workflow
NO_CHANGELOG=fix is actually not user-visible, because tarantool still
             doesn't work with enabled AVX-512 (#10671)

(cherry picked from commit a60ec82d4f07720148b0724e5feff31f76291b56)
---
 src/box/applier.cc     |  2 +-
 src/box/iproto.cc      |  4 ++--
 src/box/relay.cc       | 12 +-----------
 src/box/replication.cc |  4 ----
 src/trivia/util.h      |  8 ++++++++
 5 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/src/box/applier.cc b/src/box/applier.cc
index d2eba45248..1132081826 100644
--- a/src/box/applier.cc
+++ b/src/box/applier.cc
@@ -2130,7 +2130,7 @@ applier_init(void)
 						  sizeof(struct applier_thread *));
 	for (int i = 0; i < replication_threads; i++) {
 		struct applier_thread *thread =
-			(struct applier_thread *)xmalloc(sizeof(*thread));
+			xalloc_object(struct applier_thread);
 		applier_thread_create(thread);
 		applier_threads[i] = thread;
 	}
diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 2808303b80..4217151eff 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -3232,8 +3232,8 @@ iproto_init(int threads_count)
 	 * we don't need any accept functions.
 	 */
 	evio_service_create(loop(), &tx_binary, "tx_binary", NULL, NULL);
-	iproto_threads = (struct iproto_thread *)
-		xcalloc(threads_count, sizeof(struct iproto_thread));
+	iproto_threads = xalloc_array(struct iproto_thread, threads_count);
+	memset(iproto_threads, 0, sizeof(struct iproto_thread) * threads_count);
 
 	for (int i = 0; i < threads_count; i++, iproto_threads_count++) {
 		struct iproto_thread *iproto_thread = &iproto_threads[i];
diff --git a/src/box/relay.cc b/src/box/relay.cc
index 5b1967d391..10edf513a6 100644
--- a/src/box/relay.cc
+++ b/src/box/relay.cc
@@ -286,14 +286,7 @@ relay_new(struct replica *replica)
 	 * (Use clang UB Sanitizer, to make sure of this)
 	 */
 	assert((sizeof(struct relay) % alignof(struct relay)) == 0);
-	struct relay *relay = (struct relay *)
-		aligned_alloc(alignof(struct relay), sizeof(struct relay));
-	if (relay == NULL) {
-		diag_set(OutOfMemory, sizeof(struct relay), "aligned_alloc",
-			  "struct relay");
-		return NULL;
-	}
-
+	struct relay *relay = xalloc_object(struct relay);
 	memset(relay, 0, sizeof(struct relay));
 	relay->replica = replica;
 	relay->last_row_time = ev_monotonic_now(loop());
@@ -451,9 +444,6 @@ relay_initial_join(struct iostream *io, uint64_t sync, struct vclock *vclock,
 		   struct checkpoint_cursor *cursor)
 {
 	struct relay *relay = relay_new(NULL);
-	if (relay == NULL)
-		diag_raise();
-
 	relay_start(relay, io, sync, relay_send_initial_join_row, relay_yield,
 		    UINT64_MAX);
 	auto relay_guard = make_scoped_guard([=] {
diff --git a/src/box/replication.cc b/src/box/replication.cc
index b28bf8519d..8d2caaf0ba 100644
--- a/src/box/replication.cc
+++ b/src/box/replication.cc
@@ -257,10 +257,6 @@ replica_new(void)
 			  "struct replica");
 	}
 	replica->relay = relay_new(replica);
-	if (replica->relay == NULL) {
-		free(replica);
-		diag_raise();
-	}
 	replica->id = 0;
 	replica->anon = false;
 	replica->uuid = uuid_nil;
diff --git a/src/trivia/util.h b/src/trivia/util.h
index 7b515a1570..a2abe3a6d4 100644
--- a/src/trivia/util.h
+++ b/src/trivia/util.h
@@ -131,6 +131,14 @@ alloc_failure(const char *filename, int line, size_t size)
 #define xrealloc(ptr, size)	xalloc_impl((size), realloc, (ptr), (size))
 #define xstrdup(s)		xalloc_impl(strlen((s)) + 1, strdup, (s))
 #define xstrndup(s, n)		xalloc_impl((n) + 1, strndup, (s), (n))
+#define xaligned_alloc(size, align) \
+		xalloc_impl((size), aligned_alloc, (align), (size))
+#define xalloc_object(T) ({							\
+	(T *)xaligned_alloc(sizeof(T), alignof(T));				\
+})
+#define xalloc_array(T, count) ({						\
+	(T *)xaligned_alloc(sizeof(T) * (count), alignof(T));			\
+})
 #define xmempool_alloc(p)	xalloc_impl((p)->objsize, mempool_alloc, (p))
 #define xregion_alloc(p, size)	xalloc_impl((size), region_alloc, (p), (size))
 #define xregion_aligned_alloc(p, size, align) \
-- 
GitLab