Patch "xfs: fix bmv_count confusion w/ shared extents" has been added to the 4.9-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    xfs: fix bmv_count confusion w/ shared extents

to the 4.9-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     xfs-fix-bmv_count-confusion-w-shared-extents.patch
and it can be found in the queue-4.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.


>From hch@xxxxxx  Thu Feb  2 11:17:02 2017
From: Christoph Hellwig <hch@xxxxxx>
Date: Thu,  2 Feb 2017 08:56:11 +0100
Subject: xfs: fix bmv_count confusion w/ shared extents
To: stable@xxxxxxxxxxxxxxx
Cc: linux-xfs@xxxxxxxxxxxxxxx, "Darrick J. Wong" <darrick.wong@xxxxxxxxxx>
Message-ID: <1486022171-8076-20-git-send-email-hch@xxxxxx>


From: "Darrick J. Wong" <darrick.wong@xxxxxxxxxx>

commit c364b6d0b6cda1cd5d9ab689489adda3e82529aa upstream.

In a bmapx call, bmv_count is the total size of the array, including the
zeroth element that userspace uses to supply the search key.  The output
array starts at offset 1 so that we can set up the user for the next
invocation.  Since we now can split an extent into multiple bmap records
due to shared/unshared status, we have to be careful that we don't
overflow the output array.

In the original patch f86f403794b ("xfs: teach get_bmapx about shared
extents and the CoW fork") I used cur_ext (the output index) to check
for overflows, albeit with an off-by-one error.  Since nexleft no longer
describes the number of unfilled slots in the output, we can rip all
that out and use cur_ext for the overflow check directly.

Failure to do this causes heap corruption in bmapx callers such as
xfs_io and xfs_scrub.  xfs/328 can reproduce this problem.

Reviewed-by: Eric Sandeen <sandeen@xxxxxxxxxx>
Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
 fs/xfs/xfs_bmap_util.c |   28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -528,7 +528,6 @@ xfs_getbmap(
 	xfs_bmbt_irec_t		*map;		/* buffer for user's data */
 	xfs_mount_t		*mp;		/* file system mount point */
 	int			nex;		/* # of user extents can do */
-	int			nexleft;	/* # of user extents left */
 	int			subnex;		/* # of bmapi's can do */
 	int			nmap;		/* number of map entries */
 	struct getbmapx		*out;		/* output structure */
@@ -686,10 +685,8 @@ xfs_getbmap(
 		goto out_free_map;
 	}
 
-	nexleft = nex;
-
 	do {
-		nmap = (nexleft > subnex) ? subnex : nexleft;
+		nmap = (nex> subnex) ? subnex : nex;
 		error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
 				       XFS_BB_TO_FSB(mp, bmv->bmv_length),
 				       map, &nmap, bmapi_flags);
@@ -697,8 +694,8 @@ xfs_getbmap(
 			goto out_free_map;
 		ASSERT(nmap <= subnex);
 
-		for (i = 0; i < nmap && nexleft && bmv->bmv_length &&
-				cur_ext < bmv->bmv_count; i++) {
+		for (i = 0; i < nmap && bmv->bmv_length &&
+				cur_ext < bmv->bmv_count - 1; i++) {
 			out[cur_ext].bmv_oflags = 0;
 			if (map[i].br_state == XFS_EXT_UNWRITTEN)
 				out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
@@ -760,16 +757,27 @@ xfs_getbmap(
 				continue;
 			}
 
+			/*
+			 * In order to report shared extents accurately,
+			 * we report each distinct shared/unshared part
+			 * of a single bmbt record using multiple bmap
+			 * extents.  To make that happen, we iterate the
+			 * same map array item multiple times, each
+			 * time trimming out the subextent that we just
+			 * reported.
+			 *
+			 * Because of this, we must check the out array
+			 * index (cur_ext) directly against bmv_count-1
+			 * to avoid overflows.
+			 */
 			if (inject_map.br_startblock != NULLFSBLOCK) {
 				map[i] = inject_map;
 				i--;
-			} else
-				nexleft--;
+			}
 			bmv->bmv_entries++;
 			cur_ext++;
 		}
-	} while (nmap && nexleft && bmv->bmv_length &&
-		 cur_ext < bmv->bmv_count);
+	} while (nmap && bmv->bmv_length && cur_ext < bmv->bmv_count - 1);
 
  out_free_map:
 	kmem_free(map);


Patches currently in stable-queue which might be from hch@xxxxxx are

queue-4.9/xfs-don-t-rely-on-total-in-xfs_alloc_space_available.patch
queue-4.9/xfs-replace-xfs_mode_to_ftype-table-with-switch-statement.patch
queue-4.9/xfs-fix-bogus-minleft-manipulations.patch
queue-4.9/xfs-fix-cow-writeback-race.patch
queue-4.9/xfs-sanity-check-inode-mode-when-creating-new-dentry.patch
queue-4.9/xfs-extsize-hints-are-not-unlikely-in-xfs_bmap_btalloc.patch
queue-4.9/xfs-bump-up-reserved-blocks-in-xfs_alloc_set_aside.patch
queue-4.9/xfs-add-missing-include-dependencies-to-xfs_dir2.h.patch
queue-4.9/xfs-fix-bmv_count-confusion-w-shared-extents.patch
queue-4.9/xfs-adjust-allocation-length-in-xfs_alloc_space_available.patch
queue-4.9/xfs-verify-dirblocklog-correctly.patch
queue-4.9/xfs-fix-xfs_mode_to_ftype-prototype.patch
queue-4.9/xfs-clear-_xbf_pages-from-buffers-when-readahead-page.patch
queue-4.9/xfs-remove-racy-hasattr-check-from-attr-ops.patch
queue-4.9/xfs-make-the-assert-condition-likely.patch
queue-4.9/xfs-sanity-check-directory-inode-di_size.patch
queue-4.9/xfs-don-t-print-warnings-when-xfs_log_force-fails.patch
queue-4.9/xfs-don-t-wrap-id-in-xfs_dq_get_next_id.patch
queue-4.9/xfs-sanity-check-inode-di_mode.patch
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]