git: 6444662a563b - main - krpc: Add macros so that rpc.tlsservd can run in vnet prison
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 15 Feb 2023 13:59:52 UTC
The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=6444662a563ba714fed8563645764262c6f5e90f commit 6444662a563ba714fed8563645764262c6f5e90f Author: Rick Macklem <rmacklem@FreeBSD.org> AuthorDate: 2023-02-15 13:58:21 +0000 Commit: Rick Macklem <rmacklem@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); +} +