[PATCH v4 1/4] cacheinfo: Check for null last-level cache info

From: Ricardo Neri
Date: Tue Dec 12 2023 - 17:23:41 EST


Before determining the validity of the last-level cache info, ensure that
it has been allocated. Simply checking for non-zero cache_leaves() is not
sufficient, as some architectures (e.g., Intel processors) have non-zero
cache_leaves() before allocation.

Dereferencing NULL cacheinfo can occur in update_per_cpu_data_slice_size().
This function iterates over all online CPUs. However, a CPU may have come
online recently, but its cacheinfo may not have been allocated yet.

Cc: Andreas Herrmann <aherrmann@xxxxxxxx>
Cc: Catalin Marinas <catalin.marinas@xxxxxxx>
Cc: Chen Yu <yu.c.chen@xxxxxxxxx>
Cc: Huang Ying <ying.huang@xxxxxxxxx>
Cc: Len Brown <len.brown@xxxxxxxxx>
Cc: Radu Rendec <rrendec@xxxxxxxxxx>
Cc: Pierre Gondois <Pierre.Gondois@xxxxxxx>
Cc: Pu Wen <puwen@xxxxxxxx>
Cc: "Rafael J. Wysocki" <rafael.j.wysocki@xxxxxxxxx>
Cc: Sudeep Holla <sudeep.holla@xxxxxxx>
Cc: Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxxxxxxxx>
Cc: Will Deacon <will@xxxxxxxxxx>
Cc: Zhang Rui <rui.zhang@xxxxxxxxx>
Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@xxxxxxxxxxxxxxx>
---
Changes since v3:
* Introduced this patch.

Changes since v2:
* N/A

Changes since v1:
* N/A
---

The dereference of a NULL cacheinfo is not observed today because
cache_leaves(cpu) is zero until after init_cache_level() is called
(during the CPU hotplug callback). A subsequent changeset will set
the number of cache leaves earlier and the NULL-pointer dereference
will be observed.
---
drivers/base/cacheinfo.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index f1e79263fe61..967c5cf3fb1d 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -61,6 +61,9 @@ bool last_level_cache_is_valid(unsigned int cpu)
if (!cache_leaves(cpu))
return false;

+ if (!per_cpu_cacheinfo(cpu))
+ return false;
+
llc = per_cpu_cacheinfo_idx(cpu, cache_leaves(cpu) - 1);

return (llc->attributes & CACHE_ID) || !!llc->fw_token;
--
2.25.1