Commit 4ac63ad6 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by David S. Miller

[IPVS]: Fix sched registration race when checking for name collision.

The register_ip_vs_scheduler() checks for the scheduler with the
same name under the read-locked __ip_vs_sched_lock, then drops,
takes it for writing and puts the scheduler in list.

This is racy, since we can have a race window between the lock
being re-locked for writing.

The fix is to search the scheduler with the given name right under
the write-locked __ip_vs_sched_lock.
Signed-off-by: default avatarPavel Emelyanov <xemul@openvz.org>
Acked-by: default avatarSimon Horman <horms@verge.net.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a014bc8f
...@@ -183,19 +183,6 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) ...@@ -183,19 +183,6 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
/* increase the module use count */ /* increase the module use count */
ip_vs_use_count_inc(); ip_vs_use_count_inc();
/*
* Make sure that the scheduler with this name doesn't exist
* in the scheduler list.
*/
sched = ip_vs_sched_getbyname(scheduler->name);
if (sched) {
ip_vs_scheduler_put(sched);
ip_vs_use_count_dec();
IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
"already existed in the system\n", scheduler->name);
return -EINVAL;
}
write_lock_bh(&__ip_vs_sched_lock); write_lock_bh(&__ip_vs_sched_lock);
if (scheduler->n_list.next != &scheduler->n_list) { if (scheduler->n_list.next != &scheduler->n_list) {
...@@ -206,6 +193,20 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) ...@@ -206,6 +193,20 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
return -EINVAL; return -EINVAL;
} }
/*
* Make sure that the scheduler with this name doesn't exist
* in the scheduler list.
*/
list_for_each_entry(sched, &ip_vs_schedulers, n_list) {
if (strcmp(scheduler->name, sched->name) == 0) {
write_unlock_bh(&__ip_vs_sched_lock);
ip_vs_use_count_dec();
IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
"already existed in the system\n",
scheduler->name);
return -EINVAL;
}
}
/* /*
* Add it into the d-linked scheduler list * Add it into the d-linked scheduler list
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment