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) {