FAILED: patch "[PATCH] mm/mremap: reset unfaulted VMA page offset for" failed to apply to 6.12-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 35b0fb391b0df57383bc15985bb769f4555c97ba
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090957-prideful-repulsive-38a0@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 35b0fb391b0df57383bc15985bb769f4555c97ba Mon Sep 17 00:00:00 2001
From: "Lorenzo Stoakes (ARM)" <[email protected]>
Date: Tue, 25 Aug 2026 08:55:26 +0100
Subject: [PATCH] mm/mremap: reset unfaulted VMA page offset for
MREMAP_DONTUNMAP
Uniquely an mremap() invocation using the MREMAP_DONTUNMAP flag can reset a faulted VMA into an unfaulted one.
It does so after the page tables have been moved to the copied VMA with MREMAP_DONTUNMAP leaving the old VMA in place which is naturally unfaulted as the page tables it had are no longer present.
However, in doing so, it violates the invariant that the anonymous page offset of an unfaulted VMA is vma->vm_start >> PAGE_SHIFT.
This is because a VMA may have been faulted in, mremap()'d (causing a delta between its page offset and vma->vm_start >> PAGE_SHIFT), and then mremap()'d again with MREMAP_DONTUNMAP resulting in the unfaulting.
This condition is a violation of a fundamental assumption in mm, but now also triggers an assert in assert_sane_pgoff() which explicitly checks for this condition.
Correct it by resetting the VMA's page offset at the point of completing the MREMAP_DONTUNMAP operation.
mm/mremap.c +17 -5
@@ -1331,18 +1331,30 @@ static void dontunmap_complete(struct vma_remap_struct *vrm, {unsigned long start = vrm->addr;unsigned long end = vrm->addr + vrm->old_len; -unsigned long old_start = vrm->vma->vm_start; -unsigned long old_end = vrm->vma->vm_end; +struct vm_area_struct *vma = vrm->vma; +unsigned long old_start = vma->vm_start; +unsigned long old_end = vma->vm_end;/* We always clear VMA_LOCKED[ONFAULT]_BIT on the old VMA. */ -vma_clear_flags_mask (vrm->vma,VMA_LOCKED_MASK ); +vma_clear_flags_mask (vma,VMA_LOCKED_MASK );/* * anon_vma links of the old vma is no longer needed after its page * table has been moved. */ -if (new_vma != vrm->vma && start == old_start && end == old_end) -unlink_anon_vmas (vrm->vma); +if (new_vma != vma && start == old_start && end == old_end) { +const pgoff_t pgoff_unfaulted = vma->vm_start >>PAGE_SHIFT ; + +unlink_anon_vmas (vma); +/* +* The VMA is now unfaulted and it is an invariant that +* unfaulted anonymous VMAs have page offset equal to +* vma->vm_start >> PAGE_SHIFT. +*/ +vma_set_anon_pgoff (vma, pgoff_unfaulted); +if (vma_is_anonymous (vma) && !vma->vm_file) +vma_set_pgoff (vma, pgoff_unfaulted); + }/* Because we won't unmap we don't need to touch locked_vm. */ }
Sasha Levin
maintainerPATCH 1/1 mm/mremap: reset unfaulted VMA page offset for MREMAP_DONTUNMAP
From: "Lorenzo Stoakes (ARM)" <[email protected]>
[ Upstream commit 35b0fb391b0df57383bc15985bb769f4555c97ba ]
Uniquely an mremap() invocation using the MREMAP_DONTUNMAP flag can reset a faulted VMA into an unfaulted one.
It does so after the page tables have been moved to the copied VMA with MREMAP_DONTUNMAP leaving the old VMA in place which is naturally unfaulted as the page tables it had are no longer present.
However, in doing so, it violates the invariant that the anonymous page offset of an unfaulted VMA is vma->vm_start >> PAGE_SHIFT.
This is because a VMA may have been faulted in, mremap()'d (causing a delta between its page offset and vma->vm_start >> PAGE_SHIFT), and then mremap()'d again with MREMAP_DONTUNMAP resulting in the unfaulting.
This condition is a violation of a fundamental assumption in mm, but now also triggers an assert in assert_sane_pgoff() which explicitly checks for this condition.
Correct it by resetting the VMA's page offset at the point of completing the MREMAP_DONTUNMAP operation.
--- mm/mremap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
mm/mremap.c +11 -1
@@ -811,8 +811,18 @@ static unsigned long move_vma(struct vm_area_struct *vma,* table has been moved. */ if (new_vma != vma && vma->vm_start == old_addr && - vma->vm_end == (old_addr + old_len)) + vma->vm_end == (old_addr + old_len)) { +const pgoff_t pgoff_unfaulted = vma->vm_start >>PAGE_SHIFT ; +unlink_anon_vmas (vma); +/* +* The VMA is now unfaulted and it is an invariant that +* unfaulted anonymous VMAs have page offset equal to +* vma->vm_start >> PAGE_SHIFT. +*/ +if (vma_is_anonymous (vma) && !vma->vm_file) + vma->vm_pgoff = pgoff_unfaulted; + }/* Because we won't unmap we don't need to touch locked_vm */ return new_addr;
Signature · 1 line
2.53.0
Lorenzo Stoakes (ARM)
maintainerRe: [PATCH 6.12.y] mm/mremap: reset unfaulted VMA page offset for MREMAP_DONTUNMAP
Quoted 25 lines · Sasha Levin
From: "Lorenzo Stoakes (ARM)" <[email protected]>
[ Upstream commit
35b0fb391b0df57383bc15985bb769f4555c97ba]Uniquely an
mremap()invocation using theMREMAP_DONTUNMAPflag can reset a faulted VMA into an unfaulted one.It does so after the page tables have been moved to the copied VMA with
MREMAP_DONTUNMAPleaving the old VMA in place which is naturally unfaulted as the page tables it had are no longer present.However, in doing so, it violates the invariant that the anonymous page offset of an unfaulted VMA is
vma->vm_start>>PAGE_SHIFT.This is because a VMA may have been faulted in, mremap()'d (causing a delta between its page offset and
vma->vm_start>>PAGE_SHIFT), and then mremap()'d again withMREMAP_DONTUNMAPresulting in the unfaulting.This condition is a violation of a fundamental assumption in mm, but now also triggers an assert in
assert_sane_pgoff()which explicitly checks for this condition.Correct it by resetting the VMA's page offset at the point of completing the
MREMAP_DONTUNMAPoperation.
Quoted 16 lines
Fixes 1583aa278f5f ("mm: mremap: unlink anon_vmas when mremap with MREMAP_DONTUNMAP success")Signed-off-by Lorenzo Stoakes (ARM) <[email protected]>Reported-by [email protected]Tested-by [email protected]Reviewed-by Kunwu Chan <[email protected]>Reviewed-by Pedro Falcato <[email protected]>Cc Jann Horn <[email protected]>Cc Liam R. Howlett <[email protected]>Cc Li Xinhai <[email protected]>Cc <[email protected]>Signed-off-by Andrew Morton <[email protected]>[ adapted dontunmap_complete() changes to move_vma() using direct vm_pgoff assignment instead of unavailable helpers. ]Signed-off-by Sasha Levin <[email protected]>
LGTM thanks!
Quoted 29 lines
--- mm/mremap.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)mm/mremap.c +11
-2@@ -811,8 +811,18 @@ static unsigned long move_vma(struct vm_area_struct *vma,* table has been moved. */ if (new_vma != vma && vma->vm_start == old_addr && - vma->vm_end == (old_addr + old_len)) + vma->vm_end == (old_addr + old_len)) { +const pgoff_t pgoff_unfaulted = vma->vm_start >>PAGE_SHIFT ; +unlink_anon_vmas (vma); +/* +* The VMA is now unfaulted and it is an invariant that +* unfaulted anonymous VMAs have page offset equal to +* vma->vm_start >> PAGE_SHIFT. +*/ +if (vma_is_anonymous (vma) && !vma->vm_file) + vma->vm_pgoff = pgoff_unfaulted; + }/* Because we won't unmap we don't need to touch locked_vm */ return new_addr; --
Quoted 2 lines
2.53.0
--
Cheers, Lorenzo