Merge: mm, mremap: fix mremap() expanding for vma's with vm_ops->close()

MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/3206

Upstream commit ca3d76b0aa80 was backported in RHEL-9.2 as commit 8c20bfd27e.
This causes a failure when multiple threads within a process try to expand
an mmap, and mremap tries to merge the adjacent vma's.

RHEL-9.3 backported one fix from upstream v6.2-rc1, 6f12be792fde as RHEL-9.3 commit 0517036a0e,
as part of the 100+, RHEL-9.3 Proactive MM fixes.

In researching this reported bug, another Fixes patch for ca3d76b0aa80 was found from v6.2-rc7, d014cd7c1c35.
So, this MR is backporting this fix, which will be z-streamed into 9.3; after which it will be z-streamed into 9.2 along with 9.3's 0517036a0e commit, so 9.2 is completely repaired.

A test program was provided in Jira RHEL-9198 to show the bug, and was used to replicate the bug on a VM, and to demonstrate its repair first in 9.3, then with this added commit.
A long term test on a SQL application by a large fintech company reported seeing another vma-merge problem that has the signature that this MR repairs.

The test program will be included in future kernel-mm testing as a means to regression test mmap-based, vma-merge logic.

Please review, approve & merge into 9.4 asap, as OpenShift and the large fintech customer are anxiously awaiting the zstream-ing of the needed patches to 9.2.

JIRA: https://issues.redhat.com/browse/RHEL-9198

Signed-off-by: Donald Dutile <ddutile@redhat.com>

Approved-by: Chris von Recklinghausen <crecklin@redhat.com>
Approved-by: Rafael Aquini <aquini@redhat.com>

Signed-off-by: Scott Weaver <scweaver@redhat.com>
This commit is contained in:
Scott Weaver 2023-10-30 15:41:52 -04:00
commit 38f8d79078
1 changed files with 19 additions and 6 deletions

View File

@ -1035,16 +1035,29 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
}
/*
* Function vma_merge() is called on the extension we are adding to
* the already existing vma, vma_merge() will merge this extension with
* the already existing vma (expand operation itself) and possibly also
* with the next vma if it becomes adjacent to the expanded vma and
* otherwise compatible.
* Function vma_merge() is called on the extension we
* are adding to the already existing vma, vma_merge()
* will merge this extension with the already existing
* vma (expand operation itself) and possibly also with
* the next vma if it becomes adjacent to the expanded
* vma and otherwise compatible.
*
* However, vma_merge() can currently fail due to
* is_mergeable_vma() check for vm_ops->close (see the
* comment there). Yet this should not prevent vma
* expanding, so perform a simple expand for such vma.
* Ideally the check for close op should be only done
* when a vma would be actually removed due to a merge.
*/
vma = vma_merge(mm, vma, extension_start, extension_end,
if (!vma->vm_ops || !vma->vm_ops->close) {
vma = vma_merge(mm, vma, extension_start, extension_end,
vma->vm_flags, vma->anon_vma, vma->vm_file,
extension_pgoff, vma_policy(vma),
vma->vm_userfaultfd_ctx, anon_vma_name(vma));
} else if (vma_adjust(vma, vma->vm_start, addr + new_len,
vma->vm_pgoff, NULL)) {
vma = NULL;
}
if (!vma) {
vm_unacct_memory(pages);
ret = -ENOMEM;