From: Scott Mitchell <[email protected]>

Add __rte_may_alias attribute to unaligned_uint{16,32,64}_t typedefs
to prevent GCC strict-aliasing optimization bugs. GCC has a bug where
it incorrectly elides struct initialization when strict aliasing is
enabled, causing reads from uninitialized memory.

Add __rte_aligned(1) attribute to unaligned_uint{16,32,64}_t typedefs
which allows for safe access at any alignment. Without this, accessing
a uint16_t at an odd address is undefined behavior. Without this
UBSan detects `UndefinedBehaviorSanitizer: undefined-behavior`.

Fixes: 7621d6a8d0bd ("eal: add and use unaligned integer types")
Cc: Cyril Chemparathy <[email protected]>
Cc: [email protected]
Signed-off-by: Scott Mitchell <[email protected]>
---
 app/test/test_hash_functions.c |  6 ++++-
 lib/eal/include/rte_common.h   | 49 +++++++++++++++++++++++-----------
 2 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/app/test/test_hash_functions.c b/app/test/test_hash_functions.c
index 70820d1f19..9524e3135f 100644
--- a/app/test/test_hash_functions.c
+++ b/app/test/test_hash_functions.c
@@ -187,11 +187,15 @@ verify_jhash_32bits(void)
 {
        unsigned i, j;
        uint8_t key[64];
+       /* to guarantee alignment for rte_jhash_32b, use u32 and copy data */
+       uint32_t key32[sizeof(key) / sizeof(uint32_t)];
        uint32_t hash, hash32;
 
        for (i = 0; i < 64; i++)
                key[i] = rand() & 0xff;
 
+       memcpy(key32, key, sizeof(key));
+
        for (i = 0; i < RTE_DIM(hashtest_key_lens); i++) {
                for (j = 0; j < RTE_DIM(hashtest_initvals); j++) {
                        /* Key size must be multiple of 4 (32 bits) */
@@ -199,7 +203,7 @@ verify_jhash_32bits(void)
                                hash = rte_jhash(key, hashtest_key_lens[i],
                                                hashtest_initvals[j]);
                                /* Divide key length by 4 in rte_jhash for 32 
bits */
-                               hash32 = rte_jhash_32b((const 
unaligned_uint32_t *)key,
+                               hash32 = rte_jhash_32b(key32,
                                                hashtest_key_lens[i] >> 2,
                                                hashtest_initvals[j]);
                                if (hash != hash32) {
diff --git a/lib/eal/include/rte_common.h b/lib/eal/include/rte_common.h
index 573bf4f2ce..7b36966019 100644
--- a/lib/eal/include/rte_common.h
+++ b/lib/eal/include/rte_common.h
@@ -121,16 +121,42 @@ extern "C" {
 #define __rte_aligned(a) __attribute__((__aligned__(a)))
 #endif
 
-#ifdef RTE_ARCH_STRICT_ALIGN
-typedef uint64_t unaligned_uint64_t __rte_aligned(1);
-typedef uint32_t unaligned_uint32_t __rte_aligned(1);
-typedef uint16_t unaligned_uint16_t __rte_aligned(1);
+/**
+ * Macro to mark a type that is not subject to type-based aliasing rules
+ */
+#ifdef RTE_TOOLCHAIN_MSVC
+#define __rte_may_alias
 #else
-typedef uint64_t unaligned_uint64_t;
-typedef uint32_t unaligned_uint32_t;
-typedef uint16_t unaligned_uint16_t;
+#define __rte_may_alias __attribute__((__may_alias__))
 #endif
 
+/* Unaligned types implementation notes:
+ * __rte_aligned(1) - Reduces alignment requirement to 1 byte, allowing
+ *                    these types to safely access memory at any address.
+ *                    Without this, accessing a uint16_t at an odd address
+ *                    is undefined behavior (even on x86 where hardware
+ *                    handles it).
+ *
+ * __rte_may_alias  - Prevents strict-aliasing optimization bugs where
+ *                    compilers may incorrectly elide memory operations
+ *                    when casting between pointer types.
+ */
+
+/**
+ * Type for safe unaligned u64 access.
+ */
+typedef __rte_may_alias __rte_aligned(1) uint64_t unaligned_uint64_t;
+
+/**
+ * Type for safe unaligned u32 access.
+ */
+typedef __rte_may_alias __rte_aligned(1) uint32_t unaligned_uint32_t;
+
+/**
+ * Type for safe unaligned u16 access.
+ */
+typedef __rte_may_alias __rte_aligned(1) uint16_t unaligned_uint16_t;
+
 /**
  * @deprecated
  * @see __rte_packed_begin
@@ -159,15 +185,6 @@ typedef uint16_t unaligned_uint16_t;
 #define __rte_packed_end __attribute__((__packed__))
 #endif
 
-/**
- * Macro to mark a type that is not subject to type-based aliasing rules
- */
-#ifdef RTE_TOOLCHAIN_MSVC
-#define __rte_may_alias
-#else
-#define __rte_may_alias __attribute__((__may_alias__))
-#endif
-
 /******* Macro to mark functions and fields scheduled for removal *****/
 #ifdef RTE_TOOLCHAIN_MSVC
 #define __rte_deprecated
-- 
2.39.5 (Apple Git-154)

Reply via email to