aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-12-20 09:29:35 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-09 15:24:21 -0500
commitcd7442730bdf3c8ecdd9a0ae8d77750b359fe60e (patch)
tree637bb0cd2e0603079355f2ac2f154571cca9ebc2 /fs
parentad403b48be4d1777fdfb65966cefee9e2d8a8bcd (diff)
ext4: add explicit casts when masking cluster sizes
commit f5a44db5d2d677dfbf12deee461f85e9ec633961 upstream. The missing casts can cause the high 64-bits of the physical blocks to be lost. Set up new macros which allows us to make sure the right thing happen, even if at some point we end up supporting larger logical block numbers. Thanks to the Emese Revfy and the PaX security team for reporting this issue. Reported-by: PaX Team <pageexec@freemail.hu> Reported-by: Emese Revfy <re.emese@gmail.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/ext4.h10
-rw-r--r--fs/ext4/extents.c24
-rw-r--r--fs/ext4/mballoc.c6
3 files changed, 24 insertions, 16 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 5aae3d12d400..7bb2e2e55123 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -280,6 +280,16 @@ struct ext4_io_submit {
280/* Translate # of blks to # of clusters */ 280/* Translate # of blks to # of clusters */
281#define EXT4_NUM_B2C(sbi, blks) (((blks) + (sbi)->s_cluster_ratio - 1) >> \ 281#define EXT4_NUM_B2C(sbi, blks) (((blks) + (sbi)->s_cluster_ratio - 1) >> \
282 (sbi)->s_cluster_bits) 282 (sbi)->s_cluster_bits)
283/* Mask out the low bits to get the starting block of the cluster */
284#define EXT4_PBLK_CMASK(s, pblk) ((pblk) & \
285 ~((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
286#define EXT4_LBLK_CMASK(s, lblk) ((lblk) & \
287 ~((ext4_lblk_t) (s)->s_cluster_ratio - 1))
288/* Get the cluster offset */
289#define EXT4_PBLK_COFF(s, pblk) ((pblk) & \
290 ((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
291#define EXT4_LBLK_COFF(s, lblk) ((lblk) & \
292 ((ext4_lblk_t) (s)->s_cluster_ratio - 1))
283 293
284/* 294/*
285 * Structure of a blocks group descriptor 295 * Structure of a blocks group descriptor
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index d480d49d2696..ecabf00829e2 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1772,8 +1772,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
1772 depth = ext_depth(inode); 1772 depth = ext_depth(inode);
1773 if (!path[depth].p_ext) 1773 if (!path[depth].p_ext)
1774 goto out; 1774 goto out;
1775 b2 = le32_to_cpu(path[depth].p_ext->ee_block); 1775 b2 = EXT4_LBLK_CMASK(sbi, le32_to_cpu(path[depth].p_ext->ee_block));
1776 b2 &= ~(sbi->s_cluster_ratio - 1);
1777 1776
1778 /* 1777 /*
1779 * get the next allocated block if the extent in the path 1778 * get the next allocated block if the extent in the path
@@ -1783,7 +1782,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
1783 b2 = ext4_ext_next_allocated_block(path); 1782 b2 = ext4_ext_next_allocated_block(path);
1784 if (b2 == EXT_MAX_BLOCKS) 1783 if (b2 == EXT_MAX_BLOCKS)
1785 goto out; 1784 goto out;
1786 b2 &= ~(sbi->s_cluster_ratio - 1); 1785 b2 = EXT4_LBLK_CMASK(sbi, b2);
1787 } 1786 }
1788 1787
1789 /* check for wrap through zero on extent logical start block*/ 1788 /* check for wrap through zero on extent logical start block*/
@@ -2444,7 +2443,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
2444 * truncate operation has removed all of the blocks in 2443 * truncate operation has removed all of the blocks in
2445 * the cluster. 2444 * the cluster.
2446 */ 2445 */
2447 if (pblk & (sbi->s_cluster_ratio - 1) && 2446 if (EXT4_PBLK_COFF(sbi, pblk) &&
2448 (ee_len == num)) 2447 (ee_len == num))
2449 *partial_cluster = EXT4_B2C(sbi, pblk); 2448 *partial_cluster = EXT4_B2C(sbi, pblk);
2450 else 2449 else
@@ -3675,7 +3674,7 @@ int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
3675{ 3674{
3676 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); 3675 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
3677 ext4_lblk_t lblk_start, lblk_end; 3676 ext4_lblk_t lblk_start, lblk_end;
3678 lblk_start = lblk & (~(sbi->s_cluster_ratio - 1)); 3677 lblk_start = EXT4_LBLK_CMASK(sbi, lblk);
3679 lblk_end = lblk_start + sbi->s_cluster_ratio - 1; 3678 lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
3680 3679
3681 return ext4_find_delalloc_range(inode, lblk_start, lblk_end); 3680 return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
@@ -3734,9 +3733,9 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
3734 trace_ext4_get_reserved_cluster_alloc(inode, lblk_start, num_blks); 3733 trace_ext4_get_reserved_cluster_alloc(inode, lblk_start, num_blks);
3735 3734
3736 /* Check towards left side */ 3735 /* Check towards left side */
3737 c_offset = lblk_start & (sbi->s_cluster_ratio - 1); 3736 c_offset = EXT4_LBLK_COFF(sbi, lblk_start);
3738 if (c_offset) { 3737 if (c_offset) {
3739 lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1)); 3738 lblk_from = EXT4_LBLK_CMASK(sbi, lblk_start);
3740 lblk_to = lblk_from + c_offset - 1; 3739 lblk_to = lblk_from + c_offset - 1;
3741 3740
3742 if (ext4_find_delalloc_range(inode, lblk_from, lblk_to)) 3741 if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
@@ -3744,7 +3743,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
3744 } 3743 }
3745 3744
3746 /* Now check towards right. */ 3745 /* Now check towards right. */
3747 c_offset = (lblk_start + num_blks) & (sbi->s_cluster_ratio - 1); 3746 c_offset = EXT4_LBLK_COFF(sbi, lblk_start + num_blks);
3748 if (allocated_clusters && c_offset) { 3747 if (allocated_clusters && c_offset) {
3749 lblk_from = lblk_start + num_blks; 3748 lblk_from = lblk_start + num_blks;
3750 lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1; 3749 lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
@@ -3952,7 +3951,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
3952 struct ext4_ext_path *path) 3951 struct ext4_ext_path *path)
3953{ 3952{
3954 struct ext4_sb_info *sbi = EXT4_SB(sb); 3953 struct ext4_sb_info *sbi = EXT4_SB(sb);
3955 ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1); 3954 ext4_lblk_t c_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
3956 ext4_lblk_t ex_cluster_start, ex_cluster_end; 3955 ext4_lblk_t ex_cluster_start, ex_cluster_end;
3957 ext4_lblk_t rr_cluster_start; 3956 ext4_lblk_t rr_cluster_start;
3958 ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block); 3957 ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
@@ -3970,8 +3969,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
3970 (rr_cluster_start == ex_cluster_start)) { 3969 (rr_cluster_start == ex_cluster_start)) {
3971 if (rr_cluster_start == ex_cluster_end) 3970 if (rr_cluster_start == ex_cluster_end)
3972 ee_start += ee_len - 1; 3971 ee_start += ee_len - 1;
3973 map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) + 3972 map->m_pblk = EXT4_PBLK_CMASK(sbi, ee_start) + c_offset;
3974 c_offset;
3975 map->m_len = min(map->m_len, 3973 map->m_len = min(map->m_len,
3976 (unsigned) sbi->s_cluster_ratio - c_offset); 3974 (unsigned) sbi->s_cluster_ratio - c_offset);
3977 /* 3975 /*
@@ -4125,7 +4123,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
4125 */ 4123 */
4126 map->m_flags &= ~EXT4_MAP_FROM_CLUSTER; 4124 map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
4127 newex.ee_block = cpu_to_le32(map->m_lblk); 4125 newex.ee_block = cpu_to_le32(map->m_lblk);
4128 cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1); 4126 cluster_offset = EXT4_LBLK_CMASK(sbi, map->m_lblk);
4129 4127
4130 /* 4128 /*
4131 * If we are doing bigalloc, check to see if the extent returned 4129 * If we are doing bigalloc, check to see if the extent returned
@@ -4193,7 +4191,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
4193 * needed so that future calls to get_implied_cluster_alloc() 4191 * needed so that future calls to get_implied_cluster_alloc()
4194 * work correctly. 4192 * work correctly.
4195 */ 4193 */
4196 offset = map->m_lblk & (sbi->s_cluster_ratio - 1); 4194 offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
4197 ar.len = EXT4_NUM_B2C(sbi, offset+allocated); 4195 ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
4198 ar.goal -= offset; 4196 ar.goal -= offset;
4199 ar.logical -= offset; 4197 ar.logical -= offset;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index c1f58e0f26c3..4c0e3e023fc8 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4107,7 +4107,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
4107 ext4_get_group_no_and_offset(sb, goal, &group, &block); 4107 ext4_get_group_no_and_offset(sb, goal, &group, &block);
4108 4108
4109 /* set up allocation goals */ 4109 /* set up allocation goals */
4110 ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1); 4110 ac->ac_b_ex.fe_logical = EXT4_LBLK_CMASK(sbi, ar->logical);
4111 ac->ac_status = AC_STATUS_CONTINUE; 4111 ac->ac_status = AC_STATUS_CONTINUE;
4112 ac->ac_sb = sb; 4112 ac->ac_sb = sb;
4113 ac->ac_inode = ar->inode; 4113 ac->ac_inode = ar->inode;
@@ -4644,7 +4644,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
4644 * blocks at the beginning or the end unless we are explicitly 4644 * blocks at the beginning or the end unless we are explicitly
4645 * requested to avoid doing so. 4645 * requested to avoid doing so.
4646 */ 4646 */
4647 overflow = block & (sbi->s_cluster_ratio - 1); 4647 overflow = EXT4_PBLK_COFF(sbi, block);
4648 if (overflow) { 4648 if (overflow) {
4649 if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) { 4649 if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
4650 overflow = sbi->s_cluster_ratio - overflow; 4650 overflow = sbi->s_cluster_ratio - overflow;
@@ -4658,7 +4658,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
4658 count += overflow; 4658 count += overflow;
4659 } 4659 }
4660 } 4660 }
4661 overflow = count & (sbi->s_cluster_ratio - 1); 4661 overflow = EXT4_LBLK_COFF(sbi, count);
4662 if (overflow) { 4662 if (overflow) {
4663 if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) { 4663 if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
4664 if (count > overflow) 4664 if (count > overflow)