From: Konstantin Khorenko <khorenko@virtuozzo.com>
To: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>,
Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Cc: devel@openvz.org
Subject: [Devel] [PATCH hci-8.1 v2 0/2] mm, binfmt_elf: two fixes also posted to mainline
Date: Wed, 04 Nov 2026 19:05:39 +0100 [thread overview]
Message-ID: <20261104-b4-prep-khorenko-vstor-149847-1-upstream-fixes-v2-0-2974ec52f0fe@virtuozzo.com> (raw)
Two independent fixes for bugs that mainline has as well. Both are
posted to mainline; the backport notes name what differs in this tree.
The MADV_DOEXEC series apply on top of this one, in this order:
- mm: keep DMA-pinned MADV_DOEXEC memory working across exec
- mm, exec: fix the MADV_DOEXEC code we carry from Oracle
- mm: allow MADV_DOEXEC on VFIO BAR mappings, which relies on patch 1
- selftests/mm: broader MADV_DOEXEC coverage
Mainline
========
- Patch 1 is patch 1/2 of "mm/huge_memory: fix the copy of special
PMDs at fork", v3:
https://lore.kernel.org/r/20261014-b4-prep-vstor-149847-copy_huge_pmd-recheck-special-pmd-v3-0-85eaec8417f6@virtuozzo.com
Sashiko review:
https://sashiko.dev/#/patchset/20261014-b4-prep-vstor-149847-copy_huge_pmd-recheck-special-pmd-v3-0-85eaec8417f6@virtuozzo.com
The Sashiko review of v1 found the ppc64 issue that patch 2/2 there
fixes:
https://sashiko.dev/#/patchset/20261014-b4-prep-vstor-149847-copy_huge_pmd-recheck-special-pmd-v1-1-d225c60bc316@virtuozzo.com
- Patch 2 is "binfmt_elf: return the real error when program headers
cannot be loaded", v1:
https://lore.kernel.org/r/20261014-b4-prep-vstor-149847-binfmt_elf-enomem-load-elf-phdrs-v1-1-f39c74d55e42@virtuozzo.com
Sashiko review:
https://sashiko.dev/#/patchset/20261014-b4-prep-vstor-149847-binfmt_elf-enomem-load-elf-phdrs-v1-1-f39c74d55e42@virtuozzo.com
Kees Cook asked for a patch that changes the errno and nothing else:
https://lore.kernel.org/r/202610142140.D483AE26DF@keescook
This version does that; the mainline v2 is not posted yet.
Patch 1: copy_huge_pmd() recheck
================================
fork copies a special (PFN) huge PMD from a value read without the page
table lock. vfio-pci zaps its BAR mappings with unmap_mapping_range(),
which takes no mmap lock, when device memory is disabled or the device
is reset. A fork that races with that zap leaves the child with a BAR
mapping the zap removed: the child keeps reaching MMIO that vfio-pci has
disabled instead of getting SIGBUS. The series "mm: allow MADV_DOEXEC on
VFIO BAR mappings" copies these PMDs on every live-update exec.
In mainline this patch is now the first of two. The second deposits a
page table for the copied PMD on ppc64 in hash mode; it is not needed
here, as this tree has no huge pfnmap support on ppc64.
Patch 2: the real error from load_elf_phdrs()
=============================================
load_elf_phdrs() returns NULL on any failure, and load_elf_binary()
turns that into a fixed error: -ENOEXEC for the executable, -ELIBBAD
for its interpreter. The real cause is lost:
cause really execve() returns
------------------------------------- ---------- ----------------
bad e_phentsize, e_phnum 0 or too big bad file ENOEXEC (right)
file ends before the header table bad file ENOEXEC (right)
kmalloc() of the table fails ENOMEM ENOEXEC (wrong)
kernel_read() fails EIO/ENOMEM ENOEXEC (wrong)
For the interpreter every row gives ELIBBAD.
ENOEXEC says the file is not an executable, which is a property of the
file, not a transient failure:
- glibc's execvp() and execlp() take ENOEXEC as "not a binary" and run
the ELF file with /bin/sh, which reports a binary it cannot execute
instead of the ENOMEM or EIO.
- search_binary_handler() tries the next binary format instead of
returning the error.
- For the interpreter the caller gets ELIBBAD, "Accessing a corrupted
shared library", about an ld.so that is fine.
When it happens here: this tree lacks the v6.17 change that lets the
table grow past ELF_MIN_ALIGN, so the allocation fails in practice only
under fault injection; the read fails with an I/O error, or with
-ENOMEM when the page cache cannot take the pages.
Where it came from:
- Until commit 6a8d38945cf4 ("binfmt_elf: Hoist ELF program header
loading to a function") load_elf_binary() returned -ENOMEM and the
read error. That commit documented an ERR_PTR return but returned
NULL; commit cfc46ca4fdca later fixed the comment, not the code.
- Commit a9d9ef133f44 ("binfmt_elf: load interpreter program headers
earlier") gave the interpreter's headers the same NULL check, and with
it -ELIBBAD.
Testing
=======
On a KVM guest with this series and the four MADV_DOEXEC series on top
of it, release and debug kernels:
- a fork-vs-revoke reproducer on a vfio-pci BAR (QXL in no-IOMMU mode):
no stale child mapping; on mainline the same reproducer with a delay
in the window shows the bug and that the patch closes it;
- failslab sweep over one execve(): ENOMEM instead of ENOEXEC/ELIBBAD,
execvp() no longer falls back to /bin/sh; truncated tables and
e_phoff = 2^63 still give ENOEXEC/ELIBBAD;
- selftests/exec, the MADV_DOEXEC selftests, gup_test, a Container
start/exec/stop.
https://virtuozzo.atlassian.net/browse/VSTOR-150144
Assisted-by: LLM
---
Changes in v2:
- Patch 2: change the errno only, as asked in mainline review. A short
read is no longer read on to get the error behind it: it gives
ENOEXEC/ELIBBAD, as before the patch. The table is read with
kernel_read() directly, as elf_read() turns a short read into EIO.
- Assisted-by moved from the patches to the cover letter.
- Link to v1: http://lore.virtuozzo.com/20261014-b4-prep-khorenko-vstor-149847-1-upstream-fixes-v1-0-7fde9ffbebe9@virtuozzo.com
---
Konstantin Khorenko (2):
mm/huge_memory: recheck a special PMD under the lock in copy_huge_pmd()
binfmt_elf: return the real error when program headers cannot be loaded
fs/binfmt_elf.c | 39 ++++++++++++++++++++++++---------------
mm/huge_memory.c | 23 ++++++++++++++++-------
2 files changed, 40 insertions(+), 22 deletions(-)
---
base-commit: defa968cbe8c38f1ff0231042dee07f00d27b2c9
change-id: 20261014-b4-prep-khorenko-vstor-149847-1-upstream-fixes-4bb22a75a079
Best regards,
--
Konstantin Khorenko,
Virtuozzo Linux Kernel Team
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
next reply other threads:[~2026-11-04 18:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 18:05 Konstantin Khorenko [this message]
2026-11-04 18:05 ` [Devel] [PATCH hci-8.1 v2 1/2] mm/huge_memory: recheck a special PMD under the lock in copy_huge_pmd() Konstantin Khorenko
2026-11-04 18:08 ` no-reply
2026-11-04 18:05 ` [Devel] [PATCH hci-8.1 v2 2/2] binfmt_elf: return the real error when program headers cannot be loaded Konstantin Khorenko
2026-11-04 18:08 ` no-reply
2026-11-04 19:16 ` [Devel] [PATCH hci-8.1 v2 0/2] mm, binfmt_elf: two fixes also posted to mainline Konstantin Khorenko
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=20261104-b4-prep-khorenko-vstor-149847-1-upstream-fixes-v2-0-2974ec52f0fe@virtuozzo.com \
--to=khorenko@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox