Keep mremap growth out of occupied suffixes - #391
Conversation
| bool can_grow = | ||
| !region_range_overlaps(g, grow_off, grow_off + grow_len); |
There was a problem hiding this comment.
Refusing in-place growth here sends a source whose region extends past grow_off down the move path, which is right, and it removes the old path's worst case: a memset of grow_len zeros straight into a live MAP_SHARED file overlay, which wrote those zeros to the backing file.
One hole survives the move. cleanup_overlays_in_range rounds its teardown up to the host page (ALIGN_UP(end, hps), 16 KiB on Apple Silicon) while guest ranges are 4 KiB granular, and hvf_restore_slab_backing re-mmaps fresh slab without repopulating from the file, so growing the first 4 KiB of a shared file mapping leaves the next 12 KiB of the surviving suffix reading slab instead of file contents. That was already reachable through a separate mapping at grow_off, so it is a follow-up rather than something this change owes.
There was a problem hiding this comment.
Agreed. The 16 KiB overlay teardown is independent of this change and remains reachable through a separate mapping at grow_off. It needs a separate issue and regression test. Will take time to reproduce the follow-up and open a new issue.
jserv
left a comment
There was a problem hiding this comment.
Check https://github.com/sysprog21/elfuse/blob/main/CONTRIBUTING.md carefully.
Adjacent anonymous mappings can coalesce into a tracked region that extends beyond the requested source range. In-place growth then cleared the live suffix, although Linux permits growth only when the source range ends at the end of its VMA. Without MREMAP_MAYMOVE, the request returns ENOMEM. With the flag, only the source range relocates and the suffix remains intact. Closes sysprog21#389
60b4185 to
1836227
Compare
|
Thank @Ksld154 for contributing! |
Problem
Adjacent anonymous mappings can coalesce into a tracked region that extends
beyond the source range passed to
mremap. The in-place growth check skippedthat region when its start matched the source address, so it treated the live
suffix as free and cleared its contents.
Linux permits in-place growth only when the source range ends at the end of
its VMA. An occupied suffix must make a request without
MREMAP_MAYMOVEfailwith
ENOMEM; with the flag, only the source range may relocate.This bug caused Alpine
apkto crash while resolving packages from localrepository indexes.
Regression coverage
case that exposed the bug.
construction, independent of region-merging policy.
Both cases verify that a request without
MREMAP_MAYMOVEreturnsENOMEMwithout changing either page. They also verify that
MREMAP_MAYMOVErelocatesthe source data, zeroes the new extension, and preserves the occupied suffix.
Environment
Validation
make check-format: passedbuild/elfuse build/test-mremap: 14 passedbash tests/test-matrix.sh all: the QEMU aarch64 lane passed 271 tests withno failures; the elfuse aarch64 lane passed 292 tests, with the unrelated
test-dup-setfl-racetiming out under the full matrix load and passing whenrun alone; Rosetta-independent x86_64 guardrails passed
apk --no-network --simulate add git: three consecutive runs exitedwith status 0
make check: all 99 core tests and all mremap suites passed; the finalBusyBox
nslookupsmoke test could not reach a DNS servermake verify: not completed because Frama-C is unavailable locallyCloses #389
Summary by cubic
Protects adjacent coalesced mappings from being overwritten during in-place
mremapgrowth. Previously, growth could zero live bytes in a neighboring mapping when the region extended past the source range; now it returnsENOMEMwithoutMREMAP_MAYMOVEand relocates withMREMAP_MAYMOVE, preserving both mappings.Written for commit 1836227. Summary will update on new commits.