git: 1d88734798c2 - stable/13 - krpc: Add macros so that rpc.tlsservd can run in vnet prison

From: Rick Macklem <rmacklem_at_FreeBSD.org>
Date: Wed, 17 May 2023 14:46:22 UTC
The branch stable/13 has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=1d88734798c252a749764e9ee314f46ce9fd2b3f

commit 1d88734798c252a749764e9ee314f46ce9fd2b3f
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2023-02-15 13:58:21 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2023-05-17 14:41:53 +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.
    
    (cherry picked from commit 6444662a563ba714fed8563645764262c6f5e90f)
---
 sys/rpc/rpcsec_tls.h             | 18 ++++++++++
 sys/rpc/rpcsec_tls/rpctls_impl.c | 77 ++++++++++++++++++++++++++--------------
 2 files changed, 68 insertions(+), 27 deletions(-)

diff --git a/sys/rpc/rpcsec_tls.h b/sys/rpc/rpcsec_tls.h
index 49a7e71b7514..5781424a6180 100644
--- a/sys/rpc/rpcsec_tls.h
+++ b/sys/rpc/rpcsec_tls.h
@@ -72,6 +72,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);
@@ -82,6 +85,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 c495213b08e2..3b3452a8b624 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,12 +77,14 @@ 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;
 static struct mtx	rpctls_server_lock;
-static struct socket	*rpctls_server_so = NULL;
-static SVCXPRT		*rpctls_server_xprt = NULL;
 static struct opaque_auth rpctls_null_verf;
 
+KRPC_VNET_DEFINE_STATIC(CLIENT *, rpctls_server_handle) = NULL;
+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_server_busy) = false;
+
 static CLIENT		*rpctls_connect_client(void);
 static CLIENT		*rpctls_server_client(void);
 static enum clnt_stat	rpctls_server(SVCXPRT *xprt, struct socket *so,
@@ -127,9 +132,13 @@ 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_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
@@ -185,7 +194,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
@@ -228,8 +241,8 @@ sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap)
 		}
 	
 		mtx_lock(&rpctls_server_lock);
-		oldcl = rpctls_server_handle;
-		rpctls_server_handle = cl;
+		oldcl = KRPC_VNET(rpctls_server_handle);
+		KRPC_VNET(rpctls_server_handle) = cl;
 		mtx_unlock(&rpctls_server_lock);
 	
 		if (oldcl != NULL) {
@@ -250,8 +263,8 @@ sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap)
 		break;
 	case RPCTLS_SYSC_SRVSHUTDOWN:
 		mtx_lock(&rpctls_server_lock);
-		oldcl = rpctls_server_handle;
-		rpctls_server_handle = NULL;
+		oldcl = KRPC_VNET(rpctls_server_handle);
+		KRPC_VNET(rpctls_server_handle) = NULL;
 		mtx_unlock(&rpctls_server_lock);
 	
 		if (oldcl != NULL) {
@@ -288,10 +301,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);
@@ -316,6 +329,7 @@ sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap)
 	default:
 		error = EINVAL;
 	}
+	KRPC_CURVNET_RESTORE();
 
 	return (error);
 }
@@ -346,11 +360,13 @@ rpctls_server_client(void)
 {
 	CLIENT *cl;
 
+	KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread));
 	mtx_lock(&rpctls_server_lock);
-	cl = rpctls_server_handle;
+	cl = KRPC_VNET(rpctls_server_handle);
 	if (cl != NULL)
 		CLNT_ACQUIRE(cl);
 	mtx_unlock(&rpctls_server_lock);
+	KRPC_CURVNET_RESTORE();
 	return (cl);
 }
 
@@ -556,20 +572,22 @@ rpctls_server(SVCXPRT *xprt, struct socket *so, uint32_t *flags, uint64_t *sslp,
 	gid_t *gidp;
 	uint32_t *gidv;
 	int i;
-	static bool rpctls_server_busy = false;
 
+	KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread));
 	cl = rpctls_server_client();
-	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)
-		msleep(&rpctls_server_busy, &rpctls_server_lock, PVFS,
-		    "rtlssn", 0);
-	rpctls_server_busy = true;
-	rpctls_server_so = so;
-	rpctls_server_xprt = xprt;
+	while (KRPC_VNET(rpctls_server_busy))
+		msleep(&KRPC_VNET(rpctls_server_busy),
+		    &rpctls_server_lock, PVFS, "rtlssn", 0);
+	KRPC_VNET(rpctls_server_busy) = true;
+	KRPC_VNET(rpctls_server_so) = so;
+	KRPC_VNET(rpctls_server_xprt) = xprt;
 	mtx_unlock(&rpctls_server_lock);
 
 	/* Do the server upcall. */
@@ -603,11 +621,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 = false;
-	wakeup(&rpctls_server_busy);
+	KRPC_VNET(rpctls_server_so) = NULL;
+	KRPC_VNET(rpctls_server_xprt) = NULL;
+	KRPC_VNET(rpctls_server_busy) = false;
+	wakeup(&KRPC_VNET(rpctls_server_busy));
 	mtx_unlock(&rpctls_server_lock);
+	KRPC_CURVNET_RESTORE();
 
 	return (stat);
 }
@@ -725,8 +744,12 @@ 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 == NULL)
+	KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread));
+	if (rpctlssd_run && KRPC_VNET(rpctls_server_handle) == NULL) {
+		KRPC_CURVNET_RESTORE();
 		return (false);
+	}
+	KRPC_CURVNET_RESTORE();
 	*maxlenp = maxlen;
 	return (enable);
 }