Re: [PATCH 4/4] nfs: make nfs4_init_uniform_client_string use a dynamically allocated buffer

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

 



On Thu,  4 Jun 2015 12:44:29 -0400
Jeff Layton <jlayton@xxxxxxxxxxxxxxx> wrote:

> Change the uniform client string generator to use the same scheme as
> the nonuniform one. This one is a little simpler since we don't need to
> deal with RCU, but we do have two different cases, depending on whether
> there is a uniquifier or not.
> 
> Signed-off-by: Jeff Layton <jeff.layton@xxxxxxxxxxxxxxx>
> ---
>  fs/nfs/nfs4proc.c       | 105 ++++++++++++++++++++++++++++++++----------------
>  include/linux/nfs_xdr.h |   6 ---
>  2 files changed, 70 insertions(+), 41 deletions(-)
> 
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 49e3b3e55887..479b0f583f33 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -5000,28 +5000,71 @@ retry:
>  	return 0;
>  }
>  
> -static unsigned int
> -nfs4_init_uniform_client_string(struct nfs_client *clp,
> -				char *buf, size_t len)
> +static int
> +nfs4_init_uniquifier_client_string(struct nfs_client *clp)
>  {
> -	const char *nodename = clp->cl_rpcclient->cl_nodename;
> -	unsigned int result;
> +	int result;
> +	size_t len;
> +	char *str;
>  
>  	if (clp->cl_owner_id != NULL)
> -		return strlcpy(buf, clp->cl_owner_id, len);
> +		return 0;
> +

Self review...

The above isn't necessary since we check that in the caller.

> +	len = 10 + 10 + 1 + 10 + 1 +
> +		strlen(nfs4_client_id_uniquifier) + 1 +
> +		strlen(clp->cl_rpcclient->cl_nodename) + 1;
> +
> +	if (len > NFS4_OPAQUE_LIMIT + 1)
> +		return -EINVAL;
> +
> +	str = kmalloc(len, GFP_NOFS);
> +	if (!str)
> +		return -ENOMEM;
> +
> +	result = scnprintf(str, len, "Linux NFSv%u.%u %s/%s",
> +			clp->rpc_ops->version, clp->cl_minorversion,
> +			nfs4_client_id_uniquifier,
> +			clp->cl_rpcclient->cl_nodename);
> +	if (result >= len) {
> +		kfree(str);
> +		return -EINVAL;
> +	}
> +	clp->cl_owner_id = str;
> +	return 0;
> +}
> +
> +static int
> +nfs4_init_uniform_client_string(struct nfs_client *clp)
> +{
> +	int result;
> +	size_t len;
> +	char *str;
> +
> +	if (clp->cl_owner_id != NULL)
> +		return 0;
>  
>  	if (nfs4_client_id_uniquifier[0] != '\0')
> -		result = scnprintf(buf, len, "Linux NFSv%u.%u %s/%s",
> -				clp->rpc_ops->version,
> -				clp->cl_minorversion,
> -				nfs4_client_id_uniquifier,
> -				nodename);
> -	else
> -		result = scnprintf(buf, len, "Linux NFSv%u.%u %s",
> -				clp->rpc_ops->version, clp->cl_minorversion,
> -				nodename);
> -	clp->cl_owner_id = kstrdup(buf, GFP_NOFS);
> -	return result;
> +		return nfs4_init_uniquifier_client_string(clp);
> +
> +	len = 10 + 10 + 1 + 10 + 1 +
> +		strlen(clp->cl_rpcclient->cl_nodename) + 1;
> +
> +	str = kmalloc(len, GFP_NOFS);
> +	if (!str)
> +		return -ENOMEM;
> +
> +	if (len > NFS4_OPAQUE_LIMIT + 1)
> +		return -EINVAL;
> +

The above two if statements should be reordered. We want to check the
length before the allocation or we leak memory here when it's too long.
I'll fix that in v2 once everyone has had a chance to comment on the
rest.

> +	result = scnprintf(str, len, "Linux NFSv%u.%u %s",
> +			clp->rpc_ops->version, clp->cl_minorversion,
> +			clp->cl_rpcclient->cl_nodename);
> +	if (result >= len) {
> +		kfree(str);
> +		return -EINVAL;
> +	}
> +	clp->cl_owner_id = str;
> +	return 0;
>  }
>  
>  /*
> @@ -5088,20 +5131,14 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
>  
>  	/* nfs_client_id4 */
>  	nfs4_init_boot_verifier(clp, &sc_verifier);
> -	if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags)) {
> -		setclientid.sc_name_len =
> -				nfs4_init_uniform_client_string(clp,
> -						setclientid.sc_name,
> -						sizeof(setclientid.sc_name));
> -		if (!clp->cl_owner_id) {
> -			status = -ENOMEM;
> -			goto out;
> -		}
> -	} else {
> +
> +	if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags))
> +		status = nfs4_init_uniform_client_string(clp);
> +	else
>  		status = nfs4_init_nonuniform_client_string(clp);
> -		if (status)
> -			goto out;
> -	}
> +
> +	if (status)
> +		goto out;
>  
>  	/* cb_client4 */
>  	setclientid.sc_netid_len =
> @@ -6875,12 +6912,10 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
>  	};
>  
>  	nfs4_init_boot_verifier(clp, &verifier);
> -	args.id_len = nfs4_init_uniform_client_string(clp, args.id,
> -							sizeof(args.id));
> -	if (!clp->cl_owner_id) {
> -		status = -ENOMEM;
> +
> +	status = nfs4_init_uniform_client_string(clp);
> +	if (status)
>  		goto out;
> -	}
>  
>  	dprintk("NFS call  exchange_id auth=%s, '%s'\n",
>  		clp->cl_rpcclient->cl_auth->au_ops->au_name,
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 16991f5e274e..c959e7eb5bd4 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -984,11 +984,8 @@ struct nfs4_readlink_res {
>  	struct nfs4_sequence_res	seq_res;
>  };
>  
> -#define NFS4_SETCLIENTID_NAMELEN	(127)
>  struct nfs4_setclientid {
>  	const nfs4_verifier *		sc_verifier;
> -	unsigned int			sc_name_len;
> -	char				sc_name[NFS4_SETCLIENTID_NAMELEN + 1];
>  	u32				sc_prog;
>  	unsigned int			sc_netid_len;
>  	char				sc_netid[RPCBIND_MAXNETIDLEN + 1];
> @@ -1142,12 +1139,9 @@ struct nfs41_state_protection {
>  	struct nfs4_op_map allow;
>  };
>  
> -#define NFS4_EXCHANGE_ID_LEN	(48)
>  struct nfs41_exchange_id_args {
>  	struct nfs_client		*client;
>  	nfs4_verifier			*verifier;
> -	unsigned int 			id_len;
> -	char 				id[NFS4_EXCHANGE_ID_LEN];
>  	u32				flags;
>  	struct nfs41_state_protection	state_protect;
>  };


-- 
Jeff Layton <jlayton@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