aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/read.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-04-10 09:26:35 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-05-01 01:17:07 -0400
commit8d5658c949e6d89edc579a1f112aeee3bc232a8e (patch)
treef206d3f6809eeb0ca23c1999cf79aa294968b113 /fs/nfs/read.c
parentc63c7b051395368573779c8309aa5c990dcf2f96 (diff)
NFS: Fix a buffer overflow in the allocation of struct nfs_read/writedata
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/read.c')
-rw-r--r--fs/nfs/read.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index f0016062340d..9a55807b2a70 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -27,8 +27,8 @@
27 27
28#define NFSDBG_FACILITY NFSDBG_PAGECACHE 28#define NFSDBG_FACILITY NFSDBG_PAGECACHE
29 29
30static int nfs_pagein_multi(struct inode *, struct list_head *, size_t, int); 30static int nfs_pagein_multi(struct inode *, struct list_head *, unsigned int, size_t, int);
31static int nfs_pagein_one(struct inode *, struct list_head *, size_t, int); 31static int nfs_pagein_one(struct inode *, struct list_head *, unsigned int, size_t, int);
32static const struct rpc_call_ops nfs_read_partial_ops; 32static const struct rpc_call_ops nfs_read_partial_ops;
33static const struct rpc_call_ops nfs_read_full_ops; 33static const struct rpc_call_ops nfs_read_full_ops;
34 34
@@ -37,9 +37,8 @@ static mempool_t *nfs_rdata_mempool;
37 37
38#define MIN_POOL_READ (32) 38#define MIN_POOL_READ (32)
39 39
40struct nfs_read_data *nfs_readdata_alloc(size_t len) 40struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
41{ 41{
42 unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
43 struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_NOFS); 42 struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_NOFS);
44 43
45 if (p) { 44 if (p) {
@@ -135,9 +134,9 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
135 134
136 nfs_list_add_request(new, &one_request); 135 nfs_list_add_request(new, &one_request);
137 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) 136 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
138 nfs_pagein_multi(inode, &one_request, len, 0); 137 nfs_pagein_multi(inode, &one_request, 1, len, 0);
139 else 138 else
140 nfs_pagein_one(inode, &one_request, len, 0); 139 nfs_pagein_one(inode, &one_request, 1, len, 0);
141 return 0; 140 return 0;
142} 141}
143 142
@@ -234,7 +233,7 @@ static void nfs_execute_read(struct nfs_read_data *data)
234 * won't see the new data until our attribute cache is updated. This is more 233 * won't see the new data until our attribute cache is updated. This is more
235 * or less conventional NFS client behavior. 234 * or less conventional NFS client behavior.
236 */ 235 */
237static int nfs_pagein_multi(struct inode *inode, struct list_head *head, size_t count, int flags) 236static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
238{ 237{
239 struct nfs_page *req = nfs_list_entry(head->next); 238 struct nfs_page *req = nfs_list_entry(head->next);
240 struct page *page = req->wb_page; 239 struct page *page = req->wb_page;
@@ -250,7 +249,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, size_t
250 do { 249 do {
251 size_t len = min(nbytes,rsize); 250 size_t len = min(nbytes,rsize);
252 251
253 data = nfs_readdata_alloc(len); 252 data = nfs_readdata_alloc(1);
254 if (!data) 253 if (!data)
255 goto out_bad; 254 goto out_bad;
256 INIT_LIST_HEAD(&data->pages); 255 INIT_LIST_HEAD(&data->pages);
@@ -291,13 +290,13 @@ out_bad:
291 return -ENOMEM; 290 return -ENOMEM;
292} 291}
293 292
294static int nfs_pagein_one(struct inode *inode, struct list_head *head, size_t count, int flags) 293static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
295{ 294{
296 struct nfs_page *req; 295 struct nfs_page *req;
297 struct page **pages; 296 struct page **pages;
298 struct nfs_read_data *data; 297 struct nfs_read_data *data;
299 298
300 data = nfs_readdata_alloc(count); 299 data = nfs_readdata_alloc(npages);
301 if (!data) 300 if (!data)
302 goto out_bad; 301 goto out_bad;
303 302