From 9e53a866205e9fed6e65457ce350bebe67dc5a62 Mon Sep 17 00:00:00 2001 From: Wen Ping Teh Date: Fri, 4 Apr 2025 17:29:39 +0100 Subject: [PATCH 1/2] mod/cmn_cyprus: Move get_child_count() to internal header Moved get_child_count() to the internal header file, cmn_cyprus_discovery_setup.h, to enable other CMN-Cyprus modules to get the child count. Signed-off-by: Wen Ping Teh --- .../include/internal/cmn_cyprus_discovery_setup.h | 11 ++++++++++- module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c | 12 ++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/module/cmn_cyprus/include/internal/cmn_cyprus_discovery_setup.h b/module/cmn_cyprus/include/internal/cmn_cyprus_discovery_setup.h index 69a8eba6d..dadc36f9f 100644 --- a/module/cmn_cyprus/include/internal/cmn_cyprus_discovery_setup.h +++ b/module/cmn_cyprus/include/internal/cmn_cyprus_discovery_setup.h @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -23,4 +23,13 @@ */ int cmn_cyprus_discovery(struct cmn_cyprus_ctx *ctx); +/* + * Get number of children connected to the cross point + * + * \param[in] child_info Value of CHILD_INFO register + * + * \return Child count + */ +unsigned int cmn_cyprus_get_child_count(FWK_R uint64_t child_info); + #endif /* INTERNAL_CMN_CYPRUS_DISCOVERY_SETUP_H */ diff --git a/module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c b/module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c index 4a2230a5e..f43562eb9 100644 --- a/module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c +++ b/module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -204,7 +204,7 @@ static const char *get_cmn_cyprus_revision_name( } #endif -static inline unsigned int get_child_count(FWK_R uint64_t child_info) +unsigned int cmn_cyprus_get_child_count(FWK_R uint64_t child_info) { return (child_info & CHILD_INFO_COUNT); } @@ -536,7 +536,7 @@ static int discover_mxp_nodes(struct cmn_cyprus_mxp_reg *mxp) struct cmn_cyprus_node_cfg_reg *node; /* Get number of children connected to the cross point */ - node_count = get_child_count(mxp->CHILD_INFO); + node_count = cmn_cyprus_get_child_count(mxp->CHILD_INFO); #if FWK_LOG_LEVEL <= FWK_LOG_LEVEL_INFO print_node_info(mxp); @@ -589,7 +589,7 @@ static int discover_mesh_topology(void) MOD_NAME "Rootnode Base address: %p", (void *)shared_ctx->cfgm); /* Get number of cross points in the mesh */ - mxp_count = get_child_count(shared_ctx->cfgm->CHILD_INFO); + mxp_count = cmn_cyprus_get_child_count(shared_ctx->cfgm->CHILD_INFO); /* Traverse cross points */ for (mxp_idx = 0; mxp_idx < mxp_count; mxp_idx++) { @@ -796,7 +796,7 @@ static int cmn_cyprus_init_node_info(struct cmn_cyprus_mxp_reg *mxp) config = shared_ctx->config; /* Get the number of children connected to the cross point */ - node_count = get_child_count(mxp->CHILD_INFO); + node_count = cmn_cyprus_get_child_count(mxp->CHILD_INFO); status = FWK_SUCCESS; @@ -880,7 +880,7 @@ static int cmn_cyprus_init_ctx(void) rnsam_entry = 0; /* Get number of cross points in the mesh */ - mxp_count = get_child_count(shared_ctx->cfgm->CHILD_INFO); + mxp_count = cmn_cyprus_get_child_count(shared_ctx->cfgm->CHILD_INFO); /* Traverse cross points */ for (mxp_idx = 0; mxp_idx < mxp_count; mxp_idx++) { -- GitLab From 9bf1bf6bc889c1437b6d668f6863a22aac1399d5 Mon Sep 17 00:00:00 2001 From: Wen Ping Teh Date: Fri, 4 Apr 2025 12:59:06 +0100 Subject: [PATCH 2/2] mod/cmn_cyprus: Add bounds checking for CMN-Cyprus modules This patch adds input validation and bounds checking when accessing child nodes and shared context tables. Specifically: - Added fwk_assert() checks in cfgm_get_child_node() and mxp_get_child_node() to validate NULL pointers and ensure child_index is within bounds. - Added runtime checks in cmn_cyprus_init_node_info() to ensure rnsam_entry and ldid values are within valid limits before accessing shared context tables. Signed-off-by: Wen Ping Teh --- module/cmn_cyprus/src/cmn_cyprus_cfg_reg.c | 9 ++++++++- .../cmn_cyprus/src/cmn_cyprus_discovery_setup.c | 16 ++++++++++++++++ module/cmn_cyprus/src/cmn_cyprus_mxp_reg.c | 12 +++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/module/cmn_cyprus/src/cmn_cyprus_cfg_reg.c b/module/cmn_cyprus/src/cmn_cyprus_cfg_reg.c index aa9f54a3f..90ebe39af 100644 --- a/module/cmn_cyprus/src/cmn_cyprus_cfg_reg.c +++ b/module/cmn_cyprus/src/cmn_cyprus_cfg_reg.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -9,8 +9,12 @@ */ #include +#include #include +#include + +#include #include /* Peripheral ID Revision Numbers */ @@ -32,6 +36,9 @@ struct cmn_cyprus_node_cfg_reg *cfgm_get_child_node( unsigned int offset; struct cmn_cyprus_node_cfg_reg *child_node; + fwk_assert(cfgm != NULL); + fwk_assert(child_index < cmn_cyprus_get_child_count(cfgm->CHILD_INFO)); + offset = (cfgm->CHILD_POINTER[child_index] & CHILD_POINTER_OFFSET); /* * PERIPHBASE is the starting address of the range that all CMN‑Cyprus diff --git a/module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c b/module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c index f43562eb9..09fede26f 100644 --- a/module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c +++ b/module/cmn_cyprus/src/cmn_cyprus_discovery_setup.c @@ -827,6 +827,10 @@ static int cmn_cyprus_init_node_info(struct cmn_cyprus_mxp_reg *mxp) break; case NODE_TYPE_RN_SAM: + if (rnsam_entry >= shared_ctx->rnsam_count) { + FWK_LOG_ERR("Invalid rnsam_entry for RN_SAM: %u", rnsam_entry); + return FWK_E_RANGE; + } /* Save the node pointer in the RNSAM table */ shared_ctx->rnsam_table[rnsam_entry] = (struct cmn_cyprus_rnsam_reg *)node; @@ -835,6 +839,10 @@ static int cmn_cyprus_init_node_info(struct cmn_cyprus_mxp_reg *mxp) break; case NODE_TYPE_CCRA: + if (ldid >= shared_ctx->ccg_ra_reg_count) { + FWK_LOG_ERR("Invalid LDID for CCRA: %u", ldid); + return FWK_E_RANGE; + } shared_ctx->ccg_ra_info_table[ldid].node_id = node_info_get_id(node->NODE_INFO); shared_ctx->ccg_ra_info_table[ldid].ccg_ra = @@ -842,6 +850,10 @@ static int cmn_cyprus_init_node_info(struct cmn_cyprus_mxp_reg *mxp) break; case NODE_TYPE_CCHA: + if (ldid >= shared_ctx->ccg_ha_reg_count) { + FWK_LOG_ERR("Invalid LDID for CCHA: %u", ldid); + return FWK_E_RANGE; + } shared_ctx->ccg_ha_info_table[ldid].node_id = node_info_get_id(node->NODE_INFO); shared_ctx->ccg_ha_info_table[ldid].ccg_ha = @@ -849,6 +861,10 @@ static int cmn_cyprus_init_node_info(struct cmn_cyprus_mxp_reg *mxp) break; case NODE_TYPE_CCLA: + if (ldid >= shared_ctx->ccla_reg_count) { + FWK_LOG_ERR("Invalid LDID for CCLA: %u", ldid); + return FWK_E_RANGE; + } shared_ctx->ccla_info_table[ldid].node_id = node_info_get_id(node->NODE_INFO); shared_ctx->ccla_info_table[ldid].ccla = diff --git a/module/cmn_cyprus/src/cmn_cyprus_mxp_reg.c b/module/cmn_cyprus/src/cmn_cyprus_mxp_reg.c index a9ca01e7c..bc32ce496 100644 --- a/module/cmn_cyprus/src/cmn_cyprus_mxp_reg.c +++ b/module/cmn_cyprus/src/cmn_cyprus_mxp_reg.c @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -8,10 +8,14 @@ * Utility functions for accessing MXP node. */ +#include #include #include +#include + #include +#include #include /* MXP Port Connect Info */ @@ -37,6 +41,9 @@ struct cmn_cyprus_node_cfg_reg *mxp_get_child_node( unsigned int offset; struct cmn_cyprus_node_cfg_reg *child_node; + fwk_assert(mxp != NULL); + fwk_assert(child_index < cmn_cyprus_get_child_count(mxp->CHILD_INFO)); + offset = (mxp->CHILD_POINTER[child_index] & CHILD_POINTER_OFFSET); child_node = (struct cmn_cyprus_node_cfg_reg *)(periphbase + offset); @@ -48,6 +55,9 @@ bool mxp_is_child_external( struct cmn_cyprus_mxp_reg *mxp, unsigned int child_index) { + fwk_assert(mxp != NULL); + fwk_assert(child_index < cmn_cyprus_get_child_count(mxp->CHILD_INFO)); + /* Read External Child Node indicator, bit[31] */ return ( (mxp->CHILD_POINTER[child_index] & (1U << CHILD_POINTER_EXT_BIT_POS)) > -- GitLab