Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+30 -7
+30 -7
fs/iomap.c
··· 116 116 atomic_set(&iop->read_count, 0); 117 117 atomic_set(&iop->write_count, 0); 118 118 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); 119 125 set_page_private(page, (unsigned long)iop); 120 126 SetPagePrivate(page); 121 127 return iop; ··· 138 132 WARN_ON_ONCE(atomic_read(&iop->write_count)); 139 133 ClearPagePrivate(page); 140 134 set_page_private(page, 0); 135 + put_page(page); 141 136 kfree(iop); 142 137 } 143 138 ··· 576 569 577 570 if (page_has_private(page)) { 578 571 ClearPagePrivate(page); 572 + get_page(newpage); 579 573 set_page_private(newpage, page_private(page)); 580 574 set_page_private(page, 0); 575 + put_page(page); 581 576 SetPagePrivate(newpage); 582 577 } 583 578 ··· 1813 1804 loff_t pos = iocb->ki_pos, start = pos; 1814 1805 loff_t end = iocb->ki_pos + count - 1, ret = 0; 1815 1806 unsigned int flags = IOMAP_DIRECT; 1807 + bool wait_for_completion = is_sync_kiocb(iocb); 1816 1808 struct blk_plug plug; 1817 1809 struct iomap_dio *dio; 1818 1810 ··· 1833 1823 dio->end_io = end_io; 1834 1824 dio->error = 0; 1835 1825 dio->flags = 0; 1836 - dio->wait_for_completion = is_sync_kiocb(iocb); 1837 1826 1838 1827 dio->submit.iter = iter; 1839 1828 dio->submit.waiter = current; ··· 1887 1878 dio_warn_stale_pagecache(iocb->ki_filp); 1888 1879 ret = 0; 1889 1880 1890 - if (iov_iter_rw(iter) == WRITE && !dio->wait_for_completion && 1881 + if (iov_iter_rw(iter) == WRITE && !wait_for_completion && 1891 1882 !inode->i_sb->s_dio_done_wq) { 1892 1883 ret = sb_init_dio_done_wq(inode->i_sb); 1893 1884 if (ret < 0) ··· 1903 1894 if (ret <= 0) { 1904 1895 /* magic error code to fall back to buffered I/O */ 1905 1896 if (ret == -ENOTBLK) { 1906 - dio->wait_for_completion = true; 1897 + wait_for_completion = true; 1907 1898 ret = 0; 1908 1899 } 1909 1900 break; ··· 1925 1916 if (dio->flags & IOMAP_DIO_WRITE_FUA) 1926 1917 dio->flags &= ~IOMAP_DIO_NEED_SYNC; 1927 1918 1919 + /* 1920 + * We are about to drop our additional submission reference, which 1921 + * might be the last reference to the dio. There are three three 1922 + * different ways we can progress here: 1923 + * 1924 + * (a) If this is the last reference we will always complete and free 1925 + * the dio ourselves. 1926 + * (b) If this is not the last reference, and we serve an asynchronous 1927 + * iocb, we must never touch the dio after the decrement, the 1928 + * I/O completion handler will complete and free it. 1929 + * (c) If this is not the last reference, but we serve a synchronous 1930 + * iocb, the I/O completion handler will wake us up on the drop 1931 + * of the final reference, and we will complete and free it here 1932 + * after we got woken by the I/O completion handler. 1933 + */ 1934 + dio->wait_for_completion = wait_for_completion; 1928 1935 if (!atomic_dec_and_test(&dio->ref)) { 1929 - if (!dio->wait_for_completion) 1936 + if (!wait_for_completion) 1930 1937 return -EIOCBQUEUED; 1931 1938 1932 1939 for (;;) { ··· 1959 1934 __set_current_state(TASK_RUNNING); 1960 1935 } 1961 1936 1962 - ret = iomap_dio_complete(dio); 1963 - 1964 - return ret; 1937 + return iomap_dio_complete(dio); 1965 1938 1966 1939 out_free_dio: 1967 1940 kfree(dio);