Commit 61f98b0fca802d7e0191072606519e2230a6226d
Exists in
master
and in
20 other branches
Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
Pull nfsd bugfixes from Bruce Fields: "Just three minor bugfixes" * 'for-3.11' of git://linux-nfs.org/~bfields/linux: svcrdma: underflow issue in decode_write_list() nfsd4: fix minorversion support interface lockd: protect nlm_blocked access in nlmsvc_retry_blocked
Showing 5 changed files Side-by-side Diff
fs/lockd/svclock.c
... | ... | @@ -951,6 +951,7 @@ |
951 | 951 | unsigned long timeout = MAX_SCHEDULE_TIMEOUT; |
952 | 952 | struct nlm_block *block; |
953 | 953 | |
954 | + spin_lock(&nlm_blocked_lock); | |
954 | 955 | while (!list_empty(&nlm_blocked) && !kthread_should_stop()) { |
955 | 956 | block = list_entry(nlm_blocked.next, struct nlm_block, b_list); |
956 | 957 | |
... | ... | @@ -960,6 +961,7 @@ |
960 | 961 | timeout = block->b_when - jiffies; |
961 | 962 | break; |
962 | 963 | } |
964 | + spin_unlock(&nlm_blocked_lock); | |
963 | 965 | |
964 | 966 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", |
965 | 967 | block, block->b_when); |
966 | 968 | |
... | ... | @@ -969,7 +971,9 @@ |
969 | 971 | retry_deferred_block(block); |
970 | 972 | } else |
971 | 973 | nlmsvc_grant_blocked(block); |
974 | + spin_lock(&nlm_blocked_lock); | |
972 | 975 | } |
976 | + spin_unlock(&nlm_blocked_lock); | |
973 | 977 | |
974 | 978 | return timeout; |
975 | 979 | } |
fs/nfsd/nfs4proc.c
... | ... | @@ -1293,7 +1293,7 @@ |
1293 | 1293 | * According to RFC3010, this takes precedence over all other errors. |
1294 | 1294 | */ |
1295 | 1295 | status = nfserr_minor_vers_mismatch; |
1296 | - if (args->minorversion > nfsd_supported_minorversion) | |
1296 | + if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0) | |
1297 | 1297 | goto out; |
1298 | 1298 | |
1299 | 1299 | status = nfs41_check_op_ordering(args); |
fs/nfsd/nfsd.h
... | ... | @@ -53,7 +53,6 @@ |
53 | 53 | extern struct svc_program nfsd_program; |
54 | 54 | extern struct svc_version nfsd_version2, nfsd_version3, |
55 | 55 | nfsd_version4; |
56 | -extern u32 nfsd_supported_minorversion; | |
57 | 56 | extern struct mutex nfsd_mutex; |
58 | 57 | extern spinlock_t nfsd_drc_lock; |
59 | 58 | extern unsigned long nfsd_drc_max_mem; |
fs/nfsd/nfssvc.c
... | ... | @@ -116,7 +116,10 @@ |
116 | 116 | |
117 | 117 | }; |
118 | 118 | |
119 | -u32 nfsd_supported_minorversion = 1; | |
119 | +static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = { | |
120 | + [0] = 1, | |
121 | + [1] = 1, | |
122 | +}; | |
120 | 123 | |
121 | 124 | int nfsd_vers(int vers, enum vers_op change) |
122 | 125 | { |
123 | 126 | |
124 | 127 | |
... | ... | @@ -151,15 +154,13 @@ |
151 | 154 | return -1; |
152 | 155 | switch(change) { |
153 | 156 | case NFSD_SET: |
154 | - nfsd_supported_minorversion = minorversion; | |
157 | + nfsd_supported_minorversions[minorversion] = true; | |
155 | 158 | break; |
156 | 159 | case NFSD_CLEAR: |
157 | - if (minorversion == 0) | |
158 | - return -1; | |
159 | - nfsd_supported_minorversion = minorversion - 1; | |
160 | + nfsd_supported_minorversions[minorversion] = false; | |
160 | 161 | break; |
161 | 162 | case NFSD_TEST: |
162 | - return minorversion <= nfsd_supported_minorversion; | |
163 | + return nfsd_supported_minorversions[minorversion]; | |
163 | 164 | case NFSD_AVAIL: |
164 | 165 | return minorversion <= NFSD_SUPPORTED_MINOR_VERSION; |
165 | 166 | } |
net/sunrpc/xprtrdma/svc_rdma_marshal.c
... | ... | @@ -98,6 +98,7 @@ |
98 | 98 | */ |
99 | 99 | static u32 *decode_write_list(u32 *va, u32 *vaend) |
100 | 100 | { |
101 | + unsigned long start, end; | |
101 | 102 | int nchunks; |
102 | 103 | |
103 | 104 | struct rpcrdma_write_array *ary = |
... | ... | @@ -113,9 +114,12 @@ |
113 | 114 | return NULL; |
114 | 115 | } |
115 | 116 | nchunks = ntohl(ary->wc_nchunks); |
116 | - if (((unsigned long)&ary->wc_array[0] + | |
117 | - (sizeof(struct rpcrdma_write_chunk) * nchunks)) > | |
118 | - (unsigned long)vaend) { | |
117 | + | |
118 | + start = (unsigned long)&ary->wc_array[0]; | |
119 | + end = (unsigned long)vaend; | |
120 | + if (nchunks < 0 || | |
121 | + nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) || | |
122 | + (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) { | |
119 | 123 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", |
120 | 124 | ary, nchunks, vaend); |
121 | 125 | return NULL; |
... | ... | @@ -129,6 +133,7 @@ |
129 | 133 | |
130 | 134 | static u32 *decode_reply_array(u32 *va, u32 *vaend) |
131 | 135 | { |
136 | + unsigned long start, end; | |
132 | 137 | int nchunks; |
133 | 138 | struct rpcrdma_write_array *ary = |
134 | 139 | (struct rpcrdma_write_array *)va; |
... | ... | @@ -143,9 +148,12 @@ |
143 | 148 | return NULL; |
144 | 149 | } |
145 | 150 | nchunks = ntohl(ary->wc_nchunks); |
146 | - if (((unsigned long)&ary->wc_array[0] + | |
147 | - (sizeof(struct rpcrdma_write_chunk) * nchunks)) > | |
148 | - (unsigned long)vaend) { | |
151 | + | |
152 | + start = (unsigned long)&ary->wc_array[0]; | |
153 | + end = (unsigned long)vaend; | |
154 | + if (nchunks < 0 || | |
155 | + nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) || | |
156 | + (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) { | |
149 | 157 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", |
150 | 158 | ary, nchunks, vaend); |
151 | 159 | return NULL; |