aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2023-02-15 13:58:21 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2023-02-15 13:58:21 +0000
commit6444662a563ba714fed8563645764262c6f5e90f (patch)
tree9fd09aa0c0fe2c1d69e466ffd27e51356212311c
parentc3821149f4252f087ba5133e20896ae4274f4da1 (diff)
downloadsrc-6444662a563ba714fed8563645764262c6f5e90f.tar.gz
src-6444662a563ba714fed8563645764262c6f5e90f.zip
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
-rw-r--r--sys/rpc/rpcsec_tls.h18
-rw-r--r--sys/rpc/rpcsec_tls/rpctls_impl.c164
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);
+}
+