Commit 4ac63ad6c52e9cdefbcb54ec4575ab12b78b49d9

Authored by Pavel Emelyanov
Committed by David S. Miller
1 parent a014bc8f0f

[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: Pavel Emelyanov <xemul@openvz.org>
Acked-by: Simon Horman <horms@verge.net.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 14 additions and 13 deletions Side-by-side Diff

net/ipv4/ipvs/ip_vs_sched.c
... ... @@ -183,19 +183,6 @@
183 183 /* increase the module use count */
184 184 ip_vs_use_count_inc();
185 185  
186   - /*
187   - * Make sure that the scheduler with this name doesn't exist
188   - * in the scheduler list.
189   - */
190   - sched = ip_vs_sched_getbyname(scheduler->name);
191   - if (sched) {
192   - ip_vs_scheduler_put(sched);
193   - ip_vs_use_count_dec();
194   - IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
195   - "already existed in the system\n", scheduler->name);
196   - return -EINVAL;
197   - }
198   -
199 186 write_lock_bh(&__ip_vs_sched_lock);
200 187  
201 188 if (scheduler->n_list.next != &scheduler->n_list) {
... ... @@ -206,6 +193,20 @@
206 193 return -EINVAL;
207 194 }
208 195  
  196 + /*
  197 + * Make sure that the scheduler with this name doesn't exist
  198 + * in the scheduler list.
  199 + */
  200 + list_for_each_entry(sched, &ip_vs_schedulers, n_list) {
  201 + if (strcmp(scheduler->name, sched->name) == 0) {
  202 + write_unlock_bh(&__ip_vs_sched_lock);
  203 + ip_vs_use_count_dec();
  204 + IP_VS_ERR("register_ip_vs_scheduler(): [%s] scheduler "
  205 + "already existed in the system\n",
  206 + scheduler->name);
  207 + return -EINVAL;
  208 + }
  209 + }
209 210 /*
210 211 * Add it into the d-linked scheduler list
211 212 */