Author: rmacklem
Date: Wed Jun 17 22:50:26 2009
New Revision: 194407
URL: http://svn.freebsd.org/changeset/base/194407

Log:
  Since svc_[dg|vc|tli|tp]_create() did not hold a reference count on the
  SVCXPTR structure returned by them, it was possible for the structure
  to be free'd before svc_reg() had been completed using the structure.
  This patch acquires a reference count on the newly created structure
  that is returned by svc_[dg|vc|tli|tp]_create(). It also
  adds the appropriate SVC_RELEASE() calls to the callers, except the
  experimental nfs subsystem. The latter will be committed separately.
  
  Submitted by: dfr
  Tested by:    pho
  Approved by:  kib (mentor)

Modified:
  head/sys/nfsserver/nfs_srvkrpc.c
  head/sys/nlm/nlm_prot_impl.c
  head/sys/rpc/svc.c
  head/sys/rpc/svc_generic.c
  head/sys/rpc/svc_vc.c

Modified: head/sys/nfsserver/nfs_srvkrpc.c
==============================================================================
--- head/sys/nfsserver/nfs_srvkrpc.c    Wed Jun 17 21:58:32 2009        
(r194406)
+++ head/sys/nfsserver/nfs_srvkrpc.c    Wed Jun 17 22:50:26 2009        
(r194407)
@@ -467,6 +467,7 @@ nfssvc_addsock(struct file *fp, struct t
                fp->f_data = NULL;
                svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, NULL);
                svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, NULL);
+               SVC_RELEASE(xprt);
        }
 
        return (0);

Modified: head/sys/nlm/nlm_prot_impl.c
==============================================================================
--- head/sys/nlm/nlm_prot_impl.c        Wed Jun 17 21:58:32 2009        
(r194406)
+++ head/sys/nlm/nlm_prot_impl.c        Wed Jun 17 22:50:26 2009        
(r194407)
@@ -1389,7 +1389,7 @@ nlm_register_services(SVCPOOL *pool, int
                return (EINVAL);
        }
 
-       xprts = malloc(addr_count * sizeof(SVCXPRT *), M_NLM, M_WAITOK);
+       xprts = malloc(addr_count * sizeof(SVCXPRT *), M_NLM, M_WAITOK|M_ZERO);
        for (i = 0; i < version_count; i++) {
                for (j = 0; j < addr_count; j++) {
                        /*
@@ -1447,6 +1447,10 @@ nlm_register_services(SVCPOOL *pool, int
        }
        error = 0;
 out:
+       for (j = 0; j < addr_count; j++) {
+               if (xprts[j])
+                       SVC_RELEASE(xprts[j]);
+       }
        free(xprts, M_NLM);
        return (error);
 }

Modified: head/sys/rpc/svc.c
==============================================================================
--- head/sys/rpc/svc.c  Wed Jun 17 21:58:32 2009        (r194406)
+++ head/sys/rpc/svc.c  Wed Jun 17 22:50:26 2009        (r194407)
@@ -276,6 +276,7 @@ xprt_register(SVCXPRT *xprt)
 {
        SVCPOOL *pool = xprt->xp_pool;
 
+       SVC_ACQUIRE(xprt);
        mtx_lock(&pool->sp_lock);
        xprt->xp_registered = TRUE;
        xprt->xp_active = FALSE;

Modified: head/sys/rpc/svc_generic.c
==============================================================================
--- head/sys/rpc/svc_generic.c  Wed Jun 17 21:58:32 2009        (r194406)
+++ head/sys/rpc/svc_generic.c  Wed Jun 17 22:50:26 2009        (r194407)
@@ -120,8 +120,10 @@ svc_create(
                        /* It was not found. Now create a new one */
                        xprt = svc_tp_create(pool, dispatch, prognum, versnum,
                            NULL, nconf);
-                       if (xprt)
+                       if (xprt) {
                                num++;
+                               SVC_RELEASE(xprt);
+                       }
                }
        }
        __rpc_endconf(handle);
@@ -179,6 +181,7 @@ svc_tp_create(
                                (unsigned)prognum, (unsigned)versnum,
                                nconf->nc_netid);
                xprt_unregister(xprt);
+               SVC_RELEASE(xprt);
                return (NULL);
        }
        return (xprt);

Modified: head/sys/rpc/svc_vc.c
==============================================================================
--- head/sys/rpc/svc_vc.c       Wed Jun 17 21:58:32 2009        (r194406)
+++ head/sys/rpc/svc_vc.c       Wed Jun 17 22:50:26 2009        (r194407)
@@ -324,6 +324,7 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, st
        struct socket *so = NULL;
        struct sockaddr *sa = NULL;
        int error;
+       SVCXPRT *new_xprt;
 
        /*
         * The socket upcall calls xprt_active() which will eventually
@@ -383,10 +384,14 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, st
 
        /*
         * svc_vc_create_conn will call xprt_register - we don't need
-        * to do anything with the new connection.
+        * to do anything with the new connection except derefence it.
         */
-       if (!svc_vc_create_conn(xprt->xp_pool, so, sa))
+       new_xprt = svc_vc_create_conn(xprt->xp_pool, so, sa);
+       if (!new_xprt) {
                soclose(so);
+       } else {
+               SVC_RELEASE(new_xprt);
+       }
 
        free(sa, M_SONAME);
 
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to