From deb5df0947849c4453f305fb5b9b320289ddf75b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 18 Jul 2013 17:04:35 -0700 Subject: [PATCH] 3.9-stable patches added patches: ext4-don-t-allow-ext4_free_blocks-to-fail-due-to-enomem.patch ext4-fix-data-offset-overflow-in-ext4_xattr_fiemap-on-32-bit-archs.patch ext4-fix-data-offset-overflow-on-32-bit-archs-in-ext4_inline_data_fiemap.patch ext4-fix-overflows-in-seek_hole-seek_data-implementations.patch ext4-fix-overflow-when-counting-used-blocks-on-32-bit-architectures.patch --- ...t4_free_blocks-to-fail-due-to-enomem.patch | 45 ++++++++++ ...in-ext4_xattr_fiemap-on-32-bit-archs.patch | 42 +++++++++ ...bit-archs-in-ext4_inline_data_fiemap.patch | 32 +++++++ ...-used-blocks-on-32-bit-architectures.patch | 43 +++++++++ ...-seek_hole-seek_data-implementations.patch | 87 +++++++++++++++++++ queue-3.9/series | 5 ++ 6 files changed, 254 insertions(+) create mode 100644 queue-3.9/ext4-don-t-allow-ext4_free_blocks-to-fail-due-to-enomem.patch create mode 100644 queue-3.9/ext4-fix-data-offset-overflow-in-ext4_xattr_fiemap-on-32-bit-archs.patch create mode 100644 queue-3.9/ext4-fix-data-offset-overflow-on-32-bit-archs-in-ext4_inline_data_fiemap.patch create mode 100644 queue-3.9/ext4-fix-overflow-when-counting-used-blocks-on-32-bit-architectures.patch create mode 100644 queue-3.9/ext4-fix-overflows-in-seek_hole-seek_data-implementations.patch diff --git a/queue-3.9/ext4-don-t-allow-ext4_free_blocks-to-fail-due-to-enomem.patch b/queue-3.9/ext4-don-t-allow-ext4_free_blocks-to-fail-due-to-enomem.patch new file mode 100644 index 00000000000..17cbbc8afba --- /dev/null +++ b/queue-3.9/ext4-don-t-allow-ext4_free_blocks-to-fail-due-to-enomem.patch @@ -0,0 +1,45 @@ +From e7676a704ee0a1ef71a6b23760b5a8f6896cb1a1 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 13 Jul 2013 00:40:35 -0400 +Subject: ext4: don't allow ext4_free_blocks() to fail due to ENOMEM + +From: Theodore Ts'o + +commit e7676a704ee0a1ef71a6b23760b5a8f6896cb1a1 upstream. + +The filesystem should not be marked inconsistent if ext4_free_blocks() +is not able to allocate memory. Unfortunately some callers (most +notably ext4_truncate) don't have a way to reflect an error back up to +the VFS. And even if we did, most userspace applications won't deal +with most system calls returning ENOMEM anyway. + +Reported-by: Nagachandra P +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/mballoc.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -4622,11 +4622,16 @@ do_more: + * blocks being freed are metadata. these blocks shouldn't + * be used until this transaction is committed + */ ++ retry: + new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); + if (!new_entry) { +- ext4_mb_unload_buddy(&e4b); +- err = -ENOMEM; +- goto error_return; ++ /* ++ * We use a retry loop because ++ * ext4_free_blocks() is not allowed to fail. ++ */ ++ cond_resched(); ++ congestion_wait(BLK_RW_ASYNC, HZ/50); ++ goto retry; + } + new_entry->efd_start_cluster = bit; + new_entry->efd_group = block_group; diff --git a/queue-3.9/ext4-fix-data-offset-overflow-in-ext4_xattr_fiemap-on-32-bit-archs.patch b/queue-3.9/ext4-fix-data-offset-overflow-in-ext4_xattr_fiemap-on-32-bit-archs.patch new file mode 100644 index 00000000000..bdc7635a11d --- /dev/null +++ b/queue-3.9/ext4-fix-data-offset-overflow-in-ext4_xattr_fiemap-on-32-bit-archs.patch @@ -0,0 +1,42 @@ +From a60697f411eb365fb09e639e6f183fe33d1eb796 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 May 2013 19:38:56 -0400 +Subject: ext4: fix data offset overflow in ext4_xattr_fiemap() on 32-bit archs + +From: Jan Kara + +commit a60697f411eb365fb09e639e6f183fe33d1eb796 upstream. + +On 32-bit architectures with 32-bit sector_t computation of data offset +in ext4_xattr_fiemap() can overflow resulting in reporting bogus data +location. Fix the problem by typing block number to proper type before +shifting. + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/extents.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4605,7 +4605,7 @@ static int ext4_xattr_fiemap(struct inod + error = ext4_get_inode_loc(inode, &iloc); + if (error) + return error; +- physical = iloc.bh->b_blocknr << blockbits; ++ physical = (__u64)iloc.bh->b_blocknr << blockbits; + offset = EXT4_GOOD_OLD_INODE_SIZE + + EXT4_I(inode)->i_extra_isize; + physical += offset; +@@ -4613,7 +4613,7 @@ static int ext4_xattr_fiemap(struct inod + flags |= FIEMAP_EXTENT_DATA_INLINE; + brelse(iloc.bh); + } else { /* external block */ +- physical = EXT4_I(inode)->i_file_acl << blockbits; ++ physical = (__u64)EXT4_I(inode)->i_file_acl << blockbits; + length = inode->i_sb->s_blocksize; + } + diff --git a/queue-3.9/ext4-fix-data-offset-overflow-on-32-bit-archs-in-ext4_inline_data_fiemap.patch b/queue-3.9/ext4-fix-data-offset-overflow-on-32-bit-archs-in-ext4_inline_data_fiemap.patch new file mode 100644 index 00000000000..85a4d38de4f --- /dev/null +++ b/queue-3.9/ext4-fix-data-offset-overflow-on-32-bit-archs-in-ext4_inline_data_fiemap.patch @@ -0,0 +1,32 @@ +From eaf3793728d07d995f1e74250b2d0005f7ae98b5 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 May 2013 19:33:42 -0400 +Subject: ext4: fix data offset overflow on 32-bit archs in ext4_inline_data_fiemap() + +From: Jan Kara + +commit eaf3793728d07d995f1e74250b2d0005f7ae98b5 upstream. + +On 32-bit archs when sector_t is defined as 32-bit the logic computing +data offset in ext4_inline_data_fiemap(). Fix that by properly typing +the shifted value. + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inline.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1702,7 +1702,7 @@ int ext4_inline_data_fiemap(struct inode + if (error) + goto out; + +- physical = iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; ++ physical = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; + physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; + physical += offsetof(struct ext4_inode, i_block); + length = i_size_read(inode); diff --git a/queue-3.9/ext4-fix-overflow-when-counting-used-blocks-on-32-bit-architectures.patch b/queue-3.9/ext4-fix-overflow-when-counting-used-blocks-on-32-bit-architectures.patch new file mode 100644 index 00000000000..ecffdf9eb3e --- /dev/null +++ b/queue-3.9/ext4-fix-overflow-when-counting-used-blocks-on-32-bit-architectures.patch @@ -0,0 +1,43 @@ +From 8af8eecc1331dbf5e8c662022272cf667e213da5 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 May 2013 19:39:56 -0400 +Subject: ext4: fix overflow when counting used blocks on 32-bit architectures + +From: Jan Kara + +commit 8af8eecc1331dbf5e8c662022272cf667e213da5 upstream. + +The arithmetics adding delalloc blocks to the number of used blocks in +ext4_getattr() can easily overflow on 32-bit archs as we first multiply +number of blocks by blocksize and then divide back by 512. Make the +arithmetics more clever and also use proper type (unsigned long long +instead of unsigned long). + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4616,7 +4616,7 @@ int ext4_getattr(struct vfsmount *mnt, s + struct kstat *stat) + { + struct inode *inode; +- unsigned long delalloc_blocks; ++ unsigned long long delalloc_blocks; + + inode = dentry->d_inode; + generic_fillattr(inode, stat); +@@ -4634,7 +4634,7 @@ int ext4_getattr(struct vfsmount *mnt, s + delalloc_blocks = EXT4_C2B(EXT4_SB(inode->i_sb), + EXT4_I(inode)->i_reserved_data_blocks); + +- stat->blocks += (delalloc_blocks << inode->i_sb->s_blocksize_bits)>>9; ++ stat->blocks += delalloc_blocks << (inode->i_sb->s_blocksize_bits-9); + return 0; + } + diff --git a/queue-3.9/ext4-fix-overflows-in-seek_hole-seek_data-implementations.patch b/queue-3.9/ext4-fix-overflows-in-seek_hole-seek_data-implementations.patch new file mode 100644 index 00000000000..7d4509e0758 --- /dev/null +++ b/queue-3.9/ext4-fix-overflows-in-seek_hole-seek_data-implementations.patch @@ -0,0 +1,87 @@ +From e7293fd146846e2a44d29e0477e0860c60fb856b Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 31 May 2013 19:37:56 -0400 +Subject: ext4: fix overflows in SEEK_HOLE, SEEK_DATA implementations + +From: Jan Kara + +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 +Signed-off-by: Theodore Ts'o +Reviewed-by: Zheng Liu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/file.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -311,7 +311,7 @@ static int ext4_find_unwritten_pgoff(str + blkbits = inode->i_sb->s_blocksize_bits; + startoff = *offset; + lastoff = startoff; +- endoff = (map->m_lblk + map->m_len) << blkbits; ++ endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits; + + index = startoff >> PAGE_CACHE_SHIFT; + end = endoff >> PAGE_CACHE_SHIFT; +@@ -456,7 +456,7 @@ static loff_t ext4_seek_data(struct file + ret = ext4_map_blocks(NULL, inode, &map, 0); + if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { + if (last != start) +- dataoff = last << blkbits; ++ dataoff = (loff_t)last << blkbits; + break; + } + +@@ -467,7 +467,7 @@ static loff_t ext4_seek_data(struct file + ext4_es_find_delayed_extent(inode, last, &es); + if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { + if (last != start) +- dataoff = last << blkbits; ++ dataoff = (loff_t)last << blkbits; + break; + } + +@@ -485,7 +485,7 @@ static loff_t ext4_seek_data(struct file + } + + last++; +- dataoff = last << blkbits; ++ dataoff = (loff_t)last << blkbits; + } while (last <= end); + + mutex_unlock(&inode->i_mutex); +@@ -539,7 +539,7 @@ static loff_t ext4_seek_hole(struct file + ret = ext4_map_blocks(NULL, inode, &map, 0); + if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { + last += ret; +- holeoff = last << blkbits; ++ holeoff = (loff_t)last << blkbits; + continue; + } + +@@ -550,7 +550,7 @@ static loff_t ext4_seek_hole(struct file + ext4_es_find_delayed_extent(inode, last, &es); + if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { + last = es.es_lblk + es.es_len; +- holeoff = last << blkbits; ++ holeoff = (loff_t)last << blkbits; + continue; + } + +@@ -565,7 +565,7 @@ static loff_t ext4_seek_hole(struct file + &map, &holeoff); + if (!unwritten) { + last += ret; +- holeoff = last << blkbits; ++ holeoff = (loff_t)last << blkbits; + continue; + } + } diff --git a/queue-3.9/series b/queue-3.9/series index f3f8d9ca172..6ceccfa0f74 100644 --- a/queue-3.9/series +++ b/queue-3.9/series @@ -27,3 +27,8 @@ ahci-remove-pmp-link-online-check-in-fbs-eh.patch timer-fix-jiffies-wrap-behavior-of-round_jiffies_common.patch btrfs-fix-estale-with-btrfs-send.patch btrfs-only-do-the-tree_mod_log_free_eb-if-this-is-our-last.patch +ext4-fix-data-offset-overflow-on-32-bit-archs-in-ext4_inline_data_fiemap.patch +ext4-fix-overflows-in-seek_hole-seek_data-implementations.patch +ext4-fix-data-offset-overflow-in-ext4_xattr_fiemap-on-32-bit-archs.patch +ext4-fix-overflow-when-counting-used-blocks-on-32-bit-architectures.patch +ext4-don-t-allow-ext4_free_blocks-to-fail-due-to-enomem.patch -- 2.47.3