[PATCH] ACPI: APMT: validate node bounds before device registration
Hanjun Guo
guohanjun at huawei.com
Thu Jul 16 23:45:54 PDT 2026
Hi Pengpeng,
On 2026/7/6 17:38, Pengpeng Hou wrote:
> The APMT parser walks variable-length nodes from the ACPI table and
> passes each node pointer to the platform device that is later consumed by
> the Arm Coresight PMU driver. The loop only checked that the node start
> was before the table end before reading the full struct acpi_apmt_node and
> advancing by node->length.
>
> Validate the fixed node body and the declared node length before using the
> node. This keeps malformed short nodes from being consumed locally or
> propagated to the runtime PMU driver as platform data.
>
> Signed-off-by: Pengpeng Hou <pengpeng at iscas.ac.cn>
> ---
> drivers/acpi/arm64/apmt.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/drivers/acpi/arm64/apmt.c b/drivers/acpi/arm64/apmt.c
> index bb010f6164e5..5f341fa86fab 100644
> --- a/drivers/acpi/arm64/apmt.c
> +++ b/drivers/acpi/arm64/apmt.c
> @@ -23,6 +23,21 @@
> /* Root pointer to the mapped APMT table */
> static struct acpi_table_header *apmt_table;
>
> +static bool __init apmt_node_valid(struct acpi_table_apmt *apmt, u64 offset,
> + u64 end)
> +{
> + struct acpi_apmt_node *node;
> +
> + if (offset > end || end - offset < sizeof(*node))
> + return false;
> +
> + node = ACPI_ADD_PTR(struct acpi_apmt_node, apmt, offset);
> + if (node->length < sizeof(*node))
> + return false;
> +
> + return node->length <= end - offset;
> +}
> +
> static int __init apmt_init_resources(struct resource *res,
> struct acpi_apmt_node *node)
> {
> @@ -129,8 +144,13 @@ static int __init apmt_init_platform_devices(void)
> apmt = (struct acpi_table_apmt *)apmt_table;
> offset = sizeof(*apmt);
> end = apmt->header.length;
> + if (end < sizeof(*apmt))
> + return -EINVAL;
This means the firmware reports the wrong length of the ACPI table, it's
better to print FW_BUG here.
It's a rare case because the APMT is not work at all if the length
is less than size of the head.
>
> while (offset < end) {
> + if (!apmt_node_valid(apmt, offset, end))
> + return -EINVAL;
Do you have the real bad case? or can you trigger it?
Thanks
Hanjun
More information about the linux-arm-kernel
mailing list