From nobody Tue Sep 29 02:01:52 2026 Received: from cstnet.cn (smtp21.cstnet.cn [159.226.251.21]) (using TLSv1.2 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 21553361973; Thu, 13 Aug 2026 15:49:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.226.251.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786636156; cv=none; b=SnJrxALBkr/DAQU/LIXTrxVXZYnr1ZNHSgsSM32pshMXkZnO5+w0dnWK0PzUQQ0c3Bt1ZyLNSqFpc7IghYrZB/n7wIip2TmkRBcXBx0lFi+RfNJUE7ajQ4gqcifCQ86snP3VCPEn4AKmIsDAuLEMTBaGvyRmOI65ntVJXAA4a6s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786636156; c=relaxed/simple; bh=s177SFau+FQjuR8xwYnc0mzzaLrEN/47vTR/BVWCy5Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YTytY3pPNyGqHXq6FODRVt0J+BTyLkut7fcUk2u0fcyXvKbxoOZ/pHSxPybcSfa7qiaZvjrzcyN3sxu8B2xauo/dsKpwRCf5tzXCycyy1Emxtvi/BlPMOjTCMUwNt6bWpEpLd6T3BdDvJYoCOvX8e09y2bzrqNSAwiCSTPHJnXw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn; spf=pass smtp.mailfrom=iscas.ac.cn; arc=none smtp.client-ip=159.226.251.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iscas.ac.cn Received: from localhost.localdomain (unknown [111.196.241.250]) by APP-01 (Coremail) with SMTP id qwCowAA3DPBp531qP5Z6BQ--.54209S2; Thu, 13 Aug 2026 23:48:57 +0800 (CST) From: Pengpeng Hou To: Sunil V L , "Rafael J. Wysocki" Cc: Len Brown , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , linux-acpi@vger.kernel.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Pengpeng Hou Subject: [PATCH v2 1/3] ACPI: RHCT: validate table and node extents before traversal Date: Thu, 13 Aug 2026 23:48:57 +0800 Message-ID: <20260813154857.62247-1-pengpeng@iscas.ac.cn> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260813154600.58861-1-pengpeng@iscas.ac.cn> References: <20260813154600.58861-1-pengpeng@iscas.ac.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: qwCowAA3DPBp531qP5Z6BQ--.54209S2 X-Coremail-Antispam: 1UD129KBjvJXoWxKw4DZw13AFyUtr4fAr4DXFb_yoW7CF15pa 1IgFy5JrWrJw13Wr4xtw4ruwsIq3y0vF4UXrWrGa45tw1kKr18KFWjkrya9F1rKF1vgw47 Zan8tF98CF48AFUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUU9F14x267AKxVW8JVW5JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK02 1l84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j 6r4UJwA2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oV Cq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0 I7IYx2IY67AKxVWUAVWUtwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r 4UM4x0Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwACI402YVCY1x02628v n2kIc2xKxwCY1x0262kKe7AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7x kEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E 67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8Jw CI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWU CwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUvcS sGvfC2KfnxnUUI43ZEXa7VUbo5l5UUUUU== X-CM-SenderInfo: pshqw1xhqjqxpvfd2hldfou0/ Content-Type: text/plain; charset="utf-8" RHCT consumers construct the first node from firmware node_offset and advance using each node length. A bad offset, truncated header, or zero or oversized length can make traversal leave the table or fail to progress. Validate the root node area before constructing a pointer. Iterate at most node_count entries and require every complete node to remain within the table. Fixes: e6b9d8eddb17 ("drivers/acpi: RISC-V: Add RHCT related code") Fixes: 9ca87564190c ("RISC-V: ACPI: RHCT: Add function to get CBO block siz= es") Assisted-by: Codex:gpt-5 Signed-off-by: Pengpeng Hou --- drivers/acpi/riscv/rhct.c | 100 ++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 19 deletions(-) diff --git a/drivers/acpi/riscv/rhct.c b/drivers/acpi/riscv/rhct.c index 8f3f38c64a88..01d6e39c0c5a 100644 --- a/drivers/acpi/riscv/rhct.c +++ b/drivers/acpi/riscv/rhct.c @@ -10,6 +10,44 @@ #include #include =20 +static bool rhct_table_valid(struct acpi_table_rhct *rhct) +{ + size_t node_bytes; + + if (!rhct || rhct->header.length < sizeof(*rhct)) + return false; + + if (!rhct->node_count) + return true; + + if (rhct->node_offset < sizeof(*rhct) || + rhct->node_offset > rhct->header.length - + sizeof(struct acpi_rhct_node_header)) + return false; + + node_bytes =3D rhct->header.length - rhct->node_offset; + return rhct->node_count <=3D + node_bytes / sizeof(struct acpi_rhct_node_header); +} + +static bool rhct_node_valid(struct acpi_rhct_node_header *node, + struct acpi_rhct_node_header *end) +{ + size_t remaining; + + if ((u8 *)node >=3D (u8 *)end) + return false; + + remaining =3D (u8 *)end - (u8 *)node; + if (remaining < sizeof(*node) || node->length < sizeof(*node) || + node->length > remaining) { + pr_err(FW_BUG "Invalid RHCT node length\n"); + return false; + } + + return true; +} + static struct acpi_table_rhct *acpi_get_rhct(void) { static struct acpi_table_header *rhct; @@ -45,6 +83,7 @@ int acpi_get_riscv_isa(struct acpi_table_header *table, u= nsigned int cpu, const struct acpi_table_rhct *rhct; u32 *hart_info_node_offset; u32 acpi_cpu_id; + unsigned int i; int ret; =20 BUG_ON(acpi_disabled); @@ -61,28 +100,39 @@ int acpi_get_riscv_isa(struct acpi_table_header *table= , unsigned int cpu, const rhct =3D (struct acpi_table_rhct *)table; } =20 - end =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.len= gth); + if (!rhct_table_valid(rhct)) + return -EINVAL; + if (!rhct->node_count) + return -ENOENT; + + node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, + rhct->node_offset); + end =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, + rhct->header.length); + + for (i =3D 0; i < rhct->node_count; i++) { + if (!rhct_node_valid(node, end)) + return -EINVAL; =20 - for (node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node= _offset); - node < end; - node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->leng= th)) { if (node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO) { hart_info =3D ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr); hart_info_node_offset =3D ACPI_ADD_PTR(u32, hart_info, size_hartinfo); - if (acpi_cpu_id !=3D hart_info->uid) - continue; - - for (int i =3D 0; i < hart_info->num_offsets; i++) { - ref_node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, - rhct, hart_info_node_offset[i]); - if (ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_ISA_STRING) { - isa_node =3D ACPI_ADD_PTR(struct acpi_rhct_isa_string, - ref_node, size_hdr); - *isa =3D isa_node->isa; - return 0; + if (acpi_cpu_id =3D=3D hart_info->uid) { + for (int j =3D 0; j < hart_info->num_offsets; j++) { + ref_node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, + rhct, hart_info_node_offset[j]); + if (ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_ISA_STRING) { + isa_node =3D ACPI_ADD_PTR(struct acpi_rhct_isa_string, + ref_node, size_hdr); + *isa =3D isa_node->isa; + return 0; + } } } } + + node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, node, + node->length); } =20 return -1; @@ -141,6 +191,7 @@ void acpi_get_cbo_block_size(struct acpi_table_header *= table, u32 *cbom_size, struct acpi_rhct_node_header *node, *end; struct acpi_rhct_hart_info *hart_info; struct acpi_table_rhct *rhct; + unsigned int i; =20 if (acpi_disabled) return; @@ -162,14 +213,25 @@ void acpi_get_cbo_block_size(struct acpi_table_header= *table, u32 *cbom_size, if (cbop_size) *cbop_size =3D 0; =20 - end =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->header.len= gth); - for (node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, rhct->node= _offset); - node < end; - node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->leng= th)) { + if (!rhct_table_valid(rhct) || !rhct->node_count) + return; + + node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, + rhct->node_offset); + end =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, + rhct->header.length); + + for (i =3D 0; i < rhct->node_count; i++) { + if (!rhct_node_valid(node, end)) + return; + if (node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO) { hart_info =3D ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr); acpi_parse_hart_info_cmo_node(rhct, hart_info, cbom_size, cboz_size, cbop_size); } + + node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, node, + node->length); } } --=20 2.50.1 (Apple Git-155) From nobody Tue Sep 29 02:01:52 2026 Received: from cstnet.cn (smtp21.cstnet.cn [159.226.251.21]) (using TLSv1.2 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A183377561; Thu, 13 Aug 2026 15:57:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.226.251.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786636657; cv=none; b=P8krTvDFYWFzvPPdZigPTr9Z2G0GUzBUTfqNwtwbzPxHikEREjFkSjVysNZlMnDkq7iv/uAvr2dPpzWAJrBLL+3Iqel12TSuHjtsSnAggZw5SeLdGqwgpOpib3hlQFFCq17ZnPpAL2G1Gl3obx3G0l+g5GnC/L8FD2RH0UACfqY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786636657; c=relaxed/simple; bh=+36nsyuOs8Dwr6JtjzumNGVP593FJGJKByS1Qz+HmZE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hMnd7At3m6j1rQE8VkQ3AVlC7fPkPJKHSxgrAevi4izU9KDOLRTEON/ojjfJEBZcFJqsVduPdO/mOqt7JlRbpGU7RDJ21/pdtTSLCDxRSu+BdrgktJpbwsJyD/Dr0BUpphH1yj4wBP83jg5WJXueqWrM51qvdfFrJzDF08L/Dz8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn; spf=pass smtp.mailfrom=iscas.ac.cn; arc=none smtp.client-ip=159.226.251.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iscas.ac.cn Received: from localhost.localdomain (unknown [111.196.241.250]) by APP-01 (Coremail) with SMTP id qwCowAC3iu5l6X1qMvN6BQ--.13638S2; Thu, 13 Aug 2026 23:57:25 +0800 (CST) From: Pengpeng Hou To: Sunil V L , "Rafael J. Wysocki" Cc: Len Brown , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , linux-acpi@vger.kernel.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Pengpeng Hou Subject: [PATCH v2 2/3] ACPI: RHCT: validate hart-info offsets and node references Date: Thu, 13 Aug 2026 23:57:25 +0800 Message-ID: <20260813155725.67361-1-pengpeng@iscas.ac.cn> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260813154600.58861-1-pengpeng@iscas.ac.cn> References: <20260813154600.58861-1-pengpeng@iscas.ac.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: qwCowAC3iu5l6X1qMvN6BQ--.13638S2 X-Coremail-Antispam: 1UD129KBjvJXoWxKw4DZw13CFyrJr1fArW3trb_yoW3Gry3pF 4S9ry5AFs8Jw13Wr10qw4ruay3J34rZr4UXFZ3Ga4jyr1vkF1UKF4jk3429F1rtF1vgw4x Zr4DtFyDGF48ArUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUU9F14x267AKxVW8JVW5JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK02 1l84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j 6r4UJwA2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oV Cq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0 I7IYx2IY67AKxVWUAVWUtwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r 4UM4x0Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwACI402YVCY1x02628v n2kIc2xKxwCY1x0262kKe7AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7x kEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E 67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCw CI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWU CwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUvcS sGvfC2KfnxnUUI43ZEXa7VUbo5l5UUUUU== X-CM-SenderInfo: pshqw1xhqjqxpvfd2hldfou0/ Content-Type: text/plain; charset="utf-8" Each RHCT hart-info node contains a count followed by offsets to other RHCT nodes. Consumers trust both the offset-array extent and every referenced address. Require the complete offset array to fit in its hart-info node. Resolve each reference only when it exactly matches a validated node boundary, and reject references to another hart-info node as required by the RHCT definition. Fixes: e6b9d8eddb17 ("drivers/acpi: RISC-V: Add RHCT related code") Fixes: 9ca87564190c ("RISC-V: ACPI: RHCT: Add function to get CBO block siz= es") Assisted-by: Codex:gpt-5 Signed-off-by: Pengpeng Hou --- drivers/acpi/riscv/rhct.c | 124 +++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 23 deletions(-) diff --git a/drivers/acpi/riscv/rhct.c b/drivers/acpi/riscv/rhct.c index 01d6e39c0c5a..b1b850d58efd 100644 --- a/drivers/acpi/riscv/rhct.c +++ b/drivers/acpi/riscv/rhct.c @@ -9,6 +9,7 @@ =20 #include #include +#include =20 static bool rhct_table_valid(struct acpi_table_rhct *rhct) { @@ -48,6 +49,66 @@ static bool rhct_node_valid(struct acpi_rhct_node_header= *node, return true; } =20 +static bool rhct_node_has_data(struct acpi_rhct_node_header *node, + size_t data_size) +{ + if (node->length < sizeof(*node) || + data_size > node->length - sizeof(*node)) { + pr_err(FW_BUG "Truncated RHCT node type %u\n", node->type); + return false; + } + + return true; +} + +static struct acpi_rhct_node_header * +rhct_node_from_offset(struct acpi_table_rhct *rhct, u32 offset) +{ + struct acpi_rhct_node_header *node, *end; + unsigned int i; + + if (!rhct_table_valid(rhct) || offset < rhct->node_offset || + offset >=3D rhct->header.length) + return NULL; + + node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, + rhct->node_offset); + end =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, rhct, + rhct->header.length); + + for (i =3D 0; i < rhct->node_count; i++) { + if (!rhct_node_valid(node, end)) + return NULL; + if ((u8 *)node - (u8 *)rhct =3D=3D offset) + return node; + + node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, node, + node->length); + } + + return NULL; +} + +static bool rhct_hart_info_valid(struct acpi_rhct_node_header *node) +{ + struct acpi_rhct_hart_info *hart_info; + size_t offsets_size; + + if (!rhct_node_has_data(node, sizeof(*hart_info))) + return false; + + hart_info =3D ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, + sizeof(*node)); + if (check_mul_overflow(hart_info->num_offsets, sizeof(u32), + &offsets_size) || + offsets_size > node->length - sizeof(*node) - sizeof(*hart_info)) { + pr_err(FW_BUG "Invalid RHCT hart-info offset array\n"); + return false; + } + + return true; +} + static struct acpi_table_rhct *acpi_get_rhct(void) { static struct acpi_table_header *rhct; @@ -77,13 +138,12 @@ int acpi_get_riscv_isa(struct acpi_table_header *table= , unsigned int cpu, const { struct acpi_rhct_node_header *node, *ref_node, *end; u32 size_hdr =3D sizeof(struct acpi_rhct_node_header); - u32 size_hartinfo =3D sizeof(struct acpi_rhct_hart_info); struct acpi_rhct_hart_info *hart_info; struct acpi_rhct_isa_string *isa_node; struct acpi_table_rhct *rhct; u32 *hart_info_node_offset; - u32 acpi_cpu_id; - unsigned int i; + u32 acpi_cpu_id, ref_offset; + unsigned int i, j; int ret; =20 BUG_ON(acpi_disabled); @@ -115,12 +175,21 @@ int acpi_get_riscv_isa(struct acpi_table_header *tabl= e, unsigned int cpu, const return -EINVAL; =20 if (node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO) { - hart_info =3D ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr); - hart_info_node_offset =3D ACPI_ADD_PTR(u32, hart_info, size_hartinfo); + if (!rhct_hart_info_valid(node)) + return -EINVAL; + + hart_info =3D ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, + sizeof(*node)); + hart_info_node_offset =3D ACPI_ADD_PTR(u32, hart_info, + sizeof(*hart_info)); if (acpi_cpu_id =3D=3D hart_info->uid) { - for (int j =3D 0; j < hart_info->num_offsets; j++) { - ref_node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, - rhct, hart_info_node_offset[j]); + for (j =3D 0; j < hart_info->num_offsets; j++) { + ref_offset =3D hart_info_node_offset[j]; + ref_node =3D rhct_node_from_offset(rhct, ref_offset); + if (!ref_node || + ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO) + return -EINVAL; + if (ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_ISA_STRING) { isa_node =3D ACPI_ADD_PTR(struct acpi_rhct_isa_string, ref_node, size_hdr); @@ -138,20 +207,30 @@ int acpi_get_riscv_isa(struct acpi_table_header *tabl= e, unsigned int cpu, const return -1; } =20 -static void acpi_parse_hart_info_cmo_node(struct acpi_table_rhct *rhct, - struct acpi_rhct_hart_info *hart_info, - u32 *cbom_size, u32 *cboz_size, u32 *cbop_size) +static bool acpi_parse_hart_info_cmo_node(struct acpi_table_rhct *rhct, + struct acpi_rhct_node_header *node, + u32 *cbom_size, u32 *cboz_size, + u32 *cbop_size) { - u32 size_hartinfo =3D sizeof(struct acpi_rhct_hart_info); u32 size_hdr =3D sizeof(struct acpi_rhct_node_header); struct acpi_rhct_node_header *ref_node; + struct acpi_rhct_hart_info *hart_info; struct acpi_rhct_cmo_node *cmo_node; u32 *hart_info_node_offset; + unsigned int i; + + if (!rhct_hart_info_valid(node)) + return false; + + hart_info =3D ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, + sizeof(*node)); + hart_info_node_offset =3D ACPI_ADD_PTR(u32, hart_info, + sizeof(*hart_info)); + for (i =3D 0; i < hart_info->num_offsets; i++) { + ref_node =3D rhct_node_from_offset(rhct, hart_info_node_offset[i]); + if (!ref_node || ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO) + return false; =20 - hart_info_node_offset =3D ACPI_ADD_PTR(u32, hart_info, size_hartinfo); - for (int i =3D 0; i < hart_info->num_offsets; i++) { - ref_node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, - rhct, hart_info_node_offset[i]); if (ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_CMO) { cmo_node =3D ACPI_ADD_PTR(struct acpi_rhct_cmo_node, ref_node, size_hdr); @@ -177,6 +256,8 @@ static void acpi_parse_hart_info_cmo_node(struct acpi_t= able_rhct *rhct, } } } + + return true; } =20 /* @@ -187,9 +268,7 @@ static void acpi_parse_hart_info_cmo_node(struct acpi_t= able_rhct *rhct, void acpi_get_cbo_block_size(struct acpi_table_header *table, u32 *cbom_si= ze, u32 *cboz_size, u32 *cbop_size) { - u32 size_hdr =3D sizeof(struct acpi_rhct_node_header); struct acpi_rhct_node_header *node, *end; - struct acpi_rhct_hart_info *hart_info; struct acpi_table_rhct *rhct; unsigned int i; =20 @@ -225,11 +304,10 @@ void acpi_get_cbo_block_size(struct acpi_table_header= *table, u32 *cbom_size, if (!rhct_node_valid(node, end)) return; =20 - if (node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO) { - hart_info =3D ACPI_ADD_PTR(struct acpi_rhct_hart_info, node, size_hdr); - acpi_parse_hart_info_cmo_node(rhct, hart_info, cbom_size, - cboz_size, cbop_size); - } + if (node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO && + !acpi_parse_hart_info_cmo_node(rhct, node, cbom_size, + cboz_size, cbop_size)) + return; =20 node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length); --=20 2.50.1 (Apple Git-155) From nobody Tue Sep 29 02:01:52 2026 Received: from cstnet.cn (smtp21.cstnet.cn [159.226.251.21]) (using TLSv1.2 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB3E2379974; Thu, 13 Aug 2026 15:59:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.226.251.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786636797; cv=none; b=aze3CKO9wIWTn3BnF6UnCVejopzMBL28HsO7JIHL+mQ/xvELIiKSG3VBFybT9vXwC17Yarshn8YLeYGG0TByIkqivWc7TjWAUsug3XcNl7cggLKbeUwk5i7gwSFxQZ2rYKKkFj5sbeyrm6sFgpTP7MhtvoGjCKwT15ESajkQmlg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786636797; c=relaxed/simple; bh=0Qb04rpT00v6EDNs7TbXu4q9H2POY7V8rgaugCIj0RU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kyrsxbwGRTdnsDTULDBz1R/a/Vt9tvHKxHhaT9JSt6BjfVzDWfXWNfqfesn6cqna+MooLHqHSCaFJIdjsDnfhVpiSA1XbCMk3ftGVjCkG5IDDF3z2zOrN3yiY7nWI57cku7c7PsUkONsenz9jhDq3G5y6tvxDmxQIqN03nyT1ZY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn; spf=pass smtp.mailfrom=iscas.ac.cn; arc=none smtp.client-ip=159.226.251.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iscas.ac.cn Received: from localhost.localdomain (unknown [111.196.241.250]) by APP-01 (Coremail) with SMTP id qwCowAAX6+7w6X1qLAt7BQ--.64323S2; Thu, 13 Aug 2026 23:59:44 +0800 (CST) From: Pengpeng Hou To: Sunil V L , "Rafael J. Wysocki" Cc: Len Brown , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , linux-acpi@vger.kernel.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Pengpeng Hou Subject: [PATCH v2 3/3] ACPI: RHCT: validate ISA and CMO node payloads Date: Thu, 13 Aug 2026 23:59:44 +0800 Message-ID: <20260813155944.68729-1-pengpeng@iscas.ac.cn> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260813154600.58861-1-pengpeng@iscas.ac.cn> References: <20260813154600.58861-1-pengpeng@iscas.ac.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: qwCowAAX6+7w6X1qLAt7BQ--.64323S2 X-Coremail-Antispam: 1UD129KBjvJXoWxXr1UWr4rJFW5Cw1fJr4rGrg_yoWrtF1UpF 1a9a4rAa4UJw43Wr10q3y5uay3X34Syr4jqrWfGas8tw4kKr4UJF42kFy7uFyrZF4kWw4x Zw4DtFyFkFs5Ar7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUU9Y14x267AKxVW8JVW5JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK02 1l84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j 6r4UJwA2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oV Cq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0 I7IYx2IY67AKxVWUAVWUtwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r 4UM4x0Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwACI402YVCY1x02628v n2kIc2xKxwCY1x0262kKe7AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7x kEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E 67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCw CI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1x MIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCT nIWIevJa73UjIFyTuYvjfU5dgADUUUU X-CM-SenderInfo: pshqw1xhqjqxpvfd2hldfou0/ Content-Type: text/plain; charset="utf-8" Hart-info references can select ISA-string and cache-management-operation nodes. The consumers read those type-specific payloads without first proving that they fit, and return ISA bytes as a C string without enforcing the RHCT requirement that isa_length include a terminating NUL. Require the CMO payload to be present and the final advertised ISA byte to be NUL. Accumulate CMO values locally and publish them only after the complete table walk succeeds, so a malformed later node cannot leave partial output. Fixes: e6b9d8eddb17 ("drivers/acpi: RISC-V: Add RHCT related code") Fixes: 9ca87564190c ("RISC-V: ACPI: RHCT: Add function to get CBO block siz= es") Assisted-by: Codex:gpt-5 Signed-off-by: Pengpeng Hou --- drivers/acpi/riscv/rhct.c | 57 +++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/riscv/rhct.c b/drivers/acpi/riscv/rhct.c index b1b850d58efd..03f84a433072 100644 --- a/drivers/acpi/riscv/rhct.c +++ b/drivers/acpi/riscv/rhct.c @@ -109,6 +109,26 @@ static bool rhct_hart_info_valid(struct acpi_rhct_node= _header *node) return true; } =20 +static bool rhct_isa_string_valid(struct acpi_rhct_node_header *node) +{ + struct acpi_rhct_isa_string *isa_node; + size_t remaining; + + if (!rhct_node_has_data(node, sizeof(*isa_node))) + return false; + + isa_node =3D ACPI_ADD_PTR(struct acpi_rhct_isa_string, node, + sizeof(*node)); + remaining =3D node->length - sizeof(*node) - sizeof(*isa_node); + if (!isa_node->isa_length || isa_node->isa_length > remaining || + isa_node->isa[isa_node->isa_length - 1] !=3D '\0') { + pr_err(FW_BUG "Invalid RHCT ISA string\n"); + return false; + } + + return true; +} + static struct acpi_table_rhct *acpi_get_rhct(void) { static struct acpi_table_header *rhct; @@ -137,7 +157,6 @@ static struct acpi_table_rhct *acpi_get_rhct(void) int acpi_get_riscv_isa(struct acpi_table_header *table, unsigned int cpu, = const char **isa) { struct acpi_rhct_node_header *node, *ref_node, *end; - u32 size_hdr =3D sizeof(struct acpi_rhct_node_header); struct acpi_rhct_hart_info *hart_info; struct acpi_rhct_isa_string *isa_node; struct acpi_table_rhct *rhct; @@ -190,12 +209,16 @@ int acpi_get_riscv_isa(struct acpi_table_header *tabl= e, unsigned int cpu, const ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO) return -EINVAL; =20 - if (ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_ISA_STRING) { - isa_node =3D ACPI_ADD_PTR(struct acpi_rhct_isa_string, - ref_node, size_hdr); - *isa =3D isa_node->isa; - return 0; - } + if (ref_node->type !=3D ACPI_RHCT_NODE_TYPE_ISA_STRING) + continue; + if (!rhct_isa_string_valid(ref_node)) + return -EINVAL; + + isa_node =3D ACPI_ADD_PTR(struct acpi_rhct_isa_string, + ref_node, + sizeof(*ref_node)); + *isa =3D isa_node->isa; + return 0; } } } @@ -212,7 +235,6 @@ static bool acpi_parse_hart_info_cmo_node(struct acpi_t= able_rhct *rhct, u32 *cbom_size, u32 *cboz_size, u32 *cbop_size) { - u32 size_hdr =3D sizeof(struct acpi_rhct_node_header); struct acpi_rhct_node_header *ref_node; struct acpi_rhct_hart_info *hart_info; struct acpi_rhct_cmo_node *cmo_node; @@ -232,8 +254,11 @@ static bool acpi_parse_hart_info_cmo_node(struct acpi_= table_rhct *rhct, return false; =20 if (ref_node->type =3D=3D ACPI_RHCT_NODE_TYPE_CMO) { + if (!rhct_node_has_data(ref_node, sizeof(*cmo_node))) + return false; + cmo_node =3D ACPI_ADD_PTR(struct acpi_rhct_cmo_node, - ref_node, size_hdr); + ref_node, sizeof(*ref_node)); if (cbom_size && cmo_node->cbom_size <=3D 30) { if (!*cbom_size) *cbom_size =3D BIT(cmo_node->cbom_size); @@ -270,6 +295,7 @@ void acpi_get_cbo_block_size(struct acpi_table_header *= table, u32 *cbom_size, { struct acpi_rhct_node_header *node, *end; struct acpi_table_rhct *rhct; + u32 cbom =3D 0, cboz =3D 0, cbop =3D 0; unsigned int i; =20 if (acpi_disabled) @@ -305,11 +331,20 @@ void acpi_get_cbo_block_size(struct acpi_table_header= *table, u32 *cbom_size, return; =20 if (node->type =3D=3D ACPI_RHCT_NODE_TYPE_HART_INFO && - !acpi_parse_hart_info_cmo_node(rhct, node, cbom_size, - cboz_size, cbop_size)) + !acpi_parse_hart_info_cmo_node(rhct, node, + cbom_size ? &cbom : NULL, + cboz_size ? &cboz : NULL, + cbop_size ? &cbop : NULL)) return; =20 node =3D ACPI_ADD_PTR(struct acpi_rhct_node_header, node, node->length); } + + if (cbom_size) + *cbom_size =3D cbom; + if (cboz_size) + *cboz_size =3D cboz; + if (cbop_size) + *cbop_size =3D cbop; } --=20 2.50.1 (Apple Git-155)