git: 765ad4f03937 - main - rpcsec_tls: cleanup the rpctls_syscall()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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");