The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=a28a65140f11b54c4555d7c30ef5ae42fdf4c8a0
commit a28a65140f11b54c4555d7c30ef5ae42fdf4c8a0 Author: Rick Macklem <rmack...@freebsd.org> AuthorDate: 2025-07-19 14:51:40 +0000 Commit: Rick Macklem <rmack...@freebsd.org> CommitDate: 2025-07-19 14:51:40 +0000 rpcsec_gss.c: Avoid panics in clnt_nl_call() When rpc_gss_init() calls gssd upcall functions like gssd_import_name(), clnt_nl_call() gets calls. clnt_nl_call() requires that the currect vnet be set up. The calling sequence looks something like: rpc_gss_init()->gssd_import_name()->gssd_import_name_1()-> clnt_call_private()->clnt_nl_call() (The call to rpc_gss_init() can happen from various places, such as nfs_getauth() and clnt_vc_call().) rpc_gss_init() does not know what socket is being used for NFS client->server RPCs and may be called from various places when any VOP_xxx()->RPC call is made. As such, the calling thread might be running within a jail. However, the gssd upcalls for the NFS client must always be done to the gssd running outside of any jails. This patch sets the CURVNET to vnet0 in rpc_gss_init() to fix the problem, since that is the vnet that always should be used. This must somehow be changed if NFS mounts in vnet jails is enabled. Reviewed by: glebius Differential Revision: https://reviews.freebsd.org/D51086 --- sys/rpc/rpcsec_gss/rpcsec_gss.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/rpc/rpcsec_gss/rpcsec_gss.c b/sys/rpc/rpcsec_gss/rpcsec_gss.c index 62c71937a185..983dd251f81f 100644 --- a/sys/rpc/rpcsec_gss/rpcsec_gss.c +++ b/sys/rpc/rpcsec_gss/rpcsec_gss.c @@ -67,6 +67,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/hash.h> +#include <sys/jail.h> #include <sys/kernel.h> #include <sys/kobj.h> #include <sys/lock.h> @@ -771,6 +772,17 @@ rpc_gss_init(AUTH *auth, rpc_gss_options_ret_t *options_ret) gd->gd_cred.gc_proc = RPCSEC_GSS_INIT; gd->gd_cred.gc_seq = 0; + /* + * XXX Threads from inside jails can get here via calls + * to clnt_vc_call()->AUTH_REFRESH()->rpc_gss_refresh() + * but the NFS mount is always done outside of the + * jails in vnet0. Since the thread credentials won't + * necessarily have cr_prison == vnet0 and this function + * has no access to the socket, using vnet0 seems the + * only option. This is broken if NFS mounts are enabled + * within vnet prisons. + */ + KGSS_CURVNET_SET_QUIET(vnet0); /* * For KerberosV, if there is a client principal name, that implies * that this is a host based initiator credential in the default @@ -994,12 +1006,14 @@ out: gss_delete_sec_context(&min_stat, &gd->gd_ctx, GSS_C_NO_BUFFER); } + KGSS_CURVNET_RESTORE(); mtx_lock(&gd->gd_lock); gd->gd_state = RPCSEC_GSS_START; wakeup(gd); mtx_unlock(&gd->gd_lock); return (FALSE); } + KGSS_CURVNET_RESTORE(); mtx_lock(&gd->gd_lock); gd->gd_state = RPCSEC_GSS_ESTABLISHED;