Commit 774f8bbd9ef2e71d4ef4b89933d292091d31ca98

Authored by J. Bruce Fields
1 parent 039a87ca53

nfsd: fix startup/shutdown order bug

We must create the server before we can call init_socks or check the
number of threads.

Symptoms were a NULL pointer dereference in nfsd_svc().  Problem
identified by Jeff Layton.

Also fix a minor cleanup-on-error case in nfsd_startup().

Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

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

... ... @@ -204,6 +204,9 @@
204 204 static int nfsd_startup(unsigned short port, int nrservs)
205 205 {
206 206 int ret;
  207 +
  208 + if (nfsd_up)
  209 + return 0;
207 210 /*
208 211 * Readahead param cache - will no-op if it already exists.
209 212 * (Note therefore results will be suboptimal if number of
... ... @@ -217,7 +220,7 @@
217 220 goto out_racache;
218 221 ret = lockd_up();
219 222 if (ret)
220   - return ret;
  223 + goto out_racache;
221 224 ret = nfs4_state_start();
222 225 if (ret)
223 226 goto out_lockd;
... ... @@ -420,7 +423,7 @@
420 423 nfsd_svc(unsigned short port, int nrservs)
421 424 {
422 425 int error;
423   - bool first_thread;
  426 + bool nfsd_up_before;
424 427  
425 428 mutex_lock(&nfsd_mutex);
426 429 dprintk("nfsd: creating service\n");
427 430  
428 431  
429 432  
430 433  
431 434  
... ... @@ -432,29 +435,28 @@
432 435 if (nrservs == 0 && nfsd_serv == NULL)
433 436 goto out;
434 437  
435   - first_thread = (nfsd_serv->sv_nrthreads == 0) && (nrservs != 0);
436   -
437   - if (first_thread) {
438   - error = nfsd_startup(port, nrservs);
439   - if (error)
440   - goto out;
441   - }
442 438 error = nfsd_create_serv();
443 439 if (error)
444   - goto out_shutdown;
445   - error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
  440 + goto out;
  441 +
  442 + nfsd_up_before = nfsd_up;
  443 +
  444 + error = nfsd_startup(port, nrservs);
446 445 if (error)
447 446 goto out_destroy;
  447 + error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
  448 + if (error)
  449 + goto out_shutdown;
448 450 /* We are holding a reference to nfsd_serv which
449 451 * we don't want to count in the return value,
450 452 * so subtract 1
451 453 */
452 454 error = nfsd_serv->sv_nrthreads - 1;
453   -out_destroy:
454   - svc_destroy(nfsd_serv); /* Release server */
455 455 out_shutdown:
456   - if (error < 0 && first_thread)
  456 + if (error < 0 && !nfsd_up_before)
457 457 nfsd_shutdown();
  458 +out_destroy:
  459 + svc_destroy(nfsd_serv); /* Release server */
458 460 out:
459 461 mutex_unlock(&nfsd_mutex);
460 462 return error;