From nobody Sat Feb 01 09:02:17 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4YlRbZ4vZfz5mbCq; Sat, 01 Feb 2025 09:02:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YlRbZ07BZz41Vk; Sat, 01 Feb 2025 09:02:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1738400538; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wFOgUJPqFif5hrjvT/t8c2J3JNUIx3ERqGQRx0oZ9To=; b=pLEU8Gw3YvJG58Y59gycprcCLz1TZAUt2wRk7ETUow2K2Q0LhrYnKyhqv+gfFQgBhZ6ry4 hSefkLn+EIgO7rVcOrn4rdFLFfoVGvKVWUsz/cs4I3xSj9elx9USw9PpbCAaiqSmbTOYZJ 5EUSDTjkPoTOiWAr+uAoCn/5yZcAdIUeG6IvZ6bs9NgbwP4uNj5kORczxYWseNY4VtDvDX 75A/toTNYRsETSKOTeVXxSgCkGpbq6jRSmKXmociCAEnhgjkue+pT1PMRsp4lLjmkLSkDD 5f00CYhUuF0Fhhf4qyUEfm2wTPjghpCbsyFDHJgX06l2dgjxBChNIcQDxuGNqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1738400538; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wFOgUJPqFif5hrjvT/t8c2J3JNUIx3ERqGQRx0oZ9To=; b=vCUHgMDsq+qT6VWFIw4+rbCTqGkV11B2bufzGAfrLaBzI5oO+pRB9vuHFYM7j62Kcfow7F UzcdWWepC0mZaZRDxNy5axluLkK1aWsLFiZY/b6F+h/9OXMbFFH6cy12qeQRecclPKV/RL r/mpZ/wgMelO+sE2sMryejISin80LICVcP3BifPLnYb+IAbDIG4iR/4Qx/mMwl6FABqSFx N+FGV4bcDECqPbPKdAKvL6ecpG5q5uoslE7kMr/kDJmIpIfNgoVeZOI50V3bPLajRK0dO0 8UkrDI1VX5GC4DtXZiHjgw3YnE3DwgUxcCEc4DSH2KHUVvZg1vR8WfNzzqabMQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1738400538; a=rsa-sha256; cv=none; b=QlrnKu0mc7vWiOLJSuGVbwSy4VyL7FgsVQCuRwp1TO/HbEPGz/1jwEuOh7cM6houYJs38w RGUISJ0sbRsoQzhAeRq04o2EmXDqxUb+KYNsYBbJ8inT/Wdxm2U5OiTl4JzgbJn38MChGT D8H9d7BHrHO9oy9/2QTD+c++zOVDi1oLY0gdLljpMPuaq8oDVTnrgszyPoiLuVVHrEn5+w oAmQEN00gqfZoaP/7z5VqzDbRwvV0Pfqq3qHdPFB7ZvcVMu/zrtgRUJntt0BBLwWdGD1Dx CHHD7x1NlICo9thpnPnTWZyUKvWTgZPZU2Wh2U+/UzCi3yGAv1GBAToQRU7OqQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YlRbY6nBnzxnL; Sat, 01 Feb 2025 09:02:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 51192HvS048186; Sat, 1 Feb 2025 09:02:17 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 51192HsL048183; Sat, 1 Feb 2025 09:02:17 GMT (envelope-from git) Date: Sat, 1 Feb 2025 09:02:17 GMT Message-Id: <202502010902.51192HsL048183@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: 42eec5201ab9 - main - rpcsec_tls/server: use netlink RPC client to talk to rpc.tlsservd(8) List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 42eec5201ab936f7227950c2c159c02c9cb342d4 Auto-Submitted: auto-generated The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=42eec5201ab936f7227950c2c159c02c9cb342d4 commit 42eec5201ab936f7227950c2c159c02c9cb342d4 Author: Gleb Smirnoff AuthorDate: 2025-02-01 01:02:40 +0000 Commit: Gleb Smirnoff 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;