stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 2/3] mm/hmm: fix ZONE_DEVICE anon page mapping reuse
       [not found] <20190719192955.30462-1-rcampbell@nvidia.com>
@ 2019-07-19 19:29 ` Ralph Campbell
  2019-07-19 21:45   ` John Hubbard
  2019-07-22  9:38   ` Christoph Hellwig
  2019-07-19 19:29 ` [PATCH v2 3/3] mm/hmm: Fix bad subpage pointer in try_to_unmap_one Ralph Campbell
  1 sibling, 2 replies; 4+ messages in thread
From: Ralph Campbell @ 2019-07-19 19:29 UTC (permalink / raw)
  To: linux-mm
  Cc: linux-kernel, Ralph Campbell, stable, Christoph Hellwig,
	Dan Williams, Andrew Morton, Jason Gunthorpe, Logan Gunthorpe,
	Ira Weiny, Matthew Wilcox, Mel Gorman, Jan Kara,
	Kirill A. Shutemov, Michal Hocko, Andrea Arcangeli, Mike Kravetz,
	Jérôme Glisse

When a ZONE_DEVICE private page is freed, the page->mapping field can be
set. If this page is reused as an anonymous page, the previous value can
prevent the page from being inserted into the CPU's anon rmap table.
For example, when migrating a pte_none() page to device memory:
  migrate_vma(ops, vma, start, end, src, dst, private)
    migrate_vma_collect()
      src[] = MIGRATE_PFN_MIGRATE
    migrate_vma_prepare()
      /* no page to lock or isolate so OK */
    migrate_vma_unmap()
      /* no page to unmap so OK */
    ops->alloc_and_copy()
      /* driver allocates ZONE_DEVICE page for dst[] */
    migrate_vma_pages()
      migrate_vma_insert_page()
        page_add_new_anon_rmap()
          __page_set_anon_rmap()
            /* This check sees the page's stale mapping field */
            if (PageAnon(page))
              return
            /* page->mapping is not updated */

The result is that the migration appears to succeed but a subsequent CPU
fault will be unable to migrate the page back to system memory or worse.

Clear the page->mapping field when freeing the ZONE_DEVICE page so stale
pointer data doesn't affect future page use.

Fixes: b7a523109fb5c9d2d6dd ("mm: don't clear ->mapping in hmm_devmem_free")
Cc: stable@vger.kernel.org
Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jason Gunthorpe <jgg@mellanox.com>
Cc: Logan Gunthorpe <logang@deltatee.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Jan Kara <jack@suse.cz>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: "Jérôme Glisse" <jglisse@redhat.com>
---
 kernel/memremap.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/kernel/memremap.c b/kernel/memremap.c
index bea6f887adad..98d04466dcde 100644
--- a/kernel/memremap.c
+++ b/kernel/memremap.c
@@ -408,6 +408,30 @@ void __put_devmap_managed_page(struct page *page)
 
 		mem_cgroup_uncharge(page);
 
+		/*
+		 * When a device_private page is freed, the page->mapping field
+		 * may still contain a (stale) mapping value. For example, the
+		 * lower bits of page->mapping may still identify the page as
+		 * an anonymous page. Ultimately, this entire field is just
+		 * stale and wrong, and it will cause errors if not cleared.
+		 * One example is:
+		 *
+		 *  migrate_vma_pages()
+		 *    migrate_vma_insert_page()
+		 *      page_add_new_anon_rmap()
+		 *        __page_set_anon_rmap()
+		 *          ...checks page->mapping, via PageAnon(page) call,
+		 *            and incorrectly concludes that the page is an
+		 *            anonymous page. Therefore, it incorrectly,
+		 *            silently fails to set up the new anon rmap.
+		 *
+		 * For other types of ZONE_DEVICE pages, migration is either
+		 * handled differently or not done at all, so there is no need
+		 * to clear page->mapping.
+		 */
+		if (is_device_private_page(page))
+			page->mapping = NULL;
+
 		page->pgmap->ops->page_free(page);
 	} else if (!count)
 		__put_page(page);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 3/3] mm/hmm: Fix bad subpage pointer in try_to_unmap_one
       [not found] <20190719192955.30462-1-rcampbell@nvidia.com>
  2019-07-19 19:29 ` [PATCH v2 2/3] mm/hmm: fix ZONE_DEVICE anon page mapping reuse Ralph Campbell
@ 2019-07-19 19:29 ` Ralph Campbell
  1 sibling, 0 replies; 4+ messages in thread
From: Ralph Campbell @ 2019-07-19 19:29 UTC (permalink / raw)
  To: linux-mm
  Cc: linux-kernel, Ralph Campbell, Jérôme Glisse,
	Kirill A. Shutemov, Mike Kravetz, Christoph Hellwig,
	Jason Gunthorpe, John Hubbard, stable, Andrew Morton

When migrating an anonymous private page to a ZONE_DEVICE private page,
the source page->mapping and page->index fields are copied to the
destination ZONE_DEVICE struct page and the page_mapcount() is increased.
This is so rmap_walk() can be used to unmap and migrate the page back to
system memory. However, try_to_unmap_one() computes the subpage pointer
from a swap pte which computes an invalid page pointer and a kernel panic
results such as:

BUG: unable to handle page fault for address: ffffea1fffffffc8

Currently, only single pages can be migrated to device private memory so
no subpage computation is needed and it can be set to "page".

Fixes: a5430dda8a3a1c ("mm/migrate: support un-addressable ZONE_DEVICE page in migration")
Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
Cc: "Jérôme Glisse" <jglisse@redhat.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Jason Gunthorpe <jgg@mellanox.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
 mm/rmap.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mm/rmap.c b/mm/rmap.c
index e5dfe2ae6b0d..ec1af8b60423 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1476,6 +1476,7 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 			 * No need to invalidate here it will synchronize on
 			 * against the special swap migration pte.
 			 */
+			subpage = page;
 			goto discard;
 		}
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 2/3] mm/hmm: fix ZONE_DEVICE anon page mapping reuse
  2019-07-19 19:29 ` [PATCH v2 2/3] mm/hmm: fix ZONE_DEVICE anon page mapping reuse Ralph Campbell
@ 2019-07-19 21:45   ` John Hubbard
  2019-07-22  9:38   ` Christoph Hellwig
  1 sibling, 0 replies; 4+ messages in thread
From: John Hubbard @ 2019-07-19 21:45 UTC (permalink / raw)
  To: Ralph Campbell, linux-mm
  Cc: linux-kernel, stable, Christoph Hellwig, Dan Williams,
	Andrew Morton, Jason Gunthorpe, Logan Gunthorpe, Ira Weiny,
	Matthew Wilcox, Mel Gorman, Jan Kara, Kirill A. Shutemov,
	Michal Hocko, Andrea Arcangeli, Mike Kravetz,
	Jérôme Glisse

On 7/19/19 12:29 PM, Ralph Campbell wrote:
> When a ZONE_DEVICE private page is freed, the page->mapping field can be
> set. If this page is reused as an anonymous page, the previous value can
> prevent the page from being inserted into the CPU's anon rmap table.
> For example, when migrating a pte_none() page to device memory:
>   migrate_vma(ops, vma, start, end, src, dst, private)
>     migrate_vma_collect()
>       src[] = MIGRATE_PFN_MIGRATE
>     migrate_vma_prepare()
>       /* no page to lock or isolate so OK */
>     migrate_vma_unmap()
>       /* no page to unmap so OK */
>     ops->alloc_and_copy()
>       /* driver allocates ZONE_DEVICE page for dst[] */
>     migrate_vma_pages()
>       migrate_vma_insert_page()
>         page_add_new_anon_rmap()
>           __page_set_anon_rmap()
>             /* This check sees the page's stale mapping field */
>             if (PageAnon(page))
>               return
>             /* page->mapping is not updated */
> 
> The result is that the migration appears to succeed but a subsequent CPU
> fault will be unable to migrate the page back to system memory or worse.
> 
> Clear the page->mapping field when freeing the ZONE_DEVICE page so stale
> pointer data doesn't affect future page use.

Reviewed-by: John Hubbard <jhubbard@nvidia.com>

thanks,
-- 
John Hubbard
NVIDIA

> 
> Fixes: b7a523109fb5c9d2d6dd ("mm: don't clear ->mapping in hmm_devmem_free")
> Cc: stable@vger.kernel.org
> Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Jason Gunthorpe <jgg@mellanox.com>
> Cc: Logan Gunthorpe <logang@deltatee.com>
> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Matthew Wilcox <willy@infradead.org>
> Cc: Mel Gorman <mgorman@techsingularity.net>
> Cc: Jan Kara <jack@suse.cz>
> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Andrea Arcangeli <aarcange@redhat.com>
> Cc: Mike Kravetz <mike.kravetz@oracle.com>
> Cc: "Jérôme Glisse" <jglisse@redhat.com>
> ---
>  kernel/memremap.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/kernel/memremap.c b/kernel/memremap.c
> index bea6f887adad..98d04466dcde 100644
> --- a/kernel/memremap.c
> +++ b/kernel/memremap.c
> @@ -408,6 +408,30 @@ void __put_devmap_managed_page(struct page *page)
>  
>  		mem_cgroup_uncharge(page);
>  
> +		/*
> +		 * When a device_private page is freed, the page->mapping field
> +		 * may still contain a (stale) mapping value. For example, the
> +		 * lower bits of page->mapping may still identify the page as
> +		 * an anonymous page. Ultimately, this entire field is just
> +		 * stale and wrong, and it will cause errors if not cleared.
> +		 * One example is:
> +		 *
> +		 *  migrate_vma_pages()
> +		 *    migrate_vma_insert_page()
> +		 *      page_add_new_anon_rmap()
> +		 *        __page_set_anon_rmap()
> +		 *          ...checks page->mapping, via PageAnon(page) call,
> +		 *            and incorrectly concludes that the page is an
> +		 *            anonymous page. Therefore, it incorrectly,
> +		 *            silently fails to set up the new anon rmap.
> +		 *
> +		 * For other types of ZONE_DEVICE pages, migration is either
> +		 * handled differently or not done at all, so there is no need
> +		 * to clear page->mapping.
> +		 */
> +		if (is_device_private_page(page))
> +			page->mapping = NULL;
> +
>  		page->pgmap->ops->page_free(page);
>  	} else if (!count)
>  		__put_page(page);
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 2/3] mm/hmm: fix ZONE_DEVICE anon page mapping reuse
  2019-07-19 19:29 ` [PATCH v2 2/3] mm/hmm: fix ZONE_DEVICE anon page mapping reuse Ralph Campbell
  2019-07-19 21:45   ` John Hubbard
@ 2019-07-22  9:38   ` Christoph Hellwig
  1 sibling, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2019-07-22  9:38 UTC (permalink / raw)
  To: Ralph Campbell
  Cc: linux-mm, linux-kernel, stable, Christoph Hellwig, Dan Williams,
	Andrew Morton, Jason Gunthorpe, Logan Gunthorpe, Ira Weiny,
	Matthew Wilcox, Mel Gorman, Jan Kara, Kirill A. Shutemov,
	Michal Hocko, Andrea Arcangeli, Mike Kravetz,
	Jérôme Glisse

> +		/*
> +		 * When a device_private page is freed, the page->mapping field
> +		 * may still contain a (stale) mapping value. For example, the
> +		 * lower bits of page->mapping may still identify the page as
> +		 * an anonymous page. Ultimately, this entire field is just
> +		 * stale and wrong, and it will cause errors if not cleared.
> +		 * One example is:
> +		 *
> +		 *  migrate_vma_pages()
> +		 *    migrate_vma_insert_page()
> +		 *      page_add_new_anon_rmap()
> +		 *        __page_set_anon_rmap()
> +		 *          ...checks page->mapping, via PageAnon(page) call,
> +		 *            and incorrectly concludes that the page is an
> +		 *            anonymous page. Therefore, it incorrectly,
> +		 *            silently fails to set up the new anon rmap.
> +		 *
> +		 * For other types of ZONE_DEVICE pages, migration is either
> +		 * handled differently or not done at all, so there is no need
> +		 * to clear page->mapping.
> +		 */
> +		if (is_device_private_page(page))
> +			page->mapping = NULL;
> +

Thanks, especially for the long comment.

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-07-22  9:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20190719192955.30462-1-rcampbell@nvidia.com>
2019-07-19 19:29 ` [PATCH v2 2/3] mm/hmm: fix ZONE_DEVICE anon page mapping reuse Ralph Campbell
2019-07-19 21:45   ` John Hubbard
2019-07-22  9:38   ` Christoph Hellwig
2019-07-19 19:29 ` [PATCH v2 3/3] mm/hmm: Fix bad subpage pointer in try_to_unmap_one Ralph Campbell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).