The branch main has been updated by glebius:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=42eec5201ab936f7227950c2c159c02c9cb342d4

commit 42eec5201ab936f7227950c2c159c02c9cb342d4
Author:     Gleb Smirnoff <gleb...@freebsd.org>
AuthorDate: 2025-02-01 01:02:40 +0000
Commit:     Gleb Smirnoff <gleb...@freebsd.org>
CommitDate: 2025-02-01 09:00:27 +0000

    rpcsec_tls/server: use netlink RPC client to talk to rpc.tlsservd(8)
    
    The server part just repeats what had been done to the client.  We trust
    the parallelism of clnt_nl and we pass socket cookie to the daemon, which
    we then expect to see in the rpctls_syscall(RPCTLS_SYSC_SRVSOCKET) to find
    the corresponding socket+xprt.  We reuse the same database that is used
    for clients.
    
    Note 1: this will be optimized further in a separate commit.  This one is
    made intentionally minimal, to ease the review process.
    
    Note 2: this change intentionally ignores aspect of multiple workers of
    rpc.tlsservd(8).  This also will be addressed in a future commit.
    
    Reviewed by:            rmacklem
    Differential Revision:  https://reviews.freebsd.org/D48561
---
 sys/rpc/rpcsec_tls.h             |   3 -
 sys/rpc/rpcsec_tls/rpctls_impl.c | 392 ++++++++++-----------------------------
 sys/rpc/rpcsec_tls/rpctlssd.x    |   5 +-
 3 files changed, 98 insertions(+), 302 deletions(-)

diff --git a/sys/rpc/rpcsec_tls.h b/sys/rpc/rpcsec_tls.h
index 4c4fa20dde31..8207c57d8f7f 100644
--- a/sys/rpc/rpcsec_tls.h
+++ b/sys/rpc/rpcsec_tls.h
@@ -30,10 +30,7 @@
 
 /* Operation values for rpctls syscall. */
 #define        RPCTLS_SYSC_CLSOCKET    2
-#define        RPCTLS_SYSC_SRVSETPATH  4
 #define        RPCTLS_SYSC_SRVSOCKET   5
-#define        RPCTLS_SYSC_SRVSHUTDOWN 6
-#define        RPCTLS_SYSC_SRVSTARTUP  7
 
 /* Max nprocs for SRV startup */
 #define        RPCTLS_SRV_MAXNPROCS    16
diff --git a/sys/rpc/rpcsec_tls/rpctls_impl.c b/sys/rpc/rpcsec_tls/rpctls_impl.c
index 327233f63f1d..7b6406cdcdd3 100644
--- a/sys/rpc/rpcsec_tls/rpctls_impl.c
+++ b/sys/rpc/rpcsec_tls/rpctls_impl.c
@@ -72,25 +72,21 @@ static struct syscall_helper_data rpctls_syscalls[] = {
        SYSCALL_INIT_LAST
 };
 
-static struct mtx      rpctls_connect_lock;
-static struct mtx      rpctls_server_lock;
 static struct opaque_auth rpctls_null_verf;
 
 KRPC_VNET_DECLARE(uint64_t, svc_vc_tls_handshake_success);
 KRPC_VNET_DECLARE(uint64_t, svc_vc_tls_handshake_failed);
 
 KRPC_VNET_DEFINE_STATIC(CLIENT *, rpctls_connect_handle);
-KRPC_VNET_DEFINE_STATIC(CLIENT **, rpctls_server_handle);
-KRPC_VNET_DEFINE_STATIC(struct socket *, rpctls_server_so) = NULL;
-KRPC_VNET_DEFINE_STATIC(SVCXPRT *, rpctls_server_xprt) = NULL;
-KRPC_VNET_DEFINE_STATIC(bool, rpctls_srv_newdaemon) = false;
-KRPC_VNET_DEFINE_STATIC(int, rpctls_srv_prevproc) = 0;
-KRPC_VNET_DEFINE_STATIC(bool *, rpctls_server_busy);
+KRPC_VNET_DEFINE_STATIC(CLIENT *, rpctls_server_handle);
 
 struct upsock {
        RB_ENTRY(upsock) tree;
        struct socket *so;
-       CLIENT *cl;
+       union {
+               CLIENT *cl;
+               SVCXPRT *xp;
+       };
 };
 
 static RB_HEAD(upsock_t, upsock) upcall_sockets;
@@ -100,27 +96,20 @@ upsock_compare(const struct upsock *a, const struct upsock 
*b)
        return ((intptr_t)((uintptr_t)a->so/2 - (uintptr_t)b->so/2));
 }
 RB_GENERATE_STATIC(upsock_t, upsock, tree, upsock_compare);
+static struct mtx rpctls_lock;
 
-static CLIENT          *rpctls_server_client(int procpos);
 static enum clnt_stat  rpctls_server(SVCXPRT *xprt, struct socket *so,
                            uint32_t *flags, uint64_t *sslp,
                            uid_t *uid, int *ngrps, gid_t **gids,
                            int *procposp);
 
-static void
-rpctls_vnetinit(const void *unused __unused)
+static CLIENT *
+rpctls_client_nl_create(const char *group, const rpcprog_t program,
+    const rpcvers_t version)
 {
        CLIENT *cl;
-       int i;
 
-       KRPC_VNET(rpctls_server_handle) = malloc(sizeof(CLIENT *) *
-           RPCTLS_SRV_MAXNPROCS, M_RPC, M_WAITOK | M_ZERO);
-       KRPC_VNET(rpctls_server_busy) = malloc(sizeof(bool) *
-           RPCTLS_SRV_MAXNPROCS, M_RPC, M_WAITOK | M_ZERO);
-       for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++)
-               KRPC_VNET(rpctls_server_busy)[i] = false;
-
-       cl = client_nl_create("tlsclnt", RPCTLSCD, RPCTLSCDVERS);
+       cl = client_nl_create(group, program, version);
        KASSERT(cl, ("%s: netlink client already exist", __func__));
        /*
         * Set the try_count to 1 so that no retries of the RPC occur.  Since
@@ -133,8 +122,19 @@ rpctls_vnetinit(const void *unused __unused)
         */
        clnt_control(cl, CLSET_RETRIES, &(int){1});
        clnt_control(cl, CLSET_TIMEOUT, &(struct timeval){.tv_sec = 15});
-       clnt_control(cl, CLSET_WAITCHAN, "tlsclntd");
-       KRPC_VNET(rpctls_connect_handle) = cl;
+       clnt_control(cl, CLSET_WAITCHAN, __DECONST(char *, group));
+
+       return (cl);
+}
+
+static void
+rpctls_vnetinit(const void *unused __unused)
+{
+
+       KRPC_VNET(rpctls_connect_handle) =
+           rpctls_client_nl_create("tlsclnt", RPCTLSCD, RPCTLSCDVERS);
+       KRPC_VNET(rpctls_server_handle) =
+           rpctls_client_nl_create("tlsserv", RPCTLSSD, RPCTLSSDVERS);
 }
 VNET_SYSINIT(rpctls_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY,
     rpctls_vnetinit, NULL);
@@ -143,8 +143,8 @@ static void
 rpctls_cleanup(void *unused __unused)
 {
 
-       free(KRPC_VNET(rpctls_server_handle), M_RPC);
-       free(KRPC_VNET(rpctls_server_busy), M_RPC);
+       clnt_destroy(KRPC_VNET(rpctls_connect_handle));
+       clnt_destroy(KRPC_VNET(rpctls_server_handle));
 }
 VNET_SYSUNINIT(rpctls_cleanup, SI_SUB_VNET_DONE, SI_ORDER_ANY,
     rpctls_cleanup, NULL);
@@ -159,10 +159,7 @@ rpctls_init(void)
                printf("rpctls_init: cannot register syscall\n");
                return (error);
        }
-       mtx_init(&rpctls_connect_lock, "rpctls_connect_lock", NULL,
-           MTX_DEF);
-       mtx_init(&rpctls_server_lock, "rpctls_server_lock", NULL,
-           MTX_DEF);
+       mtx_init(&rpctls_lock, "rpctls lock", NULL, MTX_DEF);
        rpctls_null_verf.oa_flavor = AUTH_NULL;
        rpctls_null_verf.oa_base = RPCTLS_START_STRING;
        rpctls_null_verf.oa_length = strlen(RPCTLS_START_STRING);
@@ -172,20 +169,10 @@ rpctls_init(void)
 int
 sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap)
 {
-        struct sockaddr_un sun;
-        struct netconfig *nconf;
        struct file *fp;
-       struct socket *so;
        struct upsock *ups;
-       SVCXPRT *xprt;
-       char path[MAXPATHLEN];
-       int fd = -1, error, i, try_count;
-       CLIENT *cl, *oldcl[RPCTLS_SRV_MAXNPROCS];
+       int fd = -1, error;
        uint64_t ssl[3];
-       struct timeval timeo;
-#ifdef KERN_TLS
-       u_int maxlen;
-#endif
         
        error = priv_check(td, PRIV_NFS_DAEMON);
        if (error != 0)
@@ -193,183 +180,48 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
 
        KRPC_CURVNET_SET(KRPC_TD_TO_VNET(td));
        switch (uap->op) {
-       case RPCTLS_SYSC_SRVSTARTUP:
-               if (jailed(curthread->td_ucred) &&
-                   !prison_check_nfsd(curthread->td_ucred))
-                       error = EPERM;
-               if (error == 0) {
-                       /* Get rid of all old CLIENTs. */
-                       mtx_lock(&rpctls_server_lock);
-                       for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                               oldcl[i] = KRPC_VNET(rpctls_server_handle)[i];
-                               KRPC_VNET(rpctls_server_handle)[i] = NULL;
-                               KRPC_VNET(rpctls_server_busy)[i] = false;
-                       }
-                       KRPC_VNET(rpctls_srv_newdaemon) = true;
-                       KRPC_VNET(rpctls_srv_prevproc) = 0;
-                       mtx_unlock(&rpctls_server_lock);
-                       for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                               if (oldcl[i] != NULL) {
-                                       CLNT_CLOSE(oldcl[i]);
-                                       CLNT_RELEASE(oldcl[i]);
-                               }
-                       }
-               }
-               break;
-       case RPCTLS_SYSC_SRVSETPATH:
-               if (jailed(curthread->td_ucred) &&
-                   !prison_check_nfsd(curthread->td_ucred))
-                       error = EPERM;
-               if (error == 0)
-                       error = copyinstr(uap->path, path, sizeof(path), NULL);
-               if (error == 0) {
-                       error = ENXIO;
-#ifdef KERN_TLS
-                       if (rpctls_getinfo(&maxlen, false, false))
-                               error = 0;
-#endif
-               }
-               if (error == 0 && (strlen(path) + 1 > sizeof(sun.sun_path) ||
-                   strlen(path) == 0))
-                       error = EINVAL;
-       
-               cl = NULL;
-               if (error == 0) {
-                       sun.sun_family = AF_LOCAL;
-                       strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
-                       sun.sun_len = SUN_LEN(&sun);
-                       
-                       nconf = getnetconfigent("local");
-                       cl = clnt_reconnect_create(nconf,
-                           (struct sockaddr *)&sun, RPCTLSSD, RPCTLSSDVERS,
-                           RPC_MAXDATASIZE, RPC_MAXDATASIZE);
-                       /*
-                        * The number of retries defaults to INT_MAX, which
-                        * effectively means an infinite, uninterruptable loop. 
-                        * Set the try_count to 1 so that no retries of the
-                        * RPC occur.  Since it is an upcall to a local daemon,
-                        * requests should not be lost and doing one of these
-                        * RPCs multiple times is not correct.
-                        * Set a timeout (currently 15sec) and assume that
-                        * the daemon is hung if a timeout occurs.
-                        */
-                       if (cl != NULL) {
-                               try_count = 1;
-                               CLNT_CONTROL(cl, CLSET_RETRIES, &try_count);
-                               timeo.tv_sec = 15;
-                               timeo.tv_usec = 0;
-                               CLNT_CONTROL(cl, CLSET_TIMEOUT, &timeo);
-                       } else
-                               error = EINVAL;
-               }
-       
-               for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++)
-                       oldcl[i] = NULL;
-               mtx_lock(&rpctls_server_lock);
-               if (KRPC_VNET(rpctls_srv_newdaemon)) {
-                       /*
-                        * For a new daemon, the rpctls_srv_handles have
-                        * already been cleaned up by RPCTLS_SYSC_SRVSTARTUP.
-                        * Scan for an available array entry to use.
-                        */
-                       for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                               if (KRPC_VNET(rpctls_server_handle)[i] == NULL)
-                                       break;
-                       }
-                       if (i == RPCTLS_SRV_MAXNPROCS && error == 0)
-                               error = ENXIO;
-               } else {
-                       /* For an old daemon, clear out old CLIENTs. */
-                       for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                               oldcl[i] = KRPC_VNET(rpctls_server_handle)[i];
-                               KRPC_VNET(rpctls_server_handle)[i] = NULL;
-                               KRPC_VNET(rpctls_server_busy)[i] = false;
-                       }
-                       i = 0;  /* Set to use rpctls_server_handle[0]. */
-               }
-               if (error == 0)
-                       KRPC_VNET(rpctls_server_handle)[i] = cl;
-               mtx_unlock(&rpctls_server_lock);
-
-               for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                       if (oldcl[i] != NULL) {
-                               CLNT_CLOSE(oldcl[i]);
-                               CLNT_RELEASE(oldcl[i]);
-                       }
-               }
-               break;
-       case RPCTLS_SYSC_SRVSHUTDOWN:
-               mtx_lock(&rpctls_server_lock);
-               for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                       oldcl[i] = KRPC_VNET(rpctls_server_handle)[i];
-                       KRPC_VNET(rpctls_server_handle)[i] = NULL;
-               }
-               KRPC_VNET(rpctls_srv_newdaemon) = false;
-               mtx_unlock(&rpctls_server_lock);
-       
-               for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                       if (oldcl[i] != NULL) {
-                               CLNT_CLOSE(oldcl[i]);
-                               CLNT_RELEASE(oldcl[i]);
-                       }
-               }
-               break;
        case RPCTLS_SYSC_CLSOCKET:
-               mtx_lock(&rpctls_connect_lock);
+       case RPCTLS_SYSC_SRVSOCKET:
+               mtx_lock(&rpctls_lock);
                ups = RB_FIND(upsock_t, &upcall_sockets,
                    &(struct upsock){
                    .so = __DECONST(struct socket *, uap->path) });
                if (__predict_true(ups != NULL))
                        RB_REMOVE(upsock_t, &upcall_sockets, ups);
-               mtx_unlock(&rpctls_connect_lock);
+               mtx_unlock(&rpctls_lock);
                if (ups == NULL) {
                        printf("%s: socket lookup failed\n", __func__);
                        error = EPERM;
                        break;
                }
-               error = falloc(td, &fp, &fd, 0);
-               if (error == 0) {
+               if ((error = falloc(td, &fp, &fd, 0)) != 0)
+                       break;
+               soref(ups->so);
+               switch (uap->op) {
+               case RPCTLS_SYSC_CLSOCKET:
                        /*
                         * Set ssl refno so that clnt_vc_destroy() will
                         * not close the socket and will leave that for
                         * the daemon to do.
                         */
-                       soref(ups->so);
                        ssl[0] = ssl[1] = 0;
                        ssl[2] = RPCTLS_REFNO_HANDSHAKE;
                        CLNT_CONTROL(ups->cl, CLSET_TLS, ssl);
-                       finit(fp, FREAD | FWRITE, DTYPE_SOCKET, ups->so,
-                           &socketops);
-                       fdrop(fp, td);  /* Drop fp reference. */
-                       td->td_retval[0] = fd;
+                       break;
+               case RPCTLS_SYSC_SRVSOCKET:
+                       /*
+                        * Once this file descriptor is associated
+                        * with the socket, it cannot be closed by
+                        * the server side krpc code (svc_vc.c).
+                        */
+                       sx_xlock(&ups->xp->xp_lock);
+                       ups->xp->xp_tls = RPCTLS_FLAGS_HANDSHFAIL;
+                       sx_xunlock(&ups->xp->xp_lock);
+                       break;
                }
-               break;
-       case RPCTLS_SYSC_SRVSOCKET:
-               mtx_lock(&rpctls_server_lock);
-               so = KRPC_VNET(rpctls_server_so);
-               KRPC_VNET(rpctls_server_so) = NULL;
-               xprt = KRPC_VNET(rpctls_server_xprt);
-               KRPC_VNET(rpctls_server_xprt) = NULL;
-               mtx_unlock(&rpctls_server_lock);
-               if (so != NULL) {
-                       error = falloc(td, &fp, &fd, 0);
-                       if (error == 0) {
-                               /*
-                                * Once this file descriptor is associated
-                                * with the socket, it cannot be closed by
-                                * the server side krpc code (svc_vc.c).
-                                */
-                               soref(so);
-                               sx_xlock(&xprt->xp_lock);
-                               xprt->xp_tls = RPCTLS_FLAGS_HANDSHFAIL;
-                               sx_xunlock(&xprt->xp_lock);
-                               finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so,
-                                   &socketops);
-                               fdrop(fp, td);  /* Drop fp reference. */
-                               td->td_retval[0] = fd;
-                       }
-               } else
-                       error = EPERM;
+               finit(fp, FREAD | FWRITE, DTYPE_SOCKET, ups->so, &socketops);
+               fdrop(fp, td);  /* Drop fp reference. */
+               td->td_retval[0] = fd;
                break;
        default:
                error = EINVAL;
@@ -379,25 +231,6 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
        return (error);
 }
 
-/*
- * Acquire the rpctls_server_handle and return it with a reference count,
- * if it is available.
- */
-static CLIENT *
-rpctls_server_client(int procpos)
-{
-       CLIENT *cl;
-
-       KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread));
-       mtx_lock(&rpctls_server_lock);
-       cl = KRPC_VNET(rpctls_server_handle)[procpos];
-       if (cl != NULL)
-               CLNT_ACQUIRE(cl);
-       mtx_unlock(&rpctls_server_lock);
-       KRPC_CURVNET_RESTORE();
-       return (cl);
-}
-
 /* Do an upcall for a new socket connect using TLS. */
 enum clnt_stat
 rpctls_connect(CLIENT *newclient, char *certname, struct socket *so,
@@ -428,9 +261,9 @@ rpctls_connect(CLIENT *newclient, char *certname, struct 
socket *so,
        if (stat != RPC_SUCCESS)
                return (RPC_SYSTEMERROR);
 
-       mtx_lock(&rpctls_connect_lock);
+       mtx_lock(&rpctls_lock);
        RB_INSERT(upsock_t, &upcall_sockets, &ups);
-       mtx_unlock(&rpctls_connect_lock);
+       mtx_unlock(&rpctls_lock);
 
        /* Temporarily block reception during the handshake upcall. */
        val = 1;
@@ -455,12 +288,12 @@ rpctls_connect(CLIENT *newclient, char *certname, struct 
socket *so,
                        *sslp = res.ssl;
                }
        } else {
-               mtx_lock(&rpctls_connect_lock);
+               mtx_lock(&rpctls_lock);
                if (RB_FIND(upsock_t, &upcall_sockets, &ups)) {
                        struct upsock *removed __diagused;
 
                        removed = RB_REMOVE(upsock_t, &upcall_sockets, &ups);
-                       mtx_unlock(&rpctls_connect_lock);
+                       mtx_unlock(&rpctls_lock);
                        MPASS(removed == &ups);
                        /*
                         * Do a shutdown on the socket, since the daemon is
@@ -475,7 +308,7 @@ rpctls_connect(CLIENT *newclient, char *certname, struct 
socket *so,
                         * The daemon has taken the socket from the tree, but
                         * failed to do the handshake.
                         */
-                       mtx_unlock(&rpctls_connect_lock);
+                       mtx_unlock(&rpctls_lock);
                }
        }
 
@@ -513,20 +346,13 @@ rpctls_srv_handlerecord(uint64_t sec, uint64_t usec, 
uint64_t ssl, int procpos,
        struct rpctlssd_handlerecord_arg arg;
        struct rpctlssd_handlerecord_res res;
        enum clnt_stat stat;
-       CLIENT *cl;
-
-       cl = rpctls_server_client(procpos);
-       if (cl == NULL) {
-               *reterr = RPCTLSERR_NOSSL;
-               return (RPC_SUCCESS);
-       }
+       CLIENT *cl = KRPC_VNET(rpctls_server_handle);
 
        /* Do the handlerecord upcall. */
        arg.sec = sec;
        arg.usec = usec;
        arg.ssl = ssl;
        stat = rpctlssd_handlerecord_1(&arg, &res, cl);
-       CLNT_RELEASE(cl);
        if (stat == RPC_SUCCESS)
                *reterr = res.reterr;
        return (stat);
@@ -559,20 +385,13 @@ rpctls_srv_disconnect(uint64_t sec, uint64_t usec, 
uint64_t ssl, int procpos,
        struct rpctlssd_disconnect_arg arg;
        struct rpctlssd_disconnect_res res;
        enum clnt_stat stat;
-       CLIENT *cl;
-
-       cl = rpctls_server_client(procpos);
-       if (cl == NULL) {
-               *reterr = RPCTLSERR_NOSSL;
-               return (RPC_SUCCESS);
-       }
+       CLIENT *cl = KRPC_VNET(rpctls_server_handle);
 
        /* Do the disconnect upcall. */
        arg.sec = sec;
        arg.usec = usec;
        arg.ssl = ssl;
        stat = rpctlssd_disconnect_1(&arg, &res, cl);
-       CLNT_RELEASE(cl);
        if (stat == RPC_SUCCESS)
                *reterr = res.reterr;
        return (stat);
@@ -584,54 +403,33 @@ rpctls_server(SVCXPRT *xprt, struct socket *so, uint32_t 
*flags, uint64_t *sslp,
     uid_t *uid, int *ngrps, gid_t **gids, int *procposp)
 {
        enum clnt_stat stat;
-       CLIENT *cl;
+       struct upsock ups = {
+               .so = so,
+               .xp = xprt,
+       };
+       CLIENT *cl = KRPC_VNET(rpctls_server_handle);
+       struct rpctlssd_connect_arg arg;
        struct rpctlssd_connect_res res;
        gid_t *gidp;
        uint32_t *gidv;
-       int i, procpos;
-
-       KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread));
-       cl = NULL;
-       procpos = -1;
-       mtx_lock(&rpctls_server_lock);
-       for (i = (KRPC_VNET(rpctls_srv_prevproc) + 1) % RPCTLS_SRV_MAXNPROCS;
-           i != KRPC_VNET(rpctls_srv_prevproc);
-           i = (i + 1) % RPCTLS_SRV_MAXNPROCS) {
-               if (KRPC_VNET(rpctls_server_handle)[i] != NULL)
-                       break;
-       }
-       if (i == KRPC_VNET(rpctls_srv_prevproc)) {
-               if (KRPC_VNET(rpctls_server_handle)[i] != NULL)
-                       procpos = i;
-       } else
-               KRPC_VNET(rpctls_srv_prevproc) = procpos = i;
-       mtx_unlock(&rpctls_server_lock);
-       if (procpos >= 0)
-               cl = rpctls_server_client(procpos);
-       if (cl == NULL) {
-               KRPC_CURVNET_RESTORE();
-               return (RPC_SYSTEMERROR);
-       }
+       int i;
 
-       /* Serialize the server upcalls. */
-       mtx_lock(&rpctls_server_lock);
-       while (KRPC_VNET(rpctls_server_busy)[procpos])
-               msleep(&KRPC_VNET(rpctls_server_busy)[procpos],
-                   &rpctls_server_lock, PVFS, "rtlssn", 0);
-       KRPC_VNET(rpctls_server_busy)[procpos] = true;
-       KRPC_VNET(rpctls_server_so) = so;
-       KRPC_VNET(rpctls_server_xprt) = xprt;
-       mtx_unlock(&rpctls_server_lock);
+       mtx_lock(&rpctls_lock);
+       RB_INSERT(upsock_t, &upcall_sockets, &ups);
+       mtx_unlock(&rpctls_lock);
 
        /* Do the server upcall. */
        res.gid.gid_val = NULL;
-       stat = rpctlssd_connect_1(NULL, &res, cl);
+       arg.socookie = (uintptr_t)so;
+       stat = rpctlssd_connect_1(&arg, &res, cl);
        if (stat == RPC_SUCCESS) {
+#ifdef INVARIANTS
+               MPASS((RB_FIND(upsock_t, &upcall_sockets, &ups) == NULL));
+#endif
                *flags = res.flags;
                *sslp++ = res.sec;
                *sslp++ = res.usec;
                *sslp = res.ssl;
-               *procposp = procpos;
                if ((*flags & (RPCTLS_FLAGS_CERTUSER |
                    RPCTLS_FLAGS_DISABLED)) == RPCTLS_FLAGS_CERTUSER) {
                        *ngrps = res.gid.gid_len;
@@ -641,27 +439,32 @@ rpctls_server(SVCXPRT *xprt, struct socket *so, uint32_t 
*flags, uint64_t *sslp,
                        for (i = 0; i < *ngrps; i++)
                                *gidp++ = *gidv++;
                }
-       } else if (stat == RPC_TIMEDOUT) {
-               /*
-                * Do a shutdown on the socket, since the daemon is probably
-                * stuck in SSL_accept() trying to read the socket.
-                * Do not soclose() the socket, since the daemon will close()
-                * the socket after SSL_accept() returns an error.
-                */
-               soshutdown(so, SHUT_RD);
+       } else {
+               mtx_lock(&rpctls_lock);
+               if (RB_FIND(upsock_t, &upcall_sockets, &ups)) {
+                       struct upsock *removed __diagused;
+
+                       removed = RB_REMOVE(upsock_t, &upcall_sockets, &ups);
+                       mtx_unlock(&rpctls_lock);
+                       MPASS(removed == &ups);
+                       /*
+                        * Do a shutdown on the socket, since the daemon is
+                        * probably stuck in SSL_accept() trying to read the
+                        * socket.  Do not soclose() the socket, since the
+                        * daemon will close() the socket after SSL_accept()
+                        * returns an error.
+                        */
+                       soshutdown(so, SHUT_RD);
+               } else {
+                       /*
+                        * The daemon has taken the socket from the tree, but
+                        * failed to do the handshake.
+                        */
+                       mtx_unlock(&rpctls_lock);
+               }
        }
-       CLNT_RELEASE(cl);
        mem_free(res.gid.gid_val, 0);
 
-       /* Once the upcall is done, the daemon is done with the fp and so. */
-       mtx_lock(&rpctls_server_lock);
-       KRPC_VNET(rpctls_server_so) = NULL;
-       KRPC_VNET(rpctls_server_xprt) = NULL;
-       KRPC_VNET(rpctls_server_busy)[procpos] = false;
-       wakeup(&KRPC_VNET(rpctls_server_busy)[procpos]);
-       mtx_unlock(&rpctls_server_lock);
-       KRPC_CURVNET_RESTORE();
-
        return (stat);
 }
 
@@ -789,13 +592,6 @@ rpctls_getinfo(u_int *maxlenp, bool rpctlscd_run, bool 
rpctlssd_run)
            &maxlen, &siz, NULL, 0, NULL, 0);
        if (error != 0)
                return (false);
-       KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread));
-       if (rpctlssd_run && KRPC_VNET(rpctls_server_handle)[0] == NULL) {
-               KRPC_CURVNET_RESTORE();
-               return (false);
-       }
-       KRPC_CURVNET_RESTORE();
        *maxlenp = maxlen;
        return (enable);
 }
-
diff --git a/sys/rpc/rpcsec_tls/rpctlssd.x b/sys/rpc/rpcsec_tls/rpctlssd.x
index 922583284b11..e9afca084ada 100644
--- a/sys/rpc/rpcsec_tls/rpctlssd.x
+++ b/sys/rpc/rpcsec_tls/rpctlssd.x
@@ -27,6 +27,9 @@
 
 /* Modified from gssd.x for the server side of RPC-over-TLS. */
 
+struct rpctlssd_connect_arg {
+       uint64_t socookie;
+};
 
 struct rpctlssd_connect_res {
        uint32_t flags;
@@ -62,7 +65,7 @@ program RPCTLSSD {
                void RPCTLSSD_NULL(void) = 0;
 
                rpctlssd_connect_res
-               RPCTLSSD_CONNECT(void) = 1;
+               RPCTLSSD_CONNECT(rpctlssd_connect_arg) = 1;
 
                rpctlssd_handlerecord_res
                RPCTLSSD_HANDLERECORD(rpctlssd_handlerecord_arg) = 2;

Reply via email to