[PATCH v2] mm/vma: keep the unlinked VMA off the file across unmap on mmap hook failure
From: Oleg Keri
Date: Wed Oct 07 2026 - 15:48:34 EST
Since commit 2ceb21171dd9 ("mm: consistently validate VMA state after
mmap[_prepare] hooks"), the mmap error path clears vma->vm_file only
after unmap_region(), so free_pgtables() unlinks the never-linked VMA
and drops i_mmap_writable. Once it goes negative, every later shared
writable mmap of that file fails with -EPERM until reboot.
Clear vm_file across unmap_region() only, so that free_pgtables() does
not unlink a VMA that was never linked to the file, and restore it for
vma_close(): when the hook succeeded and the validation failed, the
driver's close() still runs and may use vma->vm_file.
Fixes: 2ceb21171dd9 ("mm: consistently validate VMA state after mmap[_prepare] hooks")
Signed-off-by: Oleg Keri <okerixx@xxxxxxxxx>
---
v2: keep vm_file for vma_close(): with the hook succeeded and the
validation failed the driver's close() still runs. Reported by Sashiko
via Andrew.
Seen on next-20261006: one refused PCM mmap probe from alsa-lib left the
device unmappable, so PipeWire could not play anything.
mm/vma.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/mm/vma.c b/mm/vma.c
index dfa45c64222c..531e4f53fdd7 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2616,12 +2616,15 @@ static int __mmap_new_file_vma(struct mmap_state *map,
map->vm_file = vma->vm_file;
if (error) {
+ struct file *file = vma->vm_file;
UNMAP_STATE(unmap, vmi, vma, vma->vm_start, vma->vm_end,
map->prev, map->next);
+ vma->vm_file = NULL;
vma_iter_set(vmi, vma->vm_end);
/* Undo any partial mapping done by a device driver. */
unmap_region(&unmap);
+ vma->vm_file = file;
/* Only safe once unmapped. */
vma_close(vma);
--
2.55.0