From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794590864; b=Fto9O/jeULSUGgSdeHM2h/WXEqRJWbrpaoDC0HQSd/gDhybWU5fsmtN7+0pL8nO0XJCH fr14smc4vr+s+A1nL+kXLs/jqRa9zEhmy7xYhYu3ZhD6L2lrDGnvUzH9P3CgRN8s+Is1a K5DjVOk5Kjtq0V7msBoxszV+M6kjQuiahzsMl6ltDKU/nbd/BYLCqb2FN+F2E3r8LDsrb XNv3qsgFBLwTGp8OwxOA/iMifAz7bnIXGDMWd1bXxTttPPylF8IkW775CtBQc2tCPUv/b ttlWnNbvQLFkdzjOsOl/gyRVbRqKsDOJivJuGQhgUtljjpWOi8dgAXnw2JN7G75M8AA== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794590864; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=cMCEd3yhh/sGU2c7VF807SrP09Byz5Yucu+Bx/Sh0qU=; b=bdTJTL52IN0JfvbOC3VBt2OArAQyD1DDIHc6oCuYkON4cDco58/JC9K/+GlP3x5stNIE 5l5SWLk8Dmr2iOHmc9EB88UAbwCup8ujxtbb/GQKzBvRFQn8l7X9m+P6YRQvnB4uWY++T OnHXbZ9x45+/V9oMF84p5A4P1o401NTLUau1Vo35XfkD8GsiMYEsmLZt0tdbtOg7Y3ZGJ BT3Tx9JdlJcxfxq3I7iVSNctcsQpoI4mPp6SU0gerCP+RrzQzfyOxKTts7MK7rATCpN8Q VZ7jOvk5fG6yWaoZAXjQBN0b3Q6io2gNadUL/X0ZHs70v1umQT3g2JE9GSPY2Dg/NRA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=Oyw4XVYs; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4ADA4606D49D; Fri, 13 Nov 2026 17:27:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=Oyw4XVYs Received: by smtp.kernel.org (Postfix) with ESMTPSA id E9BD01F000C4; Fri, 13 Nov 2026 17:27:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1794590864; bh=cMCEd3yhh/sGU2c7VF807SrP09Byz5Yucu+Bx/Sh0qU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Oyw4XVYsSDFMm0cd20KY3pybuSdv/JVNSLNBWqo6C++LPbGpCYqF2LBg9kNd5IFIA mZ/wcDw9opFcnTwXDldan4LSneLB6mRypOsWTpWqwoNl1H/uLqofeD0wJabQo4prUh JKyOFE6Xv6JXE1kxJA9K0girvu8FAvPU60qU57Eo= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Christian Loehle , Sumit Gupta , "Rafael J. Wysocki" , Sasha Levin Subject: [PATCH 6.12 063/670] ACPI: CPPC: Validate FFH register fields before hardware access Date: Fri, 13 Nov 2026 10:43:47 -0500 Message-ID: <20261113153813.645630683@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261113153811.177190860@linuxfoundation.org> References: <20261113153811.177190860@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: patches@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Christian Loehle commit 6b016c5c96448c0a5f09328d37f66562d154a5e5 upstream. The x86 CPPC FFH accessors construct masks and shift values using the firmware's Bit Width and Bit Offset without checking that the field fits in an MSR. A zero-width field or a field extending beyond bit 63 can therefore cause an invalid shift. The safe MSR accessors only handle an access fault, not invalid field arithmetic after a successful read. Also, the 64-bit GAS address is implicitly narrowed to the 32-bit MSR number. A descriptor with nonzero upper address bits can access a different MSR from the one described by firmware. The arm64 AMU counter readers have the same unchecked field arithmetic. Validate the field bounds before reading a counter, including both descriptors in the paired counter path. Dispatch FFH accesses before decoding the GAS Access Size in the common read and write paths. Otherwise, a large access_width can trigger an invalid shift in GET_BIT_WIDTH() before the architecture validates its register. That field has architecture-specific FFH semantics and is not needed by the generic memory/port accessor on this path. Validate x86 MSR addresses and share the field-bounds checks between related accessors within each architecture. Fixes: a6cbcdd5ab5f ("ACPI / CPPC: Add support for functional fixed hardware address") Fixes: 68c5debcc06d ("arm64: implement CPPC FFH support using AMUs") Fixes: f489c948028b ("ACPI: CPPC: Fix access width used for PCC registers") Cc: All applicable Signed-off-by: Christian Loehle Tested-by: Sumit Gupta Link: https://patch.msgid.link/20260916162805.1039247-17-christian.loehle@arm.com Signed-off-by: Rafael J. Wysocki Signed-off-by: Christian Loehle Signed-off-by: Sasha Levin --- arch/arm64/kernel/topology.c | 9 +++++++++ arch/x86/kernel/acpi/cppc.c | 15 +++++++++++++++ drivers/acpi/cppc_acpi.c | 10 ++++++---- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 052e9b9945fea..721df857d7376 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -318,10 +318,19 @@ bool cpc_ffh_supported(void) return true; } +static bool cpc_ffh_reg_valid(const struct cpc_reg *reg) +{ + return reg->bit_width && reg->bit_width <= 64 && + reg->bit_offset <= 64 - reg->bit_width; +} + int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val) { int ret = -EOPNOTSUPP; + if (!cpc_ffh_reg_valid(reg)) + return -EINVAL; + switch ((u64)reg->address) { case 0x0: ret = counters_read_on_cpu(cpu, cpu_read_corecnt, val); diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c index 12fc5f5534052..d9cfed143b797 100644 --- a/arch/x86/kernel/acpi/cppc.c +++ b/arch/x86/kernel/acpi/cppc.c @@ -4,6 +4,8 @@ * Copyright (c) 2016, Intel Corporation. */ +#include + #include #include #include @@ -43,10 +45,20 @@ bool cpc_ffh_supported(void) return true; } +static bool cpc_ffh_reg_valid(const struct cpc_reg *reg) +{ + return reg->address <= U32_MAX && reg->bit_width && + reg->bit_width <= 64 && + reg->bit_offset <= 64 - reg->bit_width; +} + int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val) { int err; + if (!cpc_ffh_reg_valid(reg)) + return -EINVAL; + err = rdmsrl_safe_on_cpu(cpunum, reg->address, val); if (!err) { u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1, @@ -63,6 +75,9 @@ int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val) u64 rd_val; int err; + if (!cpc_ffh_reg_valid(reg)) + return -EINVAL; + err = rdmsrl_safe_on_cpu(cpunum, reg->address, &rd_val); if (!err) { u64 mask = GENMASK_ULL(reg->bit_offset + reg->bit_width - 1, diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 8ad6d12b77727..241083e6d9174 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -1028,6 +1028,9 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) } *val = 0; + if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) + return cpc_read_ffh(cpu, reg, val); + size = GET_BIT_WIDTH(reg); if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { @@ -1054,8 +1057,6 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) } else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) vaddr = reg_res->sys_mem_vaddr; - else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) - return cpc_read_ffh(cpu, reg, val); else return acpi_os_read_memory((acpi_physical_address)reg->address, val, size); @@ -1101,6 +1102,9 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) struct cpc_desc *cpc_desc; unsigned long flags; + if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) + return cpc_write_ffh(cpu, reg, val); + size = GET_BIT_WIDTH(reg); if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { @@ -1125,8 +1129,6 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) } else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) vaddr = reg_res->sys_mem_vaddr; - else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) - return cpc_write_ffh(cpu, reg, val); else return acpi_os_write_memory((acpi_physical_address)reg->address, val, size); -- 2.53.0