git: 765ad4f03937 - main - rpcsec_tls: cleanup the rpctls_syscall()

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Sat, 01 Feb 2025 09:02:30 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=765ad4f03937cb90ea3cc138535bab872e30b0c4

commit 765ad4f03937cb90ea3cc138535bab872e30b0c4
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-02-01 01:03:27 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-02-01 09:00:28 +0000

    rpcsec_tls: cleanup the rpctls_syscall()
    
    With all the recent changes we don't need extra argument that specifies
    what exactly the syscalls does, neither we need a copyout-able pointer,
    just a pointer sized integer.
    
    Reviewed by:            rmacklem
    Differential Revision:  https://reviews.freebsd.org/D48649
---
 sys/kern/syscalls.master             |  3 +-
 sys/rpc/rpcsec_tls.h                 |  8 +--
 sys/rpc/rpcsec_tls/rpctls_impl.c     | 94 ++++++++++++++++++------------------
 usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c |  2 +-
 usr.sbin/rpc.tlsservd/rpc.tlsservd.c |  2 +-
 5 files changed, 53 insertions(+), 56 deletions(-)

diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 9628745da304..52502fc662be 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3249,8 +3249,7 @@
 ; 576 is initialised by the krpc code, if present.
 576	AUE_NULL	NOSTD {
 		int rpctls_syscall(
-		    int op,
-		    _In_z_ const char *path
+		    uint64_t socookie
 		);
 	}
 577	AUE_SPECIALFD	STD|CAPENABLED {
diff --git a/sys/rpc/rpcsec_tls.h b/sys/rpc/rpcsec_tls.h
index 024fb2fe68ee..97c49dc32245 100644
--- a/sys/rpc/rpcsec_tls.h
+++ b/sys/rpc/rpcsec_tls.h
@@ -28,12 +28,8 @@
 #ifndef	_RPC_RPCSEC_TLS_H_
 #define	_RPC_RPCSEC_TLS_H_
 
-/* Operation values for rpctls syscall. */
-#define	RPCTLS_SYSC_CLSOCKET	2
-#define	RPCTLS_SYSC_SRVSOCKET	5
-
-/* System call used by the rpctlscd, rpctlssd daemons. */
-int	rpctls_syscall(int, const char *);
+/* System call used by the rpc.tlsclntd(8), rpc.tlsservd(8) daemons. */
+int	rpctls_syscall(uint64_t);
 
 /* Flag bits to indicate certificate results. */
 #define	RPCTLS_FLAGS_HANDSHAKE	0x01
diff --git a/sys/rpc/rpcsec_tls/rpctls_impl.c b/sys/rpc/rpcsec_tls/rpctls_impl.c
index 49464495ad58..adca24c3e3d5 100644
--- a/sys/rpc/rpcsec_tls/rpctls_impl.c
+++ b/sys/rpc/rpcsec_tls/rpctls_impl.c
@@ -88,6 +88,7 @@ struct upsock {
 		CLIENT *cl;
 		SVCXPRT *xp;
 	};
+	bool server;
 };
 
 static RB_HEAD(upsock_t, upsock) upcall_sockets;
@@ -169,7 +170,7 @@ int
 sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap)
 {
 	struct file *fp;
-	struct upsock *ups;
+	struct upsock *upsp, ups;
 	int fd = -1, error;
         
 	error = priv_check(td, PRIV_NFS_DAEMON);
@@ -177,52 +178,51 @@ sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap)
 		return (error);
 
 	KRPC_CURVNET_SET(KRPC_TD_TO_VNET(td));
-	switch (uap->op) {
-	case RPCTLS_SYSC_CLSOCKET:
-	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_lock);
-		if (ups == NULL) {
-			printf("%s: socket lookup failed\n", __func__);
-			error = EPERM;
-			break;
-		}
-		if ((error = falloc(td, &fp, &fd, 0)) != 0)
-			break;
-		soref(ups->so);
-		switch (uap->op) {
-		case RPCTLS_SYSC_CLSOCKET:
-			/*
-			 * Initialize TLS state so that clnt_vc_destroy() will
-			 * not close the socket and will leave that for the
-			 * daemon to do.
-			 */
-			CLNT_CONTROL(ups->cl, CLSET_TLS,
-			    &(int){RPCTLS_INHANDSHAKE});
-			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;
-		}
-		finit(fp, FREAD | FWRITE, DTYPE_SOCKET, ups->so, &socketops);
-		fdrop(fp, td);	/* Drop fp reference. */
-		td->td_retval[0] = fd;
-		break;
-	default:
-		error = EINVAL;
+	mtx_lock(&rpctls_lock);
+	upsp = RB_FIND(upsock_t, &upcall_sockets,
+	    &(struct upsock){
+	    .so = __DECONST(struct socket *, uap->socookie) });
+	if (__predict_true(upsp != NULL)) {
+		RB_REMOVE(upsock_t, &upcall_sockets, upsp);
+		/*
+		 * The upsp points to stack of NFS mounting thread.  Even
+		 * though we removed it from the tree, we still don't own it.
+		 * Make a copy before releasing the lock.  The mounting thread
+		 * may timeout the RPC and unroll its stack.
+		 */
+		ups = *upsp;
+	}
+	mtx_unlock(&rpctls_lock);
+	if (upsp == NULL) {
+		KRPC_CURVNET_RESTORE();
+		printf("%s: socket lookup failed\n", __func__);
+		return (EPERM);
+	}
+	if ((error = falloc(td, &fp, &fd, 0)) != 0) {
+		KRPC_CURVNET_RESTORE();
+		return (error);
+	}
+	soref(ups.so);
+	if (ups.server) {
+		/*
+		 * 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);
+	} else {
+		/*
+		 * Initialize TLS state so that clnt_vc_destroy() will
+		 * not close the socket and will leave that for the
+		 * daemon to do.
+		 */
+		CLNT_CONTROL(ups.cl, CLSET_TLS, &(int){RPCTLS_INHANDSHAKE});
 	}
+	finit(fp, FREAD | FWRITE, DTYPE_SOCKET, ups.so, &socketops);
+	fdrop(fp, td);	/* Drop fp reference. */
+	td->td_retval[0] = fd;
 	KRPC_CURVNET_RESTORE();
 
 	return (error);
@@ -269,6 +269,7 @@ rpctls_connect(CLIENT *newclient, char *certname, struct socket *so,
 	struct upsock ups = {
 		.so = so,
 		.cl = newclient,
+		.server = false,
 	};
 	CLIENT *cl = KRPC_VNET(rpctls_connect_handle);
 
@@ -390,6 +391,7 @@ rpctls_server(SVCXPRT *xprt, uint32_t *flags, uid_t *uid, int *ngrps,
 	struct upsock ups = {
 		.so = xprt->xp_socket,
 		.xp = xprt,
+		.server = true,
 	};
 	CLIENT *cl = KRPC_VNET(rpctls_server_handle);
 	struct rpctlssd_connect_arg arg;
diff --git a/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c b/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c
index e8df84a382b5..37e0c2013ef1 100644
--- a/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c
+++ b/usr.sbin/rpc.tlsclntd/rpc.tlsclntd.c
@@ -258,7 +258,7 @@ rpctlscd_connect_2_svc(struct rpctlscd_connect_arg *argp,
 
 	rpctls_verbose_out("rpctlsd_connect: started\n");
 	/* Get the socket fd from the kernel. */
-	s = rpctls_syscall(RPCTLS_SYSC_CLSOCKET, (char *)argp->socookie);
+	s = rpctls_syscall(argp->socookie);
 	if (s < 0) {
 		result->reterr = RPCTLSERR_NOSOCKET;
 		return (TRUE);
diff --git a/usr.sbin/rpc.tlsservd/rpc.tlsservd.c b/usr.sbin/rpc.tlsservd/rpc.tlsservd.c
index 61f8601c36f5..438b745fb5de 100644
--- a/usr.sbin/rpc.tlsservd/rpc.tlsservd.c
+++ b/usr.sbin/rpc.tlsservd/rpc.tlsservd.c
@@ -403,7 +403,7 @@ rpctlssd_connect_thread(void *v)
 	}
 
 	/* Get the socket fd from the kernel. */
-	s = rpctls_syscall(RPCTLS_SYSC_SRVSOCKET, (char *)socookie);
+	s = rpctls_syscall(socookie);
 	if (s < 0) {
 		rpctls_verbose_out("rpctlssd_connect_svc: rpctls_syscall "
 		    "accept failed\n");