add patch fix-race-in-transient-ENOSPC-detection
[ext4-patch-queue.git] / fix-hang-when-processing-orphaned-inode-list
blob10145fe431e9744c6712a8f054087c326964f3cb
1 ext4: fix hang when processing corrupted orphaned inode list
3 If the orphaned inode list contains inode #5, ext4_iget() returns a
4 bad inode (since the bootloader inode should never be referenced
5 directly).  Because of the bad inode, we end up processing the inode
6 repeatedly and this hangs the machine.
8 This can be reproduced via:
10    mke2fs -t ext4 /tmp/foo.img 100
11    debugfs -w -R "ssv last_orphan 5" /tmp/foo.img
12    mount -o loop /tmp/foo.img /mnt
14 (But don't do this if you are using an unpatched kernel if you care
15 about the system staying functional.  :-)
17 This bug was found by the port of American Fuzzy Lop into the kernel
18 to find file system problems[1].  (Since it *only* happens if inode #5
19 shows up on the orphan list --- 3, 7, 8, etc. won't do it, it's not
20 surprising that AFL needed two hours before it found it.)
22 [1] http://events.linuxfoundation.org/sites/events/files/slides/AFL%20filesystem%20fuzzing%2C%20Vault%202016_0.pdf
24 Cc: stable@vger.kernel.org
25 Reported by: Vegard Nossum <vegard.nossum@oracle.com>
26 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
27 ---
28  fs/ext4/ialloc.c | 10 ++++++----
29  1 file changed, 6 insertions(+), 4 deletions(-)
31 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
32 index 237b877..c2caf2d 100644
33 --- a/fs/ext4/ialloc.c
34 +++ b/fs/ext4/ialloc.c
35 @@ -1183,11 +1183,13 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
36                 goto iget_failed;
38         /*
39 -        * If the orphans has i_nlinks > 0 then it should be able to be
40 -        * truncated, otherwise it won't be removed from the orphan list
41 -        * during processing and an infinite loop will result.
42 +        * If the orphans has i_nlinks > 0 then it should be able to
43 +        * be truncated, otherwise it won't be removed from the orphan
44 +        * list during processing and an infinite loop will result.
45 +        * Similarly, it must not be a bad inode.
46          */
47 -       if (inode->i_nlink && !ext4_can_truncate(inode))
48 +       if ((inode->i_nlink && !ext4_can_truncate(inode)) ||
49 +           is_bad_inode(inode))
50                 goto bad_orphan;
52         if (NEXT_ORPHAN(inode) > max_ino)