@samitouri / QOSamiQemu / commits / 71d027cfee

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>

Peter Maydell committed May 5, 2026 at 19:51 UTC 71d027cfee8553e2ec28efa1ddd7fd0ecbadcc86
1 file changed +6 -6
hw/net/rocker/rocker_of_dpa.c
+6 -6
@@ -99,13 +99,13 @@ typedef struct of_dpa_flow_key {
99 } nd;
100 } ipv6;
101 };
102 - int width; /* how many uint64_t's in key? */
102 + int width; /* how many uint32_t's in key? */
103 } OfDpaFlowKey;
104
105 -/* Width of key which includes field 'f' in u64s, rounded up */
105 +/* Width of key which includes field 'f' in u32s, rounded up */
106 #define FLOW_KEY_WIDTH(f) \
107 DIV_ROUND_UP(offsetof(OfDpaFlowKey, f) + sizeof_field(OfDpaFlowKey, f), \
108 - sizeof(uint64_t))
108 + sizeof(uint32_t))
109
110 typedef struct of_dpa_flow_action {
111 uint32_t goto_tbl;
@@ -304,9 +304,9 @@ static void _of_dpa_flow_match(void *key, void *value, void *user_data)
304 {
305 OfDpaFlow *flow = value;
306 OfDpaFlowMatch *match = user_data;
307 - uint64_t *k = (uint64_t *)&flow->key;
308 - uint64_t *m = (uint64_t *)&flow->mask;
309 - uint64_t *v = (uint64_t *)&match->value;
307 + uint32_t *k = (uint32_t *)&flow->key;
308 + uint32_t *m = (uint32_t *)&flow->mask;
309 + uint32_t *v = (uint32_t *)&match->value;
310 int i;
311
312 if (flow->key.tbl_id == match->value.tbl_id) {