Commit abd1ec4efd82ca06127bce833ad8a4bbec8a0dcb

Authored by Jeff Layton
Committed by J. Bruce Fields
1 parent a75c5d01e4

lockd: close potential race with rapid lockd_up/lockd_down cycle

If lockd_down is called very rapidly after lockd_up returns, then
there is a slim chance that lockd() will never be called. kthread()
will return before calling the function, so we'll end up never
actually calling the cleanup functions for the thread.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>

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

... ... @@ -50,7 +50,7 @@
50 50 static DEFINE_MUTEX(nlmsvc_mutex);
51 51 static unsigned int nlmsvc_users;
52 52 static struct task_struct *nlmsvc_task;
53   -static struct svc_serv *nlmsvc_serv;
  53 +static struct svc_rqst *nlmsvc_rqst;
54 54 int nlmsvc_grace_period;
55 55 unsigned long nlmsvc_timeout;
56 56  
57 57  
58 58  
... ... @@ -194,20 +194,11 @@
194 194  
195 195 svc_process(rqstp);
196 196 }
197   -
198 197 flush_signals(current);
199 198 if (nlmsvc_ops)
200 199 nlmsvc_invalidate_all();
201 200 nlm_shutdown_hosts();
202   -
203 201 unlock_kernel();
204   -
205   - nlmsvc_task = NULL;
206   - nlmsvc_serv = NULL;
207   -
208   - /* Exit the RPC thread */
209   - svc_exit_thread(rqstp);
210   -
211 202 return 0;
212 203 }
213 204  
214 205  
215 206  
... ... @@ -254,16 +245,15 @@
254 245 lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
255 246 {
256 247 struct svc_serv *serv;
257   - struct svc_rqst *rqstp;
258 248 int error = 0;
259 249  
260 250 mutex_lock(&nlmsvc_mutex);
261 251 /*
262 252 * Check whether we're already up and running.
263 253 */
264   - if (nlmsvc_serv) {
  254 + if (nlmsvc_rqst) {
265 255 if (proto)
266   - error = make_socks(nlmsvc_serv, proto);
  256 + error = make_socks(nlmsvc_rqst->rq_server, proto);
267 257 goto out;
268 258 }
269 259  
... ... @@ -288,9 +278,10 @@
288 278 /*
289 279 * Create the kernel thread and wait for it to start.
290 280 */
291   - rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
292   - if (IS_ERR(rqstp)) {
293   - error = PTR_ERR(rqstp);
  281 + nlmsvc_rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
  282 + if (IS_ERR(nlmsvc_rqst)) {
  283 + error = PTR_ERR(nlmsvc_rqst);
  284 + nlmsvc_rqst = NULL;
294 285 printk(KERN_WARNING
295 286 "lockd_up: svc_rqst allocation failed, error=%d\n",
296 287 error);
297 288  
298 289  
299 290  
300 291  
... ... @@ -298,16 +289,15 @@
298 289 }
299 290  
300 291 svc_sock_update_bufs(serv);
301   - nlmsvc_serv = rqstp->rq_server;
302 292  
303   - nlmsvc_task = kthread_run(lockd, rqstp, serv->sv_name);
  293 + nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, serv->sv_name);
304 294 if (IS_ERR(nlmsvc_task)) {
305 295 error = PTR_ERR(nlmsvc_task);
  296 + svc_exit_thread(nlmsvc_rqst);
306 297 nlmsvc_task = NULL;
307   - nlmsvc_serv = NULL;
  298 + nlmsvc_rqst = NULL;
308 299 printk(KERN_WARNING
309 300 "lockd_up: kthread_run failed, error=%d\n", error);
310   - svc_exit_thread(rqstp);
311 301 goto destroy_and_out;
312 302 }
313 303  
... ... @@ -346,6 +336,9 @@
346 336 BUG();
347 337 }
348 338 kthread_stop(nlmsvc_task);
  339 + svc_exit_thread(nlmsvc_rqst);
  340 + nlmsvc_task = NULL;
  341 + nlmsvc_rqst = NULL;
349 342 out:
350 343 mutex_unlock(&nlmsvc_mutex);
351 344 }