瀏覽代碼

padata: Allocate cpumask dependend recources in any case

The cpumask separation work assumes the cpumask dependend recources
present regardless of valid or invalid cpumasks. With this patch
we allocate the cpumask dependend recources in any case. This fixes
two NULL pointer dereference crashes in padata_replace and in
padata_get_cpumask.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Steffen Klassert 15 年之前
父節點
當前提交
b89661dff5
共有 1 個文件被更改,包括 7 次插入17 次删除
  1. 7 17
      kernel/padata.c

+ 7 - 17
kernel/padata.c

@@ -417,7 +417,7 @@ static void padata_init_pqueues(struct parallel_data *pd)
 	}
 	}
 
 
 	num_cpus = cpumask_weight(pd->cpumask.pcpu);
 	num_cpus = cpumask_weight(pd->cpumask.pcpu);
-	pd->max_seq_nr = (MAX_SEQ_NR / num_cpus) * num_cpus - 1;
+	pd->max_seq_nr = num_cpus ? (MAX_SEQ_NR / num_cpus) * num_cpus - 1 : 0;
 }
 }
 
 
 /* Allocate and initialize the internal cpumask dependend resources. */
 /* Allocate and initialize the internal cpumask dependend resources. */
@@ -527,21 +527,19 @@ static void padata_replace(struct padata_instance *pinst,
 	rcu_assign_pointer(pinst->pd, pd_new);
 	rcu_assign_pointer(pinst->pd, pd_new);
 
 
 	synchronize_rcu();
 	synchronize_rcu();
-	if (!pd_old)
-		goto out;
 
 
-	padata_flush_queues(pd_old);
 	if (!cpumask_equal(pd_old->cpumask.pcpu, pd_new->cpumask.pcpu))
 	if (!cpumask_equal(pd_old->cpumask.pcpu, pd_new->cpumask.pcpu))
 		notification_mask |= PADATA_CPU_PARALLEL;
 		notification_mask |= PADATA_CPU_PARALLEL;
 	if (!cpumask_equal(pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu))
 	if (!cpumask_equal(pd_old->cpumask.cbcpu, pd_new->cpumask.cbcpu))
 		notification_mask |= PADATA_CPU_SERIAL;
 		notification_mask |= PADATA_CPU_SERIAL;
 
 
+	padata_flush_queues(pd_old);
 	padata_free_pd(pd_old);
 	padata_free_pd(pd_old);
+
 	if (notification_mask)
 	if (notification_mask)
 		blocking_notifier_call_chain(&pinst->cpumask_change_notifier,
 		blocking_notifier_call_chain(&pinst->cpumask_change_notifier,
 					     notification_mask, pinst);
 					     notification_mask, pinst);
 
 
-out:
 	pinst->flags &= ~PADATA_RESET;
 	pinst->flags &= ~PADATA_RESET;
 }
 }
 
 
@@ -673,6 +671,7 @@ int __padata_set_cpumasks(struct padata_instance *pinst,
 	struct parallel_data *pd = NULL;
 	struct parallel_data *pd = NULL;
 
 
 	mutex_lock(&pinst->lock);
 	mutex_lock(&pinst->lock);
+	get_online_cpus();
 
 
 	valid = padata_validate_cpumask(pinst, pcpumask);
 	valid = padata_validate_cpumask(pinst, pcpumask);
 	if (!valid) {
 	if (!valid) {
@@ -681,20 +680,16 @@ int __padata_set_cpumasks(struct padata_instance *pinst,
 	}
 	}
 
 
 	valid = padata_validate_cpumask(pinst, cbcpumask);
 	valid = padata_validate_cpumask(pinst, cbcpumask);
-	if (!valid) {
+	if (!valid)
 		__padata_stop(pinst);
 		__padata_stop(pinst);
-		goto out_replace;
-	}
-
-	get_online_cpus();
 
 
+out_replace:
 	pd = padata_alloc_pd(pinst, pcpumask, cbcpumask);
 	pd = padata_alloc_pd(pinst, pcpumask, cbcpumask);
 	if (!pd) {
 	if (!pd) {
 		err = -ENOMEM;
 		err = -ENOMEM;
 		goto out;
 		goto out;
 	}
 	}
 
 
-out_replace:
 	cpumask_copy(pinst->cpumask.pcpu, pcpumask);
 	cpumask_copy(pinst->cpumask.pcpu, pcpumask);
 	cpumask_copy(pinst->cpumask.cbcpu, cbcpumask);
 	cpumask_copy(pinst->cpumask.cbcpu, cbcpumask);
 
 
@@ -705,7 +700,6 @@ out_replace:
 
 
 out:
 out:
 	put_online_cpus();
 	put_online_cpus();
-
 	mutex_unlock(&pinst->lock);
 	mutex_unlock(&pinst->lock);
 
 
 	return err;
 	return err;
@@ -776,11 +770,8 @@ static int __padata_remove_cpu(struct padata_instance *pinst, int cpu)
 	if (cpumask_test_cpu(cpu, cpu_online_mask)) {
 	if (cpumask_test_cpu(cpu, cpu_online_mask)) {
 
 
 		if (!padata_validate_cpumask(pinst, pinst->cpumask.pcpu) ||
 		if (!padata_validate_cpumask(pinst, pinst->cpumask.pcpu) ||
-		    !padata_validate_cpumask(pinst, pinst->cpumask.cbcpu)) {
+		    !padata_validate_cpumask(pinst, pinst->cpumask.cbcpu))
 			__padata_stop(pinst);
 			__padata_stop(pinst);
-			padata_replace(pinst, pd);
-			goto out;
-		}
 
 
 		pd = padata_alloc_pd(pinst, pinst->cpumask.pcpu,
 		pd = padata_alloc_pd(pinst, pinst->cpumask.pcpu,
 				     pinst->cpumask.cbcpu);
 				     pinst->cpumask.cbcpu);
@@ -790,7 +781,6 @@ static int __padata_remove_cpu(struct padata_instance *pinst, int cpu)
 		padata_replace(pinst, pd);
 		padata_replace(pinst, pd);
 	}
 	}
 
 
-out:
 	return 0;
 	return 0;
 }
 }