Miaohe Lin e4aed16c42 mm/memremap: fix memunmap_pages() race with get_dev_pagemap()
[ Upstream commit 1e57ffb6e3fd9583268c6462c4e3853575b21701 ]

Think about the below scene:

 CPU1			CPU2
 memunmap_pages
   percpu_ref_exit
     __percpu_ref_exit
       free_percpu(percpu_count);
         /* percpu_count is freed here! */
			 get_dev_pagemap
			   xa_load(&pgmap_array, PHYS_PFN(phys))
			     /* pgmap still in the pgmap_array */
			   percpu_ref_tryget_live(&pgmap->ref)
			     if __ref_is_percpu
			       /* __PERCPU_REF_ATOMIC_DEAD not set yet */
			       this_cpu_inc(*percpu_count)
			         /* access freed percpu_count here! */
      ref->percpu_count_ptr = __PERCPU_REF_ATOMIC_DEAD;
        /* too late... */
   pageunmap_range

To fix the issue, do percpu_ref_exit() after pgmap_array is emptied. So
we won't do percpu_ref_tryget_live() against a being freed percpu_ref.

Link: https://lkml.kernel.org/r/20220609121305.2508-1-linmiaohe@huawei.com
Fixes: b7b3c01b1915 ("mm/memremap_pages: support multiple ranges per invocation")
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2022-08-17 15:15:21 +02:00
..
2022-03-24 19:06:45 -07:00
2022-02-14 19:51:47 +01:00
2022-05-25 10:47:48 -07:00
2022-03-23 18:03:08 -07:00
2022-05-13 07:20:09 -07:00
2022-05-28 11:27:17 -07:00
2022-03-22 17:03:12 -07:00
2022-05-26 16:57:20 -07:00
2022-05-25 10:24:04 -07:00
2022-03-22 18:26:56 -07:00
2022-05-28 11:27:17 -07:00
2022-06-13 09:54:52 -07:00
2022-06-04 14:04:27 -07:00
2022-01-15 16:30:31 +02:00
2022-05-19 14:08:53 -07:00