diff options
author | Alex Elder <elder@inktank.com> | 2012-10-02 11:25:51 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-10-03 11:51:18 -0400 |
commit | 6285bc231277419255f3498d3eb5ddc9f8e7fe79 (patch) | |
tree | cfed533859b1e07896aea7d199716ef4d2704ad4 | |
parent | 457712a0bc5389b75d2c93840a684fd77df2aabb (diff) |
ceph: avoid 32-bit page index overflow
A pgoff_t is defined (by default) to have type (unsigned long). On
architectures such as i686 that's a 32-bit type. The ceph address
space code was attempting to produce 64 bit offsets by shifting a
page's index by PAGE_CACHE_SHIFT, but the result was not what was
desired because the shift occurred before the result got promoted
to 64 bits.
Fix this by converting all uses of page->index used in this way to
use the page_offset() macro, which ensures the 64-bit result has the
intended value.
This fixes http://tracker.newdream.net/issues/3112
Reported-by: Mohamed Pakkeer <pakkeer.mohideen@realimage.com>
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Sage Weil <sage@inktank.com>
-rw-r--r-- | fs/ceph/addr.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 4469b63c9b7b..22b6e4583faa 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -205,7 +205,7 @@ static int readpage_nounlock(struct file *filp, struct page *page) | |||
205 | dout("readpage inode %p file %p page %p index %lu\n", | 205 | dout("readpage inode %p file %p page %p index %lu\n", |
206 | inode, filp, page, page->index); | 206 | inode, filp, page, page->index); |
207 | err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout, | 207 | err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout, |
208 | page->index << PAGE_CACHE_SHIFT, &len, | 208 | (u64) page_offset(page), &len, |
209 | ci->i_truncate_seq, ci->i_truncate_size, | 209 | ci->i_truncate_seq, ci->i_truncate_size, |
210 | &page, 1, 0); | 210 | &page, 1, 0); |
211 | if (err == -ENOENT) | 211 | if (err == -ENOENT) |
@@ -286,7 +286,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) | |||
286 | int nr_pages = 0; | 286 | int nr_pages = 0; |
287 | int ret; | 287 | int ret; |
288 | 288 | ||
289 | off = page->index << PAGE_CACHE_SHIFT; | 289 | off = (u64) page_offset(page); |
290 | 290 | ||
291 | /* count pages */ | 291 | /* count pages */ |
292 | next_index = page->index; | 292 | next_index = page->index; |
@@ -426,7 +426,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) | |||
426 | struct ceph_inode_info *ci; | 426 | struct ceph_inode_info *ci; |
427 | struct ceph_fs_client *fsc; | 427 | struct ceph_fs_client *fsc; |
428 | struct ceph_osd_client *osdc; | 428 | struct ceph_osd_client *osdc; |
429 | loff_t page_off = page->index << PAGE_CACHE_SHIFT; | 429 | loff_t page_off = page_offset(page); |
430 | int len = PAGE_CACHE_SIZE; | 430 | int len = PAGE_CACHE_SIZE; |
431 | loff_t i_size; | 431 | loff_t i_size; |
432 | int err = 0; | 432 | int err = 0; |
@@ -817,8 +817,7 @@ get_more_pages: | |||
817 | /* ok */ | 817 | /* ok */ |
818 | if (locked_pages == 0) { | 818 | if (locked_pages == 0) { |
819 | /* prepare async write request */ | 819 | /* prepare async write request */ |
820 | offset = (unsigned long long)page->index | 820 | offset = (u64) page_offset(page); |
821 | << PAGE_CACHE_SHIFT; | ||
822 | len = wsize; | 821 | len = wsize; |
823 | req = ceph_osdc_new_request(&fsc->client->osdc, | 822 | req = ceph_osdc_new_request(&fsc->client->osdc, |
824 | &ci->i_layout, | 823 | &ci->i_layout, |
@@ -1180,7 +1179,7 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1180 | struct inode *inode = vma->vm_file->f_dentry->d_inode; | 1179 | struct inode *inode = vma->vm_file->f_dentry->d_inode; |
1181 | struct page *page = vmf->page; | 1180 | struct page *page = vmf->page; |
1182 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; | 1181 | struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; |
1183 | loff_t off = page->index << PAGE_CACHE_SHIFT; | 1182 | loff_t off = page_offset(page); |
1184 | loff_t size, len; | 1183 | loff_t size, len; |
1185 | int ret; | 1184 | int ret; |
1186 | 1185 | ||