Skip to content

Commit 6fd2152

Browse files
committed
Merge tag 'ext4_for_linus_stable2' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 fixes from Ted Ts'o: "Fix a regression in the lazytime code that was introduced in v6.1-rc1, and a use-after-free that can be triggered by a maliciously corrupted file system" * tag 'ext4_for_linus_stable2' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: fs: do not update freeing inode i_io_list ext4: fix use-after-free in ext4_ext_shift_extents
2 parents c3eb11f + 4e3c51f commit 6fd2152

2 files changed

Lines changed: 32 additions & 16 deletions

File tree

fs/ext4/extents.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5184,6 +5184,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
51845184
* and it is decreased till we reach start.
51855185
*/
51865186
again:
5187+
ret = 0;
51875188
if (SHIFT == SHIFT_LEFT)
51885189
iterator = &start;
51895190
else
@@ -5227,14 +5228,21 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
52275228
ext4_ext_get_actual_len(extent);
52285229
} else {
52295230
extent = EXT_FIRST_EXTENT(path[depth].p_hdr);
5230-
if (le32_to_cpu(extent->ee_block) > 0)
5231+
if (le32_to_cpu(extent->ee_block) > start)
52315232
*iterator = le32_to_cpu(extent->ee_block) - 1;
5232-
else
5233-
/* Beginning is reached, end of the loop */
5233+
else if (le32_to_cpu(extent->ee_block) == start)
52345234
iterator = NULL;
5235-
/* Update path extent in case we need to stop */
5236-
while (le32_to_cpu(extent->ee_block) < start)
5235+
else {
5236+
extent = EXT_LAST_EXTENT(path[depth].p_hdr);
5237+
while (le32_to_cpu(extent->ee_block) >= start)
5238+
extent--;
5239+
5240+
if (extent == EXT_LAST_EXTENT(path[depth].p_hdr))
5241+
break;
5242+
52375243
extent++;
5244+
iterator = NULL;
5245+
}
52385246
path[depth].p_ext = extent;
52395247
}
52405248
ret = ext4_ext_shift_path_extents(path, shift, inode,

fs/fs-writeback.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,18 +1712,26 @@ static int writeback_single_inode(struct inode *inode,
17121712
wb = inode_to_wb_and_lock_list(inode);
17131713
spin_lock(&inode->i_lock);
17141714
/*
1715-
* If the inode is now fully clean, then it can be safely removed from
1716-
* its writeback list (if any). Otherwise the flusher threads are
1717-
* responsible for the writeback lists.
1715+
* If the inode is freeing, its i_io_list shoudn't be updated
1716+
* as it can be finally deleted at this moment.
17181717
*/
1719-
if (!(inode->i_state & I_DIRTY_ALL))
1720-
inode_cgwb_move_to_attached(inode, wb);
1721-
else if (!(inode->i_state & I_SYNC_QUEUED)) {
1722-
if ((inode->i_state & I_DIRTY))
1723-
redirty_tail_locked(inode, wb);
1724-
else if (inode->i_state & I_DIRTY_TIME) {
1725-
inode->dirtied_when = jiffies;
1726-
inode_io_list_move_locked(inode, wb, &wb->b_dirty_time);
1718+
if (!(inode->i_state & I_FREEING)) {
1719+
/*
1720+
* If the inode is now fully clean, then it can be safely
1721+
* removed from its writeback list (if any). Otherwise the
1722+
* flusher threads are responsible for the writeback lists.
1723+
*/
1724+
if (!(inode->i_state & I_DIRTY_ALL))
1725+
inode_cgwb_move_to_attached(inode, wb);
1726+
else if (!(inode->i_state & I_SYNC_QUEUED)) {
1727+
if ((inode->i_state & I_DIRTY))
1728+
redirty_tail_locked(inode, wb);
1729+
else if (inode->i_state & I_DIRTY_TIME) {
1730+
inode->dirtied_when = jiffies;
1731+
inode_io_list_move_locked(inode,
1732+
wb,
1733+
&wb->b_dirty_time);
1734+
}
17271735
}
17281736
}
17291737

0 commit comments

Comments
 (0)