Re: [PATCH mm-hotfixes] mm/mseal: update VMA end correctly on merge

From: Andrew Morton

Date: Fri Mar 27 2026 - 11:31:45 EST


On Fri, 27 Mar 2026 09:06:40 +0000 "Lorenzo Stoakes (Oracle)" <ljs@xxxxxxxxxx> wrote:

> --- a/mm/mseal.c
> +++ b/mm/mseal.c
> @@ -66,7 +66,7 @@ static int mseal_apply(struct mm_struct *mm,
> prev = vma;
>
> for_each_vma_range(vmi, vma, end) {
> - const unsigned long curr_end = MIN(vma->vm_end, end);
> + unsigned long curr_end = MIN(vma->vm_end, end);
>
> if (!(vma->vm_flags & VM_SEALED)) {
> vm_flags_t vm_flags = vma->vm_flags | VM_SEALED;
> @@ -76,6 +76,7 @@ static int mseal_apply(struct mm_struct *mm,
> if (IS_ERR(vma))
> return PTR_ERR(vma);
> vm_flags_set(vma, VM_SEALED);
> + curr_end = vma->vm_end; /* Merge may have updated. */
> }
>
> prev = vma;

This led to some rework in your "mm/vma: convert
vma_modify_flags[_uffd]() to use vma_flags_t". Please check my
handiwork.

reject:

--- mm/mseal.c~mm-vma-convert-vma_modify_flags-to-use-vma_flags_t
+++ mm/mseal.c
@@ -68,14 +68,17 @@ static int mseal_apply(struct mm_struct
for_each_vma_range(vmi, vma, end) {
const unsigned long curr_end = MIN(vma->vm_end, end);

- if (!(vma->vm_flags & VM_SEALED)) {
- vm_flags_t vm_flags = vma->vm_flags | VM_SEALED;
+ if (!vma_test(vma, VMA_SEALED_BIT)) {
+ vma_flags_t vma_flags = vma->flags;
+
+ vma_flags_set(&vma_flags, VMA_SEALED_BIT);

vma = vma_modify_flags(&vmi, prev, vma, curr_start,
- curr_end, &vm_flags);
+ curr_end, &vma_flags);
if (IS_ERR(vma))
return PTR_ERR(vma);
- vm_flags_set(vma, VM_SEALED);
+ vma_start_write(vma);
+ vma_set_flags(vma, VMA_SEALED_BIT);
}

prev = vma;

resolution:

static int mseal_apply(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
struct vm_area_struct *vma, *prev;
unsigned long curr_start = start;
VMA_ITERATOR(vmi, mm, start);

/* We know there are no gaps so this will be non-NULL. */
vma = vma_iter_load(&vmi);
prev = vma_prev(&vmi);
if (start > vma->vm_start)
prev = vma;

for_each_vma_range(vmi, vma, end) {
unsigned long curr_end = MIN(vma->vm_end, end);

if (!vma_test(vma, VMA_SEALED_BIT)) {
vma_flags_t vma_flags = vma->flags;

vma_flags_set(&vma_flags, VMA_SEALED_BIT);

vma = vma_modify_flags(&vmi, prev, vma, curr_start,
curr_end, &vma_flags);
if (IS_ERR(vma))
return PTR_ERR(vma);
vma_start_write(vma);
vma_set_flags(vma, VMA_SEALED_BIT);
curr_end = vma->vm_end; /* Merge may have updated. */
}

prev = vma;
curr_start = curr_end;
}

return 0;
}