Skip to content

Commit 9ace868

Browse files
committed
Merge tag 'iomap-5.0-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull iomap fixes from Darrick Wong: "A couple of iomap fixes to eliminate some memory corruption and hang problems that were reported: - fix page migration when using iomap for pagecache management - fix a use-after-free bug in the directio code" * tag 'iomap-5.0-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: iomap: fix a use after free in iomap_dio_rw iomap: get/put the page in iomap_page_create/release()
2 parents 3325254 + 4ea899e commit 9ace868

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

fs/iomap.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ iomap_page_create(struct inode *inode, struct page *page)
116116
atomic_set(&iop->read_count, 0);
117117
atomic_set(&iop->write_count, 0);
118118
bitmap_zero(iop->uptodate, PAGE_SIZE / SECTOR_SIZE);
119+
120+
/*
121+
* migrate_page_move_mapping() assumes that pages with private data have
122+
* their count elevated by 1.
123+
*/
124+
get_page(page);
119125
set_page_private(page, (unsigned long)iop);
120126
SetPagePrivate(page);
121127
return iop;
@@ -132,6 +138,7 @@ iomap_page_release(struct page *page)
132138
WARN_ON_ONCE(atomic_read(&iop->write_count));
133139
ClearPagePrivate(page);
134140
set_page_private(page, 0);
141+
put_page(page);
135142
kfree(iop);
136143
}
137144

@@ -569,8 +576,10 @@ iomap_migrate_page(struct address_space *mapping, struct page *newpage,
569576

570577
if (page_has_private(page)) {
571578
ClearPagePrivate(page);
579+
get_page(newpage);
572580
set_page_private(newpage, page_private(page));
573581
set_page_private(page, 0);
582+
put_page(page);
574583
SetPagePrivate(newpage);
575584
}
576585

@@ -1804,6 +1813,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
18041813
loff_t pos = iocb->ki_pos, start = pos;
18051814
loff_t end = iocb->ki_pos + count - 1, ret = 0;
18061815
unsigned int flags = IOMAP_DIRECT;
1816+
bool wait_for_completion = is_sync_kiocb(iocb);
18071817
struct blk_plug plug;
18081818
struct iomap_dio *dio;
18091819

@@ -1823,7 +1833,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
18231833
dio->end_io = end_io;
18241834
dio->error = 0;
18251835
dio->flags = 0;
1826-
dio->wait_for_completion = is_sync_kiocb(iocb);
18271836

18281837
dio->submit.iter = iter;
18291838
dio->submit.waiter = current;
@@ -1878,7 +1887,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
18781887
dio_warn_stale_pagecache(iocb->ki_filp);
18791888
ret = 0;
18801889

1881-
if (iov_iter_rw(iter) == WRITE && !dio->wait_for_completion &&
1890+
if (iov_iter_rw(iter) == WRITE && !wait_for_completion &&
18821891
!inode->i_sb->s_dio_done_wq) {
18831892
ret = sb_init_dio_done_wq(inode->i_sb);
18841893
if (ret < 0)
@@ -1894,7 +1903,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
18941903
if (ret <= 0) {
18951904
/* magic error code to fall back to buffered I/O */
18961905
if (ret == -ENOTBLK) {
1897-
dio->wait_for_completion = true;
1906+
wait_for_completion = true;
18981907
ret = 0;
18991908
}
19001909
break;
@@ -1916,8 +1925,24 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
19161925
if (dio->flags & IOMAP_DIO_WRITE_FUA)
19171926
dio->flags &= ~IOMAP_DIO_NEED_SYNC;
19181927

1928+
/*
1929+
* We are about to drop our additional submission reference, which
1930+
* might be the last reference to the dio. There are three three
1931+
* different ways we can progress here:
1932+
*
1933+
* (a) If this is the last reference we will always complete and free
1934+
* the dio ourselves.
1935+
* (b) If this is not the last reference, and we serve an asynchronous
1936+
* iocb, we must never touch the dio after the decrement, the
1937+
* I/O completion handler will complete and free it.
1938+
* (c) If this is not the last reference, but we serve a synchronous
1939+
* iocb, the I/O completion handler will wake us up on the drop
1940+
* of the final reference, and we will complete and free it here
1941+
* after we got woken by the I/O completion handler.
1942+
*/
1943+
dio->wait_for_completion = wait_for_completion;
19191944
if (!atomic_dec_and_test(&dio->ref)) {
1920-
if (!dio->wait_for_completion)
1945+
if (!wait_for_completion)
19211946
return -EIOCBQUEUED;
19221947

19231948
for (;;) {
@@ -1934,9 +1959,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
19341959
__set_current_state(TASK_RUNNING);
19351960
}
19361961

1937-
ret = iomap_dio_complete(dio);
1938-
1939-
return ret;
1962+
return iomap_dio_complete(dio);
19401963

19411964
out_free_dio:
19421965
kfree(dio);

0 commit comments

Comments
 (0)