diff --git a/sys/kgssapi/gss_delete_sec_context.c.vnetkgssapi b/sys/kgssapi/gss_delete_sec_context.c --- a/sys/kgssapi/gss_delete_sec_context.c.vnetkgssapi +++ b/sys/kgssapi/gss_delete_sec_context.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -54,8 +55,12 @@ *minor_status = 0; - if (!kgss_gssd_handle) + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); + if (!KGSS_VNET(kgss_gssd_handle)) { + KGSS_CURVNET_RESTORE(); return (GSS_S_FAILURE); + } + KGSS_CURVNET_RESTORE(); if (*context_handle) { ctx = *context_handle; diff --git a/sys/kgssapi/gss_impl.c.vnetkgssapi b/sys/kgssapi/gss_impl.c --- a/sys/kgssapi/gss_impl.c.vnetkgssapi +++ b/sys/kgssapi/gss_impl.c @@ -31,13 +31,16 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include #include #include #include +#include #include +#include #include #include #include @@ -62,9 +65,10 @@ }; struct kgss_mech_list kgss_mechs; -CLIENT *kgss_gssd_handle; struct mtx kgss_gssd_lock; +KGSS_VNET_DEFINE(CLIENT *, kgss_gssd_handle) = NULL; + static int kgss_load(void) { @@ -134,10 +138,12 @@ } else cl = NULL; + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); mtx_lock(&kgss_gssd_lock); - oldcl = kgss_gssd_handle; - kgss_gssd_handle = cl; + oldcl = KGSS_VNET(kgss_gssd_handle); + KGSS_VNET(kgss_gssd_handle) = cl; mtx_unlock(&kgss_gssd_lock); + KGSS_CURVNET_RESTORE(); if (oldcl != NULL) { CLNT_CLOSE(oldcl); @@ -249,12 +255,16 @@ enum clnt_stat stat; OM_uint32 maj_stat; - if (!kgss_gssd_handle) + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); + if (!KGSS_VNET(kgss_gssd_handle)) { + KGSS_CURVNET_RESTORE(); return (GSS_S_FAILURE); + } args.ctx = ctx->handle; bzero(&res, sizeof(res)); - stat = gssd_export_sec_context_1(&args, &res, kgss_gssd_handle); + stat = gssd_export_sec_context_1(&args, &res, KGSS_VNET(kgss_gssd_handle)); + KGSS_CURVNET_RESTORE(); if (stat != RPC_SUCCESS) { return (GSS_S_FAILURE); } @@ -288,11 +298,13 @@ { CLIENT *cl; + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); mtx_lock(&kgss_gssd_lock); - cl = kgss_gssd_handle; + cl = KGSS_VNET(kgss_gssd_handle); if (cl != NULL) CLNT_ACQUIRE(cl); mtx_unlock(&kgss_gssd_lock); + KGSS_CURVNET_RESTORE(); return (cl); } @@ -303,6 +315,11 @@ kgssapi_modevent(module_t mod, int type, void *data) { int error = 0; +#ifdef VNET_NFSD + osd_method_t methods[PR_MAXMETHOD] = { + [PR_METHOD_REMOVE] = rpcgss_prison_cleanup, + }; +#endif switch (type) { case MOD_LOAD: @@ -331,6 +348,11 @@ rpc_gss_svc_max_data_length; mtx_init(&kgss_gssd_lock, "kgss_gssd_lock", NULL, MTX_DEF); error = kgss_load(); +#ifdef VNET_NFSD + /* XXX-BZ OSD to VNET? */ + if (error == 0) + osd_jail_register(NULL, methods); +#endif break; case MOD_UNLOAD: kgss_unload(); diff --git a/sys/kgssapi/gss_release_cred.c.vnetkgssapi b/sys/kgssapi/gss_release_cred.c --- a/sys/kgssapi/gss_release_cred.c.vnetkgssapi +++ b/sys/kgssapi/gss_release_cred.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -52,8 +53,12 @@ *minor_status = 0; - if (!kgss_gssd_handle) + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); + if (!KGSS_VNET(kgss_gssd_handle)) { + KGSS_CURVNET_RESTORE(); return (GSS_S_FAILURE); + } + KGSS_CURVNET_RESTORE(); if (*cred_handle) { args.cred = (*cred_handle)->handle; diff --git a/sys/kgssapi/gss_release_name.c.vnetkgssapi b/sys/kgssapi/gss_release_name.c --- a/sys/kgssapi/gss_release_name.c.vnetkgssapi +++ b/sys/kgssapi/gss_release_name.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -53,8 +54,12 @@ *minor_status = 0; - if (!kgss_gssd_handle) + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); + if (!KGSS_VNET(kgss_gssd_handle)) { + KGSS_CURVNET_RESTORE(); return (GSS_S_FAILURE); + } + KGSS_CURVNET_RESTORE(); if (*input_name) { name = *input_name; diff --git a/sys/kgssapi/gssapi_impl.h.vnetkgssapi b/sys/kgssapi/gssapi_impl.h --- a/sys/kgssapi/gssapi_impl.h.vnetkgssapi +++ b/sys/kgssapi/gssapi_impl.h @@ -54,9 +54,41 @@ }; LIST_HEAD(kgss_mech_list, kgss_mech); -extern CLIENT *kgss_gssd_handle; +/* Macros for VNET_NFSD. */ +#ifdef VNET_NFSD +#if !defined(VIMAGE) +options VNET_NFSD also requires options VIMAGE +#endif +/* Just define the VNET_KGSSxxx() macros as VNETxxx() macros. */ +#define KGSS_VNET_DEFINE(t, n) VNET_DEFINE(t, n) +#define KGSS_VNET_DEFINE_STATIC(t, n) VNET_DEFINE_STATIC(t, n) +#define KGSS_VNET_DECLARE(t, n) VNET_DECLARE(t, n) +#define KGSS_VNET(n) VNET(n) + +#define KGSS_CURVNET_SET(n) CURVNET_SET(n) +#define KGSS_CURVNET_SET_QUIET(n) CURVNET_SET_QUIET(n) +#define KGSS_CURVNET_RESTORE() CURVNET_RESTORE() +#define KGSS_TD_TO_VNET(n) TD_TO_VNET(n) + +/* Osd cleanup function. */ +int rpcgss_prison_cleanup(void *obj, void *data __unused); +#else /* !VNET_NFSD */ +/* Define the KGSS_VNET macros similar to !VIMAGE. */ +#define KGSS_VNET_DEFINE(t, n) t n +#define KGSS_VNET_DEFINE_STATIC(t, n) static t n +#define KGSS_VNET_DECLARE(t, n) extern t n +#define KGSS_VNET(n) (n) + +#define KGSS_CURVNET_SET(n) +#define KGSS_CURVNET_SET_QUIET(n) +#define KGSS_CURVNET_RESTORE() +#define KGSS_TD_TO_VNET(n) NULL +#endif /* VNET_NFSD */ + extern struct mtx kgss_gssd_lock; extern struct kgss_mech_list kgss_mechs; + +KGSS_VNET_DECLARE(CLIENT *, kgss_gssd_handle); CLIENT *kgss_gssd_client(void); int kgss_oid_equal(const gss_OID oid1, const gss_OID oid2); diff --git a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c.vnetkgssapi b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c --- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c.vnetkgssapi +++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c @@ -81,6 +81,7 @@ #include #include +#include #include "rpcsec_gss_int.h" @@ -102,8 +103,9 @@ SLIST_ENTRY(svc_rpc_gss_callback) cb_link; rpc_gss_callback_t cb_callback; }; -static SLIST_HEAD(svc_rpc_gss_callback_list, svc_rpc_gss_callback) - svc_rpc_gss_callbacks = SLIST_HEAD_INITIALIZER(svc_rpc_gss_callbacks); +SLIST_HEAD(svc_rpc_gss_callback_list, svc_rpc_gss_callback); +KGSS_VNET_DEFINE_STATIC(struct svc_rpc_gss_callback_list, + svc_rpc_gss_callbacks) = SLIST_HEAD_INITIALIZER(svc_rpc_gss_callbacks); struct svc_rpc_gss_svc_name { SLIST_ENTRY(svc_rpc_gss_svc_name) sn_link; @@ -114,8 +116,9 @@ u_int sn_program; u_int sn_version; }; -static SLIST_HEAD(svc_rpc_gss_svc_name_list, svc_rpc_gss_svc_name) - svc_rpc_gss_svc_names = SLIST_HEAD_INITIALIZER(svc_rpc_gss_svc_names); +SLIST_HEAD(svc_rpc_gss_svc_name_list, svc_rpc_gss_svc_name); +KGSS_VNET_DEFINE_STATIC(struct svc_rpc_gss_svc_name_list, + svc_rpc_gss_svc_names) = SLIST_HEAD_INITIALIZER(svc_rpc_gss_svc_names); enum svc_rpc_gss_client_state { CLIENT_NEW, /* still authenticating */ @@ -197,24 +200,45 @@ &svc_rpc_gss_client_count, 0, "Number of rpc-gss clients"); -struct svc_rpc_gss_client_list *svc_rpc_gss_client_hash; -struct svc_rpc_gss_client_list svc_rpc_gss_clients; -static uint32_t svc_rpc_gss_next_clientid = 1; +KGSS_VNET_DEFINE(struct svc_rpc_gss_client_list *, svc_rpc_gss_client_hash); +KGSS_VNET_DEFINE(struct svc_rpc_gss_client_list, svc_rpc_gss_clients); +KGSS_VNET_DEFINE_STATIC(uint32_t, svc_rpc_gss_next_clientid) = 1; static void svc_rpc_gss_init(void *arg) { int i; - svc_rpc_gss_client_hash = mem_alloc(sizeof(struct svc_rpc_gss_client_list) * svc_rpc_gss_client_hash_size); + KGSS_VNET(svc_rpc_gss_client_hash) = mem_alloc( + sizeof(struct svc_rpc_gss_client_list) * + svc_rpc_gss_client_hash_size); for (i = 0; i < svc_rpc_gss_client_hash_size; i++) - TAILQ_INIT(&svc_rpc_gss_client_hash[i]); - TAILQ_INIT(&svc_rpc_gss_clients); - svc_auth_reg(RPCSEC_GSS, svc_rpc_gss, rpc_gss_svc_getcred); - sx_init(&svc_rpc_gss_lock, "gsslock"); + TAILQ_INIT(&KGSS_VNET(svc_rpc_gss_client_hash)[i]); + TAILQ_INIT(&KGSS_VNET(svc_rpc_gss_clients)); + if (IS_DEFAULT_VNET(curvnet)) { + svc_auth_reg(RPCSEC_GSS, svc_rpc_gss, rpc_gss_svc_getcred); + sx_init(&svc_rpc_gss_lock, "gsslock"); + } } -SYSINIT(svc_rpc_gss_init, SI_SUB_KMEM, SI_ORDER_ANY, svc_rpc_gss_init, NULL); +VNET_SYSINIT(svc_rpc_gss_init, SI_SUB_VNET_DONE, SI_ORDER_ANY, + svc_rpc_gss_init, NULL); +#ifdef VNET_NFSD +/* Osd entry for prison cleanup. */ +int +rpcgss_prison_cleanup(void *obj, void *data __unused) +{ + struct prison *pr = obj; + + if ((pr->pr_flags & PR_VNET) == 0) + return (0); + KGSS_CURVNET_SET(pr->pr_vnet); + free(KGSS_VNET(svc_rpc_gss_client_hash), M_RPC); + KGSS_CURVNET_RESTORE(); + return (0); +} +#endif + bool_t rpc_gss_set_callback(rpc_gss_callback_t *cb) { @@ -227,7 +251,7 @@ } scb->cb_callback = *cb; sx_xlock(&svc_rpc_gss_lock); - SLIST_INSERT_HEAD(&svc_rpc_gss_callbacks, scb, cb_link); + SLIST_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_callbacks), scb, cb_link); sx_xunlock(&svc_rpc_gss_lock); return (TRUE); @@ -239,11 +263,11 @@ struct svc_rpc_gss_callback *scb; sx_xlock(&svc_rpc_gss_lock); - SLIST_FOREACH(scb, &svc_rpc_gss_callbacks, cb_link) { + SLIST_FOREACH(scb, &KGSS_VNET(svc_rpc_gss_callbacks), cb_link) { if (scb->cb_callback.program == cb->program && scb->cb_callback.version == cb->version && scb->cb_callback.callback == cb->callback) { - SLIST_REMOVE(&svc_rpc_gss_callbacks, scb, + SLIST_REMOVE(&KGSS_VNET(svc_rpc_gss_callbacks), scb, svc_rpc_gss_callback, cb_link); sx_xunlock(&svc_rpc_gss_lock); mem_free(scb, sizeof(*scb)); @@ -314,7 +338,7 @@ } sx_xlock(&svc_rpc_gss_lock); - SLIST_INSERT_HEAD(&svc_rpc_gss_svc_names, sname, sn_link); + SLIST_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_svc_names), sname, sn_link); sx_xunlock(&svc_rpc_gss_lock); return (TRUE); @@ -327,10 +351,10 @@ struct svc_rpc_gss_svc_name *sname; sx_xlock(&svc_rpc_gss_lock); - SLIST_FOREACH(sname, &svc_rpc_gss_svc_names, sn_link) { + SLIST_FOREACH(sname, &KGSS_VNET(svc_rpc_gss_svc_names), sn_link) { if (sname->sn_program == program && sname->sn_version == version) { - SLIST_REMOVE(&svc_rpc_gss_svc_names, sname, + SLIST_REMOVE(&KGSS_VNET(svc_rpc_gss_svc_names), sname, svc_rpc_gss_svc_name, sn_link); sx_xunlock(&svc_rpc_gss_lock); gss_release_cred(&min_stat, &sname->sn_cred); @@ -548,7 +572,8 @@ if (id->ci_hostid != hostid || id->ci_boottime != boottime.tv_sec) return (NULL); - list = &svc_rpc_gss_client_hash[id->ci_id % svc_rpc_gss_client_hash_size]; + list = &KGSS_VNET(svc_rpc_gss_client_hash) + [id->ci_id % svc_rpc_gss_client_hash_size]; sx_xlock(&svc_rpc_gss_lock); TAILQ_FOREACH(client, list, cl_link) { if (client->cl_id.ci_id == id->ci_id) { @@ -556,9 +581,10 @@ * Move this client to the front of the LRU * list. */ - TAILQ_REMOVE(&svc_rpc_gss_clients, client, cl_alllink); - TAILQ_INSERT_HEAD(&svc_rpc_gss_clients, client, + TAILQ_REMOVE(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink); + TAILQ_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_clients), + client, cl_alllink); refcount_acquire(&client->cl_refs); break; } @@ -591,7 +617,7 @@ client->cl_id.ci_hostid = hostid; getboottime(&boottime); client->cl_id.ci_boottime = boottime.tv_sec; - client->cl_id.ci_id = svc_rpc_gss_next_clientid++; + client->cl_id.ci_id = KGSS_VNET(svc_rpc_gss_next_clientid)++; /* * Start the client off with a short expiration time. We will @@ -601,10 +627,11 @@ client->cl_locked = FALSE; client->cl_expiration = time_uptime + 5*60; - list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; + list = &KGSS_VNET(svc_rpc_gss_client_hash) + [client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; sx_xlock(&svc_rpc_gss_lock); TAILQ_INSERT_HEAD(list, client, cl_link); - TAILQ_INSERT_HEAD(&svc_rpc_gss_clients, client, cl_alllink); + TAILQ_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink); svc_rpc_gss_client_count++; sx_xunlock(&svc_rpc_gss_lock); return (client); @@ -658,9 +685,10 @@ struct svc_rpc_gss_client_list *list; sx_assert(&svc_rpc_gss_lock, SX_XLOCKED); - list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; + list = &KGSS_VNET(svc_rpc_gss_client_hash) + [client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; TAILQ_REMOVE(list, client, cl_link); - TAILQ_REMOVE(&svc_rpc_gss_clients, client, cl_alllink); + TAILQ_REMOVE(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink); svc_rpc_gss_client_count--; } @@ -673,7 +701,8 @@ struct svc_rpc_gss_client_list *list; struct svc_rpc_gss_client *tclient; - list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; + list = &KGSS_VNET(svc_rpc_gss_client_hash) + [client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; sx_xlock(&svc_rpc_gss_lock); TAILQ_FOREACH(tclient, list, cl_link) { /* @@ -704,17 +733,18 @@ * svc_rpc_gss_clients in LRU order. */ sx_xlock(&svc_rpc_gss_lock); - client = TAILQ_LAST(&svc_rpc_gss_clients, svc_rpc_gss_client_list); + client = TAILQ_LAST(&KGSS_VNET(svc_rpc_gss_clients), + svc_rpc_gss_client_list); while (svc_rpc_gss_client_count > svc_rpc_gss_client_max && client != NULL) { svc_rpc_gss_forget_client_locked(client); sx_xunlock(&svc_rpc_gss_lock); svc_rpc_gss_release_client(client); sx_xlock(&svc_rpc_gss_lock); - client = TAILQ_LAST(&svc_rpc_gss_clients, + client = TAILQ_LAST(&KGSS_VNET(svc_rpc_gss_clients), svc_rpc_gss_client_list); } again: - TAILQ_FOREACH(client, &svc_rpc_gss_clients, cl_alllink) { + TAILQ_FOREACH(client, &KGSS_VNET(svc_rpc_gss_clients), cl_alllink) { if (client->cl_state == CLIENT_STALE || now > client->cl_expiration) { svc_rpc_gss_forget_client_locked(client); @@ -883,7 +913,8 @@ */ sx_xlock(&svc_rpc_gss_lock); if (!client->cl_sname) { - SLIST_FOREACH(sname, &svc_rpc_gss_svc_names, sn_link) { + SLIST_FOREACH(sname, &KGSS_VNET(svc_rpc_gss_svc_names), + sn_link) { if (sname->sn_program == rqst->rq_prog && sname->sn_version == rqst->rq_vers) { retry: @@ -1137,7 +1168,7 @@ * See if we have a callback for this guy. */ result = TRUE; - SLIST_FOREACH(scb, &svc_rpc_gss_callbacks, cb_link) { + SLIST_FOREACH(scb, &KGSS_VNET(svc_rpc_gss_callbacks), cb_link) { if (scb->cb_callback.program == rqst->rq_prog && scb->cb_callback.version == rqst->rq_vers) { /*