On Wed, Jul 06, 2022 at 11:24:34AM +0800, Liu Shixin wrote: > Release refcount after xas_set to fix UAF which may cause panic like this: I think we can do better. How about this? diff --git a/mm/filemap.c b/mm/filemap.c index 00e391e75880..11ae38cc4fd3 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2090,7 +2090,9 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t start, rcu_read_lock(); while ((page = find_get_entry(&xas, end, XA_PRESENT))) { + unsigned long next_idx = xas.xa_index + 1; if (!xa_is_value(page)) { + next_idx = page->index + thp_nr_pages(page); if (page->index < start) goto put; if (page->index + thp_nr_pages(page) - 1 > end) @@ -2111,14 +2113,11 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t start, put: put_page(page); next: - if (!xa_is_value(page) && PageTransHuge(page)) { - unsigned int nr_pages = thp_nr_pages(page); - - /* Final THP may cross MAX_LFS_FILESIZE on 32-bit */ - xas_set(&xas, page->index + nr_pages); - if (xas.xa_index < nr_pages) - break; - } + /* Final THP may cross MAX_LFS_FILESIZE on 32-bit */ + if (next_idx < xas.xa_index) + break; + if (next_idx != xas.xa_index + 1) + xas_set(&xas, next_idx); } rcu_read_unlock();