[to-be-updated] mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous.patch removed from -mm tree
Andrew Morton <[email protected]>
| Newsgroups | org.kernel.vger.mm-commits |
|---|---|
| Message-ID | <[email protected]> |
The quilt patch titled
Subject: mm/vma: make MAP_PRIVATE-mapped /dev/zero mappings truly anonymous
has been removed from the -mm tree. Its filename was
mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous.patch
This patch was dropped because an updated version will be issued
------------------------------------------------------
From: "Lorenzo Stoakes (ARM)" <[email protected]>
Subject: mm/vma: make MAP_PRIVATE-mapped /dev/zero mappings truly anonymous
Date: Thu, 06 Aug 2026 21:21:43 +0100
When mapping /dev/zero with MAP_PRIVATE, one ends up with strange VMAs
originating from Linux's distant past.
These have vma->vm_file set but NULL vma->vm_ops, meaning they satisfy
vma_is_anonymous() but otherwise resemble a file-backed VMA.
The introduction of anonymous page offsets and their subsequent use as
indexes for MAP_PRIVATE-file-backed mappings mean the rmap does the right
thing with these but we are left with inconsistencies.
The vma_start_pgoff(vma) == vma_start_anon_pgoff(vma) invariant is true
for all other anonymous VMAs, but not these.
These VMAs are also observable as files in /proc/<pid>/[maps, smaps,
map_files] but otherwise behave like anonymous mappings.
Therefore let's make these VMAs actually anonymous at mapping time which
will activate the anonymous code path for mappings.
This means we no longer have to account for this discrepancy anywhere and
no longer have to think about these at all.
This is user-observable, as MAP_PRIVATE-/dev/zero will no longer appear in
procfs as a file-backed mapping, but the impact of this change should be
low as likely nobody is relying upon this.
However in any case, in using MAP_PRIVATE-/dev/zero they are explicitly
asking anonymous memory, so no longer seeing these as file mappings is in
fact correct.
A previous commit gave us map_is_dev_zero() to positively identify these
mappings, so we expressly only do so for these alone.
Update assert_sane_pgoff(), the comment for vma_start_pgoff() and
linear_anon_page_index() to reflect the change.
We make this change in call_mmap_prepare() alone as /dev/zero has been
converted to an mmap_prepare hook and we do not permit nested MAP_PRIVATE
mapping of /dev/zero.
We also remove the now defunct vma_desc_set_anonymous() and eliminate the
temporary bisection hazard fix from the previous commit.
Also update the VMA userland tests to reflect the change.
Finally, update the procfs self tests proc-self-map-files-001 and
proc-self-map-files-002 which both intend to map an arbitrary file
MAP_PRIVATE then assert procfs state, but happen to choose /dev/zero.
Fix them by updating these to /proc/self/exe which is guaranteed to be
present if procfs is mounted.
Link: https://lore.kernel.org/20260806-b4-scalable-cow-virt-pgoff-v4-18-ab318a350404@kernel.org
Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: Alexander Deucher <[email protected]>
Cc: Alexander Gordeev <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alistair Popple <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Baolin Wang <[email protected]>
Cc: Baoquan He <[email protected]>
Cc: Barry Song <[email protected]>
Cc: Boris Brezillon <[email protected]>
Cc: Byungchul Park <[email protected]>
Cc: Chengming Zhou <[email protected]>
Cc: Chris Li <[email protected]>
Cc: Christan König <[email protected]>
Cc: Christian Borntraeger <[email protected]>
Cc: Claudio Imbrenda <[email protected]>
Cc: Dave Airlie <[email protected]>
Cc: David Hildenbrand (Arm) <[email protected]>
Cc: Dev Jain <[email protected]>
Cc: Gerald Schaefer <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Gregory Price (Meta) <[email protected]>
Cc: Harry Yoo <[email protected]>
Cc: Heiko Carstens <[email protected]>
Cc: Huang Ray <[email protected]>
Cc: "Huang, Ying" <[email protected]>
Cc: Ian Rogers <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: James Clark <[email protected]>
Cc: Jan Kara <[email protected]>
Cc: Jann Horn <[email protected]>
Cc: Janosch Frank <[email protected]>
Cc: Jason Gunthorpe <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: John Hubbard <[email protected]>
Cc: Joshua Hahn <[email protected]>
Cc: Kairui Song <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Kemeng Shi <[email protected]>
Cc: Lance Yang <[email protected]>
Cc: Liam R. Howlett <[email protected]>
Cc: Liviu Dudau <[email protected]>
Cc: Maarten Lankhorst <[email protected]>
Cc: Marc Rutland <[email protected]>
Cc: "Masami Hiramatsu (Google)" <[email protected]>
Cc: Matthew Auld <[email protected]>
Cc: Matthew Brost <[email protected]>
Cc: Matthew Wilcox (Oracle) <[email protected]>
Cc: Maxime Ripard <[email protected]>
Cc: Miaohe Lin <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Mike Rapoport <[email protected]>
Cc: Muchun Song <[email protected]>
Cc: Namhyung kim <[email protected]>
Cc: Naoya Horiguchi <[email protected]>
Cc: Nhat Pham <[email protected]>
Cc: Nico Pache <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Oscar Salvador <[email protected]>
Cc: Pedro Falcato <[email protected]>
Cc: Peter Xu <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Rakie Kim <[email protected]>
Cc: Rik van Riel <[email protected]>
Cc: Rodrigo Vivi <[email protected]>
Cc: Ryan Roberts <[email protected]>
Cc: Steven Price <[email protected]>
Cc: Suren Baghdasaryan <[email protected]>
Cc: Sven Schnelle <[email protected]>
Cc: <[email protected]>
Cc: Thomas Hellström <[email protected]>
Cc: Thomas Zimemrmann <[email protected]>
Cc: Vasily Gorbik <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Cc: Xu Xin <[email protected]>
Cc: Zi Yan <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
---
include/linux/mm.h | 10 ---
include/linux/pagemap.h | 3 -
mm/vma.c | 26 ++++++----
mm/vma.h | 3 -
tools/testing/selftests/proc/proc-self-map-files-001.c | 2
tools/testing/selftests/proc/proc-self-map-files-002.c | 2
tools/testing/vma/include/dup.h | 3 -
7 files changed, 23 insertions(+), 26 deletions(-)
--- a/include/linux/mm.h~mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous
+++ a/include/linux/mm.h
@@ -1554,11 +1554,6 @@ static inline void vma_set_anonymous(str
vma->vm_ops = NULL;
}
-static inline void vma_desc_set_anonymous(struct vm_area_desc *desc)
-{
- desc->vm_ops = NULL;
-}
-
static inline bool vma_is_anonymous(const struct vm_area_struct *vma)
{
return !vma->vm_ops;
@@ -4412,9 +4407,8 @@ static inline unsigned long vma_pages(co
* If @vma is a MAP_PRIVATE file-backed mapping, then this returns the
* page offset within the file.
*
- * Edge cases: nommu does not abide by these, MAP_PRIVATE-/dev/zero satisfies
- * vma_is_anonymous() but has file-backed page offset, and MAP_PRIVATE-pfnmap
- * regions have their page offset set to the first PFN in the range.
+ * Edge cases: nommu does not abide by these and CoW MAP_PRIVATE-pfnmap regions
+ * have their page offset set to the first PFN in the range.
*
* Returns: The page offset of the start of @vma.
*/
--- a/include/linux/pagemap.h~mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous
+++ a/include/linux/pagemap.h
@@ -1128,8 +1128,7 @@ static inline pgoff_t linear_anon_page_i
const pgoff_t pgoff = __linear_anon_page_index(vma, address);
VM_WARN_ON_ONCE(!vma_is_cow_mapping(vma));
- /* Account for MAP_PRIVATE-/dev/zero which is only semi-anonymous. */
- if (vma_is_anonymous(vma) && !vma->vm_file)
+ if (vma_is_anonymous(vma))
VM_WARN_ON_ONCE(pgoff != linear_page_index(vma, address));
return pgoff;
--- a/mm/vma.c~mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous
+++ a/mm/vma.c
@@ -2634,6 +2634,13 @@ static bool map_is_dev_zero(const struct
return imajor(inode) == MEM_MAJOR && iminor(inode) == DEVZERO_MINOR;
}
+static void map_set_anon(struct mmap_state *map)
+{
+ map->file = NULL;
+ map->vm_ops = NULL;
+ map->pgoff = map->addr >> PAGE_SHIFT;
+}
+
static bool map_is_private(const struct mmap_state *map)
{
return !vma_flags_test(&map->vma_flags, VMA_SHARED_BIT);
@@ -2641,10 +2648,7 @@ static bool map_is_private(const struct
static bool map_is_anon(const struct mmap_state *map)
{
- if (!map_is_private(map))
- return false;
-
- return !map->file || map_is_dev_zero(map);
+ return map_is_private(map) && !map->file;
}
/*
@@ -2676,7 +2680,7 @@ static int __mmap_new_vma(struct mmap_st
vma_iter_config(vmi, map->addr, map->end);
- if (is_anon && !map->file)
+ if (is_anon)
vma_set_anonymous(vma);
vma_set_range(vma, map->addr, map->end, map->pgoff, map->anon_pgoff);
@@ -2694,10 +2698,6 @@ static int __mmap_new_vma(struct mmap_st
else if (!is_anon)
error = shmem_zero_setup(vma);
- /* Temporary MAP_PRIVATE-/dev/zero workaround. */
- if (is_anon && map->file)
- vma_set_anonymous(vma);
-
if (error)
goto free_iter_vma;
@@ -2826,6 +2826,14 @@ static int call_mmap_prepare(struct mmap
map->vm_ops = desc->vm_ops;
map->vm_private_data = desc->private_data;
+ /*
+ * MAP_PRIVATE-/dev/zero mappings are an ancient way of getting
+ * anonymous mappings. Rather than allowing these mappings to be odd
+ * outliers, simply make them truly anonymous.
+ */
+ if (map_is_private(map) && map_is_dev_zero(map))
+ map_set_anon(map);
+
return 0;
}
--- a/mm/vma.h~mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous
+++ a/mm/vma.h
@@ -267,9 +267,6 @@ static inline void assert_sane_pgoff(str
*/
if (!vma_is_anonymous(vma))
return;
- /* MAP_PRIVATE-/dev/zero is anon, non-NULL vm_file, but has file pgoff. */
- if (vma->vm_file)
- return;
/* If faulted in, could have been remapped. */
if (vma->anon_vma)
return;
--- a/tools/testing/selftests/proc/proc-self-map-files-001.c~mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous
+++ a/tools/testing/selftests/proc/proc-self-map-files-001.c
@@ -51,7 +51,7 @@ int main(void)
int fd;
unsigned long a, b;
- fd = open("/dev/zero", O_RDONLY);
+ fd = open("/proc/self/exe", O_RDONLY);
if (fd == -1)
return 1;
--- a/tools/testing/selftests/proc/proc-self-map-files-002.c~mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous
+++ a/tools/testing/selftests/proc/proc-self-map-files-002.c
@@ -57,7 +57,7 @@ int main(void)
int fd;
unsigned long a, b;
- fd = open("/dev/zero", O_RDONLY);
+ fd = open("/proc/self/exe", O_RDONLY);
if (fd == -1)
return 1;
--- a/tools/testing/vma/include/dup.h~mm-vma-make-map_private-mapped-dev-zero-mappings-truly-anonymous
+++ a/tools/testing/vma/include/dup.h
@@ -1659,8 +1659,7 @@ static inline pgoff_t linear_anon_page_i
const pgoff_t pgoff = __linear_anon_page_index(vma, address);
VM_WARN_ON_ONCE(!vma_is_cow_mapping(vma));
- /* Account for MAP_PRIVATE-/dev/zero which is only semi-anonymous. */
- if (vma_is_anonymous(vma) && !vma->vm_file)
+ if (vma_is_anonymous(vma))
VM_WARN_ON_ONCE(pgoff != linear_page_index(vma, address));
return pgoff;
_
Patches currently in -mm which might be from [email protected] are
tools-testing-vma-add-test-to-assert-map_private-dev-zero-is-anon.patch
tools-testing-selftests-mm-add-map_private-dev-zero-merge-tests.patch
mm-add-some-missing-includes-to-mm-local-headers.patch
maintainers-add-drivers-char-memc-to-mm-misc-memory-mapping-sections.patch