All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alistair Popple <apopple@nvidia.com>
To: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
Cc: "David Hildenbrand" <david@kernel.org>,
	"Liam R. Howlett" <liam@infradead.org>,
	"Vlastimil Babka" <vbabka@kernel.org>,
	"Mike Rapoport" <rppt@kernel.org>,
	"Suren Baghdasaryan" <surenb@google.com>,
	"Michal Hocko" <mhocko@suse.com>,
	"David Rientjes" <rientjes@google.com>,
	"Shakeel Butt" <shakeel.butt@linux.dev>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Jann Horn" <jannh@google.com>,
	"Pedro Falcato" <pfalcato@suse.de>,
	"Matthew Wilcox (Oracle)" <willy@infradead.org>,
	"Jan Kara" <jack@suse.cz>, "Nhat Pham" <nphamcs@gmail.com>,
	"Johannes Weiner" <hannes@cmpxchg.org>, "Zi Yan" <ziy@nvidia.com>,
	"Matthew Brost" <matthew.brost@intel.com>,
	"Joshua Hahn" <joshua.hahnjy@gmail.com>,
	"Byungchul Park" <byungchul@sk.com>,
	"Gregory Price" <gourry@gourry.net>,
	"Ying Huang" <ying.huang@linux.alibaba.com>,
	"Usama Arif" <usama.arif@linux.dev>,
	"Kairui Song" <kasong@tencent.com>,
	"Balbir Singh" <balbirs@nvidia.com>,
	"Jérôme Glisse" <jglisse@redhat.com>,
	"Kiryl Shutsemau" <kas@kernel.org>,
	"Yu-cheng Yu" <yu-cheng.yu@intel.com>,
	"Dave Hansen" <dave.hansen@linux.intel.com>,
	"Dennis Zhou" <dennis@kernel.org>, "Tejun Heo" <tj@kernel.org>,
	"Christoph Lameter" <cl@gentwo.org>,
	"Peng Fan" <peng.fan@nxp.com>, "Josef Bacik" <jbacik@fb.com>,
	"Chris Mason" <mason@kernel.org>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	linux-fsdevel@vger.kernel.org,
	"Borislav Petkov (AMD)" <bp@alien8.de>,
	"Mark Brown" <broonie@kernel.org>,
	"Dennis Zhou (Facebook)" <dennisszhou@gmail.com>,
	"Rick Edgecombe" <rick.p.edgecombe@intel.com>,
	stable@vger.kernel.org
Subject: Re: [PATCH 09/13] mm/migrate_device: fix use-after-free of the anon rmap
Date: Thu, 12 Nov 2026 10:04:10 +1100	[thread overview]
Message-ID: <avTzHDlCiaNSzhtX@nvdebian.thelocal> (raw)
In-Reply-To: <20261111-mason-migrate-et-al-fixes-v1-9-3d2454362e8d@kernel.org>

On 2026-11-12 at 05:13 +1100, "Lorenzo Stoakes (ARM)" <ljs@kernel.org> wrote...
> A munmap() of anonymous memory can result in a use-after-free of the
> anonymous rmap if a concurrent device memory migration occurs and the
> migration runs without the mmap_lock held.
> 
> This can occur for a long-term pin of device-coherent memory, or a driver
> evicting its device memory by PFN.
> 
> Consider:
> 
>     eviction                        munmap()
>     ========                        ========
>     migrate_device_range()
>       migrate_device_unmap()
>         try_to_migrate()
>                                     zap the migration entry
>                                     unlink_anon_vmas()
>                                       last VMA: free the anon_vma
>     migrate_device_finalize()
>       remove_migration_ptes()
>         /* locks and walks the freed anon_vma */
> 
> If munmap() runs before try_to_migrate() instead, the folio is no longer
> mapped and gets no migration entry. The walk still runs, and follows the
> stale folio->mapping to the freed anon_vma.
> 
> Resolve this by pinning the anon rmap of each folio which possesses one in
> migrate_device_range(), migrate_device_pfns() and
> migrate_device_coherent_folio() before its PTEs are replaced, and
> unpinning it once the walk is done.

I was going to ask why this wouldn't also be an issue for migrate_vma_setup()
which does something similar. But in that case mmap_lock is held across setup
and finalize which I guess is what saves us there?

> A folio which is no longer mapped cannot be pinned and has no migration
> entries to remove, so skip it rather than migrating it.
> 
> Reported-by: Chris Mason <mason@kernel.org>
> Fixes: e778406b40db ("mm/migrate_device.c: add migrate_device_range()")
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> ---
>  include/linux/migrate.h |  1 +
>  mm/migrate_device.c     | 39 ++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 39 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/migrate.h b/include/linux/migrate.h
> index 78424b3824c2..c6cce7925b9b 100644
> --- a/include/linux/migrate.h
> +++ b/include/linux/migrate.h
> @@ -136,6 +136,7 @@ static inline int migrate_misplaced_folio(struct folio *folio, int node)
>  #define MIGRATE_PFN_MIGRATE	(1UL << 1)
>  #define MIGRATE_PFN_WRITE	(1UL << 3)
>  #define MIGRATE_PFN_COMPOUND	(1UL << 4)
> +#define MIGRATE_PFN_ANON_RMAP	(1UL << 5)	/* mm internal */
>  #define MIGRATE_PFN_SHIFT	6
>  
>  static inline struct page *migrate_pfn_to_page(unsigned long mpfn)
> diff --git a/mm/migrate_device.c b/mm/migrate_device.c
> index 7ebd02ec303b..5fe11dd01291 100644
> --- a/mm/migrate_device.c
> +++ b/mm/migrate_device.c
> @@ -552,6 +552,27 @@ static bool migrate_vma_check_page(struct page *page, struct page *fault_page)
>  	return true;
>  }
>  
> +/*
> + * Pin the anonymous rmap if present to allow migration entries to be safely
> + * removed. Returns true if the pin succeeded or no pin is required, and false
> + * if the folio is no longer mapped.
> + */
> +static bool pin_anon_rmap(struct folio *folio, unsigned long *src_pfn)
> +{
> +	if (!folio_test_anon(folio) || folio_test_ksm(folio))
> +		return true;
> +	if (!folio_get_anon_vma(folio)) /* Pin the anon rmap. */
> +		return false;
> +	*src_pfn |= MIGRATE_PFN_ANON_RMAP;
> +	return true;
> +}
> +
> +static void unpin_anon_rmap(struct folio *folio, unsigned long src_pfn)
> +{
> +	if (src_pfn & MIGRATE_PFN_ANON_RMAP)
> +		put_anon_vma(folio_anon_vma(folio)); /* Unpin the anon rmap. */
> +}
> +
>  /*
>   * Unmaps pages for migration. Returns number of source pfns marked as
>   * migrating.
> @@ -633,6 +654,7 @@ static unsigned long migrate_device_unmap(unsigned long *src_pfns,
>  
>  		folio = page_folio(page);
>  		remove_migration_ptes(folio, folio, 0);
> +		unpin_anon_rmap(folio, src_pfns[i]);
>  
>  		src_pfns[i] = 0;
>  		if (fault_folio != folio)
> @@ -1335,6 +1357,7 @@ static void __migrate_device_finalize(unsigned long *src_pfns,
>  		if (!folio_is_zone_device(dst))
>  			folio_add_lru(dst);
>  		remove_migration_ptes(src, dst, 0);
> +		unpin_anon_rmap(src, src_pfns[i]);
>  		if (fault_folio != src)
>  			folio_unlock(src);
>  		folio_put(src);
> @@ -1384,6 +1407,7 @@ EXPORT_SYMBOL(migrate_vma_finalize);
>  
>  static unsigned long migrate_device_pfn_lock(unsigned long pfn)
>  {
> +	unsigned long src_pfn = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
>  	struct folio *folio;
>  
>  	folio = folio_get_nontail_page(pfn_to_page(pfn));
> @@ -1395,7 +1419,13 @@ static unsigned long migrate_device_pfn_lock(unsigned long pfn)
>  		return 0;
>  	}
>  
> -	return migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
> +	if (!pin_anon_rmap(folio, &src_pfn)) {
> +		folio_unlock(folio);
> +		folio_put(folio);
> +		return 0;
> +	}
> +
> +	return src_pfn;
>  }
>  
>  /**
> @@ -1431,6 +1461,7 @@ int migrate_device_range(unsigned long *src_pfns, unsigned long start,
>  		nr = folio_nr_pages(folio);
>  		if (nr > npages - i) {
>  			if (src_pfns[i] & MIGRATE_PFN_MIGRATE) {
> +				unpin_anon_rmap(folio, src_pfns[i]);
>  				folio_unlock(folio);
>  				folio_put(folio);
>  			}
> @@ -1474,6 +1505,7 @@ int migrate_device_pfns(unsigned long *src_pfns, unsigned long npages)
>  		nr = folio_nr_pages(folio);
>  		if (nr > npages - i) {
>  			if (src_pfns[i] & MIGRATE_PFN_MIGRATE) {
> +				unpin_anon_rmap(folio, src_pfns[i]);
>  				folio_unlock(folio);
>  				folio_put(folio);
>  			}
> @@ -1509,6 +1541,11 @@ int migrate_device_coherent_folio(struct folio *folio)
>  
>  	folio_lock(folio);
>  	src_pfn = migrate_pfn(folio_pfn(folio)) | MIGRATE_PFN_MIGRATE;
> +	if (!pin_anon_rmap(folio, &src_pfn)) {
> +		folio_unlock(folio);
> +		folio_put(folio);
> +		return -EBUSY;
> +	}
>  
>  	/*
>  	 * We don't have a VMA and don't need to walk the page tables to find
> 
> -- 
> 2.56.0
> 

  reply	other threads:[~2026-11-11 23:04 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11 18:13 [PATCH 00/13] mm: batch of (urgentish?) fixes in oomk, cachestat, dev-migrate, percpu Lorenzo Stoakes (ARM)
2026-11-11 18:13 ` [PATCH 01/13] mm/mmap: free gathered pages before MMF_OOM_SKIP Lorenzo Stoakes (ARM)
2026-11-11 22:49   ` Usama Arif
2026-11-12 12:18     ` Lorenzo Stoakes (ARM)
2026-11-12 11:21   ` Pedro Falcato
2026-11-12 12:17     ` Lorenzo Stoakes (ARM)
2026-11-12 12:18       ` Lorenzo Stoakes (ARM)
2026-11-12 12:28         ` Pedro Falcato
2026-11-12 12:33           ` Lorenzo Stoakes (ARM)
2026-11-12 11:43   ` Michal Hocko
2026-11-12 12:14     ` Lorenzo Stoakes (ARM)
2026-11-12 12:48       ` Michal Hocko
2026-11-12 14:12         ` Michal Hocko
2026-11-12 14:27           ` Lorenzo Stoakes (ARM)
2026-11-12 16:59   ` Gregory Price (Meta)
2026-11-12 19:15     ` Lorenzo Stoakes (ARM)
2026-11-11 18:13 ` [PATCH 02/13] mm: cachestat: count each page only once Lorenzo Stoakes (ARM)
2026-11-11 23:26   ` Usama Arif
2026-11-12 11:27   ` Pedro Falcato
2026-11-12 13:30   ` Nhat Pham
2026-11-12 16:13   ` Johannes Weiner
2026-11-12 16:37   ` Gregory Price (Meta)
2026-11-11 18:13 ` [PATCH 03/13] mm: cachestat: restart the walk after each entry Lorenzo Stoakes (ARM)
2026-11-11 23:38   ` Usama Arif
2026-11-12 12:22     ` Lorenzo Stoakes (ARM)
2026-11-12 11:29   ` Pedro Falcato
2026-11-12 12:33   ` Nhat Pham
2026-11-12 16:15   ` Johannes Weiner
2026-11-12 16:40   ` Gregory Price (Meta)
2026-11-11 18:13 ` [PATCH 04/13] mm/migrate_device: allocate THP deferred split heads Lorenzo Stoakes (ARM)
2026-11-11 19:30   ` Kiryl Shutsemau
2026-11-11 19:40     ` David Hildenbrand (Arm)
2026-11-11 22:18       ` Andrew Morton
2026-11-11 23:02   ` Balbir Singh
2026-11-12 17:07   ` Gregory Price (Meta)
2026-11-12 18:16   ` sashiko-bot
2026-11-11 18:13 ` [PATCH 05/13] mm/migrate_device: don't collect a range twice Lorenzo Stoakes (ARM)
2026-11-12 17:15   ` Gregory Price (Meta)
2026-11-12 18:16   ` sashiko-bot
2026-11-11 18:13 ` [PATCH 06/13] mm/migrate_device: don't let go of the fault page Lorenzo Stoakes (ARM)
2026-11-12 17:56   ` Gregory Price (Meta)
2026-11-11 18:13 ` [PATCH 07/13] mm/migrate_device: look up fault folio after a split Lorenzo Stoakes (ARM)
2026-11-12 17:35   ` Gregory Price (Meta)
2026-11-12 19:12     ` Lorenzo Stoakes (ARM)
2026-11-11 18:13 ` [PATCH 08/13] mm/migrate_device: fix ksmd oops on a migrated KSM page Lorenzo Stoakes (ARM)
2026-11-11 21:54   ` David Hildenbrand (Arm)
2026-11-11 22:47     ` Alistair Popple
2026-11-11 23:27   ` Balbir Singh
2026-11-12 17:22   ` Gregory Price (Meta)
2026-11-12 18:16   ` sashiko-bot
2026-11-11 18:13 ` [PATCH 09/13] mm/migrate_device: fix use-after-free of the anon rmap Lorenzo Stoakes (ARM)
2026-11-11 23:04   ` Alistair Popple [this message]
2026-11-12 19:05     ` Lorenzo Stoakes (ARM)
2026-11-12 18:11   ` Gregory Price (Meta)
2026-11-12 19:10     ` Lorenzo Stoakes (ARM)
2026-11-12 18:16   ` sashiko-bot
2026-11-11 18:13 ` [PATCH 10/13] mm/migrate_device: refuse to migrate shadow stacks Lorenzo Stoakes (ARM)
2026-11-11 21:15   ` Balbir Singh
2026-11-11 23:15   ` Alistair Popple
2026-11-12 18:16   ` sashiko-bot
2026-11-12 19:03     ` Lorenzo Stoakes (ARM)
2026-11-12 22:53       ` Roman Gushchin
2026-11-13  0:22       ` Roman Gushchin
2026-11-11 18:13 ` [PATCH 11/13] percpu: fix contig hints that are too low Lorenzo Stoakes (ARM)
2026-11-12 18:30   ` Gregory Price (Meta)
2026-11-11 18:13 ` [PATCH 12/13] percpu: search the whole reserved chunk Lorenzo Stoakes (ARM)
2026-11-12 18:33   ` Gregory Price (Meta)
2026-11-11 18:13 ` [PATCH 13/13] percpu: queue the balance work on an unbound workqueue Lorenzo Stoakes (ARM)
2026-11-12 18:41   ` Gregory Price (Meta)
2026-11-12 18:45     ` Lorenzo Stoakes (ARM)

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=avTzHDlCiaNSzhtX@nvdebian.thelocal \
    --to=apopple@nvidia.com \
    --cc=akpm@linux-foundation.org \
    --cc=balbirs@nvidia.com \
    --cc=bp@alien8.de \
    --cc=broonie@kernel.org \
    --cc=byungchul@sk.com \
    --cc=cl@gentwo.org \
    --cc=dave.hansen@linux.intel.com \
    --cc=david@kernel.org \
    --cc=dennis@kernel.org \
    --cc=dennisszhou@gmail.com \
    --cc=gourry@gourry.net \
    --cc=hannes@cmpxchg.org \
    --cc=jack@suse.cz \
    --cc=jannh@google.com \
    --cc=jbacik@fb.com \
    --cc=jglisse@redhat.com \
    --cc=joshua.hahnjy@gmail.com \
    --cc=kas@kernel.org \
    --cc=kasong@tencent.com \
    --cc=liam@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=mason@kernel.org \
    --cc=matthew.brost@intel.com \
    --cc=mhocko@suse.com \
    --cc=nphamcs@gmail.com \
    --cc=peng.fan@nxp.com \
    --cc=pfalcato@suse.de \
    --cc=rick.p.edgecombe@intel.com \
    --cc=rientjes@google.com \
    --cc=rppt@kernel.org \
    --cc=shakeel.butt@linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=surenb@google.com \
    --cc=tj@kernel.org \
    --cc=usama.arif@linux.dev \
    --cc=vbabka@kernel.org \
    --cc=willy@infradead.org \
    --cc=ying.huang@linux.alibaba.com \
    --cc=yu-cheng.yu@intel.com \
    --cc=ziy@nvidia.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.