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
This commit is contained in:
Rick Macklem 2025-07-19 07:51:40 -07:00
parent e46c15a0f8
commit a28a65140f

View file

@ -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;