Re: [PATCH 3/3] nfs4: copy acceptor name from context to nfs_client

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2014-04-10 at 16:29 -0400, Jeff Layton wrote:
> The current CB_COMPOUND handling code tries to compare the principal
> name of the request with the cl_hostname in the client. This is not
> guaranteed to ever work, particularly if the client happened to mount
> a CNAME of the server or a non-fqdn.
> 
> Fix this by instead comparing the cr_principal string with the acceptor
> name that we get from gssd. In the event that gssd didn't send one
> down (i.e. it was too old), then we fall back to trying to use the
> cl_hostname as we do today.
> 
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
>  fs/nfs/callback.c         | 12 ++++++++++++
>  fs/nfs/client.c           |  1 +
>  fs/nfs/nfs4proc.c         | 30 +++++++++++++++++++++++++++++-
>  include/linux/nfs_fs_sb.h |  1 +
>  include/linux/nfs_xdr.h   |  1 +
>  5 files changed, 44 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
> index 073b4cf67ed9..54de482143cc 100644
> --- a/fs/nfs/callback.c
> +++ b/fs/nfs/callback.c
> @@ -428,6 +428,18 @@ check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
>  	if (p == NULL)
>  		return 0;
>  
> +	/*
> +	 * Did we get the acceptor from userland during the SETCLIENID
> +	 * negotiation?
> +	 */
> +	if (clp->cl_acceptor)
> +		return !strcmp(p, clp->cl_acceptor);
> +
> +	/*
> +	 * Otherwise try to verify it using the cl_hostname. Note that this
> +	 * doesn't work if a non-canonical hostname was used in the devname.
> +	 */
> +
>  	/* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
>  
>  	if (memcmp(p, "nfs@", 4) != 0)
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 1d09289c8f0e..6a461378fcf2 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -252,6 +252,7 @@ void nfs_free_client(struct nfs_client *clp)
>  	put_net(clp->cl_net);
>  	put_nfs_version(clp->cl_nfs_mod);
>  	kfree(clp->cl_hostname);
> +	kfree(clp->cl_acceptor);
>  	kfree(clp);
>  
>  	dprintk("<-- nfs_free_client()\n");
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 397be39c6dc8..cc6c3fe3e060 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -4896,6 +4896,18 @@ nfs4_init_callback_netid(const struct nfs_client *clp, char *buf, size_t len)
>  		return scnprintf(buf, len, "tcp");
>  }
>  
> +static void nfs4_setclientid_done(struct rpc_task *task, void *calldata)
> +{
> +	struct nfs4_setclientid *sc = calldata;
> +
> +	if (task->tk_status == 0)
> +		*sc->sc_acceptor = rpcauth_stringify_acceptor(task->tk_rqstp->rq_cred);

We can't call a GFP_KERNEL memory allocator from within a RPC callback
function. This needs to be done outside the RPC call.

> +}
> +
> +static const struct rpc_call_ops nfs4_setclientid_ops = {
> +	.rpc_call_done = nfs4_setclientid_done,
> +};
> +
>  /**
>   * nfs4_proc_setclientid - Negotiate client ID
>   * @clp: state data structure
> @@ -4915,6 +4927,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
>  		.sc_verifier = &sc_verifier,
>  		.sc_prog = program,
>  		.sc_cb_ident = clp->cl_cb_ident,
> +		.sc_acceptor = &clp->cl_acceptor,
>  	};
>  	struct rpc_message msg = {
>  		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
> @@ -4922,6 +4935,14 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
>  		.rpc_resp = res,
>  		.rpc_cred = cred,
>  	};
> +	struct rpc_task *task;
> +	struct rpc_task_setup task_setup_data = {
> +		.rpc_client = clp->cl_rpcclient,
> +		.rpc_message = &msg,
> +		.callback_ops = &nfs4_setclientid_ops,
> +		.callback_data = &setclientid,
> +		.flags = RPC_TASK_TIMEOUT,
> +	};
>  	int status;
>  
>  	/* nfs_client_id4 */
> @@ -4948,7 +4969,14 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
>  	dprintk("NFS call  setclientid auth=%s, '%.*s'\n",
>  		clp->cl_rpcclient->cl_auth->au_ops->au_name,
>  		setclientid.sc_name_len, setclientid.sc_name);
> -	status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
> +	task = rpc_run_task(&task_setup_data);
> +	if (IS_ERR(task)) {
> +		status = PTR_ERR(task);
> +		goto out;
> +	}
> +	status = task->tk_status;

Why not just do it here?

> +	rpc_put_task(task);
> +out:
>  	trace_nfs4_setclientid(clp, status);
>  	dprintk("NFS reply setclientid: %d\n", status);
>  	return status;
> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
> index 1150ea41b626..922be2e050f5 100644
> --- a/include/linux/nfs_fs_sb.h
> +++ b/include/linux/nfs_fs_sb.h
> @@ -45,6 +45,7 @@ struct nfs_client {
>  	struct sockaddr_storage	cl_addr;	/* server identifier */
>  	size_t			cl_addrlen;
>  	char *			cl_hostname;	/* hostname of server */
> +	char *			cl_acceptor;	/* GSSAPI acceptor name */
>  	struct list_head	cl_share_link;	/* link in global client list */
>  	struct list_head	cl_superblocks;	/* List of nfs_server structs */
>  
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 6fb5b2335b59..5945d88a26e2 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -1010,6 +1010,7 @@ struct nfs4_setclientid {
>  	unsigned int			sc_uaddr_len;
>  	char				sc_uaddr[RPCBIND_MAXUADDRLEN + 1];
>  	u32				sc_cb_ident;
> +	char				**sc_acceptor;
>  };
>  
>  struct nfs4_setclientid_res {

-- 
Trond Myklebust
Linux NFS client maintainer, PrimaryData
trond.myklebust@xxxxxxxxxxxxxxx


--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux