diff options
| author | Karl Mehltretter <kmehltretter@gmail.com> | 2026-09-10 22:52:34 +0200 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2026-10-22 21:09:52 +0200 |
| commit | 6c7a7007c5b7566fba4fbee1d40011fb8f833dc3 (patch) | |
| tree | b9fe832e944478371cc46962ef2d29b88ae104b2 /kernel | |
| parent | 7be4bc52fd9e0e55dc9a2e0232b89427d2c4b614 (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.c | 4 |
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; } |
