git: 033b4c1bff10 - main - kgssapi: use netlink RPC client to talk to gssd(8)

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Sat, 01 Feb 2025 09:02:07 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=033b4c1bff10925c286537e48cd2858a08cf6e70

commit 033b4c1bff10925c286537e48cd2858a08cf6e70
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-02-01 01:02:08 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-02-01 09:00:25 +0000

    kgssapi: use netlink RPC client to talk to gssd(8)
    
    Reviewed by:            rmacklem
    Differential Revision:  https://reviews.freebsd.org/D48552
---
 sys/kgssapi/gss_impl.c | 104 +++++++++++++------------------------------------
 1 file changed, 26 insertions(+), 78 deletions(-)

diff --git a/sys/kgssapi/gss_impl.c b/sys/kgssapi/gss_impl.c
index 98edd62d3247..e2569bea61f9 100644
--- a/sys/kgssapi/gss_impl.c
+++ b/sys/kgssapi/gss_impl.c
@@ -37,9 +37,6 @@
 #include <sys/mutex.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
-#include <sys/syscall.h>
-#include <sys/sysent.h>
-#include <sys/sysproto.h>
 
 #include <kgssapi/gssapi.h>
 #include <kgssapi/gssapi_impl.h>
@@ -52,14 +49,6 @@
 
 MALLOC_DEFINE(M_GSSAPI, "GSS-API", "GSS-API");
 
-/*
- * Syscall hooks
- */
-static struct syscall_helper_data gssd_syscalls[] = {
-	SYSCALL_INIT_HELPER(gssd_syscall),
-	SYSCALL_INIT_LAST
-};
-
 struct kgss_mech_list kgss_mechs;
 struct mtx kgss_gssd_lock;
 
@@ -68,87 +57,46 @@ KGSS_VNET_DEFINE(CLIENT *, kgss_gssd_handle) = NULL;
 static int
 kgss_load(void)
 {
-	int error;
+	CLIENT *cl;
 
 	LIST_INIT(&kgss_mechs);
-	error = syscall_helper_register(gssd_syscalls, SY_THR_STATIC_KLD);
-	if (error != 0)
-		return (error);
-	return (0);
-}
 
-static void
-kgss_unload(void)
-{
+	cl = client_nl_create("kgss", GSSD, GSSDVERS);
+	KASSERT(cl, ("%s: netlink client already exist", __func__));
 
-	syscall_helper_unregister(gssd_syscalls);
-}
+	/*
+	 * The transport default is no retries at all, since there could
+	 * be no userland listener to our messages.  We will retry for 5
+	 * minutes with 10 second interval.  This will potentially cure hosts
+	 * with misconfigured startup, where kernel starts sending GSS queries
+	 * before userland had started up the gssd(8) daemon.
+	 */
+	clnt_control(cl, CLSET_RETRIES, &(int){30});
+	clnt_control(cl, CLSET_TIMEOUT, &(struct timeval){.tv_sec = 300});
 
-int
-sys_gssd_syscall(struct thread *td, struct gssd_syscall_args *uap)
-{
-        struct sockaddr_un sun;
-        struct netconfig *nconf;
-	char path[MAXPATHLEN];
-	int error;
-	CLIENT *cl, *oldcl;
-        
-	error = priv_check(td, PRIV_NFS_DAEMON);
-	if (error)
-		return (error);
-
-	error = copyinstr(uap->path, path, sizeof(path), NULL);
-	if (error)
-		return (error);
-	if (strlen(path) + 1 > sizeof(sun.sun_path))
-		return (EINVAL);
-
-	if (path[0] != '\0') {
-		sun.sun_family = AF_LOCAL;
-		strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
-		sun.sun_len = SUN_LEN(&sun);
-		
-		nconf = getnetconfigent("local");
-		cl = clnt_reconnect_create(nconf,
-		    (struct sockaddr *) &sun, GSSD, GSSDVERS,
-		    RPC_MAXDATASIZE, RPC_MAXDATASIZE);
-		/*
-		 * The number of retries defaults to INT_MAX, which effectively
-		 * means an infinite, uninterruptable loop.  Limiting it to
-		 * five retries keeps it from running forever.
-		 */
-		if (cl != NULL) {
-			int retry_count = 5;
-			struct timeval timo;
-			CLNT_CONTROL(cl, CLSET_RETRIES, &retry_count);
-
-			/*
-			 * Set the timeout for an upcall to 5 minutes.  The
-			 * default of 25 seconds is not long enough for some
-			 * gss_XXX() calls done by the gssd(8) daemon.
-			 */
-			timo.tv_sec = 5 * 60;
-			timo.tv_usec = 0;
-			CLNT_CONTROL(cl, CLSET_TIMEOUT, &timo);
-		}
-	} else
-		cl = NULL;
+	/*
+	 * We literally wait on gssd(8), let's see that in top(1).
+	 */
+	clnt_control(cl, CLSET_WAITCHAN, "gssd");
 
 	KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread));
 	mtx_lock(&kgss_gssd_lock);
-	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);
-		CLNT_RELEASE(oldcl);
-	}
-
 	return (0);
 }
 
+static void
+kgss_unload(void)
+{
+
+	KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread));
+	clnt_destroy(KGSS_VNET(kgss_gssd_handle));
+	KGSS_CURVNET_RESTORE();
+}
+
 int
 kgss_oid_equal(const gss_OID oid1, const gss_OID oid2)
 {
@@ -361,7 +309,7 @@ static moduledata_t kgssapi_mod = {
 	kgssapi_modevent,
 	NULL,
 };
-DECLARE_MODULE(kgssapi, kgssapi_mod, SI_SUB_VFS, SI_ORDER_ANY);
+DECLARE_MODULE(kgssapi, kgssapi_mod, SI_SUB_VFS, SI_ORDER_SECOND);
 MODULE_DEPEND(kgssapi, xdr, 1, 1, 1);
 MODULE_DEPEND(kgssapi, krpc, 1, 1, 1);
 MODULE_VERSION(kgssapi, 1);