Skip to content

Commit e6780f7

Browse files
Hugh Dickinstorvalds
authored andcommitted
futex: Fix uninterruptible loop due to gate_area
It was found (by Sasha) that if you use a futex located in the gate area we get stuck in an uninterruptible infinite loop, much like the ZERO_PAGE issue. While looking at this problem, PeterZ realized you'll get into similar trouble when hitting any install_special_pages() mapping. And are there still drivers setting up their own special mmaps without page->mapping, and without special VM or pte flags to make get_user_pages fail? In most cases, if page->mapping is NULL, we do not need to retry at all: Linus points out that even /proc/sys/vm/drop_caches poses no problem, because it ends up using remove_mapping(), which takes care not to interfere when the page reference count is raised. But there is still one case which does need a retry: if memory pressure called shmem_writepage in between get_user_pages_fast dropping page table lock and our acquiring page lock, then the page gets switched from filecache to swapcache (and ->mapping set to NULL) whatever the refcount. Fault it back in to get the page->mapping needed for key->shared.inode. Reported-by: Sasha Levin <[email protected]> Signed-off-by: Hugh Dickins <[email protected]> Cc: [email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 06867fb commit e6780f7

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

kernel/futex.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -314,17 +314,29 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
314314
#endif
315315

316316
lock_page(page_head);
317+
318+
/*
319+
* If page_head->mapping is NULL, then it cannot be a PageAnon
320+
* page; but it might be the ZERO_PAGE or in the gate area or
321+
* in a special mapping (all cases which we are happy to fail);
322+
* or it may have been a good file page when get_user_pages_fast
323+
* found it, but truncated or holepunched or subjected to
324+
* invalidate_complete_page2 before we got the page lock (also
325+
* cases which we are happy to fail). And we hold a reference,
326+
* so refcount care in invalidate_complete_page's remove_mapping
327+
* prevents drop_caches from setting mapping to NULL beneath us.
328+
*
329+
* The case we do have to guard against is when memory pressure made
330+
* shmem_writepage move it from filecache to swapcache beneath us:
331+
* an unlikely race, but we do need to retry for page_head->mapping.
332+
*/
317333
if (!page_head->mapping) {
334+
int shmem_swizzled = PageSwapCache(page_head);
318335
unlock_page(page_head);
319336
put_page(page_head);
320-
/*
321-
* ZERO_PAGE pages don't have a mapping. Avoid a busy loop
322-
* trying to find one. RW mapping would have COW'd (and thus
323-
* have a mapping) so this page is RO and won't ever change.
324-
*/
325-
if ((page_head == ZERO_PAGE(address)))
326-
return -EFAULT;
327-
goto again;
337+
if (shmem_swizzled)
338+
goto again;
339+
return -EFAULT;
328340
}
329341

330342
/*

0 commit comments

Comments
 (0)