]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jan 2014 17:01:52 +0000 (09:01 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jan 2014 17:01:52 +0000 (09:01 -0800)
added patches:
ext4-check-for-overlapping-extents-in-ext4_valid_extent_entries.patch
ext4-fix-use-after-free-in-ext4_mb_new_blocks.patch

queue-3.4/ext4-check-for-overlapping-extents-in-ext4_valid_extent_entries.patch [new file with mode: 0644]
queue-3.4/ext4-fix-use-after-free-in-ext4_mb_new_blocks.patch [new file with mode: 0644]
queue-3.4/series

diff --git a/queue-3.4/ext4-check-for-overlapping-extents-in-ext4_valid_extent_entries.patch b/queue-3.4/ext4-check-for-overlapping-extents-in-ext4_valid_extent_entries.patch
new file mode 100644 (file)
index 0000000..3630332
--- /dev/null
@@ -0,0 +1,82 @@
+From 5946d089379a35dda0e531710b48fca05446a196 Mon Sep 17 00:00:00 2001
+From: Eryu Guan <guaneryu@gmail.com>
+Date: Tue, 3 Dec 2013 21:22:21 -0500
+Subject: ext4: check for overlapping extents in ext4_valid_extent_entries()
+
+From: Eryu Guan <guaneryu@gmail.com>
+
+commit 5946d089379a35dda0e531710b48fca05446a196 upstream.
+
+A corrupted ext4 may have out of order leaf extents, i.e.
+
+extent: lblk 0--1023, len 1024, pblk 9217, flags: LEAF UNINIT
+extent: lblk 1000--2047, len 1024, pblk 10241, flags: LEAF UNINIT
+             ^^^^ overlap with previous extent
+
+Reading such extent could hit BUG_ON() in ext4_es_cache_extent().
+
+       BUG_ON(end < lblk);
+
+The problem is that __read_extent_tree_block() tries to cache holes as
+well but assumes 'lblk' is greater than 'prev' and passes underflowed
+length to ext4_es_cache_extent(). Fix it by checking for overlapping
+extents in ext4_valid_extent_entries().
+
+I hit this when fuzz testing ext4, and am able to reproduce it by
+modifying the on-disk extent by hand.
+
+Also add the check for (ee_block + len - 1) in ext4_valid_extent() to
+make sure the value is not overflow.
+
+Ran xfstests on patched ext4 and no regression.
+
+Cc: Lukáš Czerner <lczerner@redhat.com>
+Signed-off-by: Eryu Guan <guaneryu@gmail.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/extents.c |   19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -317,8 +317,10 @@ static int ext4_valid_extent(struct inod
+ {
+       ext4_fsblk_t block = ext4_ext_pblock(ext);
+       int len = ext4_ext_get_actual_len(ext);
++      ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
++      ext4_lblk_t last = lblock + len - 1;
+-      if (len == 0)
++      if (lblock > last)
+               return 0;
+       return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
+ }
+@@ -344,11 +346,26 @@ static int ext4_valid_extent_entries(str
+       if (depth == 0) {
+               /* leaf entries */
+               struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
++              struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
++              ext4_fsblk_t pblock = 0;
++              ext4_lblk_t lblock = 0;
++              ext4_lblk_t prev = 0;
++              int len = 0;
+               while (entries) {
+                       if (!ext4_valid_extent(inode, ext))
+                               return 0;
++
++                      /* Check for overlapping extents */
++                      lblock = le32_to_cpu(ext->ee_block);
++                      len = ext4_ext_get_actual_len(ext);
++                      if ((lblock <= prev) && prev) {
++                              pblock = ext4_ext_pblock(ext);
++                              es->s_last_error_block = cpu_to_le64(pblock);
++                              return 0;
++                      }
+                       ext++;
+                       entries--;
++                      prev = lblock + len - 1;
+               }
+       } else {
+               struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh);
diff --git a/queue-3.4/ext4-fix-use-after-free-in-ext4_mb_new_blocks.patch b/queue-3.4/ext4-fix-use-after-free-in-ext4_mb_new_blocks.patch
new file mode 100644 (file)
index 0000000..f460946
--- /dev/null
@@ -0,0 +1,90 @@
+From 4e8d2139802ce4f41936a687f06c560b12115247 Mon Sep 17 00:00:00 2001
+From: Junho Ryu <jayr@google.com>
+Date: Tue, 3 Dec 2013 18:10:28 -0500
+Subject: ext4: fix use-after-free in ext4_mb_new_blocks
+
+From: Junho Ryu <jayr@google.com>
+
+commit 4e8d2139802ce4f41936a687f06c560b12115247 upstream.
+
+ext4_mb_put_pa should hold pa->pa_lock before accessing pa->pa_count.
+While ext4_mb_use_preallocated checks pa->pa_deleted first and then
+increments pa->count later, ext4_mb_put_pa decrements pa->pa_count
+before holding pa->pa_lock and then sets pa->pa_deleted.
+
+* Free sequence
+ext4_mb_put_pa (1):            atomic_dec_and_test pa->pa_count
+ext4_mb_put_pa (2):            lock pa->pa_lock
+ext4_mb_put_pa (3):                    check pa->pa_deleted
+ext4_mb_put_pa (4):                    set pa->pa_deleted=1
+ext4_mb_put_pa (5):            unlock pa->pa_lock
+ext4_mb_put_pa (6):            remove pa from a list
+ext4_mb_pa_callback:           free pa
+
+* Use sequence
+ext4_mb_use_preallocated (1):  iterate over preallocation
+ext4_mb_use_preallocated (2):  lock pa->pa_lock
+ext4_mb_use_preallocated (3):          check pa->pa_deleted
+ext4_mb_use_preallocated (4):          increase pa->pa_count
+ext4_mb_use_preallocated (5):  unlock pa->pa_lock
+ext4_mb_release_context:       access pa
+
+* Use-after-free sequence
+[initial status]               <pa->pa_deleted = 0, pa_count = 1>
+ext4_mb_use_preallocated (1):  iterate over preallocation
+ext4_mb_use_preallocated (2):  lock pa->pa_lock
+ext4_mb_use_preallocated (3):          check pa->pa_deleted
+ext4_mb_put_pa (1):            atomic_dec_and_test pa->pa_count
+[pa_count decremented]         <pa->pa_deleted = 0, pa_count = 0>
+ext4_mb_use_preallocated (4):          increase pa->pa_count
+[pa_count incremented]         <pa->pa_deleted = 0, pa_count = 1>
+ext4_mb_use_preallocated (5):  unlock pa->pa_lock
+ext4_mb_put_pa (2):            lock pa->pa_lock
+ext4_mb_put_pa (3):                    check pa->pa_deleted
+ext4_mb_put_pa (4):                    set pa->pa_deleted=1
+[race condition!]              <pa->pa_deleted = 1, pa_count = 1>
+ext4_mb_put_pa (5):            unlock pa->pa_lock
+ext4_mb_put_pa (6):            remove pa from a list
+ext4_mb_pa_callback:           free pa
+ext4_mb_release_context:       access pa
+
+AddressSanitizer has detected use-after-free in ext4_mb_new_blocks
+Bug report: http://goo.gl/rG1On3
+
+Signed-off-by: Junho Ryu <jayr@google.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/mballoc.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3326,6 +3326,9 @@ static void ext4_mb_pa_callback(struct r
+ {
+       struct ext4_prealloc_space *pa;
+       pa = container_of(head, struct ext4_prealloc_space, u.pa_rcu);
++
++      BUG_ON(atomic_read(&pa->pa_count));
++      BUG_ON(pa->pa_deleted == 0);
+       kmem_cache_free(ext4_pspace_cachep, pa);
+ }
+@@ -3339,11 +3342,13 @@ static void ext4_mb_put_pa(struct ext4_a
+       ext4_group_t grp;
+       ext4_fsblk_t grp_blk;
+-      if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
+-              return;
+-
+       /* in this short window concurrent discard can set pa_deleted */
+       spin_lock(&pa->pa_lock);
++      if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) {
++              spin_unlock(&pa->pa_lock);
++              return;
++      }
++
+       if (pa->pa_deleted == 1) {
+               spin_unlock(&pa->pa_lock);
+               return;
index 474ee28e48412021a30a7eb92fd79461dc4a1f59..4ef2f6d535f5e59c0c04c62b9bc4ebc2f6ba6041 100644 (file)
@@ -11,3 +11,5 @@ selinux-selinux_setprocattr-ptrace_parent-needs-rcu_read_lock.patch
 ftrace-initialize-the-ftrace-profiler-for-each-possible-cpu.patch
 intel_idle-initial-ivb-support.patch
 intel_idle-enable-ivb-xeon-support.patch
+ext4-fix-use-after-free-in-ext4_mb_new_blocks.patch
+ext4-check-for-overlapping-extents-in-ext4_valid_extent_entries.patch