From a41d1bc642641e36d620138f93f484921d361bce Mon Sep 17 00:00:00 2001 From: rmacklem Date: Tue, 18 Dec 2012 00:25:48 +0000 Subject: 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 --- sys/kgssapi/gss_impl.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'sys/kgssapi/gss_impl.c') diff --git a/sys/kgssapi/gss_impl.c b/sys/kgssapi/gss_impl.c index d66b4a9..365a876 100644 --- a/sys/kgssapi/gss_impl.c +++ b/sys/kgssapi/gss_impl.c @@ -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 = FALSE; 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, struct gssd_syscall_args *uap) 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, struct gssd_syscall_args *uap) 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, gss_buffer_t to) } /* + * 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, void *data) 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: /* -- cgit v1.1