From: Konstantin Khorenko <khorenko@virtuozzo.com>
To: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>,
Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>,
Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Cc: devel@openvz.org
Subject: [Devel] [PATCH hci-8.1 3/8] oracle/mm: do not write protect COW mappings when preserving across exec
Date: Wed, 14 Oct 2026 19:11:06 +0200 [thread overview]
Message-ID: <20261014-b4-prep-khorenko-vstor-149847-2-doexec-pinned-memory-v1-3-36f1120f9b57@virtuozzo.com> (raw)
In-Reply-To: <20261014-b4-prep-khorenko-vstor-149847-2-doexec-pinned-memory-v1-0-36f1120f9b57@virtuozzo.com>
From: Anthony Yznaga <anthony.yznaga@oracle.com>
A mapping that is pinned for DMA and preserved across exec can incur
a COW if write protected. The elevated reference count prevents reuse
of the mapped folio.
Orabug: 38029049
Suggested-by: Steve Sistare <steven.sistare@oracle.com>
Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
Reviewed-by: Harry Yoo <harry.yoo@oracle.com>
(cherry picked from commit f2e56cc70e62fe07efb71a1e1c2360a78cba5aff)
Taken from Oracle linux-uek branch uek8/u2. Applied cleanly.
This is the fix for the ticket: a FOLL_LONGTERM-pinned anonymous page
preserved with MADV_DOEXEC was write-protected and lost
PageAnonExclusive in vma_dup(), so the first write in the new image
COWed it and the pin kept the old page. The pinned pages now stay
exclusive and writable in the new mm, and the old mm keeps its own. The
fixes that follow write protect both again and zap the old mm's mappings
right after the copy.
Fixes: 9e6d16a6c0a1 ("oracle/mm: introduce VM_EXEC_KEEP")
https://virtuozzo.atlassian.net/browse/VSTOR-150231
Feature: oracle/mm: MADV_DOEXEC madvise() flag
Assisted-by: LLM
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
include/linux/rmap.h | 8 ++++----
mm/memory.c | 13 ++++++++++---
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 5dc4cd6e4e2c9..01e46123ab2dc 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -431,22 +431,22 @@ static __always_inline int __folio_try_dup_anon_rmap(struct folio *folio,
}
if (!folio_test_large(folio)) {
- if (PageAnonExclusive(page))
+ if (PageAnonExclusive(page) && !is_exec_keep)
ClearPageAnonExclusive(page);
atomic_inc(&folio->_mapcount);
break;
}
do {
- if (PageAnonExclusive(page))
+ if (PageAnonExclusive(page) && !is_exec_keep)
ClearPageAnonExclusive(page);
atomic_inc(&page->_mapcount);
} while (page++, --nr_pages > 0);
atomic_add(orig_nr_pages, &folio->_large_mapcount);
break;
case RMAP_LEVEL_PMD:
- if (PageAnonExclusive(page)) {
- if (unlikely(maybe_pinned) && likely(!is_exec_keep))
+ if (PageAnonExclusive(page) && !is_exec_keep) {
+ if (unlikely(maybe_pinned))
return -EBUSY;
ClearPageAnonExclusive(page);
}
diff --git a/mm/memory.c b/mm/memory.c
index d4821379529bf..a240246762751 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -956,9 +956,15 @@ static __always_inline void __copy_present_ptes(struct vm_area_struct *dst_vma,
pte_t pte, unsigned long addr, int nr)
{
struct mm_struct *src_mm = src_vma->vm_mm;
+ bool is_exec_keep = !!(dst_vma->vm_flags & VM_EXEC_KEEP);
/* If it's a COW mapping, write protect it both processes. */
- if (is_cow_mapping(src_vma->vm_flags) && pte_write(pte)) {
+ /*
+ * But don't protect it if PTEs are being copied as part of preserving
+ * memory across exec since the page may be pinned for DMA and must not
+ * be COW'd.
+ */
+ if (is_cow_mapping(src_vma->vm_flags) && pte_write(pte) && !is_exec_keep) {
wrprotect_ptes(src_mm, addr, src_pte, nr);
pte = pte_wrprotect(pte);
}
@@ -991,6 +997,7 @@ copy_present_ptes(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma
bool any_writable;
fpb_t flags = 0;
int err, nr;
+ bool is_exec_keep = !!(dst_vma->vm_flags & VM_EXEC_KEEP);
page = vm_normal_page(src_vma, addr, pte);
if (unlikely(!page))
@@ -1019,7 +1026,7 @@ copy_present_ptes(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma
return -EAGAIN;
}
rss[MM_ANONPAGES] += nr;
- VM_WARN_ON_FOLIO(PageAnonExclusive(page), folio);
+ VM_WARN_ON_FOLIO(PageAnonExclusive(page) && !is_exec_keep, folio);
} else {
folio_dup_file_rmap_ptes(folio, page, nr);
rss[mm_counter_file(folio)] += nr;
@@ -1047,7 +1054,7 @@ copy_present_ptes(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma
return err ? err : 1;
}
rss[MM_ANONPAGES]++;
- VM_WARN_ON_FOLIO(PageAnonExclusive(page), folio);
+ VM_WARN_ON_FOLIO(PageAnonExclusive(page) && !is_exec_keep, folio);
} else {
folio_dup_file_rmap_pte(folio, page);
rss[mm_counter_file(folio)]++;
--
2.43.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
next prev parent reply other threads:[~2026-10-14 17:12 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-14 17:11 [Devel] [PATCH hci-8.1 0/8] mm: keep DMA-pinned MADV_DOEXEC memory working " Konstantin Khorenko
2026-10-14 17:11 ` [Devel] [PATCH hci-8.1 1/8] oracle/mm: fix VM_BUG_ON hit when preserving memory Konstantin Khorenko
2026-10-14 17:16 ` no-reply
2026-10-14 17:11 ` [Devel] [PATCH hci-8.1 2/8] oracle/mm: hold the source mmap write lock when copying PTEs Konstantin Khorenko
2026-10-14 17:15 ` no-reply
2026-10-14 17:11 ` Konstantin Khorenko [this message]
2026-10-14 17:20 ` [Devel] [PATCH hci-8.1 3/8] oracle/mm: do not write protect COW mappings when preserving across exec no-reply
2026-10-14 17:11 ` [Devel] [PATCH hci-8.1 4/8] oracle/mm: write protect preserved PTEs but keep them exclusive Konstantin Khorenko
2026-10-14 17:18 ` no-reply
2026-10-14 17:11 ` [Devel] [PATCH hci-8.1 5/8] oracle/mm: set MMF_HAS_PINNED on the mm receiving preserved pages Konstantin Khorenko
2026-10-14 17:19 ` no-reply
2026-10-14 17:11 ` [Devel] [PATCH hci-8.1 6/8] oracle/mm: zap the preserved ranges of the old mm after copying them Konstantin Khorenko
2026-10-14 17:24 ` no-reply
2026-10-14 17:11 ` [Devel] [PATCH hci-8.1 7/8] exec: protect preserved memory against surviving shared-mm tasks Konstantin Khorenko
2026-10-14 17:24 ` no-reply
2026-10-14 17:11 ` [Devel] [PATCH hci-8.1 8/8] selftests/mm: test memory preservation across exec Konstantin Khorenko
2026-10-14 17:33 ` no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261014-b4-prep-khorenko-vstor-149847-2-doexec-pinned-memory-v1-3-36f1120f9b57@virtuozzo.com \
--to=khorenko@virtuozzo.com \
--cc=andrey.drobyshev@virtuozzo.com \
--cc=devel@openvz.org \
--cc=ptikhomirov@virtuozzo.com \
--cc=vasileios.almpanis@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.