diff options
author | Jan Kara <jack@suse.cz> | 2013-05-31 19:37:56 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-05-31 19:37:56 -0400 |
commit | e7293fd146846e2a44d29e0477e0860c60fb856b (patch) | |
tree | 7216115993c95f6648bd58fdbae91527ffedbb18 /fs/ext4/file.c | |
parent | eaf3793728d07d995f1e74250b2d0005f7ae98b5 (diff) |
ext4: fix overflows in SEEK_HOLE, SEEK_DATA implementations
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>
Diffstat (limited to 'fs/ext4/file.c')
-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 | } |