diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2012-03-02 17:13:50 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-03-20 15:36:15 -0400 |
commit | ab4684d1560f8d77f6ce82bd3f1f82937070d397 (patch) | |
tree | 71da95fc7b956d6c69f9ecf5ef98a76b158c387f /fs/nfsd/nfs4proc.c | |
parent | 8f199b8262cb150d055d29ba31faf0128ace4714 (diff) |
NFSD: Fix nfs4_verifier memory alignment
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@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 3f7dbc410e3a..2a9036670b8f 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -489,14 +489,20 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
489 | &access->ac_supported); | 489 | &access->ac_supported); |
490 | } | 490 | } |
491 | 491 | ||
492 | static void gen_boot_verifier(nfs4_verifier *verifier) | ||
493 | { | ||
494 | __be32 verf[2]; | ||
495 | |||
496 | verf[0] = (__be32)nfssvc_boot.tv_sec; | ||
497 | verf[1] = (__be32)nfssvc_boot.tv_usec; | ||
498 | memcpy(verifier->data, verf, sizeof(verifier->data)); | ||
499 | } | ||
500 | |||
492 | static __be32 | 501 | static __be32 |
493 | nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 502 | nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
494 | struct nfsd4_commit *commit) | 503 | struct nfsd4_commit *commit) |
495 | { | 504 | { |
496 | u32 *p = (u32 *)commit->co_verf.data; | 505 | gen_boot_verifier(&commit->co_verf); |
497 | *p++ = nfssvc_boot.tv_sec; | ||
498 | *p++ = nfssvc_boot.tv_usec; | ||
499 | |||
500 | return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset, | 506 | return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset, |
501 | commit->co_count); | 507 | commit->co_count); |
502 | } | 508 | } |
@@ -873,7 +879,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
873 | { | 879 | { |
874 | stateid_t *stateid = &write->wr_stateid; | 880 | stateid_t *stateid = &write->wr_stateid; |
875 | struct file *filp = NULL; | 881 | struct file *filp = NULL; |
876 | u32 *p; | ||
877 | __be32 status = nfs_ok; | 882 | __be32 status = nfs_ok; |
878 | unsigned long cnt; | 883 | unsigned long cnt; |
879 | 884 | ||
@@ -895,9 +900,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
895 | 900 | ||
896 | cnt = write->wr_buflen; | 901 | cnt = write->wr_buflen; |
897 | write->wr_how_written = write->wr_stable_how; | 902 | write->wr_how_written = write->wr_stable_how; |
898 | p = (u32 *)write->wr_verifier.data; | 903 | gen_boot_verifier(&write->wr_verifier); |
899 | *p++ = nfssvc_boot.tv_sec; | ||
900 | *p++ = nfssvc_boot.tv_usec; | ||
901 | 904 | ||
902 | status = nfsd_write(rqstp, &cstate->current_fh, filp, | 905 | status = nfsd_write(rqstp, &cstate->current_fh, filp, |
903 | write->wr_offset, rqstp->rq_vec, write->wr_vlen, | 906 | write->wr_offset, rqstp->rq_vec, write->wr_vlen, |