aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2014-10-05 22:47:07 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-10-05 22:47:07 -0400
commite2bfb088fac03c0f621886a04cffc7faa2b49b1d (patch)
tree019df92d68735cc63ba24d723b42a687dbd955d1 /fs/ext4
parent3e67cfad22230ebed85c56cbe413876f33fea82b (diff)
ext4: don't orphan or truncate the boot loader inode
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> Cc: stable@vger.kernel.org
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/inode.c7
-rw-r--r--fs/ext4/namei.c2
2 files changed, 4 insertions, 5 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 41c4f97c39d3..59983b28a93c 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -224,16 +224,15 @@ void ext4_evict_inode(struct inode *inode)
224 goto no_delete; 224 goto no_delete;
225 } 225 }
226 226
227 if (!is_bad_inode(inode)) 227 if (is_bad_inode(inode))
228 dquot_initialize(inode); 228 goto no_delete;
229 dquot_initialize(inode);
229 230
230 if (ext4_should_order_data(inode)) 231 if (ext4_should_order_data(inode))
231 ext4_begin_ordered_truncate(inode, 0); 232 ext4_begin_ordered_truncate(inode, 0);
232 truncate_inode_pages_final(&inode->i_data); 233 truncate_inode_pages_final(&inode->i_data);
233 234
234 WARN_ON(atomic_read(&EXT4_I(inode)->i_ioend_count)); 235 WARN_ON(atomic_read(&EXT4_I(inode)->i_ioend_count));
235 if (is_bad_inode(inode))
236 goto no_delete;
237 236
238 /* 237 /*
239 * Protect us against freezing - iput() caller didn't have to have any 238 * Protect us against freezing - iput() caller didn't have to have any
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 51705f8c4116..a2a9d40522d2 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2544,7 +2544,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
2544 int err = 0, rc; 2544 int err = 0, rc;
2545 bool dirty = false; 2545 bool dirty = false;
2546 2546
2547 if (!sbi->s_journal) 2547 if (!sbi->s_journal || is_bad_inode(inode))
2548 return 0; 2548 return 0;
2549 2549
2550 WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) && 2550 WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&