From: "David Hildenbrand (Arm)" <david@kernel.org>
To: "Cen Zhang (Microsoft)" <cenzhang@linux.microsoft.com>,
Andrew Morton <akpm@linux-foundation.org>,
Mike Rapoport <rppt@kernel.org>
Cc: Peter Xu <peterx@redhat.com>,
Suren Baghdasaryan <surenb@google.com>,
Andrea Arcangeli <aarcange@redhat.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org, AutonomousCodeSecurity@microsoft.com,
tgopinath@linux.microsoft.com
Subject: Re: [PATCH] userfaultfd: fix UFFDIO_MOVE livelock on large folio with extra references
Date: Tue, 13 Oct 2026 16:46:06 +0200 [thread overview]
Message-ID: <154d653f-c6ab-4357-b823-a345a8524470@kernel.org> (raw)
In-Reply-To: <20261012201514.97015-1-cenzhang@linux.microsoft.com>
On 10/12/26 22:15, Cen Zhang (Microsoft) wrote:
> To move one page out of a large folio, move_pages_ptes() first has to
> split the folio. __folio_split() refuses if the folio has any
> reference beyond its page table mappings and the caller's own, and it
> reports the refusal as -EAGAIN. move_pages() treats returned -EAGAIN
> as a transient race and keeps retrying the same address, holding the VMA
> read locks the whole time. This is incorrect since in some cases
> userspace can hold such a reference indefinitely, such as by
> registering the page as an io_uring buffer.
>
> An unprivileged user can trigger this with three threads: first holds
> such a reference on a page of a THP, second calls UFFDIO_MOVE on another
> page of the same THP and spins in the kernel forever holding the VMA
> read locks, and third calls fork() or mprotect(), which takes mmap_lock
> for writing and then waits forever for those read locks. From then on
> every mmap_lock user of that mm hangs, including other processes
> inspecting it through /proc/<pid>/, until the process is SIGKILLed.
> The hung task detector reports the blocked tasks (third one), and with
> kernel.hung_task_panic=1 the machine panics:
>
> INFO: task wedge:95 blocked for more than 122 seconds.
> task:wedge state:D stack:12528 pid:95 tgid:95 ppid:94
> Call Trace:
> __schedule+0x596/0x1110
> schedule+0x36/0xf0
> __vma_start_exclude_readers+0x100/0x170
> __vma_start_write+0x51/0xd0
> __split_vma+0x208/0x3d0
> vma_modify+0x6a8/0x840
> vma_modify_flags+0xce/0x110
> mprotect_fixup+0xbe/0x480
> do_mprotect_pkey+0x2d9/0x580
> __x64_sys_mprotect+0x1a/0x30
>
> Fix by returning -EBUSY instead of -EAGAIN in move_pages_ptes(), the
> caller of split_folio(), when the split fails. Thus, move_pages()
> does not retry -EBUSY and the ioctl drops its locks and returns to
> userspace instead of spinning.
>
> Fixes: adef440691ba ("userfaultfd: UFFDIO_MOVE uABI")
> Reported-by: AutonomousCodeSecurity@microsoft.com
> Assisted-by: LLM
> Signed-off-by: Cen Zhang (Microsoft) <cenzhang@linux.microsoft.com>
> ---
> mm/userfaultfd.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> index 74f04c323c50..500962be1162 100644
> --- a/mm/userfaultfd.c
> +++ b/mm/userfaultfd.c
> @@ -1663,8 +1663,12 @@ static long move_pages_ptes(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd
> pte_unmap(dst_pte);
> src_pte = dst_pte = NULL;
> ret = split_folio(src_folio);
> - if (ret)
> + if (ret) {
> + /* do not retry, extra refs may be held forever */
> + if (ret == -EAGAIN)
> + ret = -EBUSY;
> goto out;
> + }
> /* have to reacquire the folio after it got split */
> folio_unlock(src_folio);
> folio_put(src_folio);
Yeah, that makes sense to me.
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
--
Cheers,
David
prev parent reply other threads:[~2026-10-13 14:46 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 20:15 [PATCH] userfaultfd: fix UFFDIO_MOVE livelock on large folio with extra references Cen Zhang (Microsoft)
2026-10-13 14:46 ` David Hildenbrand (Arm) [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=154d653f-c6ab-4357-b823-a345a8524470@kernel.org \
--to=david@kernel.org \
--cc=AutonomousCodeSecurity@microsoft.com \
--cc=aarcange@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=cenzhang@linux.microsoft.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=peterx@redhat.com \
--cc=rppt@kernel.org \
--cc=stable@vger.kernel.org \
--cc=surenb@google.com \
--cc=tgopinath@linux.microsoft.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.