aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4proc.c1
-rw-r--r--fs/nfsd/nfs4state.c20
-rw-r--r--include/linux/nfsd/xdr4.h1
3 files changed, 17 insertions, 5 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 3fdcca53212a..db208dd8fdca 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -910,6 +910,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
910 resp->tag = args->tag; 910 resp->tag = args->tag;
911 resp->opcnt = 0; 911 resp->opcnt = 0;
912 resp->rqstp = rqstp; 912 resp->rqstp = rqstp;
913 resp->cstate.minorversion = args->minorversion;
913 resp->cstate.replay_owner = NULL; 914 resp->cstate.replay_owner = NULL;
914 fh_init(&resp->cstate.current_fh, NFS4_FHSIZE); 915 fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
915 fh_init(&resp->cstate.save_fh, NFS4_FHSIZE); 916 fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d227f85b5ed2..374aaf3808e8 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1943,11 +1943,21 @@ find_file(struct inode *ino)
1943 return NULL; 1943 return NULL;
1944} 1944}
1945 1945
1946static inline int access_valid(u32 x) 1946static inline int access_valid(u32 x, u32 minorversion)
1947{ 1947{
1948 if (x < NFS4_SHARE_ACCESS_READ) 1948 if ((x & NFS4_SHARE_ACCESS_MASK) < NFS4_SHARE_ACCESS_READ)
1949 return 0; 1949 return 0;
1950 if (x > NFS4_SHARE_ACCESS_BOTH) 1950 if ((x & NFS4_SHARE_ACCESS_MASK) > NFS4_SHARE_ACCESS_BOTH)
1951 return 0;
1952 x &= ~NFS4_SHARE_ACCESS_MASK;
1953 if (minorversion && x) {
1954 if ((x & NFS4_SHARE_WANT_MASK) > NFS4_SHARE_WANT_CANCEL)
1955 return 0;
1956 if ((x & NFS4_SHARE_WHEN_MASK) > NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED)
1957 return 0;
1958 x &= ~(NFS4_SHARE_WANT_MASK | NFS4_SHARE_WHEN_MASK);
1959 }
1960 if (x)
1951 return 0; 1961 return 0;
1952 return 1; 1962 return 1;
1953} 1963}
@@ -2495,7 +2505,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
2495 __be32 status; 2505 __be32 status;
2496 2506
2497 status = nfserr_inval; 2507 status = nfserr_inval;
2498 if (!access_valid(open->op_share_access) 2508 if (!access_valid(open->op_share_access, resp->cstate.minorversion)
2499 || !deny_valid(open->op_share_deny)) 2509 || !deny_valid(open->op_share_deny))
2500 goto out; 2510 goto out;
2501 /* 2511 /*
@@ -3104,7 +3114,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
3104 (int)cstate->current_fh.fh_dentry->d_name.len, 3114 (int)cstate->current_fh.fh_dentry->d_name.len,
3105 cstate->current_fh.fh_dentry->d_name.name); 3115 cstate->current_fh.fh_dentry->d_name.name);
3106 3116
3107 if (!access_valid(od->od_share_access) 3117 if (!access_valid(od->od_share_access, cstate->minorversion)
3108 || !deny_valid(od->od_share_deny)) 3118 || !deny_valid(od->od_share_deny))
3109 return nfserr_inval; 3119 return nfserr_inval;
3110 3120
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index b8b3dcba28cc..5e16935a1eaf 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -53,6 +53,7 @@ struct nfsd4_compound_state {
53 struct nfsd4_slot *slot; 53 struct nfsd4_slot *slot;
54 __be32 *statp; 54 __be32 *statp;
55 size_t iovlen; 55 size_t iovlen;
56 u32 minorversion;
56 u32 status; 57 u32 status;
57}; 58};
58 59