[v2 05/16] mm/migrate_device: move softleaf_to_folio() inside device-private branch
From: Usama Arif
Date: Tue Jun 02 2026 - 11:06:11 EST
migrate_vma_collect_pmd() calls softleaf_to_folio() on a non-present
PMD before checking the entry's type. softleaf_to_folio() converts
the entry's offset to a PFN, which is only meaningful for migration
or device-private entries.
A PMD swap entry's offset is a swap offset, not a PFN, so the
lookup would either return a bogus folio pointer or trip pfn_to_page
validation on a debug kernel. In the non-device-private path the
returned folio is then unused (the OR short-circuits to
migrate_vma_collect_skip()), but the lookup itself is already
unsafe.
Move the softleaf_to_folio() call inside the device-private branch
where the folio is actually needed, mirroring the equivalent
change_non_present_huge_pmd() fix.
Signed-off-by: Usama Arif <usama.arif@xxxxxxxxx>
---
mm/migrate_device.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index ab93a8d11b70..87f079b64265 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -166,11 +166,14 @@ static int migrate_vma_collect_huge_pmd(pmd_t *pmdp, unsigned long start,
} else if (!pmd_present(*pmdp)) {
const softleaf_t entry = softleaf_from_pmd(*pmdp);
- folio = softleaf_to_folio(entry);
-
if (!softleaf_is_device_private(entry) ||
- !(migrate->flags & MIGRATE_VMA_SELECT_DEVICE_PRIVATE) ||
- (folio->pgmap->owner != migrate->pgmap_owner)) {
+ !(migrate->flags & MIGRATE_VMA_SELECT_DEVICE_PRIVATE)) {
+ spin_unlock(ptl);
+ return migrate_vma_collect_skip(start, end, walk);
+ }
+
+ folio = softleaf_to_folio(entry);
+ if (folio->pgmap->owner != migrate->pgmap_owner) {
spin_unlock(ptl);
return migrate_vma_collect_skip(start, end, walk);
}
--
2.52.0