summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorKarl Mehltretter <kmehltretter@gmail.com>2026-09-10 22:52:34 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2026-10-22 21:09:52 +0200
commit6c7a7007c5b7566fba4fbee1d40011fb8f833dc3 (patch)
treeb9fe832e944478371cc46962ef2d29b88ae104b2 /kernel
parent7be4bc52fd9e0e55dc9a2e0232b89427d2c4b614 (diff)
PM: EM: allocate the cpumask for every perf domain
em_create_pd() allocates space for the trailing cpus[] flexible array only for CPU devices. A performance domain registered for another device therefore has no storage for its cpumask. All performance domains are added to em_pd_list. The netlink interface does not distinguish CPU and non-CPU domains when it calls cpumask_weight() or iterates over pd->cpus. A request for a non-CPU domain reads cpumask_size() bytes beyond the allocation and can report bits from the following memory as CPU attributes. KASAN reports slab-out-of-bounds reads for both dump and by-ID requests against a synthetic non-CPU performance domain. GET_PERF_DOMAINS does not require GENL_ADMIN_PERM, so an unprivileged request can reach this path when a GPU or another devfreq device has registered an energy model. Allocate the cpumask for non-CPU domains too. The zeroed mask remains empty, as required for the documented unused field. Fixes: d8eef0453132 ("PM: EM: Implement em_nl_get_pds_doit()") Cc: All Applicable <stable@vger.kernel.org> Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com> Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> Link: https://patch.msgid.link/20260910205234.5392-1-kmehltretter@gmail.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/energy_model.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index a76089e2ce8c..d19a65461ae8 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -439,7 +439,9 @@ static int em_create_pd(struct device *dev, int nr_states,
cpumask_copy(em_span_cpus(pd), cpus);
} else {
- pd = kzalloc_obj(*pd);
+ /* Readers expect pd->cpus to exist and remain empty. */
+ pd = kzalloc_flex(*pd, cpus,
+ BITS_TO_LONGS(large_cpumask_bits));
if (!pd)
return -ENOMEM;
}