From: Hui Tang tanghui20@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7HFZV CVE: NA
----------------------------------------
There may be NULL pointer derefrence when hotplug running and creating taskgroup concurrently.
sched_autogroup_create_attach -> sched_create_group -> alloc_fair_sched_group -> init_auto_affinity -> init_affinity_domains -> cpumask_copy(xx, sched_domain_span(tmp)) { tmp may be free due rcu lock missing }
{ hotplug will rebuild sched domain } sched_cpu_activate -> build_sched_domains -> cpuset_cpu_active -> partition_sched_domains -> build_sched_domains -> cpu_attach_domain -> destroy_sched_domains -> call_rcu(&sd->rcu, destroy_sched_domains_rcu)
So sd should be protect with rcu lock in entire critical zone.
[ 599.811593] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 600.112821] pc : init_affinity_domains+0xf4/0x200 [ 600.125918] lr : init_affinity_domains+0xd4/0x200 [ 600.331355] Call trace: [ 600.338734] init_affinity_domains+0xf4/0x200 [ 600.347955] init_auto_affinity+0x78/0xc0 [ 600.356622] alloc_fair_sched_group+0xd8/0x210 [ 600.365594] sched_create_group+0x48/0xc0 [ 600.373970] sched_autogroup_create_attach+0x54/0x190 [ 600.383311] ksys_setsid+0x110/0x130 [ 600.391014] __arm64_sys_setsid+0x18/0x24 [ 600.399156] el0_svc_common+0x118/0x170 [ 600.406818] el0_svc_handler+0x3c/0x80 [ 600.414188] el0_svc+0x8/0x640 [ 600.420719] Code: b40002c0 9104e002 f9402061 a9401444 (a9001424) [ 600.430504] SMP: stopping secondary CPUs [ 600.441751] Starting crashdump kernel...
Fixes: 713cfd2684fa ("sched: Introduce smart grid scheduling strategy for cfs") Signed-off-by: Hui Tang tanghui20@huawei.com Reviewed-by: Zhang Qiao zhangqiao22@huawei.com Signed-off-by: Zhang Changzhong zhangchangzhong@huawei.com --- kernel/sched/fair.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index e9eb00e..622d433 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5582,7 +5582,7 @@ void free_affinity_domains(struct affinity_domain *ad) { int i;
- for (i = 0; i < ad->dcount; i++) { + for (i = 0; i < AD_LEVEL_MAX; i++) { kfree(ad->domains[i]); kfree(ad->domains_orig[i]); ad->domains[i] = NULL; @@ -5621,6 +5621,12 @@ static int init_affinity_domains(struct affinity_domain *ad) int i = 0; int cpu;
+ for (i = 0; i < AD_LEVEL_MAX; i++) { + ad->domains[i] = kmalloc(sizeof(cpumask_t), GFP_KERNEL); + if (!ad->domains[i]) + goto err; + } + rcu_read_lock(); cpu = cpumask_first_and(cpu_active_mask, housekeeping_cpumask(HK_FLAG_DOMAIN)); @@ -5629,21 +5635,12 @@ static int init_affinity_domains(struct affinity_domain *ad) dcount++; }
- if (!sd) { + if (!sd || dcount > AD_LEVEL_MAX) { rcu_read_unlock(); - return -EINVAL; - } - rcu_read_unlock(); - - for (i = 0; i < dcount; i++) { - ad->domains[i] = kmalloc(sizeof(cpumask_t), GFP_KERNEL); - if (!ad->domains[i]) { - ad->dcount = i; - goto err; - } + ret = -EINVAL; + goto err; }
- rcu_read_lock(); idlest = sd_find_idlest_group(sd); cpu = group_find_idlest_cpu(idlest); i = 0;