From e930be9630a5b993c0db5a06ef30c28b646c19ee Mon Sep 17 00:00:00 2001 From: Yong-Xuan Wang Date: Sat, 11 Oct 2025 09:12:17 +0800 Subject: [PATCH 1/2] cacheinfo: Fix shared_cpu_map to handle shared caches at different levels stable inclusion from stable-v6.1.18 commit 2f588d0345d69a35e451077afed428fd057a5e34 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICY4B5 CVE: CVE-2023-53254 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2f588d0345d69a35e451077afed428fd057a5e34 -------------------------------- [ Upstream commit 198102c9103fc78d8478495971947af77edb05c1 ] The cacheinfo sets up the shared_cpu_map by checking whether the caches with the same index are shared between CPUs. However, this will trigger slab-out-of-bounds access if the CPUs do not have the same cache hierarchy. Another problem is the mismatched shared_cpu_map when the shared cache does not have the same index between CPUs. CPU0 I D L3 index 0 1 2 x ^ ^ ^ ^ index 0 1 2 3 CPU1 I D L2 L3 This patch checks each cache is shared with all caches on other CPUs. Reviewed-by: Pierre Gondois Signed-off-by: Yong-Xuan Wang Link: https://lore.kernel.org/r/20230117105133.4445-2-yongxuan.wang@sifive.com Signed-off-by: Sudeep Holla Signed-off-by: Sasha Levin Conflicts: drivers/base/cacheinfo.c [conflict due to commit b14e8d21f7 ("cacheinfo: Add helper to access any cache index for a given CPU") is not backport] Signed-off-by: Zhang Qilong --- drivers/base/cacheinfo.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 91a7e2b22e986..0709d03ffe3b5 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -257,7 +257,7 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf, *sib_leaf; - unsigned int index; + unsigned int index, sib_index; int ret = 0; if (this_cpu_ci->cpu_map_populated) @@ -285,10 +285,13 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) if (i == cpu || !sib_cpu_ci->info_list) continue;/* skip if itself or no cacheinfo */ - sib_leaf = sib_cpu_ci->info_list + index; - if (cache_leaves_are_shared(this_leaf, sib_leaf)) { - cpumask_set_cpu(cpu, &sib_leaf->shared_cpu_map); - cpumask_set_cpu(i, &this_leaf->shared_cpu_map); + for (sib_index = 0; sib_index < cache_leaves(i); sib_index++) { + sib_leaf = sib_cpu_ci->info_list + sib_index; + if (cache_leaves_are_shared(this_leaf, sib_leaf)) { + cpumask_set_cpu(cpu, &sib_leaf->shared_cpu_map); + cpumask_set_cpu(i, &this_leaf->shared_cpu_map); + break; + } } } /* record the maximum cache line size */ @@ -303,7 +306,7 @@ static void cache_shared_cpu_map_remove(unsigned int cpu) { struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf, *sib_leaf; - unsigned int sibling, index; + unsigned int sibling, index, sib_index; for (index = 0; index < cache_leaves(cpu); index++) { this_leaf = this_cpu_ci->info_list + index; @@ -317,9 +320,14 @@ static void cache_shared_cpu_map_remove(unsigned int cpu) if (!sib_cpu_ci->info_list) continue; - sib_leaf = sib_cpu_ci->info_list + index; - cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map); - cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map); + for (sib_index = 0; sib_index < cache_leaves(sibling); sib_index++) { + sib_leaf = sib_cpu_ci->info_list + sib_index; + if (cache_leaves_are_shared(this_leaf, sib_leaf)) { + cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map); + cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map); + break; + } + } } if (of_have_populated_dt()) of_node_put(this_leaf->fw_token); -- Gitee From 7d40c980ea2a1b4e8d2d5f9bd89fddcd0571a801 Mon Sep 17 00:00:00 2001 From: K Prateek Nayak Date: Sat, 11 Oct 2025 09:12:42 +0800 Subject: [PATCH 2/2] drivers: base: cacheinfo: Fix shared_cpu_map changes in event of CPU hotplug stable inclusion from stable-v6.1.33 commit 4d776371127ec55590d49eea7579e77f555548ad category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ICY4B5 CVE: CVE-2023-53254 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=4d776371127ec55590d49eea7579e77f555548ad -------------------------------- [ Upstream commit 126310c9f669c9a8c875a3e5c2292299ca90225d ] While building the shared_cpu_map, check if the cache level and cache type matches. On certain systems that build the cache topology based on the instance ID, there are cases where the same ID may repeat across multiple cache levels, leading inaccurate topology. In event of CPU offlining, the cache_shared_cpu_map_remove() does not consider if IDs at same level are being compared. As a result, when same IDs repeat across different cache levels, the CPU going offline is not removed from all the shared_cpu_map. Below is the output of cache topology of CPU8 and it's SMT sibling after CPU8 is offlined on a dual socket 3rd Generation AMD EPYC processor (2 x 64C/128T) running kernel release v6.3: # for i in /sys/devices/system/cpu/cpu8/cache/index*/shared_cpu_list; do echo -n "$i: "; cat $i; done /sys/devices/system/cpu/cpu8/cache/index0/shared_cpu_list: 8,136 /sys/devices/system/cpu/cpu8/cache/index1/shared_cpu_list: 8,136 /sys/devices/system/cpu/cpu8/cache/index2/shared_cpu_list: 8,136 /sys/devices/system/cpu/cpu8/cache/index3/shared_cpu_list: 8-15,136-143 # echo 0 > /sys/devices/system/cpu/cpu8/online # for i in /sys/devices/system/cpu/cpu136/cache/index*/shared_cpu_list; do echo -n "$i: "; cat $i; done /sys/devices/system/cpu/cpu136/cache/index0/shared_cpu_list: 136 /sys/devices/system/cpu/cpu136/cache/index1/shared_cpu_list: 8,136 /sys/devices/system/cpu/cpu136/cache/index2/shared_cpu_list: 8,136 /sys/devices/system/cpu/cpu136/cache/index3/shared_cpu_list: 9-15,136-143 CPU8 is removed from index0 (L1i) but remains in the shared_cpu_list of index1 (L1d) and index2 (L2). Since L1i, L1d, and L2 are shared by the SMT siblings, and they have the same cache instance ID, CPU 2 is only removed from the first index with matching ID which is index1 (L1i) in this case. With this fix, the results are as expected when performing the same experiment on the same system: # for i in /sys/devices/system/cpu/cpu8/cache/index*/shared_cpu_list; do echo -n "$i: "; cat $i; done /sys/devices/system/cpu/cpu8/cache/index0/shared_cpu_list: 8,136 /sys/devices/system/cpu/cpu8/cache/index1/shared_cpu_list: 8,136 /sys/devices/system/cpu/cpu8/cache/index2/shared_cpu_list: 8,136 /sys/devices/system/cpu/cpu8/cache/index3/shared_cpu_list: 8-15,136-143 # echo 0 > /sys/devices/system/cpu/cpu8/online # for i in /sys/devices/system/cpu/cpu136/cache/index*/shared_cpu_list; do echo -n "$i: "; cat $i; done /sys/devices/system/cpu/cpu136/cache/index0/shared_cpu_list: 136 /sys/devices/system/cpu/cpu136/cache/index1/shared_cpu_list: 136 /sys/devices/system/cpu/cpu136/cache/index2/shared_cpu_list: 136 /sys/devices/system/cpu/cpu136/cache/index3/shared_cpu_list: 9-15,136-143 When rebuilding topology, the same problem appears as cache_shared_cpu_map_setup() implements a similar logic. Consider the same 3rd Generation EPYC processor: CPUs in Core 1, that share the L1 and L2 caches, have L1 and L2 instance ID as 1. For all the CPUs on the second chiplet, the L3 ID is also 1 leading to grouping on CPUs from Core 1 (1, 17) and the entire second chiplet (8-15, 24-31) as CPUs sharing one cache domain. This went undetected since x86 processors depended on arch specific populate_cache_leaves() method to repopulate the shared_cpus_map when CPU came back online until kernel release v6.3-rc5. Fixes: 198102c9103f ("cacheinfo: Fix shared_cpu_map to handle shared caches at different levels") Signed-off-by: K Prateek Nayak Reviewed-by: Sudeep Holla Link: https://lore.kernel.org/r/20230508084115.1157-2-kprateek.nayak@amd.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin Conflicts: drivers/base/cacheinfo.c [conflict due to code line difference] Signed-off-by: Zhang Qilong --- drivers/base/cacheinfo.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 0709d03ffe3b5..c415519f8db26 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -287,6 +287,16 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) continue;/* skip if itself or no cacheinfo */ for (sib_index = 0; sib_index < cache_leaves(i); sib_index++) { sib_leaf = sib_cpu_ci->info_list + sib_index; + + /* + * Comparing cache IDs only makes sense if the leaves + * belong to the same cache level of same type. Skip + * the check if level and type do not match. + */ + if (sib_leaf->level != this_leaf->level || + sib_leaf->type != this_leaf->type) + continue; + if (cache_leaves_are_shared(this_leaf, sib_leaf)) { cpumask_set_cpu(cpu, &sib_leaf->shared_cpu_map); cpumask_set_cpu(i, &this_leaf->shared_cpu_map); @@ -322,6 +332,16 @@ static void cache_shared_cpu_map_remove(unsigned int cpu) for (sib_index = 0; sib_index < cache_leaves(sibling); sib_index++) { sib_leaf = sib_cpu_ci->info_list + sib_index; + + /* + * Comparing cache IDs only makes sense if the leaves + * belong to the same cache level of same type. Skip + * the check if level and type do not match. + */ + if (sib_leaf->level != this_leaf->level || + sib_leaf->type != this_leaf->type) + continue; + if (cache_leaves_are_shared(this_leaf, sib_leaf)) { cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map); cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map); -- Gitee