diff options
| author | Jan Kara <jack@suse.cz> | 2013-05-31 19:37:56 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-21 21:21:32 -0400 |
| commit | 80747f06d94394d0c2bc384515abe0ba460e58f4 (patch) | |
| tree | 4a5081790f777be5c7fcd39bc4e1652dabedb460 /fs/ext4 | |
| parent | e47438e6af1377ae8b29d2c0262513f54f17adcd (diff) | |
ext4: fix overflows in SEEK_HOLE, SEEK_DATA implementations
commit e7293fd146846e2a44d29e0477e0860c60fb856b upstream.
ext4_lblk_t is just u32 so multiplying it by blocksize can easily
overflow for files larger than 4 GB. Fix that by properly typing the
block offsets before shifting.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Zheng Liu <wenqing.lz@taobao.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/ext4')
| -rw-r--r-- | fs/ext4/file.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index b1b4d51b5d86..b19f0a457f32 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
| @@ -312,7 +312,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, | |||
| 312 | blkbits = inode->i_sb->s_blocksize_bits; | 312 | blkbits = inode->i_sb->s_blocksize_bits; |
| 313 | startoff = *offset; | 313 | startoff = *offset; |
| 314 | lastoff = startoff; | 314 | lastoff = startoff; |
| 315 | endoff = (map->m_lblk + map->m_len) << blkbits; | 315 | endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits; |
| 316 | 316 | ||
| 317 | index = startoff >> PAGE_CACHE_SHIFT; | 317 | index = startoff >> PAGE_CACHE_SHIFT; |
| 318 | end = endoff >> PAGE_CACHE_SHIFT; | 318 | end = endoff >> PAGE_CACHE_SHIFT; |
| @@ -457,7 +457,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) | |||
| 457 | ret = ext4_map_blocks(NULL, inode, &map, 0); | 457 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 458 | if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { | 458 | if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { |
| 459 | if (last != start) | 459 | if (last != start) |
| 460 | dataoff = last << blkbits; | 460 | dataoff = (loff_t)last << blkbits; |
| 461 | break; | 461 | break; |
| 462 | } | 462 | } |
| 463 | 463 | ||
| @@ -468,7 +468,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) | |||
| 468 | ext4_es_find_delayed_extent_range(inode, last, last, &es); | 468 | ext4_es_find_delayed_extent_range(inode, last, last, &es); |
| 469 | if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { | 469 | if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { |
| 470 | if (last != start) | 470 | if (last != start) |
| 471 | dataoff = last << blkbits; | 471 | dataoff = (loff_t)last << blkbits; |
| 472 | break; | 472 | break; |
| 473 | } | 473 | } |
| 474 | 474 | ||
| @@ -486,7 +486,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) | |||
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | last++; | 488 | last++; |
| 489 | dataoff = last << blkbits; | 489 | dataoff = (loff_t)last << blkbits; |
| 490 | } while (last <= end); | 490 | } while (last <= end); |
| 491 | 491 | ||
| 492 | mutex_unlock(&inode->i_mutex); | 492 | mutex_unlock(&inode->i_mutex); |
| @@ -540,7 +540,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) | |||
| 540 | ret = ext4_map_blocks(NULL, inode, &map, 0); | 540 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 541 | if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { | 541 | if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { |
| 542 | last += ret; | 542 | last += ret; |
| 543 | holeoff = last << blkbits; | 543 | holeoff = (loff_t)last << blkbits; |
| 544 | continue; | 544 | continue; |
| 545 | } | 545 | } |
| 546 | 546 | ||
| @@ -551,7 +551,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) | |||
| 551 | ext4_es_find_delayed_extent_range(inode, last, last, &es); | 551 | ext4_es_find_delayed_extent_range(inode, last, last, &es); |
| 552 | if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { | 552 | if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { |
| 553 | last = es.es_lblk + es.es_len; | 553 | last = es.es_lblk + es.es_len; |
| 554 | holeoff = last << blkbits; | 554 | holeoff = (loff_t)last << blkbits; |
| 555 | continue; | 555 | continue; |
| 556 | } | 556 | } |
| 557 | 557 | ||
| @@ -566,7 +566,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) | |||
| 566 | &map, &holeoff); | 566 | &map, &holeoff); |
| 567 | if (!unwritten) { | 567 | if (!unwritten) { |
| 568 | last += ret; | 568 | last += ret; |
| 569 | holeoff = last << blkbits; | 569 | holeoff = (loff_t)last << blkbits; |
| 570 | continue; | 570 | continue; |
| 571 | } | 571 | } |
| 572 | } | 572 | } |
