Re: [PATCH] NFSD: Fix nfs4_verifier memory alignment

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

 



On Fri, Mar 02, 2012 at 05:13:50PM -0500, Chuck Lever wrote:
> Clean up due to code review.
> 
> The nfs4_verifier's data field is not guaranteed to be u32-aligned.
> Casting an array of chars to a u32 * is considered generally
> hazardous.
> 
> We can fix most of this by using a __be32 array to generate the
> verifier's contents and then byte-copying it into the verifier field.
> 
> However, there is one spot where there is a backwards compatibility
> constraint: the do_nfsd_create() call expects a verifier which is
> 32-bit aligned.  Fix this spot by forcing the alignment of the create
> verifier in the nfsd4_open args structure.
> 
> Also, sizeof(nfs4_verifer) is the size of the in-core verifier data
> structure, but NFS4_VERIFIER_SIZE is the number of octets in an XDR'd
> verifier.  The two are not interchangeable, even if they happen to
> have the same value.
> 
> Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
> ---
> 
> Hi Bruce-
> 
> Compile-tested only.  Does this look reasonable?

Looks fine, but the setclientid verifier stuff belongs in a separate
patch.

--b.

> 
> 
>  fs/nfsd/nfs4proc.c  |   19 +++++++++++--------
>  fs/nfsd/nfs4state.c |    8 ++++----
>  fs/nfsd/nfs4xdr.c   |   28 ++++++++++++++--------------
>  fs/nfsd/xdr4.h      |    4 ++--
>  4 files changed, 31 insertions(+), 28 deletions(-)
> 
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index 896da74..e4b5748 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -481,14 +481,20 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  			   &access->ac_supported);
>  }
>  
> +static void gen_boot_verifier(nfs4_verifier *verifier)
> +{
> +	__be32 verf[2];
> +
> +	verf[0] = (__be32)nfssvc_boot.tv_sec;
> +	verf[1] = (__be32)nfssvc_boot.tv_usec;
> +	memcpy(verifier->data, verf, sizeof(verifier->data));
> +}
> +
>  static __be32
>  nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  	     struct nfsd4_commit *commit)
>  {
> -	u32 *p = (u32 *)commit->co_verf.data;
> -	*p++ = nfssvc_boot.tv_sec;
> -	*p++ = nfssvc_boot.tv_usec;
> -
> +	gen_boot_verifier(&commit->co_verf);
>  	return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
>  			     commit->co_count);
>  }
> @@ -865,7 +871,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  {
>  	stateid_t *stateid = &write->wr_stateid;
>  	struct file *filp = NULL;
> -	u32 *p;
>  	__be32 status = nfs_ok;
>  	unsigned long cnt;
>  
> @@ -887,9 +892,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  
>  	cnt = write->wr_buflen;
>  	write->wr_how_written = write->wr_stable_how;
> -	p = (u32 *)write->wr_verifier.data;
> -	*p++ = nfssvc_boot.tv_sec;
> -	*p++ = nfssvc_boot.tv_usec;
> +	gen_boot_verifier(&write->wr_verifier);
>  
>  	status =  nfsd_write(rqstp, &cstate->current_fh, filp,
>  			     write->wr_offset, rqstp->rq_vec, write->wr_vlen,
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index c5cddd6..9f0e139 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -1138,12 +1138,12 @@ static void gen_clid(struct nfs4_client *clp)
>  
>  static void gen_confirm(struct nfs4_client *clp)
>  {
> +	__be32 verf[2];
>  	static u32 i;
> -	u32 *p;
>  
> -	p = (u32 *)clp->cl_confirm.data;
> -	*p++ = get_seconds();
> -	*p++ = i++;
> +	verf[0] = (__be32)get_seconds();
> +	verf[1] = (__be32)i++;
> +	memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data));
>  }
>  
>  static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t)
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index 0ec5a1b..1701ad6 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -755,14 +755,14 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
>  				goto out;
>  			break;
>  		case NFS4_CREATE_EXCLUSIVE:
> -			READ_BUF(8);
> -			COPYMEM(open->op_verf.data, 8);
> +			READ_BUF(NFS4_VERIFIER_SIZE);
> +			COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
>  			break;
>  		case NFS4_CREATE_EXCLUSIVE4_1:
>  			if (argp->minorversion < 1)
>  				goto xdr_error;
> -			READ_BUF(8);
> -			COPYMEM(open->op_verf.data, 8);
> +			READ_BUF(NFS4_VERIFIER_SIZE);
> +			COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
>  			status = nfsd4_decode_fattr(argp, open->op_bmval,
>  				&open->op_iattr, &open->op_acl);
>  			if (status)
> @@ -994,8 +994,8 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
>  {
>  	DECODE_HEAD;
>  
> -	READ_BUF(8);
> -	COPYMEM(setclientid->se_verf.data, 8);
> +	READ_BUF(NFS4_VERIFIER_SIZE);
> +	COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
>  
>  	status = nfsd4_decode_opaque(argp, &setclientid->se_name);
>  	if (status)
> @@ -1020,9 +1020,9 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s
>  {
>  	DECODE_HEAD;
>  
> -	READ_BUF(8 + sizeof(nfs4_verifier));
> +	READ_BUF(8 + NFS4_VERIFIER_SIZE);
>  	COPYMEM(&scd_c->sc_clientid, 8);
> -	COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier));
> +	COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
>  
>  	DECODE_TAIL;
>  }
> @@ -2661,8 +2661,8 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
>  	__be32 *p;
>  
>  	if (!nfserr) {
> -		RESERVE_SPACE(8);
> -		WRITEMEM(commit->co_verf.data, 8);
> +		RESERVE_SPACE(NFS4_VERIFIER_SIZE);
> +		WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE);
>  		ADJUST_ARGS();
>  	}
>  	return nfserr;
> @@ -3008,7 +3008,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
>  	if (resp->xbuf->page_len)
>  		return nfserr_resource;
>  
> -	RESERVE_SPACE(8);  /* verifier */
> +	RESERVE_SPACE(NFS4_VERIFIER_SIZE);
>  	savep = p;
>  
>  	/* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
> @@ -3209,9 +3209,9 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n
>  	__be32 *p;
>  
>  	if (!nfserr) {
> -		RESERVE_SPACE(8 + sizeof(nfs4_verifier));
> +		RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE);
>  		WRITEMEM(&scd->se_clientid, 8);
> -		WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
> +		WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE);
>  		ADJUST_ARGS();
>  	}
>  	else if (nfserr == nfserr_clid_inuse) {
> @@ -3232,7 +3232,7 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
>  		RESERVE_SPACE(16);
>  		WRITE32(write->wr_bytes_written);
>  		WRITE32(write->wr_how_written);
> -		WRITEMEM(write->wr_verifier.data, 8);
> +		WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE);
>  		ADJUST_ARGS();
>  	}
>  	return nfserr;
> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> index 2364747..8d1031a 100644
> --- a/fs/nfsd/xdr4.h
> +++ b/fs/nfsd/xdr4.h
> @@ -216,7 +216,8 @@ struct nfsd4_open {
>  	u32		op_createmode;      /* request */
>  	u32		op_bmval[3];        /* request */
>  	struct iattr	iattr;              /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
> -	nfs4_verifier	verf;               /* EXCLUSIVE4 */
> +	nfs4_verifier	op_verf __attribute__((aligned(32)));
> +					    /* EXCLUSIVE4 */
>  	clientid_t	op_clientid;        /* request */
>  	struct xdr_netobj op_owner;           /* request */
>  	u32		op_seqid;           /* request */
> @@ -234,7 +235,6 @@ struct nfsd4_open {
>  	struct nfs4_acl *op_acl;
>  };
>  #define op_iattr	iattr
> -#define op_verf		verf
>  
>  struct nfsd4_open_confirm {
>  	stateid_t	oc_req_stateid		/* request */;
> 
--
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