Page MenuHomeFreeBSD

D37777.diff
No OneTemporary

D37777.diff

diff --git a/sys/rpc/rpc_generic.c.vnet b/sys/rpc/rpc_generic.c
--- a/sys/rpc/rpc_generic.c.vnet
+++ b/sys/rpc/rpc_generic.c
@@ -45,10 +45,12 @@
#include "opt_inet6.h"
#include <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
+#include <sys/osd.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/sbuf.h>
@@ -958,6 +960,10 @@
return (mhead);
}
+#ifdef VNET_NFSD
+int rpctls_prison_cleanup(void *obj, void *data __unused);
+#endif
+
/*
* Kernel module glue
*/
@@ -965,10 +971,19 @@
krpc_modevent(module_t mod, int type, void *data)
{
int error = 0;
+#ifdef VNET_NFSD
+ osd_method_t methods[PR_MAXMETHOD] = {
+ [PR_METHOD_REMOVE] = rpctls_prison_cleanup,
+ };
+#endif
switch (type) {
case MOD_LOAD:
error = rpctls_init();
+#ifdef VNET_NFSD
+ /* XXX-BZ OSD to VNET? */
+ osd_jail_register(NULL, methods);
+#endif
break;
case MOD_UNLOAD:
/*
diff --git a/sys/rpc/rpcsec_tls.h.vnet b/sys/rpc/rpcsec_tls.h
--- a/sys/rpc/rpcsec_tls.h.vnet
+++ b/sys/rpc/rpcsec_tls.h
@@ -86,6 +86,35 @@
/* ssl refno value to indicate TLS handshake being done. */
#define RPCTLS_REFNO_HANDSHAKE 0xFFFFFFFFFFFFFFFFULL
+/* Macros for VNET_NFSD. */
+#ifdef VNET_NFSD
+#if !defined(VIMAGE)
+options VNET_NFSD also requires options VIMAGE
+#endif
+/* Just define the VNET_KRPCxxx() macros as VNETxxx() macros. */
+#define KRPC_VNET_DEFINE(t, n) VNET_DEFINE(t, n)
+#define KRPC_VNET_DEFINE_STATIC(t, n) VNET_DEFINE_STATIC(t, n)
+#define KRPC_VNET(n) VNET(n)
+
+#define KRPC_CURVNET_SET(n) CURVNET_SET(n)
+#define KRPC_CURVNET_SET_QUIET(n) CURVNET_SET_QUIET(n)
+#define KRPC_CURVNET_RESTORE() CURVNET_RESTORE()
+#define KRPC_TD_TO_VNET(n) TD_TO_VNET(n)
+
+/* Jail OSD cleanup function. */
+int rpctls_prison_cleanup(void *obj, void *data __unused);
+#else /* !VNET_NFSD */
+/* Define the KRPC_VNET macros similar to !VIMAGE. */
+#define KRPC_VNET_DEFINE(t, n) t n
+#define KRPC_VNET_DEFINE_STATIC(t, n) static t n
+#define KRPC_VNET(n) (n)
+
+#define KRPC_CURVNET_SET(n)
+#define KRPC_CURVNET_SET_QUIET(n)
+#define KRPC_CURVNET_RESTORE()
+#define KRPC_TD_TO_VNET(n) NULL
+#endif /* VNET_NFSD */
+
#endif /* _KERNEL */
#endif /* _RPC_RPCSEC_TLS_H_ */
diff --git a/sys/rpc/rpcsec_tls/rpctls_impl.c.vnet b/sys/rpc/rpcsec_tls/rpctls_impl.c
--- a/sys/rpc/rpcsec_tls/rpctls_impl.c.vnet
+++ b/sys/rpc/rpcsec_tls/rpctls_impl.c
@@ -38,6 +38,7 @@
#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 @@
#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 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,27 @@
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;
+}
+#ifdef VNET_NFSD
+VNET_SYSINIT(rpctls_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY,
+ rpctls_vnetinit, NULL);
+#endif
+
int
rpctls_init(void)
{
- int error, i;
+ int error;
error = syscall_helper_register(rpctls_syscalls, SY_THR_STATIC_KLD);
if (error != 0) {
@@ -107,8 +128,9 @@
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;
+#ifndef VNET_NFSD
+ rpctls_vnetinit(NULL);
+#endif
return (0);
}
@@ -133,27 +155,36 @@
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 +240,11 @@
}
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 +289,14 @@
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 +304,14 @@
} 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 +335,10 @@
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 +377,10 @@
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 +405,7 @@
default:
error = EINVAL;
}
+ KRPC_CURVNET_RESTORE();
return (error);
}
@@ -400,11 +436,13 @@
{
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 +649,37 @@
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 +714,12 @@
/* 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 +838,30 @@
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);
}
+
+#ifdef VNET_NFSD
+/* Osd entry for prison cleanup. */
+int
+rpctls_prison_cleanup(void *obj, void *data __unused)
+{
+ struct prison *pr = obj;
+
+ if ((pr->pr_flags & PR_VNET) == 0)
+ return (0);
+ KRPC_CURVNET_SET(pr->pr_vnet);
+ free(KRPC_VNET(rpctls_server_handle), M_RPC);
+ free(KRPC_VNET(rpctls_server_busy), M_RPC);
+ KRPC_CURVNET_RESTORE();
+ return (0);
+}
+#endif

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 7, 12:35 PM (20 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17032268
Default Alt Text
D37777.diff (12 KB)

Event Timeline