Commit ab4684d1 authored by Chuck Lever's avatar Chuck Lever Committed by J. Bruce Fields

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: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 8f199b82
...@@ -489,14 +489,20 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -489,14 +489,20 @@ nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
&access->ac_supported); &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 static __be32
nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_commit *commit) struct nfsd4_commit *commit)
{ {
u32 *p = (u32 *)commit->co_verf.data; gen_boot_verifier(&commit->co_verf);
*p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec;
return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset, return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
commit->co_count); commit->co_count);
} }
...@@ -873,7 +879,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -873,7 +879,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
{ {
stateid_t *stateid = &write->wr_stateid; stateid_t *stateid = &write->wr_stateid;
struct file *filp = NULL; struct file *filp = NULL;
u32 *p;
__be32 status = nfs_ok; __be32 status = nfs_ok;
unsigned long cnt; unsigned long cnt;
...@@ -895,9 +900,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -895,9 +900,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
cnt = write->wr_buflen; cnt = write->wr_buflen;
write->wr_how_written = write->wr_stable_how; write->wr_how_written = write->wr_stable_how;
p = (u32 *)write->wr_verifier.data; gen_boot_verifier(&write->wr_verifier);
*p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec;
status = nfsd_write(rqstp, &cstate->current_fh, filp, status = nfsd_write(rqstp, &cstate->current_fh, filp,
write->wr_offset, rqstp->rq_vec, write->wr_vlen, write->wr_offset, rqstp->rq_vec, write->wr_vlen,
......
...@@ -1174,12 +1174,12 @@ static void gen_clid(struct nfs4_client *clp) ...@@ -1174,12 +1174,12 @@ static void gen_clid(struct nfs4_client *clp)
static void gen_confirm(struct nfs4_client *clp) static void gen_confirm(struct nfs4_client *clp)
{ {
__be32 verf[2];
static u32 i; static u32 i;
u32 *p;
p = (u32 *)clp->cl_confirm.data; verf[0] = (__be32)get_seconds();
*p++ = get_seconds(); verf[1] = (__be32)i++;
*p++ = 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) static struct nfs4_stid *find_stateid(struct nfs4_client *cl, stateid_t *t)
......
...@@ -749,14 +749,14 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) ...@@ -749,14 +749,14 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
goto out; goto out;
break; break;
case NFS4_CREATE_EXCLUSIVE: case NFS4_CREATE_EXCLUSIVE:
READ_BUF(8); READ_BUF(NFS4_VERIFIER_SIZE);
COPYMEM(open->op_verf.data, 8); COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
break; break;
case NFS4_CREATE_EXCLUSIVE4_1: case NFS4_CREATE_EXCLUSIVE4_1:
if (argp->minorversion < 1) if (argp->minorversion < 1)
goto xdr_error; goto xdr_error;
READ_BUF(8); READ_BUF(NFS4_VERIFIER_SIZE);
COPYMEM(open->op_verf.data, 8); COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
status = nfsd4_decode_fattr(argp, open->op_bmval, status = nfsd4_decode_fattr(argp, open->op_bmval,
&open->op_iattr, &open->op_acl); &open->op_iattr, &open->op_acl);
if (status) if (status)
...@@ -989,8 +989,8 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient ...@@ -989,8 +989,8 @@ nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclient
{ {
DECODE_HEAD; DECODE_HEAD;
READ_BUF(8); READ_BUF(NFS4_VERIFIER_SIZE);
COPYMEM(setclientid->se_verf.data, 8); COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
status = nfsd4_decode_opaque(argp, &setclientid->se_name); status = nfsd4_decode_opaque(argp, &setclientid->se_name);
if (status) if (status)
...@@ -1015,9 +1015,9 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s ...@@ -1015,9 +1015,9 @@ nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_s
{ {
DECODE_HEAD; DECODE_HEAD;
READ_BUF(8 + sizeof(nfs4_verifier)); READ_BUF(8 + NFS4_VERIFIER_SIZE);
COPYMEM(&scd_c->sc_clientid, 8); COPYMEM(&scd_c->sc_clientid, 8);
COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier)); COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
DECODE_TAIL; DECODE_TAIL;
} }
...@@ -2659,8 +2659,8 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ ...@@ -2659,8 +2659,8 @@ nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
__be32 *p; __be32 *p;
if (!nfserr) { if (!nfserr) {
RESERVE_SPACE(8); RESERVE_SPACE(NFS4_VERIFIER_SIZE);
WRITEMEM(commit->co_verf.data, 8); WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE);
ADJUST_ARGS(); ADJUST_ARGS();
} }
return nfserr; return nfserr;
...@@ -3020,7 +3020,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 ...@@ -3020,7 +3020,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
if (resp->xbuf->page_len) if (resp->xbuf->page_len)
return nfserr_resource; return nfserr_resource;
RESERVE_SPACE(8); /* verifier */ RESERVE_SPACE(NFS4_VERIFIER_SIZE);
savep = p; savep = p;
/* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
...@@ -3221,9 +3221,9 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n ...@@ -3221,9 +3221,9 @@ nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct n
__be32 *p; __be32 *p;
if (!nfserr) { if (!nfserr) {
RESERVE_SPACE(8 + sizeof(nfs4_verifier)); RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE);
WRITEMEM(&scd->se_clientid, 8); WRITEMEM(&scd->se_clientid, 8);
WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier)); WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE);
ADJUST_ARGS(); ADJUST_ARGS();
} }
else if (nfserr == nfserr_clid_inuse) { else if (nfserr == nfserr_clid_inuse) {
...@@ -3244,7 +3244,7 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w ...@@ -3244,7 +3244,7 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
RESERVE_SPACE(16); RESERVE_SPACE(16);
WRITE32(write->wr_bytes_written); WRITE32(write->wr_bytes_written);
WRITE32(write->wr_how_written); WRITE32(write->wr_how_written);
WRITEMEM(write->wr_verifier.data, 8); WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE);
ADJUST_ARGS(); ADJUST_ARGS();
} }
return nfserr; return nfserr;
......
...@@ -228,7 +228,8 @@ struct nfsd4_open { ...@@ -228,7 +228,8 @@ struct nfsd4_open {
u32 op_createmode; /* request */ u32 op_createmode; /* request */
u32 op_bmval[3]; /* request */ u32 op_bmval[3]; /* request */
struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */ struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
nfs4_verifier verf; /* EXCLUSIVE4 */ nfs4_verifier op_verf __attribute__((aligned(32)));
/* EXCLUSIVE4 */
clientid_t op_clientid; /* request */ clientid_t op_clientid; /* request */
struct xdr_netobj op_owner; /* request */ struct xdr_netobj op_owner; /* request */
u32 op_seqid; /* request */ u32 op_seqid; /* request */
...@@ -247,7 +248,6 @@ struct nfsd4_open { ...@@ -247,7 +248,6 @@ struct nfsd4_open {
struct nfs4_acl *op_acl; struct nfs4_acl *op_acl;
}; };
#define op_iattr iattr #define op_iattr iattr
#define op_verf verf
struct nfsd4_open_confirm { struct nfsd4_open_confirm {
stateid_t oc_req_stateid /* request */; stateid_t oc_req_stateid /* request */;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment