Commit 61f98b0f authored by Linus Torvalds's avatar Linus Torvalds

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
parents c0d15cc7 b2781e10
...@@ -951,6 +951,7 @@ nlmsvc_retry_blocked(void) ...@@ -951,6 +951,7 @@ nlmsvc_retry_blocked(void)
unsigned long timeout = MAX_SCHEDULE_TIMEOUT; unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
struct nlm_block *block; struct nlm_block *block;
spin_lock(&nlm_blocked_lock);
while (!list_empty(&nlm_blocked) && !kthread_should_stop()) { while (!list_empty(&nlm_blocked) && !kthread_should_stop()) {
block = list_entry(nlm_blocked.next, struct nlm_block, b_list); block = list_entry(nlm_blocked.next, struct nlm_block, b_list);
...@@ -960,6 +961,7 @@ nlmsvc_retry_blocked(void) ...@@ -960,6 +961,7 @@ nlmsvc_retry_blocked(void)
timeout = block->b_when - jiffies; timeout = block->b_when - jiffies;
break; break;
} }
spin_unlock(&nlm_blocked_lock);
dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
block, block->b_when); block, block->b_when);
...@@ -969,7 +971,9 @@ nlmsvc_retry_blocked(void) ...@@ -969,7 +971,9 @@ nlmsvc_retry_blocked(void)
retry_deferred_block(block); retry_deferred_block(block);
} else } else
nlmsvc_grant_blocked(block); nlmsvc_grant_blocked(block);
spin_lock(&nlm_blocked_lock);
} }
spin_unlock(&nlm_blocked_lock);
return timeout; return timeout;
} }
...@@ -1293,7 +1293,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, ...@@ -1293,7 +1293,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
* According to RFC3010, this takes precedence over all other errors. * According to RFC3010, this takes precedence over all other errors.
*/ */
status = nfserr_minor_vers_mismatch; status = nfserr_minor_vers_mismatch;
if (args->minorversion > nfsd_supported_minorversion) if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
goto out; goto out;
status = nfs41_check_op_ordering(args); status = nfs41_check_op_ordering(args);
......
...@@ -53,7 +53,6 @@ struct readdir_cd { ...@@ -53,7 +53,6 @@ struct readdir_cd {
extern struct svc_program nfsd_program; extern struct svc_program nfsd_program;
extern struct svc_version nfsd_version2, nfsd_version3, extern struct svc_version nfsd_version2, nfsd_version3,
nfsd_version4; nfsd_version4;
extern u32 nfsd_supported_minorversion;
extern struct mutex nfsd_mutex; extern struct mutex nfsd_mutex;
extern spinlock_t nfsd_drc_lock; extern spinlock_t nfsd_drc_lock;
extern unsigned long nfsd_drc_max_mem; extern unsigned long nfsd_drc_max_mem;
......
...@@ -116,7 +116,10 @@ struct svc_program nfsd_program = { ...@@ -116,7 +116,10 @@ struct svc_program nfsd_program = {
}; };
u32 nfsd_supported_minorversion = 1; static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = {
[0] = 1,
[1] = 1,
};
int nfsd_vers(int vers, enum vers_op change) int nfsd_vers(int vers, enum vers_op change)
{ {
...@@ -151,15 +154,13 @@ int nfsd_minorversion(u32 minorversion, enum vers_op change) ...@@ -151,15 +154,13 @@ int nfsd_minorversion(u32 minorversion, enum vers_op change)
return -1; return -1;
switch(change) { switch(change) {
case NFSD_SET: case NFSD_SET:
nfsd_supported_minorversion = minorversion; nfsd_supported_minorversions[minorversion] = true;
break; break;
case NFSD_CLEAR: case NFSD_CLEAR:
if (minorversion == 0) nfsd_supported_minorversions[minorversion] = false;
return -1;
nfsd_supported_minorversion = minorversion - 1;
break; break;
case NFSD_TEST: case NFSD_TEST:
return minorversion <= nfsd_supported_minorversion; return nfsd_supported_minorversions[minorversion];
case NFSD_AVAIL: case NFSD_AVAIL:
return minorversion <= NFSD_SUPPORTED_MINOR_VERSION; return minorversion <= NFSD_SUPPORTED_MINOR_VERSION;
} }
......
...@@ -98,6 +98,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, ...@@ -98,6 +98,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch,
*/ */
static u32 *decode_write_list(u32 *va, u32 *vaend) static u32 *decode_write_list(u32 *va, u32 *vaend)
{ {
unsigned long start, end;
int nchunks; int nchunks;
struct rpcrdma_write_array *ary = struct rpcrdma_write_array *ary =
...@@ -113,9 +114,12 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) ...@@ -113,9 +114,12 @@ static u32 *decode_write_list(u32 *va, u32 *vaend)
return NULL; return NULL;
} }
nchunks = ntohl(ary->wc_nchunks); nchunks = ntohl(ary->wc_nchunks);
if (((unsigned long)&ary->wc_array[0] +
(sizeof(struct rpcrdma_write_chunk) * nchunks)) > start = (unsigned long)&ary->wc_array[0];
(unsigned long)vaend) { end = (unsigned long)vaend;
if (nchunks < 0 ||
nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) ||
(start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) {
dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
ary, nchunks, vaend); ary, nchunks, vaend);
return NULL; return NULL;
...@@ -129,6 +133,7 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) ...@@ -129,6 +133,7 @@ static u32 *decode_write_list(u32 *va, u32 *vaend)
static u32 *decode_reply_array(u32 *va, u32 *vaend) static u32 *decode_reply_array(u32 *va, u32 *vaend)
{ {
unsigned long start, end;
int nchunks; int nchunks;
struct rpcrdma_write_array *ary = struct rpcrdma_write_array *ary =
(struct rpcrdma_write_array *)va; (struct rpcrdma_write_array *)va;
...@@ -143,9 +148,12 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend) ...@@ -143,9 +148,12 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend)
return NULL; return NULL;
} }
nchunks = ntohl(ary->wc_nchunks); nchunks = ntohl(ary->wc_nchunks);
if (((unsigned long)&ary->wc_array[0] +
(sizeof(struct rpcrdma_write_chunk) * nchunks)) > start = (unsigned long)&ary->wc_array[0];
(unsigned long)vaend) { end = (unsigned long)vaend;
if (nchunks < 0 ||
nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) ||
(start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) {
dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n",
ary, nchunks, vaend); ary, nchunks, vaend);
return NULL; return NULL;
......
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