The branch main has been updated by rmacklem:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=6444662a563ba714fed8563645764262c6f5e90f

commit 6444662a563ba714fed8563645764262c6f5e90f
Author:     Rick Macklem <rmack...@freebsd.org>
AuthorDate: 2023-02-15 13:58:21 +0000
Commit:     Rick Macklem <rmack...@freebsd.org>
CommitDate: 2023-02-15 13:58:21 +0000

    krpc: Add macros so that rpc.tlsservd can run in vnet prison
    
    Commit 7344856e3a6d added a lot of macros that will front end
    vnet macros so that nfsd(8) can run in vnet prison.
    This patch adds similar macros named KRPC_VNETxxx so that
    the rpc.tlsservd(8) daemon can run in a vnet prison, once the
    macros front end the vnet ones.  For now, they are null macros.
    
    MFC after:      3 months
---
 sys/rpc/rpcsec_tls.h             |  18 +++++
 sys/rpc/rpcsec_tls/rpctls_impl.c | 164 +++++++++++++++++++++++++--------------
 2 files changed, 125 insertions(+), 57 deletions(-)

diff --git a/sys/rpc/rpcsec_tls.h b/sys/rpc/rpcsec_tls.h
index 6c49f9577cc8..ac2fee1b09fc 100644
--- a/sys/rpc/rpcsec_tls.h
+++ b/sys/rpc/rpcsec_tls.h
@@ -76,6 +76,9 @@ enum clnt_stat        rpctls_srv_disconnect(uint64_t sec, 
uint64_t usec,
 /* Initialization function for rpcsec_tls. */
 int            rpctls_init(void);
 
+/* Cleanup function for rpcsec_tls. */
+void           rpctls_cleanup(void);
+
 /* Get TLS information function. */
 bool           rpctls_getinfo(u_int *maxlen, bool rpctlscd_run,
                    bool rpctlssd_run);
@@ -86,6 +89,21 @@ bool         rpctls_getinfo(u_int *maxlen, bool rpctlscd_run,
 /* ssl refno value to indicate TLS handshake being done. */
 #define        RPCTLS_REFNO_HANDSHAKE  0xFFFFFFFFFFFFFFFFULL
 
+/* Macros for VIMAGE. */
+/* Define the KRPC_VNET macros similar to !VIMAGE. */
+#define        KRPC_VNET_NAME(n)               n
+#define        KRPC_VNET_DECLARE(t, n)         extern t n
+#define        KRPC_VNET_DEFINE(t, n)          t n
+#define        KRPC_VNET_DEFINE_STATIC(t, n)   static t n
+#define        KRPC_VNET(n)                    (n)
+
+#define        CTLFLAG_KRPC_VNET               0
+
+#define        KRPC_CURVNET_SET(n)
+#define        KRPC_CURVNET_SET_QUIET(n)
+#define        KRPC_CURVNET_RESTORE()
+#define        KRPC_TD_TO_VNET(n)              NULL
+
 #endif /* _KERNEL */
 
 #endif /* _RPC_RPCSEC_TLS_H_ */
diff --git a/sys/rpc/rpcsec_tls/rpctls_impl.c b/sys/rpc/rpcsec_tls/rpctls_impl.c
index 9d7f686af768..4e9d52bf5d48 100644
--- a/sys/rpc/rpcsec_tls/rpctls_impl.c
+++ b/sys/rpc/rpcsec_tls/rpctls_impl.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/capsicum.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
+#include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -51,6 +52,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysent.h>
 #include <sys/sysproto.h>
 
+#include <net/vnet.h>
+
 #include <rpc/rpc.h>
 #include <rpc/rpc_com.h>
 #include <rpc/rpcsec_tls.h>
@@ -74,15 +77,16 @@ static CLIENT               *rpctls_connect_handle;
 static struct mtx      rpctls_connect_lock;
 static struct socket   *rpctls_connect_so = NULL;
 static CLIENT          *rpctls_connect_cl = NULL;
-static CLIENT          *rpctls_server_handle[RPCTLS_SRV_MAXNPROCS];
 static struct mtx      rpctls_server_lock;
-static struct socket   *rpctls_server_so = NULL;
-static SVCXPRT         *rpctls_server_xprt = NULL;
-static bool            rpctls_srv_newdaemon = false;
-static int             rpctls_srv_prevproc = 0;
-static bool            rpctls_server_busy[RPCTLS_SRV_MAXNPROCS];
 static struct opaque_auth rpctls_null_verf;
 
+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);
+
 static CLIENT          *rpctls_connect_client(void);
 static CLIENT          *rpctls_server_client(int procpos);
 static enum clnt_stat  rpctls_server(SVCXPRT *xprt, struct socket *so,
@@ -90,10 +94,25 @@ static enum clnt_stat       rpctls_server(SVCXPRT *xprt, 
struct socket *so,
                            uid_t *uid, int *ngrps, gid_t **gids,
                            int *procposp);
 
+static void
+rpctls_vnetinit(const void *unused __unused)
+{
+       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;
+}
+SYSINIT(rpctls_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY,
+    rpctls_vnetinit, NULL);
+
 int
 rpctls_init(void)
 {
-       int error, i;
+       int error;
 
        error = syscall_helper_register(rpctls_syscalls, SY_THR_STATIC_KLD);
        if (error != 0) {
@@ -107,8 +126,6 @@ rpctls_init(void)
        rpctls_null_verf.oa_flavor = AUTH_NULL;
        rpctls_null_verf.oa_base = RPCTLS_START_STRING;
        rpctls_null_verf.oa_length = strlen(RPCTLS_START_STRING);
-       for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++)
-               rpctls_server_busy[i] = false;
        return (0);
 }
 
@@ -133,27 +150,36 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
        if (error != 0)
                return (error);
 
+       KRPC_CURVNET_SET(KRPC_TD_TO_VNET(td));
        switch (uap->op) {
        case RPCTLS_SYSC_SRVSTARTUP:
-               /* Get rid of all old CLIENTs. */
-               mtx_lock(&rpctls_server_lock);
-               for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                       oldcl[i] = rpctls_server_handle[i];
-                       rpctls_server_handle[i] = NULL;
-                       rpctls_server_busy[i] = false;
-               }
-               rpctls_srv_newdaemon = true;
-               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]);
+               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_CLSETPATH:
-               error = copyinstr(uap->path, path, sizeof(path), NULL);
+               if (jailed(curthread->td_ucred))
+                       error = EPERM;
+               if (error == 0)
+                       error = copyinstr(uap->path, path, sizeof(path), NULL);
                if (error == 0) {
                        error = ENXIO;
 #ifdef KERN_TLS
@@ -209,7 +235,11 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
                }
                break;
        case RPCTLS_SYSC_SRVSETPATH:
-               error = copyinstr(uap->path, path, sizeof(path), NULL);
+               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
@@ -254,14 +284,14 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
                for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++)
                        oldcl[i] = NULL;
                mtx_lock(&rpctls_server_lock);
-               if (rpctls_srv_newdaemon) {
+               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 (rpctls_server_handle[i] == NULL)
+                               if (KRPC_VNET(rpctls_server_handle)[i] == NULL)
                                        break;
                        }
                        if (i == RPCTLS_SRV_MAXNPROCS && error == 0)
@@ -269,14 +299,14 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
                } else {
                        /* For an old daemon, clear out old CLIENTs. */
                        for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                               oldcl[i] = rpctls_server_handle[i];
-                               rpctls_server_handle[i] = NULL;
-                               rpctls_server_busy[i] = false;
+                               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)
-                       rpctls_server_handle[i] = cl;
+                       KRPC_VNET(rpctls_server_handle)[i] = cl;
                mtx_unlock(&rpctls_server_lock);
 
                for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
@@ -300,10 +330,10 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
        case RPCTLS_SYSC_SRVSHUTDOWN:
                mtx_lock(&rpctls_server_lock);
                for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
-                       oldcl[i] = rpctls_server_handle[i];
-                       rpctls_server_handle[i] = NULL;
+                       oldcl[i] = KRPC_VNET(rpctls_server_handle)[i];
+                       KRPC_VNET(rpctls_server_handle)[i] = NULL;
                }
-               rpctls_srv_newdaemon = false;
+               KRPC_VNET(rpctls_srv_newdaemon) = false;
                mtx_unlock(&rpctls_server_lock);
        
                for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) {
@@ -342,10 +372,10 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
                break;
        case RPCTLS_SYSC_SRVSOCKET:
                mtx_lock(&rpctls_server_lock);
-               so = rpctls_server_so;
-               rpctls_server_so = NULL;
-               xprt = rpctls_server_xprt;
-               rpctls_server_xprt = NULL;
+               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);
@@ -370,6 +400,7 @@ sys_rpctls_syscall(struct thread *td, struct 
rpctls_syscall_args *uap)
        default:
                error = EINVAL;
        }
+       KRPC_CURVNET_RESTORE();
 
        return (error);
 }
@@ -400,11 +431,13 @@ rpctls_server_client(int procpos)
 {
        CLIENT *cl;
 
+       KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread));
        mtx_lock(&rpctls_server_lock);
-       cl = rpctls_server_handle[procpos];
+       cl = KRPC_VNET(rpctls_server_handle)[procpos];
        if (cl != NULL)
                CLNT_ACQUIRE(cl);
        mtx_unlock(&rpctls_server_lock);
+       KRPC_CURVNET_RESTORE();
        return (cl);
 }
 
@@ -611,33 +644,37 @@ rpctls_server(SVCXPRT *xprt, struct socket *so, uint32_t 
*flags, uint64_t *sslp,
        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 = (rpctls_srv_prevproc + 1) % RPCTLS_SRV_MAXNPROCS;
-           i != rpctls_srv_prevproc; i = (i + 1) % RPCTLS_SRV_MAXNPROCS) {
-               if (rpctls_server_handle[i] != NULL)
+       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 == rpctls_srv_prevproc) {
-               if (rpctls_server_handle[i] != NULL)
+       if (i == KRPC_VNET(rpctls_srv_prevproc)) {
+               if (KRPC_VNET(rpctls_server_handle)[i] != NULL)
                        procpos = i;
        } else
-               rpctls_srv_prevproc = procpos = i;
+               KRPC_VNET(rpctls_srv_prevproc) = procpos = i;
        mtx_unlock(&rpctls_server_lock);
        if (procpos >= 0)
                cl = rpctls_server_client(procpos);
-       if (cl == NULL)
+       if (cl == NULL) {
+               KRPC_CURVNET_RESTORE();
                return (RPC_SYSTEMERROR);
+       }
 
        /* Serialize the server upcalls. */
        mtx_lock(&rpctls_server_lock);
-       while (rpctls_server_busy[procpos])
-               msleep(&rpctls_server_busy[procpos], &rpctls_server_lock, PVFS,
-                   "rtlssn", 0);
-       rpctls_server_busy[procpos] = true;
-       rpctls_server_so = so;
-       rpctls_server_xprt = xprt;
+       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);
 
        /* Do the server upcall. */
@@ -672,11 +709,12 @@ rpctls_server(SVCXPRT *xprt, struct socket *so, uint32_t 
*flags, uint64_t *sslp,
 
        /* Once the upcall is done, the daemon is done with the fp and so. */
        mtx_lock(&rpctls_server_lock);
-       rpctls_server_so = NULL;
-       rpctls_server_xprt = NULL;
-       rpctls_server_busy[procpos] = false;
-       wakeup(&rpctls_server_busy[procpos]);
+       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);
 }
@@ -795,9 +833,21 @@ rpctls_getinfo(u_int *maxlenp, bool rpctlscd_run, bool 
rpctlssd_run)
                return (false);
        if (rpctlscd_run && rpctls_connect_handle == NULL)
                return (false);
-       if (rpctlssd_run && rpctls_server_handle[0] == NULL)
+       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);
 }
 
+void
+rpctls_cleanup(void)
+{
+
+       free(KRPC_VNET(rpctls_server_handle), M_RPC);
+       free(KRPC_VNET(rpctls_server_busy), M_RPC);
+}
+

Reply via email to