aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2006-01-08 04:03:05 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:13:54 -0500
commit54b21a7992a31d30c9a91f7e0a00ffdb4bd0caee (patch)
tree33eca2bf3c1edfd3d76cc0f7c96a392239c6d2ec
parent676121fcb66c861804e38d94214fd5670a1ef595 (diff)
[PATCH] fix possible PAGE_CACHE_SHIFT overflows
We've had two instances recently of overflows when doing 64_bit_value = (32_bit_value << PAGE_CACHE_SHIFT) I did a tree-wide grep of `<<.*PAGE_CACHE_SHIFT' and this is the result. - afs_rxfs_fetch_descriptor.offset is of type off_t, which seems broken. - jfs and jffs are limited to 4GB anyway. - reiserfs map_block_for_writepage() takes an unsigned long for the block - it should take sector_t. (It'll fail for huge filesystems with blocksize<PAGE_CACHE_SIZE) - cramfs_read() needs to use sector_t (I think cramsfs is busted on large filesystems anyway) - affs is limited in file size anyway. - I generally didn't fix 32-bit overflows in directory operations. - arm's __flush_dcache_page() is peculiar. What if the page lies beyond 4G? - gss_wrap_req_priv() needs checking (snd_buf->page_base) Cc: Oleg Drokin <green@linuxhacker.ru> Cc: David Howells <dhowells@redhat.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: <reiserfs-dev@namesys.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Anton Altaparmakov <aia21@cantab.net> Cc: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Cc: Roman Zippel <zippel@linux-m68k.org> Cc: <linux-fsdevel@vger.kernel.org> Cc: Miklos Szeredi <miklos@szeredi.hu> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Trond Myklebust <trond.myklebust@fys.uio.no> Cc: Neil Brown <neilb@cse.unsw.edu.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/afs/dir.c2
-rw-r--r--fs/buffer.c6
-rw-r--r--fs/freevxfs/vxfs_immed.c4
-rw-r--r--fs/jffs/inode-v23.c4
-rw-r--r--fs/mpage.c4
-rw-r--r--fs/romfs/inode.c6
-rw-r--r--fs/smbfs/file.c4
-rw-r--r--fs/sysv/dir.c4
8 files changed, 17 insertions, 17 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 6682d6d7f294..5c61c24dab2a 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -137,7 +137,7 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
137#endif 137#endif
138 138
139 /* determine how many magic numbers there should be in this page */ 139 /* determine how many magic numbers there should be in this page */
140 latter = dir->i_size - (page->index << PAGE_CACHE_SHIFT); 140 latter = dir->i_size - page_offset(page);
141 if (latter >= PAGE_SIZE) 141 if (latter >= PAGE_SIZE)
142 qty = PAGE_SIZE; 142 qty = PAGE_SIZE;
143 else 143 else
diff --git a/fs/buffer.c b/fs/buffer.c
index 263df0f192aa..55f0975a9b15 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1762,7 +1762,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
1762 * handle that here by just cleaning them. 1762 * handle that here by just cleaning them.
1763 */ 1763 */
1764 1764
1765 block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); 1765 block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
1766 head = page_buffers(page); 1766 head = page_buffers(page);
1767 bh = head; 1767 bh = head;
1768 1768
@@ -2635,7 +2635,7 @@ int block_truncate_page(struct address_space *mapping,
2635 pgoff_t index = from >> PAGE_CACHE_SHIFT; 2635 pgoff_t index = from >> PAGE_CACHE_SHIFT;
2636 unsigned offset = from & (PAGE_CACHE_SIZE-1); 2636 unsigned offset = from & (PAGE_CACHE_SIZE-1);
2637 unsigned blocksize; 2637 unsigned blocksize;
2638 pgoff_t iblock; 2638 sector_t iblock;
2639 unsigned length, pos; 2639 unsigned length, pos;
2640 struct inode *inode = mapping->host; 2640 struct inode *inode = mapping->host;
2641 struct page *page; 2641 struct page *page;
@@ -2651,7 +2651,7 @@ int block_truncate_page(struct address_space *mapping,
2651 return 0; 2651 return 0;
2652 2652
2653 length = blocksize - length; 2653 length = blocksize - length;
2654 iblock = index << (PAGE_CACHE_SHIFT - inode->i_blkbits); 2654 iblock = (sector_t)index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
2655 2655
2656 page = grab_cache_page(mapping, index); 2656 page = grab_cache_page(mapping, index);
2657 err = -ENOMEM; 2657 err = -ENOMEM;
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
index d0401dc68d41..6f5df1700e95 100644
--- a/fs/freevxfs/vxfs_immed.c
+++ b/fs/freevxfs/vxfs_immed.c
@@ -99,8 +99,8 @@ static int
99vxfs_immed_readpage(struct file *fp, struct page *pp) 99vxfs_immed_readpage(struct file *fp, struct page *pp)
100{ 100{
101 struct vxfs_inode_info *vip = VXFS_INO(pp->mapping->host); 101 struct vxfs_inode_info *vip = VXFS_INO(pp->mapping->host);
102 u_int64_t offset = pp->index << PAGE_CACHE_SHIFT; 102 u_int64_t offset = (u_int64_t)pp->index << PAGE_CACHE_SHIFT;
103 caddr_t kaddr; 103 caddr_t kaddr;
104 104
105 kaddr = kmap(pp); 105 kaddr = kmap(pp);
106 memcpy(kaddr, vip->vii_immed.vi_immed + offset, PAGE_CACHE_SIZE); 106 memcpy(kaddr, vip->vii_immed.vi_immed + offset, PAGE_CACHE_SIZE);
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 3dcc6d2162cb..2559ee10beda 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -757,7 +757,7 @@ jffs_do_readpage_nolock(struct file *file, struct page *page)
757 757
758 read_len = 0; 758 read_len = 0;
759 result = 0; 759 result = 0;
760 offset = page->index << PAGE_CACHE_SHIFT; 760 offset = page_offset(page);
761 761
762 kmap(page); 762 kmap(page);
763 buf = page_address(page); 763 buf = page_address(page);
@@ -1545,7 +1545,7 @@ jffs_commit_write(struct file *filp, struct page *page,
1545{ 1545{
1546 void *addr = page_address(page) + from; 1546 void *addr = page_address(page) + from;
1547 /* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */ 1547 /* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */
1548 loff_t pos = (page->index<<PAGE_CACHE_SHIFT) + from; 1548 loff_t pos = page_offset(page) + from;
1549 1549
1550 return jffs_file_write(filp, addr, to-from, &pos); 1550 return jffs_file_write(filp, addr, to-from, &pos);
1551} /* jffs_commit_write() */ 1551} /* jffs_commit_write() */
diff --git a/fs/mpage.c b/fs/mpage.c
index f1d2d02bd4c8..e431cb3878d6 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -184,7 +184,7 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
184 if (page_has_buffers(page)) 184 if (page_has_buffers(page))
185 goto confused; 185 goto confused;
186 186
187 block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits); 187 block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
188 last_block = (i_size_read(inode) + blocksize - 1) >> blkbits; 188 last_block = (i_size_read(inode) + blocksize - 1) >> blkbits;
189 189
190 bh.b_page = page; 190 bh.b_page = page;
@@ -466,7 +466,7 @@ __mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
466 * The page has no buffers: map it to disk 466 * The page has no buffers: map it to disk
467 */ 467 */
468 BUG_ON(!PageUptodate(page)); 468 BUG_ON(!PageUptodate(page));
469 block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits); 469 block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
470 last_block = (i_size - 1) >> blkbits; 470 last_block = (i_size - 1) >> blkbits;
471 map_bh.b_page = page; 471 map_bh.b_page = page;
472 for (page_block = 0; page_block < blocks_per_page; ) { 472 for (page_block = 0; page_block < blocks_per_page; ) {
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index c74f382dabba..0a13859fd57b 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -418,7 +418,7 @@ static int
418romfs_readpage(struct file *file, struct page * page) 418romfs_readpage(struct file *file, struct page * page)
419{ 419{
420 struct inode *inode = page->mapping->host; 420 struct inode *inode = page->mapping->host;
421 unsigned long offset, avail, readlen; 421 loff_t offset, avail, readlen;
422 void *buf; 422 void *buf;
423 int result = -EIO; 423 int result = -EIO;
424 424
@@ -429,8 +429,8 @@ romfs_readpage(struct file *file, struct page * page)
429 goto err_out; 429 goto err_out;
430 430
431 /* 32 bit warning -- but not for us :) */ 431 /* 32 bit warning -- but not for us :) */
432 offset = page->index << PAGE_CACHE_SHIFT; 432 offset = page_offset(page);
433 if (offset < inode->i_size) { 433 if (offset < i_size_read(inode)) {
434 avail = inode->i_size-offset; 434 avail = inode->i_size-offset;
435 readlen = min_t(unsigned long, avail, PAGE_SIZE); 435 readlen = min_t(unsigned long, avail, PAGE_SIZE);
436 if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) { 436 if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) {
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 3c6eb3ba718e..7042e62726a4 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -209,8 +209,8 @@ smb_updatepage(struct file *file, struct page *page, unsigned long offset,
209{ 209{
210 struct dentry *dentry = file->f_dentry; 210 struct dentry *dentry = file->f_dentry;
211 211
212 DEBUG1("(%s/%s %d@%ld)\n", DENTRY_PATH(dentry), 212 DEBUG1("(%s/%s %d@%lld)\n", DENTRY_PATH(dentry), count,
213 count, (page->index << PAGE_CACHE_SHIFT)+offset); 213 ((unsigned long long)page->index << PAGE_CACHE_SHIFT) + offset);
214 214
215 return smb_writepage_sync(dentry->d_inode, page, offset, count); 215 return smb_writepage_sync(dentry->d_inode, page, offset, count);
216} 216}
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 69a085abad6f..cce8b05cba5a 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -103,7 +103,7 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
103 offset = (char *)de - kaddr; 103 offset = (char *)de - kaddr;
104 104
105 over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN), 105 over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
106 (n<<PAGE_CACHE_SHIFT) | offset, 106 ((loff_t)n<<PAGE_CACHE_SHIFT) | offset,
107 fs16_to_cpu(SYSV_SB(sb), de->inode), 107 fs16_to_cpu(SYSV_SB(sb), de->inode),
108 DT_UNKNOWN); 108 DT_UNKNOWN);
109 if (over) { 109 if (over) {
@@ -115,7 +115,7 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
115 } 115 }
116 116
117done: 117done:
118 filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; 118 filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset;
119 unlock_kernel(); 119 unlock_kernel();
120 return 0; 120 return 0;
121} 121}