From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id DA20D489EF for ; Mon, 27 Oct 2025 17:20:29 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D51D34028B; Mon, 27 Oct 2025 17:20:29 +0100 (CET) Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) by mails.dpdk.org (Postfix) with ESMTP id 4042240647 for ; Mon, 27 Oct 2025 17:20:28 +0100 (CET) Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-4270a3464caso2333354f8f.1 for ; Mon, 27 Oct 2025 09:20:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1761582028; x=1762186828; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BwSglSkIZaaHzP6KUaEBg2TI4JcRc4/FtRUwYjkV9Es=; b=dHFbaWfxxxeRzoqpKK9fMQy93wQjTSkts2TpklEm3eq/3FhB/+gJHpb8Fc3KNE/kyU dSlnRbLj7nIQ7AIiHnHmM3q21YDfCjZf9dDtOiovPiNp2c9ufStwB8a97y61XWo4snjh hTykQ1s7VrpBfm19jA2xt9Y4o2+OktkF3eJbFdLUXx0St/OfumgX9mwWZ4G6oC6emVSD KxUrzsE/0Co4EThekq9omWuZVs2ThNlUbcBUUfyi/cQfcF/GMs/RLgIydOAm8BJeE9Wz q28/F5I6T7R7ipgl7wiS0CmbuNsJIVC/pZ2Ir0m3hiLySw8HVsCHekxVuKDuWusJwRjU ybUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761582028; x=1762186828; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BwSglSkIZaaHzP6KUaEBg2TI4JcRc4/FtRUwYjkV9Es=; b=G3jGPytBTyjCCgwsuVO/g2yWlLjet4A8QgcsB6i/VeZ08xQCj7rXzg5xWzstoFWVGg 9jOQz71dxCmEtU/G2pC4jA/sagRDJBJEgI9r4rGQhD4y8TQWFuSv3TTRPGzrrRrKwjnQ 0uYmD+cNb4ArEV7fbNOGQBlgJUTdobN93zzThm1lDPKr+3BpIr3z0w6v8iCh3obvM+au M+0Y4DVBoBTCnW/xmDHaS3Si4YxHzYCKyxwcqUnPNHHKz7IsHMcYVjQKpDhLB9E4N6Qv C7Cch+GVGukHP1a/N+6Cp0pMOV5RK+QYcEpFbeJRkzFHIu2ChFCpnkxhqUuQfayUJJGJ XFJQ== X-Forwarded-Encrypted: i=1; AJvYcCWbb/yrgkuNVbK8YbjD6DcCoi0InlXXsHWSQjUTcmx0VPSmLuNrXp1wTnV6LbAG+MXFiZGyHPY=@dpdk.org X-Gm-Message-State: AOJu0YyCr0S9rL6H3gwjM6QvBEKG4mkfxkh5mm8u75sjUWy2yBZYcZfs k1ejKa8Od+8n4oYBVhSpKVL2YTgyR7vnSBTTF9j/L4kbmUb+Iu5sbbDp X-Gm-Gg: ASbGncvSd0mzd4yPLOC+SwTTBeegtT7dpRaVQ11t9kNJOzzknDpfY+OBCx86tG7irv2 z7DOSYC1U3U+3uQCqYvniYiy/33IXunRIkWxx/De1E4X74XI9TGsAtsik1ywhLwMymUiPqNTo0r V74t+EoVKn+0qvNogKkc93mMCuvjpKIYAFDqknO19fv6SlgHtWACKurLQ+K6w/gO68jRevL1PFN AsVEQaR/M4jduFfYhyGSgNbV1xfFfR9Iz/cVwqBk2O0lcZCGZ2oBZG/ReFBrdXzVqyg0R1r4tT4 G6MqnMvTkVULniGxeH/064jmUXVonwGFkKoInhRFoj8ZESdTiBUF0you80PWT+Cr1R09JMj8hOd 9pb3XSagzZOlhldXXN7mHJSbcFWRM+UpweIluHIwW1FunuePiektf4LO/BLyCgMzr+dMCWJE+Mt lKdVJfY7wG7DxztirO X-Google-Smtp-Source: AGHT+IG3nolj0hnvXIaPQSVGTIP35jq86HPgcnv7EbH8kzcl7yEChBqja9dg55iOsUQmjmcPSmqf4g== X-Received: by 2002:a05:6000:26ce:b0:427:5e6:c0e5 with SMTP id ffacd0b85a97d-429a7e75aaamr232010f8f.39.1761582027650; Mon, 27 Oct 2025 09:20:27 -0700 (PDT) Received: from localhost ([2a01:4b00:d036:ae00:6fc5:c3bc:147e:832c]) by smtp.gmail.com with UTF8SMTPSA id ffacd0b85a97d-429952e2e06sm15064717f8f.46.2025.10.27.09.20.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Oct 2025 09:20:27 -0700 (PDT) From: luca.boccassi@gmail.com To: David Marchand Cc: Kiran Kumar K , dpdk stable Subject: patch 'graph: fix unaligned access in stats' has been queued to stable release 22.11.11 Date: Mon, 27 Oct 2025 16:18:45 +0000 Message-ID: <20251027162001.3710450-7-luca.boccassi@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251027162001.3710450-1-luca.boccassi@gmail.com> References: <20251027162001.3710450-1-luca.boccassi@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Hi, FYI, your patch has been queued to stable release 22.11.11 Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet. It will be pushed if I get no objections before 10/29/25. So please shout if anyone has objections. Also note that after the patch there's a diff of the upstream commit vs the patch applied to the branch. This will indicate if there was any rebasing needed to apply to the stable branch. If there were code changes for rebasing (ie: not only metadata diffs), please double check that the rebase was correctly done. Queued patches are on a temporary branch at: https://github.com/bluca/dpdk-stable This queued commit can be viewed at: https://github.com/bluca/dpdk-stable/commit/f4c9a3f5434a2ff68bbd783b41eaf402a416b22f Thanks. Luca Boccassi --- >From f4c9a3f5434a2ff68bbd783b41eaf402a416b22f Mon Sep 17 00:00:00 2001 From: David Marchand Date: Fri, 4 Jul 2025 11:15:03 +0200 Subject: [PATCH] graph: fix unaligned access in stats [ upstream commit 826af93a68f358f8eb4f363e42d114b93fde0d69 ] UBSan reports: ../lib/graph/graph_stats.c:208:13: runtime error: member access within misaligned address 0x000054742c50 for type 'struct rte_graph_cluster_stats', which requires 64 byte alignment ../lib/graph/graph_stats.c:257:12: runtime error: member access within misaligned address 0x00002219fd30 for type 'struct rte_graph_cluster_stats', which requires 64 byte alignment The current code goes into various complex (non aligned) reallocations / memset / memcpy. Simplify this by computing how many nodes are present in the cluster of graphes. Then directly call rte_malloc for the whole stats object. As a bonus, this change also fixes leaks: - if any error occurred before call to rte_malloc, since the xstats objects stored in the glibc allocated stats object were not freed, - if an allocation failure occurs, with constructs using ptr = realloc(ptr, sz), since the original ptr is lost, Fixes: af1ae8b6a32c ("graph: implement stats") Signed-off-by: David Marchand Acked-by: Kiran Kumar K --- lib/graph/graph_stats.c | 96 +++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/lib/graph/graph_stats.c b/lib/graph/graph_stats.c index c0140ba922..da2cff7a36 100644 --- a/lib/graph/graph_stats.c +++ b/lib/graph/graph_stats.c @@ -35,7 +35,6 @@ struct rte_graph_cluster_stats { rte_node_t max_nodes; int socket_id; void *cookie; - size_t sz; struct cluster_node clusters[]; } __rte_cache_aligned; @@ -99,15 +98,55 @@ graph_cluster_stats_cb(bool is_first, bool is_last, void *cookie, return 0; }; +static uint32_t +cluster_count_nodes(const struct cluster *cluster) +{ + rte_node_t *nodes = NULL; + uint32_t max_nodes = 0; + + for (unsigned int i = 0; i < cluster->nb_graphs; i++) { + struct graph_node *graph_node; + + STAILQ_FOREACH(graph_node, &cluster->graphs[i]->node_list, next) { + rte_node_t *new_nodes; + unsigned int n; + + for (n = 0; n < max_nodes; n++) { + if (nodes[n] != graph_node->node->id) + continue; + break; + } + if (n != max_nodes) + continue; + + max_nodes++; + new_nodes = realloc(nodes, max_nodes * sizeof(nodes[0])); + if (new_nodes == NULL) { + free(nodes); + return 0; + } + nodes = new_nodes; + nodes[n] = graph_node->node->id; + } + } + free(nodes); + + return max_nodes; +} + static struct rte_graph_cluster_stats * stats_mem_init(struct cluster *cluster, const struct rte_graph_cluster_stats_param *prm) { - size_t sz = sizeof(struct rte_graph_cluster_stats); struct rte_graph_cluster_stats *stats; rte_graph_cluster_stats_cb_t fn; int socket_id = prm->socket_id; uint32_t cluster_node_size; + uint32_t max_nodes; + + max_nodes = cluster_count_nodes(cluster); + if (max_nodes == 0) + return NULL; /* Fix up callback */ fn = prm->fn; @@ -119,25 +158,23 @@ stats_mem_init(struct cluster *cluster, cluster_node_size += cluster->nb_graphs * sizeof(struct rte_node *); cluster_node_size = RTE_ALIGN(cluster_node_size, RTE_CACHE_LINE_SIZE); - stats = realloc(NULL, sz); + stats = rte_zmalloc_socket(NULL, sizeof(struct rte_graph_cluster_stats) + + max_nodes * cluster_node_size, 0, socket_id); if (stats) { - memset(stats, 0, sz); stats->fn = fn; stats->cluster_node_size = cluster_node_size; stats->max_nodes = 0; stats->socket_id = socket_id; stats->cookie = prm->cookie; - stats->sz = sz; } return stats; } static int -stats_mem_populate(struct rte_graph_cluster_stats **stats_in, +stats_mem_populate(struct rte_graph_cluster_stats *stats, struct rte_graph *graph, struct graph_node *graph_node) { - struct rte_graph_cluster_stats *stats = *stats_in; rte_node_t id = graph_node->node->id; struct cluster_node *cluster; struct rte_node *node; @@ -162,41 +199,22 @@ stats_mem_populate(struct rte_graph_cluster_stats **stats_in, cluster = RTE_PTR_ADD(cluster, stats->cluster_node_size); } - /* Hey, it is a new node, allocate space for it in the reel */ - stats = realloc(stats, stats->sz + stats->cluster_node_size); - if (stats == NULL) - SET_ERR_JMP(ENOMEM, err, "Realloc failed"); - *stats_in = NULL; - - /* Clear the new struct cluster_node area */ - cluster = RTE_PTR_ADD(stats, stats->sz), - memset(cluster, 0, stats->cluster_node_size); memcpy(cluster->stat.name, graph_node->node->name, RTE_NODE_NAMESIZE); cluster->stat.id = graph_node->node->id; cluster->stat.hz = rte_get_timer_hz(); node = graph_node_id_to_ptr(graph, id); if (node == NULL) - SET_ERR_JMP(ENOENT, free, "Failed to find node %s in graph %s", + SET_ERR_JMP(ENOENT, err, "Failed to find node %s in graph %s", graph_node->node->name, graph->name); cluster->nodes[cluster->nb_nodes++] = node; - stats->sz += stats->cluster_node_size; stats->max_nodes++; - *stats_in = stats; return 0; -free: - free(stats); err: return -rte_errno; } -static void -stats_mem_fini(struct rte_graph_cluster_stats *stats) -{ - free(stats); -} - static void cluster_init(struct cluster *cluster) { @@ -265,10 +283,7 @@ struct rte_graph_cluster_stats * rte_graph_cluster_stats_create(const struct rte_graph_cluster_stats_param *prm) { struct rte_graph_cluster_stats *stats, *rc = NULL; - struct graph_node *graph_node; struct cluster cluster; - struct graph *graph; - const char *pattern; rte_graph_t i; /* Sanity checks */ @@ -286,35 +301,34 @@ rte_graph_cluster_stats_create(const struct rte_graph_cluster_stats_param *prm) graph_spinlock_lock(); /* Expand graph pattern and add the graph to the cluster */ for (i = 0; i < prm->nb_graph_patterns; i++) { - pattern = prm->graph_patterns[i]; - if (expand_pattern_to_cluster(&cluster, pattern)) + if (expand_pattern_to_cluster(&cluster, prm->graph_patterns[i])) goto bad_pattern; } /* Alloc the stats memory */ stats = stats_mem_init(&cluster, prm); if (stats == NULL) - SET_ERR_JMP(ENOMEM, bad_pattern, "Failed alloc stats memory"); + SET_ERR_JMP(ENOMEM, bad_pattern, "Failed rte_malloc for stats memory"); /* Iterate over M(Graph) x N (Nodes in graph) */ for (i = 0; i < cluster.nb_graphs; i++) { + struct graph_node *graph_node; + struct graph *graph; + graph = cluster.graphs[i]; STAILQ_FOREACH(graph_node, &graph->node_list, next) { struct rte_graph *graph_fp = graph->graph; - if (stats_mem_populate(&stats, graph_fp, graph_node)) + if (stats_mem_populate(stats, graph_fp, graph_node)) goto realloc_fail; } } - /* Finally copy to hugepage memory to avoid pressure on rte_realloc */ - rc = rte_malloc_socket(NULL, stats->sz, 0, stats->socket_id); - if (rc) - rte_memcpy(rc, stats, stats->sz); - else - SET_ERR_JMP(ENOMEM, realloc_fail, "rte_malloc failed"); + rc = stats; + stats = NULL; realloc_fail: - stats_mem_fini(stats); + if (stats != NULL) + rte_graph_cluster_stats_destroy(stats); bad_pattern: graph_spinlock_unlock(); cluster_fini(&cluster); -- 2.47.3 --- Diff of the applied patch vs upstream commit (please double-check if non-empty: --- --- - 2025-10-27 15:54:35.116080658 +0000 +++ 0007-graph-fix-unaligned-access-in-stats.patch 2025-10-27 15:54:34.719947643 +0000 @@ -1 +1 @@ -From 826af93a68f358f8eb4f363e42d114b93fde0d69 Mon Sep 17 00:00:00 2001 +From f4c9a3f5434a2ff68bbd783b41eaf402a416b22f Mon Sep 17 00:00:00 2001 @@ -5,0 +6,2 @@ +[ upstream commit 826af93a68f358f8eb4f363e42d114b93fde0d69 ] + @@ -32 +33,0 @@ -Cc: stable@dpdk.org @@ -37,2 +38,2 @@ - lib/graph/graph_stats.c | 102 +++++++++++++++++++++++----------------- - 1 file changed, 58 insertions(+), 44 deletions(-) + lib/graph/graph_stats.c | 96 +++++++++++++++++++++++------------------ + 1 file changed, 55 insertions(+), 41 deletions(-) @@ -41 +42 @@ -index 583ad8dbd5..e0fc8fd25c 100644 +index c0140ba922..da2cff7a36 100644 @@ -44 +45,2 @@ -@@ -37,7 +37,6 @@ struct __rte_cache_aligned rte_graph_cluster_stats { +@@ -35,7 +35,6 @@ struct rte_graph_cluster_stats { + rte_node_t max_nodes; @@ -46 +47,0 @@ - bool dispatch; @@ -51,3 +52,3 @@ - }; -@@ -178,15 +177,55 @@ graph_cluster_stats_cb_dispatch(bool is_first, bool is_last, void *cookie, - return graph_cluster_stats_cb(true, is_first, is_last, cookie, stat); + } __rte_cache_aligned; +@@ -99,15 +98,55 @@ graph_cluster_stats_cb(bool is_first, bool is_last, void *cookie, + return 0; @@ -109 +110 @@ -@@ -203,25 +242,23 @@ stats_mem_init(struct cluster *cluster, +@@ -119,25 +158,23 @@ stats_mem_init(struct cluster *cluster, @@ -138 +139 @@ -@@ -247,21 +284,12 @@ stats_mem_populate(struct rte_graph_cluster_stats **stats_in, +@@ -162,41 +199,22 @@ stats_mem_populate(struct rte_graph_cluster_stats **stats_in, @@ -160,30 +160,0 @@ - if (graph_node->node->xstats) { -@@ -270,7 +298,7 @@ stats_mem_populate(struct rte_graph_cluster_stats **stats_in, - sizeof(uint64_t) * graph_node->node->xstats->nb_xstats, - RTE_CACHE_LINE_SIZE, stats->socket_id); - if (cluster->stat.xstat_count == NULL) -- SET_ERR_JMP(ENOMEM, free, "Failed to allocate memory node %s graph %s", -+ SET_ERR_JMP(ENOMEM, err, "Failed to allocate memory node %s graph %s", - graph_node->node->name, graph->name); - - cluster->stat.xstat_desc = rte_zmalloc_socket(NULL, -@@ -278,7 +306,7 @@ stats_mem_populate(struct rte_graph_cluster_stats **stats_in, - RTE_CACHE_LINE_SIZE, stats->socket_id); - if (cluster->stat.xstat_desc == NULL) { - rte_free(cluster->stat.xstat_count); -- SET_ERR_JMP(ENOMEM, free, "Failed to allocate memory node %s graph %s", -+ SET_ERR_JMP(ENOMEM, err, "Failed to allocate memory node %s graph %s", - graph_node->node->name, graph->name); - } - -@@ -288,30 +316,20 @@ stats_mem_populate(struct rte_graph_cluster_stats **stats_in, - RTE_NODE_XSTAT_DESC_SIZE) < 0) { - rte_free(cluster->stat.xstat_count); - rte_free(cluster->stat.xstat_desc); -- SET_ERR_JMP(E2BIG, free, -+ SET_ERR_JMP(E2BIG, err, - "Error description overflow node %s graph %s", - graph_node->node->name, graph->name); - } - } - } @@ -211 +182 @@ -@@ -381,10 +399,7 @@ struct rte_graph_cluster_stats * +@@ -265,10 +283,7 @@ struct rte_graph_cluster_stats * @@ -222 +193 @@ -@@ -402,37 +417,36 @@ rte_graph_cluster_stats_create(const struct rte_graph_cluster_stats_param *prm) +@@ -286,35 +301,34 @@ rte_graph_cluster_stats_create(const struct rte_graph_cluster_stats_param *prm) @@ -250,2 +220,0 @@ - if (graph->graph->model == RTE_GRAPH_MODEL_MCORE_DISPATCH) - stats->dispatch = true;