From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0C2C48A8C2 for ; Thu, 13 Aug 2026 18:54:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786647283; cv=none; b=JBIPeCn93fxC+vcFD5PcdA8NtoqW4l3bYTS6HA0Aw9id7gxgl/t0UEtbFKtU4PxNC70LO2qkap1XS5J5Bghrsi/G9xaLKS63iPQK2CJzIL1VX/7i942QrYEtN8YU50Ppk5jl0z3nveL/6rvlydXOOf60u1hBtCgbIwEgqIdOv2I= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786647283; c=relaxed/simple; bh=mOp7JhDdLxQC4YV4wIzfEOZNrjsvibEb2L1sfi+Ltic=; h=Date:To:From:Subject:Message-Id; b=lwv5Odagn3cLtq2030wTYfrZ49bVEMCCZGiqRGaCZmRtEuHW2PpjyHMM4f1iOxoAaGVcI2+t8XTa8X6YLgJYKu1/Ur9TLebYA2EIOEQwkCrU5anWip3ntL319EVQfL4e5vOXMfEte44zMBsNZPC+If5vAUYQ49DwGwjLqw40gA8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b=kA7132/4; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b="kA7132/4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8AED91F000E9; Thu, 13 Aug 2026 18:54:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux-foundation.org; s=korg; t=1786647281; bh=wo4bfj+S6Ee5tP+sc5ApSQc9X4Xh3mgQjWMLm8J3VFM=; h=Date:To:From:Subject; b=kA7132/4NuPeMPlt5tVUe3Vf3IaFKOkr3/7XUktz7SALSwz1V2nZhuU9puAH5h7kZ DCYyXDnAqs1SQ7dd3C3xJkNY2eIO1wdMroFzqROb5ESfzSrlGF4TKYAwu+eQigzry3 W54OnOEzMbrCvbl7xRqFPTNPkCI1/CcUjRZniH4c= Date: Thu, 13 Aug 2026 11:54:41 -0700 To: mm-commits@vger.kernel.org,ljs@kernel.org,akpm@linux-foundation.org From: Andrew Morton Subject: + mm-vma-fix-self-merge-check-in-copy_vma.patch added to mm-unstable branch Message-Id: <20260813185441.8AED91F000E9@smtp.kernel.org> Precedence: bulk X-Mailing-List: mm-commits@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: The patch titled Subject: mm/vma: fix self-merge check in copy_vma() has been added to the -mm mm-unstable branch. Its filename is mm-vma-fix-self-merge-check-in-copy_vma.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-vma-fix-self-merge-check-in-copy_vma.patch This patch will later appear in the mm-unstable branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via various branches at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there most days ------------------------------------------------------ From: "Lorenzo Stoakes (ARM)" Subject: mm/vma: fix self-merge check in copy_vma() Date: Thu, 13 Aug 2026 18:32:24 +0100 The existing logic is very confusing so improve things. Firstly rename the confusing faulted_in_anon_vma variable to can_self_merge and update this when the page offset is updated. What is being checked for is a 'self-merge' - that is between the VMA being remapped and its prior VMA (remember that this is copy_vma() - if a non-MREMAP_DONTUNMAP remap the original VMA is only removed afterwards). This can happen if the VMA is moved immediately adjacent to itself, either before or after it: |----------------|----------------| | | | v | v |...............||---------------||...............| | new || old || new | |...............||---------------||---------------| In these cases the old VMA is simply expanded to cover the new range. It is also possible for the move to both self-merge and merge with a prior VMA if it is placed between a preceding VMA and its old self: |---------------| | | v | |---------------||...............||---------------| | prev || new || old | |---------------||...............||---------------| In this case, the old VMA is removed and 'prev' is expanded and replaces it. Since copy_vma_and_data() which calls copy_vma() intends to reference the old VMA after the merge, it must have this pointer updated. This kind of self-merge is not possible with a succeeding merge, as the merge always prefers to expand the preceding VMA if possible. copy_vma() accounts for this by explicitly checking to see if a self-merge occurred and updating the vmap pointer if so. However it incorrect did so even for a subsequent merge (this is simply a noop so it had no impact). So change this to only check for the case which matters - a backwards merge - and rearrange the parameters to make it clearer we're doing that - i.e. check new_vma->vm_start < old_vma_start (having already renamed vma_start to old_vma_start to make it clear this is the previous VMA). Also update the existing wall-of-text comment to be a lot clearer. While we're here, replace the VM_BUG_ON_VMA() with a VM_WARN_ON_ONCE_VMA() and update the VMA userland tests accordingly. No functional change intended. Link: https://lore.kernel.org/20260813-b4-scalable-cow-virt-pgoff-v5-7-c21581c0c3c8@kernel.org Signed-off-by: Lorenzo Stoakes (ARM) Acked-by: David Hildenbrand (Arm) Cc: Adrian Hunter Cc: Alexander Deucher Cc: Alexander Gordeev Cc: Alexander Shishkin Cc: Alistair Popple Cc: Arnaldo Carvalho de Melo Cc: Arnd Bergmann Cc: Baolin Wang Cc: Baoquan He Cc: Barry Song Cc: Boris Brezillon Cc: Byungchul Park Cc: Chengming Zhou Cc: Chris Li Cc: Christan König Cc: Christian Borntraeger Cc: Claudio Imbrenda Cc: Dave Airlie Cc: Dev Jain Cc: Gerald Schaefer Cc: Greg Kroah-Hartman Cc: Gregory Price (Meta) Cc: Harry Yoo Cc: Heiko Carstens Cc: Huang Ray Cc: "Huang, Ying" Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jan Kara Cc: Jann Horn Cc: Janosch Frank Cc: Jason Gunthorpe Cc: Jiri Olsa Cc: John Hubbard Cc: Joshua Hahn Cc: Kairui Song Cc: Kees Cook Cc: Kemeng Shi Cc: Lance Yang Cc: Liam R. Howlett Cc: Liviu Dudau Cc: Maarten Lankhorst Cc: Marc Rutland Cc: "Masami Hiramatsu (Google)" Cc: Matthew Auld Cc: Matthew Brost Cc: Matthew Wilcox (Oracle) Cc: Maxime Ripard Cc: Miaohe Lin Cc: Michal Hocko Cc: Mike Rapoport Cc: Muchun Song Cc: Namhyung kim Cc: Naoya Horiguchi Cc: Nhat Pham Cc: Nico Pache Cc: Oleg Nesterov Cc: Oscar Salvador Cc: Pedro Falcato Cc: Peter Xu Cc: Peter Zijlstra Cc: Rakie Kim Cc: Rik van Riel Cc: Rodrigo Vivi Cc: Ryan Roberts Cc: Steven Price Cc: Suren Baghdasaryan Cc: Sven Schnelle Cc: Thomas Hellström Cc: Thomas Zimemrmann Cc: Vasily Gorbik Cc: Vlastimil Babka Cc: xu xin Cc: Zi Yan Signed-off-by: Andrew Morton --- mm/vma.c | 35 +++++++++++++---------------- tools/testing/vma/vma_internal.h | 1 2 files changed, 17 insertions(+), 19 deletions(-) --- a/mm/vma.c~mm-vma-fix-self-merge-check-in-copy_vma +++ a/mm/vma.c @@ -1911,10 +1911,10 @@ struct vm_area_struct *copy_vma(struct v bool *need_rmap_locks) { struct vm_area_struct *vma = *vmap; - unsigned long vma_start = vma->vm_start; + unsigned long old_vma_start = vma->vm_start; struct mm_struct *mm = vma->vm_mm; struct vm_area_struct *new_vma; - bool faulted_in_anon_vma = true; + bool can_self_merge = false; VMA_ITERATOR(vmi, mm, addr); VMG_VMA_STATE(vmg, &vmi, NULL, vma, addr, addr + len); @@ -1924,7 +1924,7 @@ struct vm_area_struct *copy_vma(struct v */ if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) { pgoff = addr >> PAGE_SHIFT; - faulted_in_anon_vma = false; + can_self_merge = true; } /* @@ -1944,24 +1944,21 @@ struct vm_area_struct *copy_vma(struct v new_vma = vma_merge_copied_range(&vmg); if (new_vma) { - /* - * Source vma may have been merged into new_vma - */ - if (unlikely(vma_start >= new_vma->vm_start && - vma_start < new_vma->vm_end)) { + /* Self-merged and VMA replaced. */ + if (unlikely(new_vma->vm_start < old_vma_start && + new_vma->vm_end > old_vma_start)) { /* - * The only way we can get a vma_merge with - * self during an mremap is if the vma hasn't - * been faulted in yet and we were allowed to - * reset the dst vma->vm_pgoff to the - * destination address of the mremap to allow - * the merge to happen. mremap must change the - * vm_pgoff linearity between src and dst vmas - * (in turn preventing a vma_merge) to be - * safe. It is only safe to keep the vm_pgoff - * linear if there are no pages mapped yet. + * The only way a VMA can both self-merge and be + * replaced is if the remap places the new VMA + * immediately prior to its old self ('next') and + * immediately after another VMA ('prev') causing the + * next to be removed and prev to be expanded to cover + * the entire range. + * + * This should only be possible if the page offset was + * updated, i.e. the VMA is unfaulted. */ - VM_BUG_ON_VMA(faulted_in_anon_vma, new_vma); + VM_WARN_ON_ONCE_VMA(!can_self_merge, new_vma); *vmap = vma = new_vma; } *need_rmap_locks = --- a/tools/testing/vma/vma_internal.h~mm-vma-fix-self-merge-check-in-copy_vma +++ a/tools/testing/vma/vma_internal.h @@ -53,6 +53,7 @@ typedef __bitwise unsigned int vm_fault_ #define VM_WARN_ON(_expr) (WARN_ON(_expr)) #define VM_WARN_ON_ONCE(_expr) (WARN_ON_ONCE(_expr)) +#define VM_WARN_ON_ONCE_VMA(_expr, _vma) (WARN_ON_ONCE(_expr)) #define VM_WARN_ON_VMG(_expr, _vmg) (WARN_ON(_expr)) #define VM_BUG_ON(_expr) (BUG_ON(_expr)) #define VM_BUG_ON_VMA(_expr, _vma) (BUG_ON(_expr)) _ Patches currently in -mm which might be from ljs@kernel.org are mm-vma-introduce-vma-anon-page-offset-field-and-add-helpers.patch mm-provide-vma_is_cow_mapping-and-remove-is_cow_mapping.patch mm-introduce-linear_anon_page_index.patch mm-abstract-vma_address-and-introduce-vma_anon_address.patch mm-update-print_bad_page_map-to-show-anon-index-if-appropriate.patch mm-introduce-and-use-vma_filebacked_address.patch mm-vma-fix-self-merge-check-in-copy_vma.patch tools-testing-vma-add-tests-for-copy_vma-self-merge.patch mm-propagate-vma-anonymous-page-offset-on-map-remap-split-merge.patch mm-rmap-track-whether-the-page-vma-mapped-pgoff-is-anonymous.patch mm-clean-up-vma_address_end.patch mm-huge_memory-update-remove_migration_pmd-to-accept-a-folio.patch mm-migrate-calculate-large-folio-page-index-using-pfn.patch mm-rmap-use-anon-pgoff-to-track-map_private-file-backed-anon-folios.patch tools-testing-vma-expand-vma-merge-tests-to-assert-anon-pgoff.patch tools-testing-selftests-mm-test-anonymous-page-offset-merge-behaviour.patch mm-add-some-missing-includes-to-mm-local-headers.patch maintainers-add-drivers-char-memc-to-mm-misc-memory-mapping-sections.patch