NFSd: set nfsd_serv to NULL after service destruction
authorStanislav Kinsbursky <skinsbursky@parallels.com>
Tue, 3 Jul 2012 12:46:41 +0000 (16:46 +0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 25 Jul 2012 13:21:31 +0000 (09:21 -0400)
In nfsd_destroy():

if (destroy)
svc_shutdown_net(nfsd_serv, net);
svc_destroy(nfsd_server);

svc_shutdown_net(nfsd_serv, net) calls nfsd_last_thread(), which sets
nfsd_serv to NULL, causing a NULL dereference on the following line.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfsd.h
fs/nfsd/nfssvc.c

index 7b248a24d5c5271a5a022c8b07314ed6e7bcc105..2244222368ab29cf4681d0d94012055bc5861f02 100644 (file)
@@ -82,6 +82,8 @@ static inline void nfsd_destroy(struct net *net)
        if (destroy)
                svc_shutdown_net(nfsd_serv, net);
        svc_destroy(nfsd_serv);
+       if (destroy)
+               nfsd_serv = NULL;
 }
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
index 8621e36ce8dd125e26958fe84a6df91a3d2db97b..240473cb708ff8a726d2b881d9d7ec2b42339653 100644 (file)
@@ -254,8 +254,6 @@ static void nfsd_shutdown(void)
 
 static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
 {
-       /* When last nfsd thread exits we need to do some clean-up */
-       nfsd_serv = NULL;
        nfsd_shutdown();
 
        svc_rpcb_cleanup(serv, net);
@@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize(void)
 int nfsd_create_serv(void)
 {
        int error;
+       struct net *net = current->nsproxy->net_ns;
 
        WARN_ON(!mutex_is_locked(&nfsd_mutex));
        if (nfsd_serv) {
@@ -346,7 +345,7 @@ int nfsd_create_serv(void)
        if (nfsd_serv == NULL)
                return -ENOMEM;
 
-       error = svc_bind(nfsd_serv, current->nsproxy->net_ns);
+       error = svc_bind(nfsd_serv, net);
        if (error < 0) {
                svc_destroy(nfsd_serv);
                return error;
@@ -557,12 +556,13 @@ nfsd(void *vrqstp)
        nfsdstats.th_cnt --;
 
 out:
-       if (rqstp->rq_server->sv_nrthreads == 1)
-               svc_shutdown_net(rqstp->rq_server, &init_net);
+       rqstp->rq_server = NULL;
 
        /* Release the thread */
        svc_exit_thread(rqstp);
 
+       nfsd_destroy(&init_net);
+
        /* Release module */
        mutex_unlock(&nfsd_mutex);
        module_put_and_exit(0);