[PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps

Lorenzo Stoakes posted 5 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Lorenzo Stoakes 1 month, 1 week ago
Currently, if a user needs to determine if guard regions are present in a
range, they have to scan all VMAs (or have knowledge of which ones might
have guard regions).

Since commit 8e2f2aeb8b48 ("fs/proc/task_mmu: add guard region bit to
pagemap") and the related commit a516403787e0 ("fs/proc: extend the
PAGEMAP_SCAN ioctl to report guard regions"), users can use either
/proc/$pid/pagemap or the PAGEMAP_SCAN functionality to perform this
operation at a virtual address level.

This is not ideal, and it gives no visibility at a /proc/$pid/smaps level
that guard regions exist in ranges.

This patch remedies the situation by establishing a new VMA flag,
VM_MAYBE_GUARD, to indicate that a VMA may contain guard regions (it is
uncertain because we cannot reasonably determine whether a
MADV_GUARD_REMOVE call has removed all of the guard regions in a VMA, and
additionally VMAs may change across merge/split).

We utilise 0x800 for this flag which makes it available to 32-bit
architectures also, a flag that was previously used by VM_DENYWRITE, which
was removed in commit 8d0920bde5eb ("mm: remove VM_DENYWRITE") and hasn't
bee reused yet.

We also update the smaps logic and documentation to identify these VMAs.

Another major use of this functionality is that we can use it to identify
that we ought to copy page tables on fork.

We do not actually implement usage of this flag in mm/madvise.c yet as we
need to allow some VMA flags to be applied atomically under mmap/VMA read
lock in order to avoid the need to acquire a write lock for this purpose.

Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
 Documentation/filesystems/proc.rst | 1 +
 fs/proc/task_mmu.c                 | 1 +
 include/linux/mm.h                 | 3 +++
 include/trace/events/mmflags.h     | 1 +
 mm/memory.c                        | 4 ++++
 tools/testing/vma/vma_internal.h   | 3 +++
 6 files changed, 13 insertions(+)

diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
index 0b86a8022fa1..b8a423ca590a 100644
--- a/Documentation/filesystems/proc.rst
+++ b/Documentation/filesystems/proc.rst
@@ -591,6 +591,7 @@ encoded manner. The codes are the following:
     sl    sealed
     lf    lock on fault pages
     dp    always lazily freeable mapping
+    gu    maybe contains guard regions (if not set, definitely doesn't)
     ==    =======================================
 
 Note that there is no guarantee that every flag and associated mnemonic will
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 8a9894aefbca..a420dcf9ffbb 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1147,6 +1147,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
 		[ilog2(VM_MAYSHARE)]	= "ms",
 		[ilog2(VM_GROWSDOWN)]	= "gd",
 		[ilog2(VM_PFNMAP)]	= "pf",
+		[ilog2(VM_MAYBE_GUARD)]	= "gu",
 		[ilog2(VM_LOCKED)]	= "lo",
 		[ilog2(VM_IO)]		= "io",
 		[ilog2(VM_SEQ_READ)]	= "sr",
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6e5ca5287e21..2a5516bff75a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -271,6 +271,8 @@ extern struct rw_semaphore nommu_region_sem;
 extern unsigned int kobjsize(const void *objp);
 #endif
 
+#define VM_MAYBE_GUARD_BIT 11
+
 /*
  * vm_flags in vm_area_struct, see mm_types.h.
  * When changing, update also include/trace/events/mmflags.h
@@ -296,6 +298,7 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_UFFD_MISSING	0
 #endif /* CONFIG_MMU */
 #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
+#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */
 #define VM_UFFD_WP	0x00001000	/* wrprotect pages tracking */
 
 #define VM_LOCKED	0x00002000
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
index aa441f593e9a..a6e5a44c9b42 100644
--- a/include/trace/events/mmflags.h
+++ b/include/trace/events/mmflags.h
@@ -213,6 +213,7 @@ IF_HAVE_PG_ARCH_3(arch_3)
 	{VM_UFFD_MISSING,		"uffd_missing"	},		\
 IF_HAVE_UFFD_MINOR(VM_UFFD_MINOR,	"uffd_minor"	)		\
 	{VM_PFNMAP,			"pfnmap"	},		\
+	{VM_MAYBE_GUARD,		"maybe_guard"	},		\
 	{VM_UFFD_WP,			"uffd_wp"	},		\
 	{VM_LOCKED,			"locked"	},		\
 	{VM_IO,				"io"		},		\
diff --git a/mm/memory.c b/mm/memory.c
index 046579a6ec2f..334732ab6733 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1480,6 +1480,10 @@ vma_needs_copy(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma)
 	if (src_vma->anon_vma)
 		return true;
 
+	/* Guard regions have momdified page tables that require copying. */
+	if (src_vma->vm_flags & VM_MAYBE_GUARD)
+		return true;
+
 	/*
 	 * Don't copy ptes where a page fault will fill them correctly.  Fork
 	 * becomes much lighter when there are big shared or private readonly
diff --git a/tools/testing/vma/vma_internal.h b/tools/testing/vma/vma_internal.h
index c68d382dac81..ddf58a5e1add 100644
--- a/tools/testing/vma/vma_internal.h
+++ b/tools/testing/vma/vma_internal.h
@@ -46,6 +46,8 @@ extern unsigned long dac_mmap_min_addr;
 
 #define MMF_HAS_MDWE	28
 
+#define VM_MAYBE_GUARD_BIT 11
+
 #define VM_NONE		0x00000000
 #define VM_READ		0x00000001
 #define VM_WRITE	0x00000002
@@ -56,6 +58,7 @@ extern unsigned long dac_mmap_min_addr;
 #define VM_MAYEXEC	0x00000040
 #define VM_GROWSDOWN	0x00000100
 #define VM_PFNMAP	0x00000400
+#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */
 #define VM_LOCKED	0x00002000
 #define VM_IO           0x00004000
 #define VM_SEQ_READ	0x00008000	/* App will access data sequentially */
-- 
2.51.0
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Pedro Falcato 1 month, 1 week ago
On Thu, Nov 06, 2025 at 10:46:12AM +0000, Lorenzo Stoakes wrote:
> Currently, if a user needs to determine if guard regions are present in a
> range, they have to scan all VMAs (or have knowledge of which ones might
> have guard regions).
> 
> Since commit 8e2f2aeb8b48 ("fs/proc/task_mmu: add guard region bit to
> pagemap") and the related commit a516403787e0 ("fs/proc: extend the
> PAGEMAP_SCAN ioctl to report guard regions"), users can use either
> /proc/$pid/pagemap or the PAGEMAP_SCAN functionality to perform this
> operation at a virtual address level.
> 
> This is not ideal, and it gives no visibility at a /proc/$pid/smaps level
> that guard regions exist in ranges.
> 
> This patch remedies the situation by establishing a new VMA flag,
> VM_MAYBE_GUARD, to indicate that a VMA may contain guard regions (it is
> uncertain because we cannot reasonably determine whether a
> MADV_GUARD_REMOVE call has removed all of the guard regions in a VMA, and
> additionally VMAs may change across merge/split).
> 
> We utilise 0x800 for this flag which makes it available to 32-bit
> architectures also, a flag that was previously used by VM_DENYWRITE, which
> was removed in commit 8d0920bde5eb ("mm: remove VM_DENYWRITE") and hasn't
> bee reused yet.
> 
> We also update the smaps logic and documentation to identify these VMAs.
> 
> Another major use of this functionality is that we can use it to identify
> that we ought to copy page tables on fork.
> 
> We do not actually implement usage of this flag in mm/madvise.c yet as we
> need to allow some VMA flags to be applied atomically under mmap/VMA read
> lock in order to avoid the need to acquire a write lock for this purpose.
> 
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> ---
>  Documentation/filesystems/proc.rst | 1 +
>  fs/proc/task_mmu.c                 | 1 +
>  include/linux/mm.h                 | 3 +++
>  include/trace/events/mmflags.h     | 1 +
>  mm/memory.c                        | 4 ++++
>  tools/testing/vma/vma_internal.h   | 3 +++
>  6 files changed, 13 insertions(+)
> 
> diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
> index 0b86a8022fa1..b8a423ca590a 100644
> --- a/Documentation/filesystems/proc.rst
> +++ b/Documentation/filesystems/proc.rst
> @@ -591,6 +591,7 @@ encoded manner. The codes are the following:
>      sl    sealed
>      lf    lock on fault pages
>      dp    always lazily freeable mapping
> +    gu    maybe contains guard regions (if not set, definitely doesn't)
>      ==    =======================================

The nittiest
of nits:     =============================================================


>  
>  Note that there is no guarantee that every flag and associated mnemonic will
> diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> index 8a9894aefbca..a420dcf9ffbb 100644
> --- a/fs/proc/task_mmu.c
> +++ b/fs/proc/task_mmu.c
> @@ -1147,6 +1147,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
>  		[ilog2(VM_MAYSHARE)]	= "ms",
>  		[ilog2(VM_GROWSDOWN)]	= "gd",
>  		[ilog2(VM_PFNMAP)]	= "pf",
> +		[ilog2(VM_MAYBE_GUARD)]	= "gu",
>  		[ilog2(VM_LOCKED)]	= "lo",
>  		[ilog2(VM_IO)]		= "io",
>  		[ilog2(VM_SEQ_READ)]	= "sr",
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 6e5ca5287e21..2a5516bff75a 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -271,6 +271,8 @@ extern struct rw_semaphore nommu_region_sem;
>  extern unsigned int kobjsize(const void *objp);
>  #endif
>  
> +#define VM_MAYBE_GUARD_BIT 11
> +
>  /*
>   * vm_flags in vm_area_struct, see mm_types.h.
>   * When changing, update also include/trace/events/mmflags.h
> @@ -296,6 +298,7 @@ extern unsigned int kobjsize(const void *objp);
>  #define VM_UFFD_MISSING	0
>  #endif /* CONFIG_MMU */
>  #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
> +#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */

Don't we also need an adjustment on the rust side for this BIT()? Like we
for f04aad36a07c ("mm/ksm: fix flag-dropping behavior in ksm_madvise").

In any case:
Reviewed-by: Pedro Falcato <pfalcato@suse.de>

-- 
Pedro
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Lorenzo Stoakes 1 month, 1 week ago
+cc Alice for rust stuff

On Thu, Nov 06, 2025 at 02:27:56PM +0000, Pedro Falcato wrote:
> On Thu, Nov 06, 2025 at 10:46:12AM +0000, Lorenzo Stoakes wrote:
> > Currently, if a user needs to determine if guard regions are present in a
> > range, they have to scan all VMAs (or have knowledge of which ones might
> > have guard regions).
> >
> > Since commit 8e2f2aeb8b48 ("fs/proc/task_mmu: add guard region bit to
> > pagemap") and the related commit a516403787e0 ("fs/proc: extend the
> > PAGEMAP_SCAN ioctl to report guard regions"), users can use either
> > /proc/$pid/pagemap or the PAGEMAP_SCAN functionality to perform this
> > operation at a virtual address level.
> >
> > This is not ideal, and it gives no visibility at a /proc/$pid/smaps level
> > that guard regions exist in ranges.
> >
> > This patch remedies the situation by establishing a new VMA flag,
> > VM_MAYBE_GUARD, to indicate that a VMA may contain guard regions (it is
> > uncertain because we cannot reasonably determine whether a
> > MADV_GUARD_REMOVE call has removed all of the guard regions in a VMA, and
> > additionally VMAs may change across merge/split).
> >
> > We utilise 0x800 for this flag which makes it available to 32-bit
> > architectures also, a flag that was previously used by VM_DENYWRITE, which
> > was removed in commit 8d0920bde5eb ("mm: remove VM_DENYWRITE") and hasn't
> > bee reused yet.
> >
> > We also update the smaps logic and documentation to identify these VMAs.
> >
> > Another major use of this functionality is that we can use it to identify
> > that we ought to copy page tables on fork.
> >
> > We do not actually implement usage of this flag in mm/madvise.c yet as we
> > need to allow some VMA flags to be applied atomically under mmap/VMA read
> > lock in order to avoid the need to acquire a write lock for this purpose.
> >
> > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > ---
> >  Documentation/filesystems/proc.rst | 1 +
> >  fs/proc/task_mmu.c                 | 1 +
> >  include/linux/mm.h                 | 3 +++
> >  include/trace/events/mmflags.h     | 1 +
> >  mm/memory.c                        | 4 ++++
> >  tools/testing/vma/vma_internal.h   | 3 +++
> >  6 files changed, 13 insertions(+)
> >
> > diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
> > index 0b86a8022fa1..b8a423ca590a 100644
> > --- a/Documentation/filesystems/proc.rst
> > +++ b/Documentation/filesystems/proc.rst
> > @@ -591,6 +591,7 @@ encoded manner. The codes are the following:
> >      sl    sealed
> >      lf    lock on fault pages
> >      dp    always lazily freeable mapping
> > +    gu    maybe contains guard regions (if not set, definitely doesn't)
> >      ==    =======================================
>
> The nittiest
> of nits:     =============================================================

Sigh :) OK will fix.

>
>
> >
> >  Note that there is no guarantee that every flag and associated mnemonic will
> > diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> > index 8a9894aefbca..a420dcf9ffbb 100644
> > --- a/fs/proc/task_mmu.c
> > +++ b/fs/proc/task_mmu.c
> > @@ -1147,6 +1147,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
> >  		[ilog2(VM_MAYSHARE)]	= "ms",
> >  		[ilog2(VM_GROWSDOWN)]	= "gd",
> >  		[ilog2(VM_PFNMAP)]	= "pf",
> > +		[ilog2(VM_MAYBE_GUARD)]	= "gu",
> >  		[ilog2(VM_LOCKED)]	= "lo",
> >  		[ilog2(VM_IO)]		= "io",
> >  		[ilog2(VM_SEQ_READ)]	= "sr",
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index 6e5ca5287e21..2a5516bff75a 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -271,6 +271,8 @@ extern struct rw_semaphore nommu_region_sem;
> >  extern unsigned int kobjsize(const void *objp);
> >  #endif
> >
> > +#define VM_MAYBE_GUARD_BIT 11
> > +
> >  /*
> >   * vm_flags in vm_area_struct, see mm_types.h.
> >   * When changing, update also include/trace/events/mmflags.h
> > @@ -296,6 +298,7 @@ extern unsigned int kobjsize(const void *objp);
> >  #define VM_UFFD_MISSING	0
> >  #endif /* CONFIG_MMU */
> >  #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
> > +#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */
>
> Don't we also need an adjustment on the rust side for this BIT()? Like we
> for f04aad36a07c ("mm/ksm: fix flag-dropping behavior in ksm_madvise").

That's a bit unhelpful if rust can't cope with extremely basic assignments like
that and we just have to know to add helpers :/

We do BIT() stuff for e.g. VM_HIGH_ARCH_n, VM_UFFD_MINOR_BIT,
VM_ALLOW_ANY_UNCACHED_BIT, VM_DROPPABLE_BIT and VM_SEALED_BIT too and no such
helpers there, So not sure if this is required?

Alice - why is it these 'non-trivial' defines were fine but VM_MERGEABLE was
problematic? That seems strange.

I see [0], so let me build rust here and see if it moans, if it moans I'll add
it.

[0]:https://lore.kernel.org/oe-kbuild-all/CANiq72kOhRdGtQe2UVYmDLdbw6VNkiMtdFzkQizsfQV0gLY1Hg@mail.gmail.com/

>
> In any case:
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>

Thanks

>
> --
> Pedro
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Alice Ryhl 1 month, 1 week ago
On Thu, Nov 06, 2025 at 02:54:33PM +0000, Lorenzo Stoakes wrote:
> +cc Alice for rust stuff
> 
> On Thu, Nov 06, 2025 at 02:27:56PM +0000, Pedro Falcato wrote:
> > On Thu, Nov 06, 2025 at 10:46:12AM +0000, Lorenzo Stoakes wrote:
> > > Currently, if a user needs to determine if guard regions are present in a
> > > range, they have to scan all VMAs (or have knowledge of which ones might
> > > have guard regions).
> > >
> > > Since commit 8e2f2aeb8b48 ("fs/proc/task_mmu: add guard region bit to
> > > pagemap") and the related commit a516403787e0 ("fs/proc: extend the
> > > PAGEMAP_SCAN ioctl to report guard regions"), users can use either
> > > /proc/$pid/pagemap or the PAGEMAP_SCAN functionality to perform this
> > > operation at a virtual address level.
> > >
> > > This is not ideal, and it gives no visibility at a /proc/$pid/smaps level
> > > that guard regions exist in ranges.
> > >
> > > This patch remedies the situation by establishing a new VMA flag,
> > > VM_MAYBE_GUARD, to indicate that a VMA may contain guard regions (it is
> > > uncertain because we cannot reasonably determine whether a
> > > MADV_GUARD_REMOVE call has removed all of the guard regions in a VMA, and
> > > additionally VMAs may change across merge/split).
> > >
> > > We utilise 0x800 for this flag which makes it available to 32-bit
> > > architectures also, a flag that was previously used by VM_DENYWRITE, which
> > > was removed in commit 8d0920bde5eb ("mm: remove VM_DENYWRITE") and hasn't
> > > bee reused yet.
> > >
> > > We also update the smaps logic and documentation to identify these VMAs.
> > >
> > > Another major use of this functionality is that we can use it to identify
> > > that we ought to copy page tables on fork.
> > >
> > > We do not actually implement usage of this flag in mm/madvise.c yet as we
> > > need to allow some VMA flags to be applied atomically under mmap/VMA read
> > > lock in order to avoid the need to acquire a write lock for this purpose.
> > >
> > > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > > ---
> > >  Documentation/filesystems/proc.rst | 1 +
> > >  fs/proc/task_mmu.c                 | 1 +
> > >  include/linux/mm.h                 | 3 +++
> > >  include/trace/events/mmflags.h     | 1 +
> > >  mm/memory.c                        | 4 ++++
> > >  tools/testing/vma/vma_internal.h   | 3 +++
> > >  6 files changed, 13 insertions(+)
> > >
> > > diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
> > > index 0b86a8022fa1..b8a423ca590a 100644
> > > --- a/Documentation/filesystems/proc.rst
> > > +++ b/Documentation/filesystems/proc.rst
> > > @@ -591,6 +591,7 @@ encoded manner. The codes are the following:
> > >      sl    sealed
> > >      lf    lock on fault pages
> > >      dp    always lazily freeable mapping
> > > +    gu    maybe contains guard regions (if not set, definitely doesn't)
> > >      ==    =======================================
> >
> > The nittiest
> > of nits:     =============================================================
> 
> Sigh :) OK will fix.
> 
> >
> >
> > >
> > >  Note that there is no guarantee that every flag and associated mnemonic will
> > > diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> > > index 8a9894aefbca..a420dcf9ffbb 100644
> > > --- a/fs/proc/task_mmu.c
> > > +++ b/fs/proc/task_mmu.c
> > > @@ -1147,6 +1147,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
> > >  		[ilog2(VM_MAYSHARE)]	= "ms",
> > >  		[ilog2(VM_GROWSDOWN)]	= "gd",
> > >  		[ilog2(VM_PFNMAP)]	= "pf",
> > > +		[ilog2(VM_MAYBE_GUARD)]	= "gu",
> > >  		[ilog2(VM_LOCKED)]	= "lo",
> > >  		[ilog2(VM_IO)]		= "io",
> > >  		[ilog2(VM_SEQ_READ)]	= "sr",
> > > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > > index 6e5ca5287e21..2a5516bff75a 100644
> > > --- a/include/linux/mm.h
> > > +++ b/include/linux/mm.h
> > > @@ -271,6 +271,8 @@ extern struct rw_semaphore nommu_region_sem;
> > >  extern unsigned int kobjsize(const void *objp);
> > >  #endif
> > >
> > > +#define VM_MAYBE_GUARD_BIT 11
> > > +
> > >  /*
> > >   * vm_flags in vm_area_struct, see mm_types.h.
> > >   * When changing, update also include/trace/events/mmflags.h
> > > @@ -296,6 +298,7 @@ extern unsigned int kobjsize(const void *objp);
> > >  #define VM_UFFD_MISSING	0
> > >  #endif /* CONFIG_MMU */
> > >  #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
> > > +#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */
> >
> > Don't we also need an adjustment on the rust side for this BIT()? Like we
> > for f04aad36a07c ("mm/ksm: fix flag-dropping behavior in ksm_madvise").
> 
> That's a bit unhelpful if rust can't cope with extremely basic assignments like
> that and we just have to know to add helpers :/
> 
> We do BIT() stuff for e.g. VM_HIGH_ARCH_n, VM_UFFD_MINOR_BIT,
> VM_ALLOW_ANY_UNCACHED_BIT, VM_DROPPABLE_BIT and VM_SEALED_BIT too and no such
> helpers there, So not sure if this is required?
> 
> Alice - why is it these 'non-trivial' defines were fine but VM_MERGEABLE was
> problematic? That seems strange.
> 
> I see [0], so let me build rust here and see if it moans, if it moans I'll add
> it.
> 
> [0]:https://lore.kernel.org/oe-kbuild-all/CANiq72kOhRdGtQe2UVYmDLdbw6VNkiMtdFzkQizsfQV0gLY1Hg@mail.gmail.com/

When you use #define to declare a constant whose right-hand-side
contains a function-like macro such as BIT(), bindgen does not define a
Rust version of that constant. However, VM_MAYBE_GUARD is not referenced
in Rust anywhere, so that isn't a problem.

It was a problem with VM_MERGEABLE because rust/kernel/mm/virt.rs
references it.

Note that it's only the combination of #define and function-like macro
that triggers this condition. If the constant is defined using another
mechanism such as enum {}, then bindgen will generate the constant no
matter how complex the right-hand-side is. The problem is that bindgen
can't tell whether a #define is just a constant or not.

Alice
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Lorenzo Stoakes 1 month, 1 week ago
On Fri, Nov 07, 2025 at 09:13:00AM +0000, Alice Ryhl wrote:
> On Thu, Nov 06, 2025 at 02:54:33PM +0000, Lorenzo Stoakes wrote:
> > +cc Alice for rust stuff
> >
> > On Thu, Nov 06, 2025 at 02:27:56PM +0000, Pedro Falcato wrote:
> > > On Thu, Nov 06, 2025 at 10:46:12AM +0000, Lorenzo Stoakes wrote:
> > > > Currently, if a user needs to determine if guard regions are present in a
> > > > range, they have to scan all VMAs (or have knowledge of which ones might
> > > > have guard regions).
> > > >
> > > > Since commit 8e2f2aeb8b48 ("fs/proc/task_mmu: add guard region bit to
> > > > pagemap") and the related commit a516403787e0 ("fs/proc: extend the
> > > > PAGEMAP_SCAN ioctl to report guard regions"), users can use either
> > > > /proc/$pid/pagemap or the PAGEMAP_SCAN functionality to perform this
> > > > operation at a virtual address level.
> > > >
> > > > This is not ideal, and it gives no visibility at a /proc/$pid/smaps level
> > > > that guard regions exist in ranges.
> > > >
> > > > This patch remedies the situation by establishing a new VMA flag,
> > > > VM_MAYBE_GUARD, to indicate that a VMA may contain guard regions (it is
> > > > uncertain because we cannot reasonably determine whether a
> > > > MADV_GUARD_REMOVE call has removed all of the guard regions in a VMA, and
> > > > additionally VMAs may change across merge/split).
> > > >
> > > > We utilise 0x800 for this flag which makes it available to 32-bit
> > > > architectures also, a flag that was previously used by VM_DENYWRITE, which
> > > > was removed in commit 8d0920bde5eb ("mm: remove VM_DENYWRITE") and hasn't
> > > > bee reused yet.
> > > >
> > > > We also update the smaps logic and documentation to identify these VMAs.
> > > >
> > > > Another major use of this functionality is that we can use it to identify
> > > > that we ought to copy page tables on fork.
> > > >
> > > > We do not actually implement usage of this flag in mm/madvise.c yet as we
> > > > need to allow some VMA flags to be applied atomically under mmap/VMA read
> > > > lock in order to avoid the need to acquire a write lock for this purpose.
> > > >
> > > > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > > > ---
> > > >  Documentation/filesystems/proc.rst | 1 +
> > > >  fs/proc/task_mmu.c                 | 1 +
> > > >  include/linux/mm.h                 | 3 +++
> > > >  include/trace/events/mmflags.h     | 1 +
> > > >  mm/memory.c                        | 4 ++++
> > > >  tools/testing/vma/vma_internal.h   | 3 +++
> > > >  6 files changed, 13 insertions(+)
> > > >
> > > > diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
> > > > index 0b86a8022fa1..b8a423ca590a 100644
> > > > --- a/Documentation/filesystems/proc.rst
> > > > +++ b/Documentation/filesystems/proc.rst
> > > > @@ -591,6 +591,7 @@ encoded manner. The codes are the following:
> > > >      sl    sealed
> > > >      lf    lock on fault pages
> > > >      dp    always lazily freeable mapping
> > > > +    gu    maybe contains guard regions (if not set, definitely doesn't)
> > > >      ==    =======================================
> > >
> > > The nittiest
> > > of nits:     =============================================================
> >
> > Sigh :) OK will fix.
> >
> > >
> > >
> > > >
> > > >  Note that there is no guarantee that every flag and associated mnemonic will
> > > > diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> > > > index 8a9894aefbca..a420dcf9ffbb 100644
> > > > --- a/fs/proc/task_mmu.c
> > > > +++ b/fs/proc/task_mmu.c
> > > > @@ -1147,6 +1147,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
> > > >  		[ilog2(VM_MAYSHARE)]	= "ms",
> > > >  		[ilog2(VM_GROWSDOWN)]	= "gd",
> > > >  		[ilog2(VM_PFNMAP)]	= "pf",
> > > > +		[ilog2(VM_MAYBE_GUARD)]	= "gu",
> > > >  		[ilog2(VM_LOCKED)]	= "lo",
> > > >  		[ilog2(VM_IO)]		= "io",
> > > >  		[ilog2(VM_SEQ_READ)]	= "sr",
> > > > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > > > index 6e5ca5287e21..2a5516bff75a 100644
> > > > --- a/include/linux/mm.h
> > > > +++ b/include/linux/mm.h
> > > > @@ -271,6 +271,8 @@ extern struct rw_semaphore nommu_region_sem;
> > > >  extern unsigned int kobjsize(const void *objp);
> > > >  #endif
> > > >
> > > > +#define VM_MAYBE_GUARD_BIT 11
> > > > +
> > > >  /*
> > > >   * vm_flags in vm_area_struct, see mm_types.h.
> > > >   * When changing, update also include/trace/events/mmflags.h
> > > > @@ -296,6 +298,7 @@ extern unsigned int kobjsize(const void *objp);
> > > >  #define VM_UFFD_MISSING	0
> > > >  #endif /* CONFIG_MMU */
> > > >  #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
> > > > +#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */
> > >
> > > Don't we also need an adjustment on the rust side for this BIT()? Like we
> > > for f04aad36a07c ("mm/ksm: fix flag-dropping behavior in ksm_madvise").
> >
> > That's a bit unhelpful if rust can't cope with extremely basic assignments like
> > that and we just have to know to add helpers :/
> >
> > We do BIT() stuff for e.g. VM_HIGH_ARCH_n, VM_UFFD_MINOR_BIT,
> > VM_ALLOW_ANY_UNCACHED_BIT, VM_DROPPABLE_BIT and VM_SEALED_BIT too and no such
> > helpers there, So not sure if this is required?
> >
> > Alice - why is it these 'non-trivial' defines were fine but VM_MERGEABLE was
> > problematic? That seems strange.
> >
> > I see [0], so let me build rust here and see if it moans, if it moans I'll add
> > it.
> >
> > [0]:https://lore.kernel.org/oe-kbuild-all/CANiq72kOhRdGtQe2UVYmDLdbw6VNkiMtdFzkQizsfQV0gLY1Hg@mail.gmail.com/
>
> When you use #define to declare a constant whose right-hand-side
> contains a function-like macro such as BIT(), bindgen does not define a
> Rust version of that constant. However, VM_MAYBE_GUARD is not referenced
> in Rust anywhere, so that isn't a problem.
>
> It was a problem with VM_MERGEABLE because rust/kernel/mm/virt.rs
> references it.
>
> Note that it's only the combination of #define and function-like macro
> that triggers this condition. If the constant is defined using another
> mechanism such as enum {}, then bindgen will generate the constant no
> matter how complex the right-hand-side is. The problem is that bindgen
> can't tell whether a #define is just a constant or not.
>
> Alice

Thanks, I guess we can update as we go as rust needs. Or I can do a big update
as part of my VMA flag series respin?
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Alice Ryhl 1 month, 1 week ago
On Fri, Nov 07, 2025 at 09:44:22AM +0000, Lorenzo Stoakes wrote:
> On Fri, Nov 07, 2025 at 09:13:00AM +0000, Alice Ryhl wrote:
> > On Thu, Nov 06, 2025 at 02:54:33PM +0000, Lorenzo Stoakes wrote:
> > > +cc Alice for rust stuff
> > >
> > > On Thu, Nov 06, 2025 at 02:27:56PM +0000, Pedro Falcato wrote:
> > > > On Thu, Nov 06, 2025 at 10:46:12AM +0000, Lorenzo Stoakes wrote:
> > > > >  /*
> > > > >   * vm_flags in vm_area_struct, see mm_types.h.
> > > > >   * When changing, update also include/trace/events/mmflags.h
> > > > > @@ -296,6 +298,7 @@ extern unsigned int kobjsize(const void *objp);
> > > > >  #define VM_UFFD_MISSING	0
> > > > >  #endif /* CONFIG_MMU */
> > > > >  #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
> > > > > +#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */
> > > >
> > > > Don't we also need an adjustment on the rust side for this BIT()? Like we
> > > > for f04aad36a07c ("mm/ksm: fix flag-dropping behavior in ksm_madvise").
> > >
> > > That's a bit unhelpful if rust can't cope with extremely basic assignments like
> > > that and we just have to know to add helpers :/
> > >
> > > We do BIT() stuff for e.g. VM_HIGH_ARCH_n, VM_UFFD_MINOR_BIT,
> > > VM_ALLOW_ANY_UNCACHED_BIT, VM_DROPPABLE_BIT and VM_SEALED_BIT too and no such
> > > helpers there, So not sure if this is required?
> > >
> > > Alice - why is it these 'non-trivial' defines were fine but VM_MERGEABLE was
> > > problematic? That seems strange.
> > >
> > > I see [0], so let me build rust here and see if it moans, if it moans I'll add
> > > it.
> > >
> > > [0]:https://lore.kernel.org/oe-kbuild-all/CANiq72kOhRdGtQe2UVYmDLdbw6VNkiMtdFzkQizsfQV0gLY1Hg@mail.gmail.com/
> >
> > When you use #define to declare a constant whose right-hand-side
> > contains a function-like macro such as BIT(), bindgen does not define a
> > Rust version of that constant. However, VM_MAYBE_GUARD is not referenced
> > in Rust anywhere, so that isn't a problem.
> >
> > It was a problem with VM_MERGEABLE because rust/kernel/mm/virt.rs
> > references it.
> >
> > Note that it's only the combination of #define and function-like macro
> > that triggers this condition. If the constant is defined using another
> > mechanism such as enum {}, then bindgen will generate the constant no
> > matter how complex the right-hand-side is. The problem is that bindgen
> > can't tell whether a #define is just a constant or not.
> 
> Thanks, I guess we can update as we go as rust needs. Or I can do a big update
> as part of my VMA flag series respin?

Whenever you think is a good time works for me.

I think it would be nice to move those constants so they use enum {}
instead of #define at some point.

Alice
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Lorenzo Stoakes 1 month, 1 week ago
On Fri, Nov 07, 2025 at 12:12:43PM +0000, Alice Ryhl wrote:
> On Fri, Nov 07, 2025 at 09:44:22AM +0000, Lorenzo Stoakes wrote:
> > On Fri, Nov 07, 2025 at 09:13:00AM +0000, Alice Ryhl wrote:
> > > On Thu, Nov 06, 2025 at 02:54:33PM +0000, Lorenzo Stoakes wrote:
> > > > +cc Alice for rust stuff
> > > >
> > > > On Thu, Nov 06, 2025 at 02:27:56PM +0000, Pedro Falcato wrote:
> > > > > On Thu, Nov 06, 2025 at 10:46:12AM +0000, Lorenzo Stoakes wrote:
> > > > > >  /*
> > > > > >   * vm_flags in vm_area_struct, see mm_types.h.
> > > > > >   * When changing, update also include/trace/events/mmflags.h
> > > > > > @@ -296,6 +298,7 @@ extern unsigned int kobjsize(const void *objp);
> > > > > >  #define VM_UFFD_MISSING	0
> > > > > >  #endif /* CONFIG_MMU */
> > > > > >  #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
> > > > > > +#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */
> > > > >
> > > > > Don't we also need an adjustment on the rust side for this BIT()? Like we
> > > > > for f04aad36a07c ("mm/ksm: fix flag-dropping behavior in ksm_madvise").
> > > >
> > > > That's a bit unhelpful if rust can't cope with extremely basic assignments like
> > > > that and we just have to know to add helpers :/
> > > >
> > > > We do BIT() stuff for e.g. VM_HIGH_ARCH_n, VM_UFFD_MINOR_BIT,
> > > > VM_ALLOW_ANY_UNCACHED_BIT, VM_DROPPABLE_BIT and VM_SEALED_BIT too and no such
> > > > helpers there, So not sure if this is required?
> > > >
> > > > Alice - why is it these 'non-trivial' defines were fine but VM_MERGEABLE was
> > > > problematic? That seems strange.
> > > >
> > > > I see [0], so let me build rust here and see if it moans, if it moans I'll add
> > > > it.
> > > >
> > > > [0]:https://lore.kernel.org/oe-kbuild-all/CANiq72kOhRdGtQe2UVYmDLdbw6VNkiMtdFzkQizsfQV0gLY1Hg@mail.gmail.com/
> > >
> > > When you use #define to declare a constant whose right-hand-side
> > > contains a function-like macro such as BIT(), bindgen does not define a
> > > Rust version of that constant. However, VM_MAYBE_GUARD is not referenced
> > > in Rust anywhere, so that isn't a problem.
> > >
> > > It was a problem with VM_MERGEABLE because rust/kernel/mm/virt.rs
> > > references it.
> > >
> > > Note that it's only the combination of #define and function-like macro
> > > that triggers this condition. If the constant is defined using another
> > > mechanism such as enum {}, then bindgen will generate the constant no
> > > matter how complex the right-hand-side is. The problem is that bindgen
> > > can't tell whether a #define is just a constant or not.
> >
> > Thanks, I guess we can update as we go as rust needs. Or I can do a big update
> > as part of my VMA flag series respin?
>
> Whenever you think is a good time works for me.
>
> I think it would be nice to move those constants so they use enum {}
> instead of #define at some point.

Yeah I will do as part of my VMA series :) which actually is a neater solution
to this in general (and can drop the existing binding helpers then actually).

>
> Alice

Thanks, Lorenzo
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Lorenzo Stoakes 1 month, 1 week ago
On Thu, Nov 06, 2025 at 02:54:33PM +0000, Lorenzo Stoakes wrote:
> > >  Note that there is no guarantee that every flag and associated mnemonic will
> > > diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> > > index 8a9894aefbca..a420dcf9ffbb 100644
> > > --- a/fs/proc/task_mmu.c
> > > +++ b/fs/proc/task_mmu.c
> > > @@ -1147,6 +1147,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
> > >  		[ilog2(VM_MAYSHARE)]	= "ms",
> > >  		[ilog2(VM_GROWSDOWN)]	= "gd",
> > >  		[ilog2(VM_PFNMAP)]	= "pf",
> > > +		[ilog2(VM_MAYBE_GUARD)]	= "gu",
> > >  		[ilog2(VM_LOCKED)]	= "lo",
> > >  		[ilog2(VM_IO)]		= "io",
> > >  		[ilog2(VM_SEQ_READ)]	= "sr",
> > > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > > index 6e5ca5287e21..2a5516bff75a 100644
> > > --- a/include/linux/mm.h
> > > +++ b/include/linux/mm.h
> > > @@ -271,6 +271,8 @@ extern struct rw_semaphore nommu_region_sem;
> > >  extern unsigned int kobjsize(const void *objp);
> > >  #endif
> > >
> > > +#define VM_MAYBE_GUARD_BIT 11
> > > +
> > >  /*
> > >   * vm_flags in vm_area_struct, see mm_types.h.
> > >   * When changing, update also include/trace/events/mmflags.h
> > > @@ -296,6 +298,7 @@ extern unsigned int kobjsize(const void *objp);
> > >  #define VM_UFFD_MISSING	0
> > >  #endif /* CONFIG_MMU */
> > >  #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
> > > +#define VM_MAYBE_GUARD	BIT(VM_MAYBE_GUARD_BIT)	/* The VMA maybe contains guard regions. */
> >
> > Don't we also need an adjustment on the rust side for this BIT()? Like we
> > for f04aad36a07c ("mm/ksm: fix flag-dropping behavior in ksm_madvise").
>
> That's a bit unhelpful if rust can't cope with extremely basic assignments like
> that and we just have to know to add helpers :/
>
> We do BIT() stuff for e.g. VM_HIGH_ARCH_n, VM_UFFD_MINOR_BIT,
> VM_ALLOW_ANY_UNCACHED_BIT, VM_DROPPABLE_BIT and VM_SEALED_BIT too and no such
> helpers there, So not sure if this is required?
>
> Alice - why is it these 'non-trivial' defines were fine but VM_MERGEABLE was
> problematic? That seems strange.
>
> I see [0], so let me build rust here and see if it moans, if it moans I'll add
> it.

I built with CONFIG_RUST=y and everything compiles ok so seems rust is fine with
it?

Strange that we need it for some things but not others though?
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Vlastimil Babka 1 month, 1 week ago
On 11/6/25 11:46, Lorenzo Stoakes wrote:
> Currently, if a user needs to determine if guard regions are present in a
> range, they have to scan all VMAs (or have knowledge of which ones might
> have guard regions).
> 
> Since commit 8e2f2aeb8b48 ("fs/proc/task_mmu: add guard region bit to
> pagemap") and the related commit a516403787e0 ("fs/proc: extend the
> PAGEMAP_SCAN ioctl to report guard regions"), users can use either
> /proc/$pid/pagemap or the PAGEMAP_SCAN functionality to perform this
> operation at a virtual address level.
> 
> This is not ideal, and it gives no visibility at a /proc/$pid/smaps level
> that guard regions exist in ranges.
> 
> This patch remedies the situation by establishing a new VMA flag,
> VM_MAYBE_GUARD, to indicate that a VMA may contain guard regions (it is
> uncertain because we cannot reasonably determine whether a
> MADV_GUARD_REMOVE call has removed all of the guard regions in a VMA, and
> additionally VMAs may change across merge/split).
> 
> We utilise 0x800 for this flag which makes it available to 32-bit
> architectures also, a flag that was previously used by VM_DENYWRITE, which
> was removed in commit 8d0920bde5eb ("mm: remove VM_DENYWRITE") and hasn't
> bee reused yet.
> 
> We also update the smaps logic and documentation to identify these VMAs.
> 
> Another major use of this functionality is that we can use it to identify
> that we ought to copy page tables on fork.
> 
> We do not actually implement usage of this flag in mm/madvise.c yet as we
> need to allow some VMA flags to be applied atomically under mmap/VMA read
> lock in order to avoid the need to acquire a write lock for this purpose.
> 
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>

Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
Re: [PATCH v2 1/5] mm: introduce VM_MAYBE_GUARD and make visible in /proc/$pid/smaps
Posted by Lorenzo Stoakes 1 month, 1 week ago
On Thu, Nov 06, 2025 at 12:12:10PM +0100, Vlastimil Babka wrote:
> On 11/6/25 11:46, Lorenzo Stoakes wrote:
> > Currently, if a user needs to determine if guard regions are present in a
> > range, they have to scan all VMAs (or have knowledge of which ones might
> > have guard regions).
> >
> > Since commit 8e2f2aeb8b48 ("fs/proc/task_mmu: add guard region bit to
> > pagemap") and the related commit a516403787e0 ("fs/proc: extend the
> > PAGEMAP_SCAN ioctl to report guard regions"), users can use either
> > /proc/$pid/pagemap or the PAGEMAP_SCAN functionality to perform this
> > operation at a virtual address level.
> >
> > This is not ideal, and it gives no visibility at a /proc/$pid/smaps level
> > that guard regions exist in ranges.
> >
> > This patch remedies the situation by establishing a new VMA flag,
> > VM_MAYBE_GUARD, to indicate that a VMA may contain guard regions (it is
> > uncertain because we cannot reasonably determine whether a
> > MADV_GUARD_REMOVE call has removed all of the guard regions in a VMA, and
> > additionally VMAs may change across merge/split).
> >
> > We utilise 0x800 for this flag which makes it available to 32-bit
> > architectures also, a flag that was previously used by VM_DENYWRITE, which
> > was removed in commit 8d0920bde5eb ("mm: remove VM_DENYWRITE") and hasn't
> > bee reused yet.
> >
> > We also update the smaps logic and documentation to identify these VMAs.
> >
> > Another major use of this functionality is that we can use it to identify
> > that we ought to copy page tables on fork.
> >
> > We do not actually implement usage of this flag in mm/madvise.c yet as we
> > need to allow some VMA flags to be applied atomically under mmap/VMA read
> > lock in order to avoid the need to acquire a write lock for this purpose.
> >
> > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
>
> Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
>

Thanks