Commit 71d027cfee for qemu.org
commit 71d027cfee8553e2ec28efa1ddd7fd0ecbadcc86
Author: Peter Maydell <peter.maydell@linaro.org>
Date: Tue May 5 19:51:57 2026 +0100
hw/net/rocker_of_dpa: Avoid unaligned accesses in _of_dpa_flow_match()
_of_dpa_flow_match() tries to do masked comparisons of OfDpaFlowkey
structs by casting pointers to them to uint64_t* and then doing the
memory accesses as 64-bit. This is undefined behaviour because the
pointers might not be 64-bit aligned, and the UB sanitizer spots this:
../../hw/net/rocker/rocker_of_dpa.c:321:20: runtime error: load of misaligned address 0x512000164044 for type 'uint64_t' (aka 'unsigned long'), which requires 8 byte alignment
0x512000164044: note: pointer points here
02 00 00 00 00 00 ff ff 00 00 00 00 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^
We do know that OfDpaFlowKey structs must be at least aligned enough
for uint32_t accesses, because that's the type of the first field.
Switch to using uint32_t accesses in the loop.
Because the "width" field is always set via the FLOW_KEY_WIDTH macro
and not exposed to the guest, we can adjust the macro to store the
number of uint32_t to be checked rather than needing to change the
loop boundary in the match function.
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Jason Wang <jasowang@redhat.com>
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 958f3006c1..3d6f55b512 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -99,13 +99,13 @@ typedef struct of_dpa_flow_key {
} nd;
} ipv6;
};
- int width; /* how many uint64_t's in key? */
+ int width; /* how many uint32_t's in key? */
} OfDpaFlowKey;
-/* Width of key which includes field 'f' in u64s, rounded up */
+/* Width of key which includes field 'f' in u32s, rounded up */
#define FLOW_KEY_WIDTH(f) \
DIV_ROUND_UP(offsetof(OfDpaFlowKey, f) + sizeof_field(OfDpaFlowKey, f), \
- sizeof(uint64_t))
+ sizeof(uint32_t))
typedef struct of_dpa_flow_action {
uint32_t goto_tbl;
@@ -304,9 +304,9 @@ static void _of_dpa_flow_match(void *key, void *value, void *user_data)
{
OfDpaFlow *flow = value;
OfDpaFlowMatch *match = user_data;
- uint64_t *k = (uint64_t *)&flow->key;
- uint64_t *m = (uint64_t *)&flow->mask;
- uint64_t *v = (uint64_t *)&match->value;
+ uint32_t *k = (uint32_t *)&flow->key;
+ uint32_t *m = (uint32_t *)&flow->mask;
+ uint32_t *v = (uint32_t *)&match->value;
int i;
if (flow->key.tbl_id == match->value.tbl_id) {