Skip to contentSkip to conversation

userfaultfd: wait on source PMD during UFFDIO_MOVE

PATCH Applied Usama Arif 7 participants 7 messages Jul 5 – Jul 11

Subsystems (2)
lore
Share & tools
lore

Usama Arif

author reviewer
#0 lore raw

PATCH 1/1 userfaultfd: wait on source PMD during UFFDIO_MOVE

move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock, and, for migration entries, waits with pmd_migration_entry_wait().

Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked() then waits without a folio reference, which is safe only while serialized against migration-entry removal by the real PT lock.

Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().

---
 mm/huge_memory.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/huge_memory.c +1 -1
index bdd8635922f9..c0892cc533a9 100644
@@ -2775,7 +2775,7 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
 	if (!pmd_trans_huge(src_pmdval)) {
 		spin_unlock(src_ptl);
 		if (pmd_is_migration_entry(src_pmdval)) {
-			pmd_migration_entry_wait(mm, &src_pmdval);
+			pmd_migration_entry_wait(mm, src_pmd);
 			return -EAGAIN;
 		}
 		return -ENOENT;
Signature · 1 line
2.53.0-Meta
Reviewed-by on v1 1/1
#1 lore raw
Quoted 13 lines · Usama Arif

move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock,
and, for migration entries, waits with pmd_migration_entry_wait().

Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and
re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked()
then waits without a folio reference, which is safe only while serialized
against migration-entry removal by the real PT lock.

Quoted 7 lines

Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().

Link:
https://sashiko.dev/#/patchset/20260703173903.3789516-1-usama.arif%40linux.dev?part=8

Fixes adef440691ba ("userfaultfd: UFFDIO_MOVE uABI")
Signature · 1 line
All Rights Reversed.
maintainer
#2 lore raw
In reply to Usama Arif
Quoted 10 lines · On Sun, 5 Jul 2026 06:12:31 -0700 Usama Arif <[email protected]> wrote:

move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock, and, for migration entries, waits with pmd_migration_entry_wait().

Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked() then waits without a folio reference, which is safe only while serialized against migration-entry removal by the real PT lock.

Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().

Thanks.

Quoted 2 lines

Sashiko says "wild spinlock acquisition and memory corruption", so I'll add a cc:stable to this.

Quoted 11 lines
mm/huge_memory.c +1 -1
@@ -2775,7 +2775,7 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
 	if (!pmd_trans_huge(src_pmdval)) {
 		spin_unlock(src_ptl);
 		if (pmd_is_migration_entry(src_pmdval)) {
-			pmd_migration_entry_wait(mm, &src_pmdval);
+			pmd_migration_entry_wait(mm, src_pmd);
 			return -EAGAIN;
 		}
 		return -ENOENT;
reviewer Reviewed-by on v1 1/1
#3 lore raw
In reply to Usama Arif
Quoted 9 lines · Usama Arif

move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock, and, for migration entries, waits with pmd_migration_entry_wait().

Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked() then waits without a folio reference, which is safe only while serialized against migration-entry removal by the real PT lock.

Quoted 7 lines

Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().

---

Good catch. Agree with Andrew that we should cc stable.

reviewer Reviewed-by on v1 1/1
#4 lore raw
In reply to Usama Arif
Quoted 6 lines · Usama Arif

move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock, and, for migration entries, waits with pmd_migration_entry_wait().

Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked()

Well spotted!

Quoted 10 lines

then waits without a folio reference, which is safe only while serialized against migration-entry removal by the real PT lock.

Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().

---

As Andrew and Baolin pointed out, this should go to stable ;)

With that,

maintainer Acked-by on v1 1/1
#5 lore raw
In reply to Usama Arif
Quoted 24 lines · Usama Arif

move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock, and, for migration entries, waits with pmd_migration_entry_wait().

Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked() then waits without a folio reference, which is safe only while serialized against migration-entry removal by the real PT lock.

Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().

---
 mm/huge_memory.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/huge_memory.c +0 -0
index bdd8635922f9..c0892cc533a9 100644

mm/huge_memory.c int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm · line 2781

Quoted 8 lines
mm/huge_memory.c +1 -1
@@ -2775,7 +2775,7 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
 	if (!pmd_trans_huge(src_pmdval)) {
 		spin_unlock(src_ptl);
 		if (pmd_is_migration_entry(src_pmdval)) {
-			pmd_migration_entry_wait(mm, &src_pmdval);
+			pmd_migration_entry_wait(mm, src_pmd);
 			return -EAGAIN;
 		}
 		return -ENOENT;

Looks good and follows roughly what we do in __handle_mm_fault().

Signature · 3 lines
Cheers,

David
Reviewed-by on v1 1/1
#6 lore raw
In reply to Usama Arif
Quoted 8 lines · Usama Arif

move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock, and, for migration entries, waits with pmd_migration_entry_wait().

Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked() then waits without a folio reference, which is safe only while serialized against migration-entry removal by the real PT lock.

Yikes!

Quoted 7 lines

Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().

LGTM so:

Quoted 18 lines
---
 mm/huge_memory.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/huge_memory.c +1 -2
index bdd8635922f9..c0892cc533a9 100644
@@ -2775,7 +2775,7 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
 	if (!pmd_trans_huge(src_pmdval)) {
 		spin_unlock(src_ptl);
 		if (pmd_is_migration_entry(src_pmdval)) {
-			pmd_migration_entry_wait(mm, &src_pmdval);
+			pmd_migration_entry_wait(mm, src_pmd);
 			return -EAGAIN;
 		}
 		return -ENOENT;
--
Quoted 2 lines

2.53.0-Meta

Cheers, Lorenzo