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

Commit d87a8ade authored by Andy Adamson's avatar Andy Adamson Committed by J. Bruce Fields
Browse files

nfsd41: access_valid



For nfs41, the open share flags are used also for
delegation "wants" and "signals".  Check that they are valid.

Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 60adfc50
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -910,6 +910,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
	resp->tag = args->tag;
	resp->tag = args->tag;
	resp->opcnt = 0;
	resp->opcnt = 0;
	resp->rqstp = rqstp;
	resp->rqstp = rqstp;
	resp->cstate.minorversion = args->minorversion;
	resp->cstate.replay_owner = NULL;
	resp->cstate.replay_owner = NULL;
	fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
	fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
	fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
	fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
+15 −5
Original line number Original line Diff line number Diff line
@@ -1943,11 +1943,21 @@ find_file(struct inode *ino)
	return NULL;
	return NULL;
}
}


static inline int access_valid(u32 x)
static inline int access_valid(u32 x, u32 minorversion)
{
{
	if (x < NFS4_SHARE_ACCESS_READ)
	if ((x & NFS4_SHARE_ACCESS_MASK) < NFS4_SHARE_ACCESS_READ)
		return 0;
		return 0;
	if (x > NFS4_SHARE_ACCESS_BOTH)
	if ((x & NFS4_SHARE_ACCESS_MASK) > NFS4_SHARE_ACCESS_BOTH)
		return 0;
	x &= ~NFS4_SHARE_ACCESS_MASK;
	if (minorversion && x) {
		if ((x & NFS4_SHARE_WANT_MASK) > NFS4_SHARE_WANT_CANCEL)
			return 0;
		if ((x & NFS4_SHARE_WHEN_MASK) > NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED)
			return 0;
		x &= ~(NFS4_SHARE_WANT_MASK | NFS4_SHARE_WHEN_MASK);
	}
	if (x)
		return 0;
		return 0;
	return 1;
	return 1;
}
}
@@ -2495,7 +2505,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
	__be32 status;
	__be32 status;


	status = nfserr_inval;
	status = nfserr_inval;
	if (!access_valid(open->op_share_access)
	if (!access_valid(open->op_share_access, resp->cstate.minorversion)
			|| !deny_valid(open->op_share_deny))
			|| !deny_valid(open->op_share_deny))
		goto out;
		goto out;
	/*
	/*
@@ -3104,7 +3114,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
			(int)cstate->current_fh.fh_dentry->d_name.len,
			(int)cstate->current_fh.fh_dentry->d_name.len,
			cstate->current_fh.fh_dentry->d_name.name);
			cstate->current_fh.fh_dentry->d_name.name);


	if (!access_valid(od->od_share_access)
	if (!access_valid(od->od_share_access, cstate->minorversion)
			|| !deny_valid(od->od_share_deny))
			|| !deny_valid(od->od_share_deny))
		return nfserr_inval;
		return nfserr_inval;


+1 −0
Original line number Original line Diff line number Diff line
@@ -53,6 +53,7 @@ struct nfsd4_compound_state {
	struct nfsd4_slot	*slot;
	struct nfsd4_slot	*slot;
	__be32			*statp;
	__be32			*statp;
	size_t			iovlen;
	size_t			iovlen;
	u32			minorversion;
	u32			status;
	u32			status;
};
};