[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