Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+11 −8
Original line number Original line Diff line number Diff line
@@ -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,
{
{
	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,


	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,
+4 −4
Original line number Original line Diff line number Diff line
@@ -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)
+14 −14
Original line number Original line Diff line number Diff line
@@ -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
{
{
	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
{
{
	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_
	__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
	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
	__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
		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;
+2 −2
Original line number Original line Diff line number Diff line
@@ -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 {
	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 */;