Commit 5e16923b authored by NeilBrown's avatar NeilBrown Committed by Anna Schumaker
Browse files

NFS/SUNRPC: don't lookup machine credential until rpcauth_bindcred().



When NFS creates a machine credential, it is a "generic" credential,
not tied to any auth protocol, and is really just a container for
the princpal name.
This doesn't get linked to a genuine credential until rpcauth_bindcred()
is called.
The lookup always succeeds, so various places that test if the machine
credential is NULL, are pointless.

As a step towards getting rid of generic credentials, this patch gets
rid of generic machine credentials.  The nfs_client and rpc_client
just hold a pointer to a constant principal name.
When a machine credential is wanted, a special static 'struct rpc_cred'
pointer is used. rpcauth_bindcred() recognizes this, finds the
principal from the client, and binds the correct credential.

Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent ecd5f97e
Loading
Loading
Loading
Loading
+2 −9
Original line number Diff line number Diff line
@@ -151,7 +151,6 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version);
struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
{
	struct nfs_client *clp;
	struct rpc_cred *cred;
	int err = -ENOMEM;

	if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
@@ -182,9 +181,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
	clp->cl_proto = cl_init->proto;
	clp->cl_net = get_net(cl_init->net);

	cred = rpc_lookup_machine_cred("*");
	if (!IS_ERR(cred))
		clp->cl_machine_cred = cred;
	clp->cl_principal = "*";
	nfs_fscache_get_client_cookie(clp);

	return clp;
@@ -246,11 +243,6 @@ void nfs_free_client(struct nfs_client *clp)
	if (!IS_ERR(clp->cl_rpcclient))
		rpc_shutdown_client(clp->cl_rpcclient);

	if (clp->cl_machine_cred != NULL)
		put_rpccred(clp->cl_machine_cred);
	if (clp->cl_root_cred != NULL)
		put_rpccred(clp->cl_root_cred);

	put_net(clp->cl_net);
	put_nfs_version(clp->cl_nfs_mod);
	kfree(clp->cl_hostname);
@@ -529,6 +521,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
		return PTR_ERR(clnt);
	}

	clnt->cl_principal = clp->cl_principal;
	clp->cl_rpcclient = clnt;
	return 0;
}
+1 −8
Original line number Diff line number Diff line
@@ -338,7 +338,6 @@ static inline bool
_nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode,
		    struct rpc_clnt **clntp, struct rpc_message *msg)
{
	struct rpc_cred *newcred = NULL;
	rpc_authflavor_t flavor;

	if (sp4_mode == NFS_SP4_MACH_CRED_CLEANUP ||
@@ -353,13 +352,7 @@ _nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode,
			return false;
	}
	if (test_bit(sp4_mode, &clp->cl_sp4_flags)) {
		spin_lock(&clp->cl_lock);
		if (clp->cl_machine_cred != NULL)
			/* don't call get_rpccred on the machine cred -
			 * a reference will be held for life of clp */
			newcred = clp->cl_machine_cred;
		spin_unlock(&clp->cl_lock);
		msg->rpc_cred = newcred;
		msg->rpc_cred = rpc_machine_cred();

		flavor = clp->cl_rpcclient->cl_auth->au_flavor;
		WARN_ON_ONCE(flavor != RPC_AUTH_GSS_KRB5I &&
+4 −17
Original line number Diff line number Diff line
@@ -166,28 +166,15 @@ out:

struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp)
{
	struct rpc_cred *cred = clp->cl_root_cred;

	if (!cred)
		cred = clp->cl_machine_cred;
	if (cred)
		return get_rpccred(cred);
	return cred;
	return get_rpccred(rpc_machine_cred());
}

static void nfs4_root_machine_cred(struct nfs_client *clp)
{
	struct rpc_cred *new;

	new = rpc_lookup_machine_cred(NULL);
	spin_lock(&clp->cl_lock);
	if (clp->cl_root_cred == NULL) {
		clp->cl_root_cred = new;
		new = NULL;
	}
	spin_unlock(&clp->cl_lock);
	if (new != NULL)
		put_rpccred(new);
	/* Force root creds instead of machine */
	clp->cl_principal = NULL;
	clp->cl_rpcclient->cl_principal = NULL;
}

static struct rpc_cred *
+4 −8
Original line number Diff line number Diff line
@@ -847,14 +847,10 @@ static int max_cb_time(struct net *net)
static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
{
	if (clp->cl_minorversion == 0) {
		char *principal = clp->cl_cred.cr_targ_princ ?
		client->cl_principal = clp->cl_cred.cr_targ_princ ?
			clp->cl_cred.cr_targ_princ : "nfs";
		struct rpc_cred *cred;

		cred = rpc_lookup_machine_cred(principal);
		if (!IS_ERR(cred))
			get_rpccred(cred);
		return cred;
		return get_rpccred(rpc_machine_cred());
	} else {
		struct rpc_auth *auth = client->cl_auth;
		struct auth_cred acred = {};
+1 −2
Original line number Diff line number Diff line
@@ -58,8 +58,7 @@ struct nfs_client {
	struct nfs_subversion *	cl_nfs_mod;	/* pointer to nfs version module */

	u32			cl_minorversion;/* NFSv4 minorversion */
	struct rpc_cred		*cl_machine_cred;
	struct rpc_cred		*cl_root_cred;	/* Use when machine_cred is ineffective */
	const char *		cl_principal;  /* used for machine cred */

#if IS_ENABLED(CONFIG_NFS_V4)
	struct list_head	cl_ds_clients; /* auth flavor data servers */
Loading