diff mbox series

[2/2] userfaultfd: Don't BUG_ON() if khugepaged yanks our page table

Message ID 20240812-uffd-thp-flip-fix-v1-2-4fc1db7ccdd0@google.com (mailing list archive)
State New
Headers show
Series userfaultfd: fix races around pmd_trans_huge() check | expand

Commit Message

Jann Horn Aug. 12, 2024, 4:42 p.m. UTC
Since khugepaged was changed to allow retracting page tables in file
mappings without holding the mmap lock, these BUG_ON()s are wrong - get rid
of them.

We could also remove the preceding "if (unlikely(...))" block, but then
we could reach pte_offset_map_lock() with transhuge pages not just for file
mappings but also for anonymous mappings - which would probably be fine but
I think is not necessarily expected.

Cc: stable@vger.kernel.org
Fixes: 1d65b771bc08 ("mm/khugepaged: retract_page_tables() without mmap or vma lock")
Signed-off-by: Jann Horn <jannh@google.com>
---
 mm/userfaultfd.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Comments

Qi Zheng Aug. 13, 2024, 6:24 a.m. UTC | #1
On 2024/8/13 00:42, Jann Horn wrote:
> Since khugepaged was changed to allow retracting page tables in file
> mappings without holding the mmap lock, these BUG_ON()s are wrong - get rid
> of them.
> 
> We could also remove the preceding "if (unlikely(...))" block, but then
> we could reach pte_offset_map_lock() with transhuge pages not just for file
> mappings but also for anonymous mappings - which would probably be fine but
> I think is not necessarily expected.
> 
> Cc: stable@vger.kernel.org
> Fixes: 1d65b771bc08 ("mm/khugepaged: retract_page_tables() without mmap or vma lock")
> Signed-off-by: Jann Horn <jannh@google.com>
> ---
>   mm/userfaultfd.c | 7 ++++---
>   1 file changed, 4 insertions(+), 3 deletions(-)

Reviewed-by: Qi Zheng <zhengqi.arch@bytedance.com>

> 
> diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> index ec3750467aa5..0dfa97db6feb 100644
> --- a/mm/userfaultfd.c
> +++ b/mm/userfaultfd.c
> @@ -806,9 +806,10 @@ static __always_inline ssize_t mfill_atomic(struct userfaultfd_ctx *ctx,
>   			err = -EFAULT;
>   			break;
>   		}
> -
> -		BUG_ON(pmd_none(*dst_pmd));
> -		BUG_ON(pmd_trans_huge(*dst_pmd));
> +		/*
> +		 * For shmem mappings, khugepaged is allowed to remove page
> +		 * tables under us; pte_offset_map_lock() will deal with that.
> +		 */
>   
>   		err = mfill_atomic_pte(dst_pmd, dst_vma, dst_addr,
>   				       src_addr, flags, &folio);
>
David Hildenbrand Aug. 13, 2024, 9:27 a.m. UTC | #2
On 12.08.24 18:42, Jann Horn wrote:
> Since khugepaged was changed to allow retracting page tables in file
> mappings without holding the mmap lock, these BUG_ON()s are wrong - get rid
> of them.
> 
> We could also remove the preceding "if (unlikely(...))" block, but then
> we could reach pte_offset_map_lock() with transhuge pages not just for file
> mappings but also for anonymous mappings - which would probably be fine but
> I think is not necessarily expected.
> 
> Cc: stable@vger.kernel.org
> Fixes: 1d65b771bc08 ("mm/khugepaged: retract_page_tables() without mmap or vma lock")
> Signed-off-by: Jann Horn <jannh@google.com>
> ---
>   mm/userfaultfd.c | 7 ++++---
>   1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> index ec3750467aa5..0dfa97db6feb 100644
> --- a/mm/userfaultfd.c
> +++ b/mm/userfaultfd.c
> @@ -806,9 +806,10 @@ static __always_inline ssize_t mfill_atomic(struct userfaultfd_ctx *ctx,
>   			err = -EFAULT;
>   			break;
>   		}
> -
> -		BUG_ON(pmd_none(*dst_pmd));
> -		BUG_ON(pmd_trans_huge(*dst_pmd));
> +		/*
> +		 * For shmem mappings, khugepaged is allowed to remove page
> +		 * tables under us; pte_offset_map_lock() will deal with that.
> +		 */
>   
>   		err = mfill_atomic_pte(dst_pmd, dst_vma, dst_addr,
>   				       src_addr, flags, &folio);
> 

Acked-by: David Hildenbrand <david@redhat.com>
diff mbox series

Patch

diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index ec3750467aa5..0dfa97db6feb 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -806,9 +806,10 @@  static __always_inline ssize_t mfill_atomic(struct userfaultfd_ctx *ctx,
 			err = -EFAULT;
 			break;
 		}
-
-		BUG_ON(pmd_none(*dst_pmd));
-		BUG_ON(pmd_trans_huge(*dst_pmd));
+		/*
+		 * For shmem mappings, khugepaged is allowed to remove page
+		 * tables under us; pte_offset_map_lock() will deal with that.
+		 */
 
 		err = mfill_atomic_pte(dst_pmd, dst_vma, dst_addr,
 				       src_addr, flags, &folio);