aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara2017-05-26 16:45:45 -0500
committerGreg Kroah-Hartman2017-10-12 04:27:35 -0500
commit40c00e5fac3abbd5e6fa08e93fa99b3e632ece16 (patch)
tree82575b3f77809c7c87e42444d2fb95e6d6622a21
parent90fd6738731b6d105fc8f04832ae17a9ac82c05c (diff)
downloadti-linux-kernel-40c00e5fac3abbd5e6fa08e93fa99b3e632ece16.tar.gz
ti-linux-kernel-40c00e5fac3abbd5e6fa08e93fa99b3e632ece16.tar.xz
ti-linux-kernel-40c00e5fac3abbd5e6fa08e93fa99b3e632ece16.zip
ext4: fix data corruption for mmap writes
commit a056bdaae7a181f7dcc876cfab2f94538e508709 upstream. mpage_submit_page() can race with another process growing i_size and writing data via mmap to the written-back page. As mpage_submit_page() samples i_size too early, it may happen that ext4_bio_write_page() zeroes out too large tail of the page and thus corrupts user data. Fix the problem by sampling i_size only after the page has been write-protected in page tables by clear_page_dirty_for_io() call. Reported-by: Michael Zimmer <michael@swarm64.com> CC: stable@vger.kernel.org Fixes: cb20d5188366f04d96d2e07b1240cc92170ade40 Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/ext4/inode.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1796d1bd9a1d..194a6baa4283 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1946,15 +1946,29 @@ static int ext4_writepage(struct page *page,
1946static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page) 1946static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page)
1947{ 1947{
1948 int len; 1948 int len;
1949 loff_t size = i_size_read(mpd->inode); 1949 loff_t size;
1950 int err; 1950 int err;
1951 1951
1952 BUG_ON(page->index != mpd->first_page); 1952 BUG_ON(page->index != mpd->first_page);
1953 if (page->index == size >> PAGE_CACHE_SHIFT)
1954 len = size & ~PAGE_CACHE_MASK;
1955 else
1956 len = PAGE_CACHE_SIZE;
1957 clear_page_dirty_for_io(page); 1953 clear_page_dirty_for_io(page);
1954 /*
1955 * We have to be very careful here! Nothing protects writeback path
1956 * against i_size changes and the page can be writeably mapped into
1957 * page tables. So an application can be growing i_size and writing
1958 * data through mmap while writeback runs. clear_page_dirty_for_io()
1959 * write-protects our page in page tables and the page cannot get
1960 * written to again until we release page lock. So only after
1961 * clear_page_dirty_for_io() we are safe to sample i_size for
1962 * ext4_bio_write_page() to zero-out tail of the written page. We rely
1963 * on the barrier provided by TestClearPageDirty in
1964 * clear_page_dirty_for_io() to make sure i_size is really sampled only
1965 * after page tables are updated.
1966 */
1967 size = i_size_read(mpd->inode);
1968 if (page->index == size >> PAGE_SHIFT)
1969 len = size & ~PAGE_MASK;
1970 else
1971 len = PAGE_SIZE;
1958 err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false); 1972 err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false);
1959 if (!err) 1973 if (!err)
1960 mpd->wbc->nr_to_write--; 1974 mpd->wbc->nr_to_write--;