Fix incorrect pointer conversion in SMC_UUID_RET()
authorSandrine Bailleux <sandrine.bailleux@arm.com>
Mon, 2 Jul 2018 11:01:16 +0000 (13:01 +0200)
committerSandrine Bailleux <sandrine.bailleux@arm.com>
Tue, 3 Jul 2018 15:35:08 +0000 (17:35 +0200)
Casting a pointer to a struct uuid into a pointer to uint32_t may
result in a pointer that is not correctly aligned, which constitutes
an undefined behaviour. In the case of TF, this also generates a data
abort because alignment fault checking is enabled (through the SCTLR.A
bit).

This patch modifies the SMC_UUID_RET() macro to read the uuid
structure without any pointer aliasing. A helper function then
combines every set of 4 bytes into a 32-bit value suitable to be
returned through the x0-x3 registers.

This fixes a violation of MISRA rule 11.3.

Change-Id: I53ee73bb4cb332f4d8286055ceceb6f347caa080
Signed-off-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
include/lib/aarch32/smccc_helpers.h
include/lib/aarch64/smccc_helpers.h
include/lib/smccc.h

index 240dd13fbc621e934e8dfa06e7b78b11652ac4c3..731c26fbf42e650aa44e0e603eeae5912265eb4c 100644 (file)
@@ -129,13 +129,6 @@ CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch);
        SMC_RET3(_h, (_r0), (_r1), (_r2));      \
 }
 
-/* Return a UUID in the SMC return registers */
-#define SMC_UUID_RET(_h, _uuid) \
-       SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
-                        ((const uint32_t *) &(_uuid))[1], \
-                        ((const uint32_t *) &(_uuid))[2], \
-                        ((const uint32_t *) &(_uuid))[3])
-
 /*
  * Helper macro to retrieve the SMC parameters from smc_ctx_t.
  */
index 1b33a0d157b09d91d0fdcb330faaa35f455cd54b..4d9217bcc1c1f37b1232d642ca7df9d0afc6d845 100644 (file)
 #define SMC_SET_EL3(_h, _e, _v)                                        \
        write_ctx_reg((get_el3state_ctx(_h)), (_e), (_v))
 
-/* Return a UUID in the SMC return registers */
-#define SMC_UUID_RET(_h, _uuid)                                        \
-       SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0],      \
-                        ((const uint32_t *) &(_uuid))[1],      \
-                        ((const uint32_t *) &(_uuid))[2],      \
-                        ((const uint32_t *) &(_uuid))[3])
-
 /*
  * Helper macro to retrieve the SMC parameters from cpu_context_t.
  */
index cb722b0e2e238fc57f7c827e409635ddbaa4a046..a07e510b872884212f2db1408281aac48e3dd4a6 100644 (file)
                { _n0, _n1, _n2, _n3, _n4, _n5 }                        \
        }
 
+/*
+ * Return a UUID in the SMC return registers.
+ *
+ * Acccording to section 5.3 of the SMCCC, UUIDs are returned as a single
+ * 128-bit value using the SMC32 calling convention. This value is mapped to
+ * argument registers x0-x3 on AArch64 (resp. r0-r3 on AArch32). x0 for example
+ * shall hold bytes 0 to 3, with byte 0 in the low-order bits.
+ */
+static inline uint32_t smc_uuid_word(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
+{
+       return ((uint32_t) b0) | (((uint32_t) b1) << 8) |
+               (((uint32_t) b2) << 16) | (((uint32_t) b3) << 24);
+}
+
+#define SMC_UUID_RET(_h, _uuid)                                                        \
+       SMC_RET4(handle,                                                        \
+               smc_uuid_word((_uuid).time_low[0], (_uuid).time_low[1],         \
+                             (_uuid).time_low[2], (_uuid).time_low[3]),        \
+               smc_uuid_word((_uuid).time_mid[0], (_uuid).time_mid[1],         \
+                             (_uuid).time_hi_and_version[0],                   \
+                             (_uuid).time_hi_and_version[1]),                  \
+               smc_uuid_word((_uuid).clock_seq_hi_and_reserved,                \
+                             (_uuid).clock_seq_low, (_uuid).node[0],           \
+                             (_uuid).node[1]),                                 \
+               smc_uuid_word((_uuid).node[2], (_uuid).node[3],                 \
+                             (_uuid).node[4], (_uuid).node[5]))
+
 #endif /*__ASSEMBLY__*/
 #endif /* __SMCCC_H__ */