linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages
@ 2025-11-24 22:54 Joshua Hahn
  2025-11-25  1:10 ` SeongJae Park
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Joshua Hahn @ 2025-11-24 22:54 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Vlastimil Babka, Jonathan Corbet, Mike Rapoport, linux-doc,
	linux-kernel, linux-mm, kernel-team

Use-after-free and double-free bugs can be very difficult to track down.
The kernel is good at tracking these and preventing bad pages from being
used/created through simple checks gated behind "check_pages_enabled".

Currently, the only ways to enable this flag is by building with
CONFIG_DEBUG_VM, or as a side effect of other checks such as
init_on_{alloc, free}, page_poisoning, or debug_pagealloc among others.
These solutions are powerful, but may often be too coarse in balancing
the performance vs. safety that a user may want, particularly in
latency-sensitive production environments.

Introduce a new boot parameter "check_pages", which enables page checking
with no other side effects. It takes kstrbool-able inputs as an argument
(i.e. 0/1, true/false, on/off, ...). This patch is backwards-compatible;
setting CONFIG_DEBUG_VM still enables page checking.

Signed-off-by: Joshua Hahn <joshua.hahnjy@gmail.com>
---
v1 --> v2:
- Changed check_pages from a build config into a boot config, as suggested
  by Vlastimil.
- Introduced the second patch, which decouples page checking from 
  init_on_page_alloc and init_on_page_free.
---

 Documentation/admin-guide/kernel-parameters.txt |  8 ++++++++
 mm/mm_init.c                                    | 11 ++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 6c42061ca20e..0ba9561440a7 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -669,6 +669,14 @@
 			nokmem -- Disable kernel memory accounting.
 			nobpf -- Disable BPF memory accounting.
 
+	check_pages=	[MM,EARLY] Enable sanity checking of pages after
+			allocations / before freeing. This adds checks to catch
+			double-frees, use-after-frees, and other sources of
+			page corruption by inspecting page internals (flags,
+			mapcount/refcount, memcg_data, etc.).
+			Format: { "0" | "1" }
+			Default: 0 (1 if CONFIG_DEBUG_VM is set)
+
 	checkreqprot=	[SELINUX] Set initial checkreqprot flag value.
 			Format: { "0" | "1" }
 			See security/selinux/Kconfig help text.
diff --git a/mm/mm_init.c b/mm/mm_init.c
index c6812b4dbb2e..01d46efc42b4 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -2525,6 +2525,14 @@ early_param("init_on_free", early_init_on_free);
 
 DEFINE_STATIC_KEY_MAYBE(CONFIG_DEBUG_VM, check_pages_enabled);
 
+static bool _check_pages_enabled_early __initdata;
+
+static int __init early_check_pages(char *buf)
+{
+	return kstrtobool(buf, &_check_pages_enabled_early);
+}
+early_param("check_pages", early_check_pages);
+
 /*
  * Enable static keys related to various memory debugging and hardening options.
  * Some override others, and depend on early params that are evaluated in the
@@ -2591,7 +2599,8 @@ static void __init mem_debugging_and_hardening_init(void)
 	 * of struct pages being allocated or freed. With CONFIG_DEBUG_VM it's
 	 * enabled already.
 	 */
-	if (!IS_ENABLED(CONFIG_DEBUG_VM) && want_check_pages)
+	if (!IS_ENABLED(CONFIG_DEBUG_VM) && (_check_pages_enabled_early ||
+					     want_check_pages))
 		static_branch_enable(&check_pages_enabled);
 }
 
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages
  2025-11-24 22:54 [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages Joshua Hahn
@ 2025-11-25  1:10 ` SeongJae Park
  2025-11-25  8:44 ` Michal Hocko
  2025-11-25 10:23 ` Mike Rapoport
  2 siblings, 0 replies; 5+ messages in thread
From: SeongJae Park @ 2025-11-25  1:10 UTC (permalink / raw)
  To: Joshua Hahn
  Cc: SeongJae Park, Andrew Morton, Vlastimil Babka, Jonathan Corbet,
	Mike Rapoport, linux-doc, linux-kernel, linux-mm, kernel-team

On Mon, 24 Nov 2025 14:54:06 -0800 Joshua Hahn <joshua.hahnjy@gmail.com> wrote:

> Use-after-free and double-free bugs can be very difficult to track down.
> The kernel is good at tracking these and preventing bad pages from being
> used/created through simple checks gated behind "check_pages_enabled".
> 
> Currently, the only ways to enable this flag is by building with
> CONFIG_DEBUG_VM, or as a side effect of other checks such as
> init_on_{alloc, free}, page_poisoning, or debug_pagealloc among others.
> These solutions are powerful, but may often be too coarse in balancing
> the performance vs. safety that a user may want, particularly in
> latency-sensitive production environments.
> 
> Introduce a new boot parameter "check_pages", which enables page checking
> with no other side effects. It takes kstrbool-able inputs as an argument
> (i.e. 0/1, true/false, on/off, ...). This patch is backwards-compatible;
> setting CONFIG_DEBUG_VM still enables page checking.
> 
> Signed-off-by: Joshua Hahn <joshua.hahnjy@gmail.com>

Acked-by: SeongJae Park <sj@kernel.org>


Thanks,
SJ

[...]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages
  2025-11-24 22:54 [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages Joshua Hahn
  2025-11-25  1:10 ` SeongJae Park
@ 2025-11-25  8:44 ` Michal Hocko
  2025-11-25 10:23 ` Mike Rapoport
  2 siblings, 0 replies; 5+ messages in thread
From: Michal Hocko @ 2025-11-25  8:44 UTC (permalink / raw)
  To: Joshua Hahn
  Cc: Andrew Morton, Vlastimil Babka, Jonathan Corbet, Mike Rapoport,
	linux-doc, linux-kernel, linux-mm, kernel-team

On Mon 24-11-25 14:54:06, Joshua Hahn wrote:
> Use-after-free and double-free bugs can be very difficult to track down.
> The kernel is good at tracking these and preventing bad pages from being
> used/created through simple checks gated behind "check_pages_enabled".
> 
> Currently, the only ways to enable this flag is by building with
> CONFIG_DEBUG_VM, or as a side effect of other checks such as
> init_on_{alloc, free}, page_poisoning, or debug_pagealloc among others.
> These solutions are powerful, but may often be too coarse in balancing
> the performance vs. safety that a user may want, particularly in
> latency-sensitive production environments.
> 
> Introduce a new boot parameter "check_pages", which enables page checking
> with no other side effects. It takes kstrbool-able inputs as an argument
> (i.e. 0/1, true/false, on/off, ...). This patch is backwards-compatible;
> setting CONFIG_DEBUG_VM still enables page checking.

Arguing with performance without any performance numbers is not really
convincing but the change makes some sense to me even without that.
DEBUG_VM is just everything-in-one-bag thing which is not suitable for
production use and bad_page checks might still be valuable for such a
use.

> Signed-off-by: Joshua Hahn <joshua.hahnjy@gmail.com>

Acked-by: Michal Hocko <mhocko@suse.com>

> ---
> v1 --> v2:
> - Changed check_pages from a build config into a boot config, as suggested
>   by Vlastimil.
> - Introduced the second patch, which decouples page checking from 
>   init_on_page_alloc and init_on_page_free.
> ---
> 
>  Documentation/admin-guide/kernel-parameters.txt |  8 ++++++++
>  mm/mm_init.c                                    | 11 ++++++++++-
>  2 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 6c42061ca20e..0ba9561440a7 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -669,6 +669,14 @@
>  			nokmem -- Disable kernel memory accounting.
>  			nobpf -- Disable BPF memory accounting.
>  
> +	check_pages=	[MM,EARLY] Enable sanity checking of pages after
> +			allocations / before freeing. This adds checks to catch
> +			double-frees, use-after-frees, and other sources of
> +			page corruption by inspecting page internals (flags,
> +			mapcount/refcount, memcg_data, etc.).
> +			Format: { "0" | "1" }
> +			Default: 0 (1 if CONFIG_DEBUG_VM is set)
> +
>  	checkreqprot=	[SELINUX] Set initial checkreqprot flag value.
>  			Format: { "0" | "1" }
>  			See security/selinux/Kconfig help text.
> diff --git a/mm/mm_init.c b/mm/mm_init.c
> index c6812b4dbb2e..01d46efc42b4 100644
> --- a/mm/mm_init.c
> +++ b/mm/mm_init.c
> @@ -2525,6 +2525,14 @@ early_param("init_on_free", early_init_on_free);
>  
>  DEFINE_STATIC_KEY_MAYBE(CONFIG_DEBUG_VM, check_pages_enabled);
>  
> +static bool _check_pages_enabled_early __initdata;
> +
> +static int __init early_check_pages(char *buf)
> +{
> +	return kstrtobool(buf, &_check_pages_enabled_early);
> +}
> +early_param("check_pages", early_check_pages);
> +
>  /*
>   * Enable static keys related to various memory debugging and hardening options.
>   * Some override others, and depend on early params that are evaluated in the
> @@ -2591,7 +2599,8 @@ static void __init mem_debugging_and_hardening_init(void)
>  	 * of struct pages being allocated or freed. With CONFIG_DEBUG_VM it's
>  	 * enabled already.
>  	 */
> -	if (!IS_ENABLED(CONFIG_DEBUG_VM) && want_check_pages)
> +	if (!IS_ENABLED(CONFIG_DEBUG_VM) && (_check_pages_enabled_early ||
> +					     want_check_pages))
>  		static_branch_enable(&check_pages_enabled);
>  }
>  
> -- 
> 2.47.3

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages
  2025-11-24 22:54 [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages Joshua Hahn
  2025-11-25  1:10 ` SeongJae Park
  2025-11-25  8:44 ` Michal Hocko
@ 2025-11-25 10:23 ` Mike Rapoport
  2025-11-25 18:44   ` Joshua Hahn
  2 siblings, 1 reply; 5+ messages in thread
From: Mike Rapoport @ 2025-11-25 10:23 UTC (permalink / raw)
  To: Joshua Hahn
  Cc: Andrew Morton, Vlastimil Babka, Jonathan Corbet, linux-doc,
	linux-kernel, linux-mm, kernel-team

On Mon, Nov 24, 2025 at 02:54:06PM -0800, Joshua Hahn wrote:
> Use-after-free and double-free bugs can be very difficult to track down.
> The kernel is good at tracking these and preventing bad pages from being
> used/created through simple checks gated behind "check_pages_enabled".
> 
> Currently, the only ways to enable this flag is by building with
> CONFIG_DEBUG_VM, or as a side effect of other checks such as
> init_on_{alloc, free}, page_poisoning, or debug_pagealloc among others.
> These solutions are powerful, but may often be too coarse in balancing
> the performance vs. safety that a user may want, particularly in
> latency-sensitive production environments.
> 
> Introduce a new boot parameter "check_pages", which enables page checking
> with no other side effects. It takes kstrbool-able inputs as an argument
> (i.e. 0/1, true/false, on/off, ...). This patch is backwards-compatible;
> setting CONFIG_DEBUG_VM still enables page checking.
> 
> Signed-off-by: Joshua Hahn <joshua.hahnjy@gmail.com>
> ---
> v1 --> v2:
> - Changed check_pages from a build config into a boot config, as suggested
>   by Vlastimil.
> - Introduced the second patch, which decouples page checking from 
>   init_on_page_alloc and init_on_page_free.
> ---
> 
>  Documentation/admin-guide/kernel-parameters.txt |  8 ++++++++
>  mm/mm_init.c                                    | 11 ++++++++++-
>  2 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 6c42061ca20e..0ba9561440a7 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -669,6 +669,14 @@
>  			nokmem -- Disable kernel memory accounting.
>  			nobpf -- Disable BPF memory accounting.
>  
> +	check_pages=	[MM,EARLY] Enable sanity checking of pages after
> +			allocations / before freeing. This adds checks to catch
> +			double-frees, use-after-frees, and other sources of
> +			page corruption by inspecting page internals (flags,
> +			mapcount/refcount, memcg_data, etc.).
> +			Format: { "0" | "1" }
> +			Default: 0 (1 if CONFIG_DEBUG_VM is set)
> +
>  	checkreqprot=	[SELINUX] Set initial checkreqprot flag value.
>  			Format: { "0" | "1" }
>  			See security/selinux/Kconfig help text.
> diff --git a/mm/mm_init.c b/mm/mm_init.c
> index c6812b4dbb2e..01d46efc42b4 100644
> --- a/mm/mm_init.c
> +++ b/mm/mm_init.c
> @@ -2525,6 +2525,14 @@ early_param("init_on_free", early_init_on_free);
>  
>  DEFINE_STATIC_KEY_MAYBE(CONFIG_DEBUG_VM, check_pages_enabled);
>  
> +static bool _check_pages_enabled_early __initdata;

No need in the leading underscore.

> +
> +static int __init early_check_pages(char *buf)
> +{
> +	return kstrtobool(buf, &_check_pages_enabled_early);
> +}
> +early_param("check_pages", early_check_pages);
> +
>  /*
>   * Enable static keys related to various memory debugging and hardening options.
>   * Some override others, and depend on early params that are evaluated in the
> @@ -2591,7 +2599,8 @@ static void __init mem_debugging_and_hardening_init(void)
>  	 * of struct pages being allocated or freed. With CONFIG_DEBUG_VM it's
>  	 * enabled already.
>  	 */
> -	if (!IS_ENABLED(CONFIG_DEBUG_VM) && want_check_pages)
> +	if (!IS_ENABLED(CONFIG_DEBUG_VM) && (_check_pages_enabled_early ||
> +					     want_check_pages))

You can initialize want_check_pages to check_pages_enabled_early, would be
clearer IMO.

>  		static_branch_enable(&check_pages_enabled);
>  }
>  
> -- 
> 2.47.3

-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages
  2025-11-25 10:23 ` Mike Rapoport
@ 2025-11-25 18:44   ` Joshua Hahn
  0 siblings, 0 replies; 5+ messages in thread
From: Joshua Hahn @ 2025-11-25 18:44 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Andrew Morton, Vlastimil Babka, Jonathan Corbet, linux-doc,
	linux-kernel, linux-mm, kernel-team

On Tue, 25 Nov 2025 12:23:14 +0200 Mike Rapoport <rppt@kernel.org> wrote:

> On Mon, Nov 24, 2025 at 02:54:06PM -0800, Joshua Hahn wrote:
> > Use-after-free and double-free bugs can be very difficult to track down.
> > The kernel is good at tracking these and preventing bad pages from being
> > used/created through simple checks gated behind "check_pages_enabled".
> > 
> > Currently, the only ways to enable this flag is by building with
> > CONFIG_DEBUG_VM, or as a side effect of other checks such as
> > init_on_{alloc, free}, page_poisoning, or debug_pagealloc among others.
> > These solutions are powerful, but may often be too coarse in balancing
> > the performance vs. safety that a user may want, particularly in
> > latency-sensitive production environments.
> > 
> > Introduce a new boot parameter "check_pages", which enables page checking
> > with no other side effects. It takes kstrbool-able inputs as an argument
> > (i.e. 0/1, true/false, on/off, ...). This patch is backwards-compatible;
> > setting CONFIG_DEBUG_VM still enables page checking.
> > 
> > Signed-off-by: Joshua Hahn <joshua.hahnjy@gmail.com>

...

Hello Mike, thank you for your review!

> > +static bool _check_pages_enabled_early __initdata;
> 
> No need in the leading underscore.

Gotcha, no preference here on my end at all, so I'm happy to drop the leading
underscore. I was just modeling the variable after _init_on_alloc_enabled_early
and _init_on_free_enabled_early, but it seems like those are the only ones
that do have this leading underscore anyways.

> > +
> > +static int __init early_check_pages(char *buf)
> > +{
> > +	return kstrtobool(buf, &_check_pages_enabled_early);
> > +}
> > +early_param("check_pages", early_check_pages);
> > +
> >  /*
> >   * Enable static keys related to various memory debugging and hardening options.
> >   * Some override others, and depend on early params that are evaluated in the
> > @@ -2591,7 +2599,8 @@ static void __init mem_debugging_and_hardening_init(void)
> >  	 * of struct pages being allocated or freed. With CONFIG_DEBUG_VM it's
> >  	 * enabled already.
> >  	 */
> > -	if (!IS_ENABLED(CONFIG_DEBUG_VM) && want_check_pages)
> > +	if (!IS_ENABLED(CONFIG_DEBUG_VM) && (_check_pages_enabled_early ||
> > +					     want_check_pages))
> 
> You can initialize want_check_pages to check_pages_enabled_early, would be
> clearer IMO.

Yup, totally makes sense as well. I'll include this change in v3.
Thank you for all your feedback, I hope you have a great day!

Joshua

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-11-25 18:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-24 22:54 [PATCH v2 1/2] mm/mm_init: Introduce a boot parameter for check_pages Joshua Hahn
2025-11-25  1:10 ` SeongJae Park
2025-11-25  8:44 ` Michal Hocko
2025-11-25 10:23 ` Mike Rapoport
2025-11-25 18:44   ` Joshua Hahn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).