diff --git a/sys/kgssapi/gss_delete_sec_context.c b/sys/kgssapi/gss_delete_sec_context.c index 4d520feb71b..82f9e6b8f37 100644 --- a/sys/kgssapi/gss_delete_sec_context.c +++ b/sys/kgssapi/gss_delete_sec_context.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -54,8 +55,12 @@ gss_delete_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, *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 b/sys/kgssapi/gss_impl.c index 9b1277298e3..aa882d9f333 100644 --- a/sys/kgssapi/gss_impl.c +++ b/sys/kgssapi/gss_impl.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -38,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -62,9 +64,10 @@ static struct syscall_helper_data gssd_syscalls[] = { }; 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 +137,12 @@ sys_gssd_syscall(struct thread *td, struct gssd_syscall_args *uap) } 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 +254,16 @@ kgss_transfer_context(gss_ctx_id_t ctx) 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 +297,13 @@ kgss_gssd_client(void) { 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); } diff --git a/sys/kgssapi/gss_release_cred.c b/sys/kgssapi/gss_release_cred.c index 70dd3a058ad..dfd4322a1a3 100644 --- a/sys/kgssapi/gss_release_cred.c +++ b/sys/kgssapi/gss_release_cred.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -52,8 +53,12 @@ gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) *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 b/sys/kgssapi/gss_release_name.c index 16050226cc8..4f7e8db5ae9 100644 --- a/sys/kgssapi/gss_release_name.c +++ b/sys/kgssapi/gss_release_name.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -53,8 +54,12 @@ gss_release_name(OM_uint32 *minor_status, gss_name_t *input_name) *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 b/sys/kgssapi/gssapi_impl.h index 1b8fb2ff6c3..72f379de4eb 100644 --- a/sys/kgssapi/gssapi_impl.h +++ b/sys/kgssapi/gssapi_impl.h @@ -54,10 +54,24 @@ struct kgss_mech { }; LIST_HEAD(kgss_mech_list, kgss_mech); -extern CLIENT *kgss_gssd_handle; +/* Macros for VIMAGE. */ +/* Define the KGSS_VNET macros similar to !VIMAGE. */ +#define KGSS_VNET_NAME(n) n +#define KGSS_VNET_DECLARE(t, n) extern t n +#define KGSS_VNET_DEFINE(t, n) t n +#define KGSS_VNET_DEFINE_STATIC(t, n) static 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 + 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); extern void kgss_install_mech(gss_OID mech_type, const char *name, diff --git a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c index f375a184d1c..d01ca1260a6 100644 --- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c +++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c @@ -102,8 +102,9 @@ struct svc_rpc_gss_callback { 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 +115,9 @@ struct svc_rpc_gss_svc_name { 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,23 +199,28 @@ SYSCTL_UINT(_kern_rpc_gss, OID_AUTO, client_count, CTLFLAG_RD, &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); +SYSINIT(svc_rpc_gss_init, SI_SUB_VNET_DONE, SI_ORDER_ANY, + svc_rpc_gss_init, NULL); bool_t rpc_gss_set_callback(rpc_gss_callback_t *cb) @@ -227,7 +234,7 @@ rpc_gss_set_callback(rpc_gss_callback_t *cb) } 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 +246,11 @@ rpc_gss_clear_callback(rpc_gss_callback_t *cb) 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 +321,7 @@ rpc_gss_set_svc_name(const char *principal, const char *mechanism, } 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 +334,10 @@ rpc_gss_clear_svc_name(u_int program, u_int version) 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); @@ -478,12 +485,7 @@ rpc_gss_svc_getcred(struct svc_req *req, struct ucred **crp, int *flavorp) cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid; cr->cr_rgid = cr->cr_svgid = uc->gid; crsetgroups(cr, uc->gidlen, uc->gidlist); -#ifdef VNET_NFSD - if (jailed(curthread->td_ucred)) - cr->cr_prison = curthread->td_ucred->cr_prison; - else -#endif - cr->cr_prison = &prison0; + cr->cr_prison = curthread->td_ucred->cr_prison; prison_hold(cr->cr_prison); *crp = crhold(cr); @@ -548,7 +550,8 @@ svc_rpc_gss_find_client(struct svc_rpc_gss_clientid *id) 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 +559,10 @@ svc_rpc_gss_find_client(struct svc_rpc_gss_clientid *id) * 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 +595,7 @@ svc_rpc_gss_create_client(void) 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 +605,11 @@ svc_rpc_gss_create_client(void) 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 +663,10 @@ svc_rpc_gss_forget_client_locked(struct svc_rpc_gss_client *client) 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 +679,8 @@ svc_rpc_gss_forget_client(struct svc_rpc_gss_client *client) 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 +711,18 @@ svc_rpc_gss_timeout_clients(void) * 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 +891,8 @@ svc_rpc_gss_accept_sec_context(struct svc_rpc_gss_client *client, */ 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 +1146,7 @@ svc_rpc_gss_callback(struct svc_rpc_gss_client *client, struct svc_req *rqst) * 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) { /* @@ -1273,6 +1282,7 @@ svc_rpc_gss(struct svc_req *rqst, struct rpc_msg *msg) int call_stat; enum auth_stat result; + KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); rpc_gss_log_debug("in svc_rpc_gss()"); /* Garbage collect old clients. */ @@ -1282,8 +1292,10 @@ svc_rpc_gss(struct svc_req *rqst, struct rpc_msg *msg) rqst->rq_verf = _null_auth; /* Deserialize client credentials. */ - if (rqst->rq_cred.oa_length <= 0) + if (rqst->rq_cred.oa_length <= 0) { + KGSS_CURVNET_RESTORE(); return (AUTH_BADCRED); + } memset(&gc, 0, sizeof(gc)); @@ -1292,6 +1304,7 @@ svc_rpc_gss(struct svc_req *rqst, struct rpc_msg *msg) if (!xdr_rpc_gss_cred(&xdrs, &gc)) { XDR_DESTROY(&xdrs); + KGSS_CURVNET_RESTORE(); return (AUTH_BADCRED); } XDR_DESTROY(&xdrs); @@ -1527,6 +1540,7 @@ out: svc_rpc_gss_release_client(client); xdr_free((xdrproc_t) xdr_rpc_gss_cred, (char *) &gc); + KGSS_CURVNET_RESTORE(); return (result); }