From owner-svn-src-head@FreeBSD.ORG Tue Dec 18 00:25:51 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 9D085CE5; Tue, 18 Dec 2012 00:25:51 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 7FF5F8FC1A; Tue, 18 Dec 2012 00:25:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qBI0Ppm2009921; Tue, 18 Dec 2012 00:25:51 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qBI0Pm9Z009904; Tue, 18 Dec 2012 00:25:48 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201212180025.qBI0Pm9Z009904@svn.freebsd.org> From: Rick Macklem Date: Tue, 18 Dec 2012 00:25:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r244370 - head/sys/kgssapi X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Dec 2012 00:25:51 -0000 Author: rmacklem Date: Tue Dec 18 00:25:48 2012 New Revision: 244370 URL: http://svnweb.freebsd.org/changeset/base/244370 Log: Piete.Brooks at cl.cam.ac.uk reported via email a crash which was caused by use of an invalid kgss_gssd_handle during an upcall to the gssd daemon when it has exited. This patch seems to avoid the crashes by holding a reference count on the kgss_gssd_handle until the upcall is done. It also adds a new mutex kgss_gssd_lock used to make manipulation of kgss_gssd_handle SMP safe. Tested by: Illias A. Marinos, Herbert Poeckl Reviewed by: jhb MFC after: 2 weeks Modified: head/sys/kgssapi/gss_accept_sec_context.c head/sys/kgssapi/gss_acquire_cred.c head/sys/kgssapi/gss_canonicalize_name.c head/sys/kgssapi/gss_delete_sec_context.c head/sys/kgssapi/gss_display_status.c head/sys/kgssapi/gss_export_name.c head/sys/kgssapi/gss_impl.c head/sys/kgssapi/gss_import_name.c head/sys/kgssapi/gss_init_sec_context.c head/sys/kgssapi/gss_pname_to_uid.c head/sys/kgssapi/gss_release_cred.c head/sys/kgssapi/gss_release_name.c head/sys/kgssapi/gss_set_cred_option.c head/sys/kgssapi/gssapi_impl.h Modified: head/sys/kgssapi/gss_accept_sec_context.c ============================================================================== --- head/sys/kgssapi/gss_accept_sec_context.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_accept_sec_context.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -58,9 +60,13 @@ OM_uint32 gss_accept_sec_context(OM_uint gss_ctx_id_t ctx = *context_handle; gss_name_t name; gss_cred_id_t cred; + CLIENT *cl; - if (!kgss_gssd_handle) + cl = kgss_gssd_client(); + if (cl == NULL) { + *minor_status = 0; return (GSS_S_FAILURE); + } if (ctx) args.ctx = ctx->handle; @@ -74,7 +80,8 @@ OM_uint32 gss_accept_sec_context(OM_uint args.input_chan_bindings = input_chan_bindings; bzero(&res, sizeof(res)); - stat = gssd_accept_sec_context_1(&args, &res, kgss_gssd_handle); + stat = gssd_accept_sec_context_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); Modified: head/sys/kgssapi/gss_acquire_cred.c ============================================================================== --- head/sys/kgssapi/gss_acquire_cred.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_acquire_cred.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -55,8 +57,11 @@ gss_acquire_cred(OM_uint32 *minor_status enum clnt_stat stat; gss_cred_id_t cred; int i; + CLIENT *cl; - if (!kgss_gssd_handle) + *minor_status = 0; + cl = kgss_gssd_client(); + if (cl == NULL) return (GSS_S_FAILURE); args.uid = curthread->td_ucred->cr_uid; @@ -69,7 +74,8 @@ gss_acquire_cred(OM_uint32 *minor_status args.cred_usage = cred_usage; bzero(&res, sizeof(res)); - stat = gssd_acquire_cred_1(&args, &res, kgss_gssd_handle); + stat = gssd_acquire_cred_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); @@ -80,7 +86,6 @@ gss_acquire_cred(OM_uint32 *minor_status return (res.major_status); } - *minor_status = 0; cred = malloc(sizeof(struct _gss_cred_id_t), M_GSSAPI, M_WAITOK); cred->handle = res.output_cred; *output_cred_handle = cred; Modified: head/sys/kgssapi/gss_canonicalize_name.c ============================================================================== --- head/sys/kgssapi/gss_canonicalize_name.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_canonicalize_name.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -48,15 +50,19 @@ gss_canonicalize_name(OM_uint32 *minor_s struct canonicalize_name_args args; enum clnt_stat stat; gss_name_t name; + CLIENT *cl; - if (!kgss_gssd_handle) + *minor_status = 0; + cl = kgss_gssd_client(); + if (cl == NULL) return (GSS_S_FAILURE); args.input_name = input_name->handle; args.mech_type = mech_type; bzero(&res, sizeof(res)); - stat = gssd_canonicalize_name_1(&args, &res, kgss_gssd_handle); + stat = gssd_canonicalize_name_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); @@ -69,7 +75,6 @@ gss_canonicalize_name(OM_uint32 *minor_s name = malloc(sizeof(struct _gss_name_t), M_GSSAPI, M_WAITOK); name->handle = res.output_name; - *minor_status = 0; *output_name = name; return (GSS_S_COMPLETE); Modified: head/sys/kgssapi/gss_delete_sec_context.c ============================================================================== --- head/sys/kgssapi/gss_delete_sec_context.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_delete_sec_context.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -46,6 +48,9 @@ gss_delete_sec_context(OM_uint32 *minor_ struct delete_sec_context_args args; enum clnt_stat stat; gss_ctx_id_t ctx; + CLIENT *cl; + + *minor_status = 0; if (!kgss_gssd_handle) return (GSS_S_FAILURE); @@ -60,9 +65,13 @@ gss_delete_sec_context(OM_uint32 *minor_ */ if (ctx->handle) { args.ctx = ctx->handle; + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); bzero(&res, sizeof(res)); - stat = gssd_delete_sec_context_1(&args, &res, kgss_gssd_handle); + stat = gssd_delete_sec_context_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); @@ -85,7 +94,5 @@ gss_delete_sec_context(OM_uint32 *minor_ } } - *minor_status = 0; - return (GSS_S_COMPLETE); } Modified: head/sys/kgssapi/gss_display_status.c ============================================================================== --- head/sys/kgssapi/gss_display_status.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_display_status.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -49,8 +51,11 @@ gss_display_status(OM_uint32 *minor_stat struct display_status_res res; struct display_status_args args; enum clnt_stat stat; + CLIENT *cl; - if (!kgss_gssd_handle) + *minor_status = 0; + cl = kgss_gssd_client(); + if (cl == NULL) return (GSS_S_FAILURE); args.status_value = status_value; @@ -59,7 +64,8 @@ gss_display_status(OM_uint32 *minor_stat args.message_context = *message_context; bzero(&res, sizeof(res)); - stat = gssd_display_status_1(&args, &res, kgss_gssd_handle); + stat = gssd_display_status_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); @@ -70,7 +76,6 @@ gss_display_status(OM_uint32 *minor_stat return (res.major_status); } - *minor_status = 0; *message_context = res.message_context; kgss_copy_buffer(&res.status_string, status_string); xdr_free((xdrproc_t) xdr_display_status_res, &res); Modified: head/sys/kgssapi/gss_export_name.c ============================================================================== --- head/sys/kgssapi/gss_export_name.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_export_name.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -45,14 +47,18 @@ gss_export_name(OM_uint32 *minor_status, struct export_name_res res; struct export_name_args args; enum clnt_stat stat; + CLIENT *cl; - if (!kgss_gssd_handle) + *minor_status = 0; + cl = kgss_gssd_client(); + if (cl == NULL) return (GSS_S_FAILURE); args.input_name = input_name->handle; bzero(&res, sizeof(res)); - stat = gssd_export_name_1(&args, &res, kgss_gssd_handle); + stat = gssd_export_name_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); @@ -63,7 +69,6 @@ gss_export_name(OM_uint32 *minor_status, return (res.major_status); } - *minor_status = 0; kgss_copy_buffer(&res.exported_name, exported_name); xdr_free((xdrproc_t) xdr_export_name_res, &res); Modified: head/sys/kgssapi/gss_impl.c ============================================================================== --- head/sys/kgssapi/gss_impl.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_impl.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,8 +31,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include #include #include @@ -59,6 +61,7 @@ static bool_t gssd_syscall_registered = struct kgss_mech_list kgss_mechs; CLIENT *kgss_gssd_handle; +struct mtx kgss_gssd_lock; static void kgss_init(void *dummy) @@ -92,14 +95,12 @@ sys_gssd_syscall(struct thread *td, stru struct netconfig *nconf; char path[MAXPATHLEN]; int error; + CLIENT *cl, *oldcl; error = priv_check(td, PRIV_NFS_DAEMON); if (error) return (error); - if (kgss_gssd_handle) - CLNT_DESTROY(kgss_gssd_handle); - error = copyinstr(uap->path, path, sizeof(path), NULL); if (error) return (error); @@ -109,10 +110,20 @@ sys_gssd_syscall(struct thread *td, stru sun.sun_len = SUN_LEN(&sun); nconf = getnetconfigent("local"); - kgss_gssd_handle = clnt_reconnect_create(nconf, + cl = clnt_reconnect_create(nconf, (struct sockaddr *) &sun, GSSD, GSSDVERS, RPC_MAXDATASIZE, RPC_MAXDATASIZE); + mtx_lock(&kgss_gssd_lock); + oldcl = kgss_gssd_handle; + kgss_gssd_handle = cl; + mtx_unlock(&kgss_gssd_lock); + + if (oldcl != NULL) { + CLNT_CLOSE(oldcl); + CLNT_RELEASE(oldcl); + } + return (0); } @@ -249,6 +260,23 @@ kgss_copy_buffer(const gss_buffer_t from } /* + * Acquire the kgss_gssd_handle and return it with a reference count, + * if it is available. + */ +CLIENT * +kgss_gssd_client(void) +{ + CLIENT *cl; + + mtx_lock(&kgss_gssd_lock); + cl = kgss_gssd_handle; + if (cl != NULL) + CLNT_ACQUIRE(cl); + mtx_unlock(&kgss_gssd_lock); + return (cl); +} + +/* * Kernel module glue */ static int @@ -280,6 +308,7 @@ kgssapi_modevent(module_t mod, int type, rpc_gss_get_principal_name; rpc_gss_entries.rpc_gss_svc_max_data_length = rpc_gss_svc_max_data_length; + mtx_init(&kgss_gssd_lock, "kgss_gssd_lock", NULL, MTX_DEF); break; case MOD_UNLOAD: /* Modified: head/sys/kgssapi/gss_import_name.c ============================================================================== --- head/sys/kgssapi/gss_import_name.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_import_name.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -48,18 +50,21 @@ gss_import_name(OM_uint32 *minor_status, struct import_name_args args; enum clnt_stat stat; gss_name_t name; + CLIENT *cl; *minor_status = 0; *output_name = GSS_C_NO_NAME; - if (!kgss_gssd_handle) + cl = kgss_gssd_client(); + if (cl == NULL) return (GSS_S_FAILURE); args.input_name_buffer = *input_name_buffer; args.input_name_type = input_name_type; bzero(&res, sizeof(res)); - stat = gssd_import_name_1(&args, &res, kgss_gssd_handle); + stat = gssd_import_name_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); Modified: head/sys/kgssapi/gss_init_sec_context.c ============================================================================== --- head/sys/kgssapi/gss_init_sec_context.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_init_sec_context.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -60,10 +62,12 @@ gss_init_sec_context(OM_uint32 * minor_s struct init_sec_context_args args; enum clnt_stat stat; gss_ctx_id_t ctx = *context_handle; + CLIENT *cl; *minor_status = 0; - if (!kgss_gssd_handle) + cl = kgss_gssd_client(); + if (cl == NULL) return (GSS_S_FAILURE); args.uid = curthread->td_ucred->cr_uid; @@ -88,7 +92,8 @@ gss_init_sec_context(OM_uint32 * minor_s } bzero(&res, sizeof(res)); - stat = gssd_init_sec_context_1(&args, &res, kgss_gssd_handle); + stat = gssd_init_sec_context_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); Modified: head/sys/kgssapi/gss_pname_to_uid.c ============================================================================== --- head/sys/kgssapi/gss_pname_to_uid.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_pname_to_uid.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -45,20 +47,23 @@ gss_pname_to_uid(OM_uint32 *minor_status struct pname_to_uid_res res; struct pname_to_uid_args args; enum clnt_stat stat; + CLIENT *cl; *minor_status = 0; - if (!kgss_gssd_handle) - return (GSS_S_FAILURE); - if (pname == GSS_C_NO_NAME) return (GSS_S_BAD_NAME); + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); + args.pname = pname->handle; args.mech = mech; bzero(&res, sizeof(res)); - stat = gssd_pname_to_uid_1(&args, &res, kgss_gssd_handle); + stat = gssd_pname_to_uid_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); @@ -83,20 +88,23 @@ gss_pname_to_unix_cred(OM_uint32 *minor_ struct pname_to_uid_args args; enum clnt_stat stat; int i, n; + CLIENT *cl; *minor_status = 0; - if (!kgss_gssd_handle) - return (GSS_S_FAILURE); - if (pname == GSS_C_NO_NAME) return (GSS_S_BAD_NAME); + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); + args.pname = pname->handle; args.mech = mech; bzero(&res, sizeof(res)); - stat = gssd_pname_to_uid_1(&args, &res, kgss_gssd_handle); + stat = gssd_pname_to_uid_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); Modified: head/sys/kgssapi/gss_release_cred.c ============================================================================== --- head/sys/kgssapi/gss_release_cred.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_release_cred.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -44,13 +46,21 @@ gss_release_cred(OM_uint32 *minor_status struct release_cred_res res; struct release_cred_args args; enum clnt_stat stat; + CLIENT *cl; + + *minor_status = 0; if (!kgss_gssd_handle) return (GSS_S_FAILURE); if (*cred_handle) { args.cred = (*cred_handle)->handle; - stat = gssd_release_cred_1(&args, &res, kgss_gssd_handle); + + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); + stat = gssd_release_cred_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); @@ -63,7 +73,5 @@ gss_release_cred(OM_uint32 *minor_status return (res.major_status); } - *minor_status = 0; - return (GSS_S_COMPLETE); } Modified: head/sys/kgssapi/gss_release_name.c ============================================================================== --- head/sys/kgssapi/gss_release_name.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_release_name.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -45,6 +47,9 @@ gss_release_name(OM_uint32 *minor_status struct release_name_args args; enum clnt_stat stat; gss_name_t name; + CLIENT *cl; + + *minor_status = 0; if (!kgss_gssd_handle) return (GSS_S_FAILURE); @@ -53,7 +58,11 @@ gss_release_name(OM_uint32 *minor_status name = *input_name; args.input_name = name->handle; - stat = gssd_release_name_1(&args, &res, kgss_gssd_handle); + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); + stat = gssd_release_name_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); @@ -68,7 +77,5 @@ gss_release_name(OM_uint32 *minor_status } } - *minor_status = 0; - return (GSS_S_COMPLETE); } Modified: head/sys/kgssapi/gss_set_cred_option.c ============================================================================== --- head/sys/kgssapi/gss_set_cred_option.c Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gss_set_cred_option.c Tue Dec 18 00:25:48 2012 (r244370) @@ -31,7 +31,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -47,10 +49,12 @@ gss_set_cred_option(OM_uint32 *minor_sta struct set_cred_option_res res; struct set_cred_option_args args; enum clnt_stat stat; + CLIENT *cl; *minor_status = 0; - if (!kgss_gssd_handle) + cl = kgss_gssd_client(); + if (cl == NULL) return (GSS_S_FAILURE); if (cred) @@ -61,7 +65,8 @@ gss_set_cred_option(OM_uint32 *minor_sta args.option_value = *option_value; bzero(&res, sizeof(res)); - stat = gssd_set_cred_option_1(&args, &res, kgss_gssd_handle); + stat = gssd_set_cred_option_1(&args, &res, cl); + CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; Modified: head/sys/kgssapi/gssapi_impl.h ============================================================================== --- head/sys/kgssapi/gssapi_impl.h Tue Dec 18 00:00:07 2012 (r244369) +++ head/sys/kgssapi/gssapi_impl.h Tue Dec 18 00:25:48 2012 (r244370) @@ -53,8 +53,10 @@ struct kgss_mech { LIST_HEAD(kgss_mech_list, kgss_mech); extern CLIENT *kgss_gssd_handle; +extern struct mtx kgss_gssd_lock; extern struct kgss_mech_list kgss_mechs; +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, struct kobj_class *cls);