[Devel] [PATCH hci-8.1 5/7] exec: refuse to preserve memory across a privilege-changing exec

Konstantin Khorenko khorenko at virtuozzo.com
Wed Oct 14 20:12:24 MSK 2026


Since commit 9e6d16a6c0a1 ("oracle/mm: introduce VM_EXEC_KEEP") a pinned
page in a preserved range is shared with the new image instead of
copied, and since commit 37d9f55655ea ("oracle/mm: do not write protect
COW mappings when preserving across exec") it is not copied on write
either: long-term pins taken before the exec, such as a VFIO DMA mapping
or io_uring fixed buffers, keep pointing at it. That is what the feature
is for, DMA into the pages has to continue across exec.

When the exec is a secure one, for a set-id or file-capability binary or
an LSM transition that asks for AT_SECURE, this hands a write path into
the privileged image to whoever drives those pins: the user who set them
up keeps the device or the io_uring fd in another process and has the
device or io_uring write into the memory of the new image. The pins
cannot be revoked, and zapping the ranges in the old mm does not touch
them.

Refuse the exec with EPERM from reserve_preserved_mem() when
bprm->secureexec is set. bprm_creds_from_file() has already run at that
point and the check is before the point of no return, so the caller gets
the error from execve(), can drop MADV_DOEXEC and retry. secureexec is
computed before the ptrace downgrade, so a ptraced setuid exec is
refused as well. A root task that regains dropped capabilities through
exec does not set it and is not refused.

Fixes: 9e6d16a6c0a1 ("oracle/mm: introduce VM_EXEC_KEEP")
https://virtuozzo.atlassian.net/browse/VSTOR-150232

Feature: oracle/mm: MADV_DOEXEC madvise() flag
Assisted-by: LLM
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 fs/exec.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index 5bf856e829af3..49a0a9693eb8a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1021,6 +1021,10 @@ static int reserve_preserved_mem(struct linux_binprm *bprm)
 	if (!preserve)
 		return 0;
 
+	/* Pins taken under the old credentials outlive the exec. */
+	if (bprm->secureexec)
+		return -EPERM;
+
 	/* A clone is either counted here or already visible in the task list. */
 	spin_lock(&mm->page_table_lock);
 	if (mm->exec_keep_active || mm->exec_keep_clones)

-- 
2.43.0



More information about the Devel mailing list