diff options
-rw-r--r-- | fs/nfsd/nfs4proc.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 20 | ||||
-rw-r--r-- | include/linux/nfsd/xdr4.h | 1 |
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 | ||
1946 | static inline int access_valid(u32 x) | 1946 | static 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 | ||