Commit 6fd2152f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents c3eb11fb 4e3c51f4
Loading
Loading
Loading
Loading
+13 −5
Original line number Diff line number Diff line
@@ -5184,6 +5184,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
	 * and it is decreased till we reach start.
	 */
again:
	ret = 0;
	if (SHIFT == SHIFT_LEFT)
		iterator = &start;
	else
@@ -5227,14 +5228,21 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
					ext4_ext_get_actual_len(extent);
		} else {
			extent = EXT_FIRST_EXTENT(path[depth].p_hdr);
			if (le32_to_cpu(extent->ee_block) > 0)
			if (le32_to_cpu(extent->ee_block) > start)
				*iterator = le32_to_cpu(extent->ee_block) - 1;
			else
				/* Beginning is reached, end of the loop */
			else if (le32_to_cpu(extent->ee_block) == start)
				iterator = NULL;
			/* Update path extent in case we need to stop */
			while (le32_to_cpu(extent->ee_block) < start)
			else {
				extent = EXT_LAST_EXTENT(path[depth].p_hdr);
				while (le32_to_cpu(extent->ee_block) >= start)
					extent--;

				if (extent == EXT_LAST_EXTENT(path[depth].p_hdr))
					break;

				extent++;
				iterator = NULL;
			}
			path[depth].p_ext = extent;
		}
		ret = ext4_ext_shift_path_extents(path, shift, inode,
+19 −11
Original line number Diff line number Diff line
@@ -1712,9 +1712,14 @@ static int writeback_single_inode(struct inode *inode,
	wb = inode_to_wb_and_lock_list(inode);
	spin_lock(&inode->i_lock);
	/*
	 * If the inode is now fully clean, then it can be safely removed from
	 * its writeback list (if any).  Otherwise the flusher threads are
	 * responsible for the writeback lists.
	 * If the inode is freeing, its i_io_list shoudn't be updated
	 * as it can be finally deleted at this moment.
	 */
	if (!(inode->i_state & I_FREEING)) {
		/*
		 * If the inode is now fully clean, then it can be safely
		 * removed from its writeback list (if any). Otherwise the
		 * flusher threads are responsible for the writeback lists.
		 */
		if (!(inode->i_state & I_DIRTY_ALL))
			inode_cgwb_move_to_attached(inode, wb);
@@ -1723,7 +1728,10 @@ static int writeback_single_inode(struct inode *inode,
				redirty_tail_locked(inode, wb);
			else if (inode->i_state & I_DIRTY_TIME) {
				inode->dirtied_when = jiffies;
			inode_io_list_move_locked(inode, wb, &wb->b_dirty_time);
				inode_io_list_move_locked(inode,
							  wb,
							  &wb->b_dirty_time);
			}
		}
	}