Re: [PATCH 1/3] mm/mempolicy: skip device-private PMDs when queueing folios

From: Balbir Singh

Date: Tue Jul 07 2026 - 19:49:33 EST


On Tue, Jul 07, 2026 at 06:45:07AM -0700, Usama Arif wrote:
> queue_folios_pmd() is called under pmd_trans_huge_lock(), whose
> pmd_is_huge() check returns true for any non-present, non-none huge
> PMD - including a device-private swap entry. Passing such a PMD to
> pmd_folio() extracts garbage bits as a PFN and returns a bogus folio
> pointer.
>
> Potential trigger: an HMM-based GPU driver migrates an anonymous THP
> folio to device memory via migrate_vma_pages(), leaving a device-private
> PMD. Userspace then calls mbind(), migrate_pages() or
> set_mempolicy_home_node() on that range.
>
> Skip device-private PMDs, matching how queue_folios_pte_range() skips
> device-private PTE entries by checking !pte_present().
>
> Reported-by: sashiko-bot <sashiko-bot@xxxxxxxxxx>
> Link: https://sashiko.dev/#/patchset/20260703173903.3789516-1-usama.arif%40linux.dev?part=6
> Fixes: 368076f52ebe ("mm/huge_memory: add device-private THP support to PMD operations")
> Signed-off-by: Usama Arif <usama.arif@xxxxxxxxx>
> ---
> mm/mempolicy.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index 914f81863db5..eda817539c77 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -659,6 +659,8 @@ static void queue_folios_pmd(pmd_t *pmd, struct mm_walk *walk)
> qp->nr_failed++;
> return;
> }
> + if (unlikely(pmd_is_device_private_entry(*pmd)))
> + return;

The changelog lead me to believe that this is skipped via
!pmd_present()? Do we need to skip just device private entries Shouldn't
we set qp->nr_failed++ similar to what we do for migration entries or do
we silently ignore them?

> folio = pmd_folio(*pmd);
> if (is_huge_zero_folio(folio)) {
> walk->action = ACTION_CONTINUE;
>

Thanks,
Balbir