diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-04-10 09:26:35 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-05-01 01:17:07 -0400 |
commit | 8d5658c949e6d89edc579a1f112aeee3bc232a8e (patch) | |
tree | f206d3f6809eeb0ca23c1999cf79aa294968b113 /fs/nfs/write.c | |
parent | c63c7b051395368573779c8309aa5c990dcf2f96 (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/write.c')
-rw-r--r-- | fs/nfs/write.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 6ce2d94e7b3f..0a8bbc399689 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -72,9 +72,8 @@ void nfs_commit_free(struct nfs_write_data *wdata) | |||
72 | call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free); | 72 | call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free); |
73 | } | 73 | } |
74 | 74 | ||
75 | struct nfs_write_data *nfs_writedata_alloc(size_t len) | 75 | struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) |
76 | { | 76 | { |
77 | unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
78 | struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS); | 77 | struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS); |
79 | 78 | ||
80 | if (p) { | 79 | if (p) { |
@@ -832,7 +831,7 @@ static void nfs_execute_write(struct nfs_write_data *data) | |||
832 | * Generate multiple small requests to write out a single | 831 | * Generate multiple small requests to write out a single |
833 | * contiguous dirty area on one page. | 832 | * contiguous dirty area on one page. |
834 | */ | 833 | */ |
835 | static int nfs_flush_multi(struct inode *inode, struct list_head *head, size_t count, int how) | 834 | static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how) |
836 | { | 835 | { |
837 | struct nfs_page *req = nfs_list_entry(head->next); | 836 | struct nfs_page *req = nfs_list_entry(head->next); |
838 | struct page *page = req->wb_page; | 837 | struct page *page = req->wb_page; |
@@ -848,7 +847,7 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, size_t c | |||
848 | do { | 847 | do { |
849 | size_t len = min(nbytes, wsize); | 848 | size_t len = min(nbytes, wsize); |
850 | 849 | ||
851 | data = nfs_writedata_alloc(len); | 850 | data = nfs_writedata_alloc(1); |
852 | if (!data) | 851 | if (!data) |
853 | goto out_bad; | 852 | goto out_bad; |
854 | list_add(&data->pages, &list); | 853 | list_add(&data->pages, &list); |
@@ -897,13 +896,13 @@ out_bad: | |||
897 | * This is the case if nfs_updatepage detects a conflicting request | 896 | * This is the case if nfs_updatepage detects a conflicting request |
898 | * that has been written but not committed. | 897 | * that has been written but not committed. |
899 | */ | 898 | */ |
900 | static int nfs_flush_one(struct inode *inode, struct list_head *head, size_t count, int how) | 899 | static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how) |
901 | { | 900 | { |
902 | struct nfs_page *req; | 901 | struct nfs_page *req; |
903 | struct page **pages; | 902 | struct page **pages; |
904 | struct nfs_write_data *data; | 903 | struct nfs_write_data *data; |
905 | 904 | ||
906 | data = nfs_writedata_alloc(count); | 905 | data = nfs_writedata_alloc(npages); |
907 | if (!data) | 906 | if (!data) |
908 | goto out_bad; | 907 | goto out_bad; |
909 | 908 | ||