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

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
...@@ -910,6 +910,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, ...@@ -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);
......
...@@ -1943,11 +1943,21 @@ find_file(struct inode *ino) ...@@ -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 ...@@ -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, ...@@ -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;
......
...@@ -53,6 +53,7 @@ struct nfsd4_compound_state { ...@@ -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;
}; };
......
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