]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ext4: don't orphan or truncate the boot loader inode
authorTheodore Ts'o <tytso@mit.edu>
Mon, 6 Oct 2014 02:47:07 +0000 (22:47 -0400)
committerBen Hutchings <ben@decadent.org.uk>
Sun, 14 Dec 2014 16:23:46 +0000 (16:23 +0000)
commit e2bfb088fac03c0f621886a04cffc7faa2b49b1d upstream.

The boot loader inode (inode #5) should never be visible in the
directory hierarchy, but it's possible if the file system is corrupted
that there will be a directory entry that points at inode #5.  In
order to avoid accidentally trashing it, when such a directory inode
is opened, the inode will be marked as a bad inode, so that it's not
possible to modify (or read) the inode from userspace.

Unfortunately, when we unlink this (invalid/illegal) directory entry,
we will put the bad inode on the ophan list, and then when try to
unlink the directory, we don't actually remove the bad inode from the
orphan list before freeing in-memory inode structure.  This means the
in-memory orphan list is corrupted, leading to a kernel oops.

In addition, avoid truncating a bad inode in ext4_destroy_inode(),
since truncating the boot loader inode is not a smart thing to do.

Reported-by: Sami Liedes <sami.liedes@iki.fi>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
fs/ext4/inode.c
fs/ext4/namei.c

index 55d4f461992cf3ce8e399aefbf0e72ec5e4e8348..c343cdc9dc1520da66e0fc54c3eba20d87d2fd91 100644 (file)
@@ -155,15 +155,14 @@ void ext4_evict_inode(struct inode *inode)
                goto no_delete;
        }
 
-       if (!is_bad_inode(inode))
-               dquot_initialize(inode);
+       if (is_bad_inode(inode))
+               goto no_delete;
+       dquot_initialize(inode);
 
        if (ext4_should_order_data(inode))
                ext4_begin_ordered_truncate(inode, 0);
        truncate_inode_pages(&inode->i_data, 0);
 
-       if (is_bad_inode(inode))
-               goto no_delete;
 
        handle = ext4_journal_start(inode, ext4_blocks_for_truncate(inode)+3);
        if (IS_ERR(handle)) {
index 2e0e34f957ccfe465d2b59906fb223d1b7ab3140..c4bf1ad616b619985ebc69bda739032fda81f0d5 100644 (file)
@@ -1979,7 +1979,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
        struct ext4_iloc iloc;
        int err = 0, rc;
 
-       if (!ext4_handle_valid(handle))
+       if (!ext4_handle_valid(handle) || is_bad_inode(inode))
                return 0;
 
        mutex_lock(&EXT4_SB(sb)->s_orphan_lock);