public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mm/vmstat: reject invalid stat_interval values
@ 2026-04-10 11:25 Cao Ruichuang
  2026-04-10 12:32 ` Michal Hocko
  0 siblings, 1 reply; 2+ messages in thread
From: Cao Ruichuang @ 2026-04-10 11:25 UTC (permalink / raw)
  To: Andrew Morton, linux-mm
  Cc: David Hildenbrand, Lorenzo Stoakes, Liam R . Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	linux-kernel, Cao Ruichuang

vm.stat_interval is exposed in seconds, but proc_dointvec_jiffies()
currently accepts zero and negative values. In the current tree,
writing 0 succeeds and leaves /proc/sys/vm/stat_interval at 0.

vmstat_update() uses the stored jiffy interval directly when it
requeues its delayed work, so a zero interval can drive excessive
kworker CPU usage. Negative values are not meaningful either.

Switch vm.stat_interval to a small custom sysctl handler that keeps
the existing seconds-based userspace ABI while rejecting values below
1 and capping the upper bound at INT_MAX / HZ.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=220226
Signed-off-by: Cao Ruichuang <create0818@163.com>
---
 mm/vmstat.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/mm/vmstat.c b/mm/vmstat.c
index 86b14b0f77b..f48d3bdad64 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1964,6 +1964,7 @@ static const struct seq_operations vmstat_op = {
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
 static int sysctl_stat_interval __read_mostly = HZ;
+static const int sysctl_stat_interval_max = INT_MAX / HZ;
 static int vmstat_late_init_done;
 
 #ifdef CONFIG_PROC_FS
@@ -1972,6 +1973,26 @@ static void refresh_vm_stats(struct work_struct *work)
 	refresh_cpu_vm_stats(true);
 }
 
+static int vmstat_stat_interval_handler(const struct ctl_table *table, int write,
+					void *buffer, size_t *lenp, loff_t *ppos)
+{
+	int interval = sysctl_stat_interval / HZ;
+	const struct ctl_table tmp = {
+		.data	= &interval,
+		.maxlen	= sizeof(interval),
+		.mode	= table->mode,
+		.extra1	= SYSCTL_ONE,
+		.extra2	= (void *)&sysctl_stat_interval_max,
+	};
+	int ret;
+
+	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+	if (!ret && write)
+		sysctl_stat_interval = interval * HZ;
+
+	return ret;
+}
+
 static int vmstat_refresh(const struct ctl_table *table, int write,
 		   void *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2236,7 +2257,7 @@ static const struct ctl_table vmstat_table[] = {
 		.data		= &sysctl_stat_interval,
 		.maxlen		= sizeof(sysctl_stat_interval),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_jiffies,
+		.proc_handler	= vmstat_stat_interval_handler,
 	},
 	{
 		.procname	= "stat_refresh",
-- 
2.39.5 (Apple Git-154)


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

* Re: [PATCH] mm/vmstat: reject invalid stat_interval values
  2026-04-10 11:25 [PATCH] mm/vmstat: reject invalid stat_interval values Cao Ruichuang
@ 2026-04-10 12:32 ` Michal Hocko
  0 siblings, 0 replies; 2+ messages in thread
From: Michal Hocko @ 2026-04-10 12:32 UTC (permalink / raw)
  To: Cao Ruichuang
  Cc: Andrew Morton, linux-mm, David Hildenbrand, Lorenzo Stoakes,
	Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, linux-kernel

On Fri 10-04-26 19:25:54, Cao Ruichuang wrote:
> vm.stat_interval is exposed in seconds, but proc_dointvec_jiffies()
> currently accepts zero and negative values. In the current tree,
> writing 0 succeeds and leaves /proc/sys/vm/stat_interval at 0.
> 
> vmstat_update() uses the stored jiffy interval directly when it
> requeues its delayed work, so a zero interval can drive excessive
> kworker CPU usage. Negative values are not meaningful either.
> 
> Switch vm.stat_interval to a small custom sysctl handler that keeps
> the existing seconds-based userspace ABI while rejecting values below
> 1 and capping the upper bound at INT_MAX / HZ.

This is admin only interface and we usually trust them to know what they
are doing. The same applies here. There are many interface behaving this
way. Is there any specific reason why we should treat this one
differently or are you suggesting to change this approach and sanitize
all of them? Changing just this one in isolation is IMHO not worth it.

> 
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=220226
> Signed-off-by: Cao Ruichuang <create0818@163.com>
> ---
>  mm/vmstat.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/mm/vmstat.c b/mm/vmstat.c
> index 86b14b0f77b..f48d3bdad64 100644
> --- a/mm/vmstat.c
> +++ b/mm/vmstat.c
> @@ -1964,6 +1964,7 @@ static const struct seq_operations vmstat_op = {
>  #ifdef CONFIG_SMP
>  static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
>  static int sysctl_stat_interval __read_mostly = HZ;
> +static const int sysctl_stat_interval_max = INT_MAX / HZ;
>  static int vmstat_late_init_done;
>  
>  #ifdef CONFIG_PROC_FS
> @@ -1972,6 +1973,26 @@ static void refresh_vm_stats(struct work_struct *work)
>  	refresh_cpu_vm_stats(true);
>  }
>  
> +static int vmstat_stat_interval_handler(const struct ctl_table *table, int write,
> +					void *buffer, size_t *lenp, loff_t *ppos)
> +{
> +	int interval = sysctl_stat_interval / HZ;
> +	const struct ctl_table tmp = {
> +		.data	= &interval,
> +		.maxlen	= sizeof(interval),
> +		.mode	= table->mode,
> +		.extra1	= SYSCTL_ONE,
> +		.extra2	= (void *)&sysctl_stat_interval_max,
> +	};
> +	int ret;
> +
> +	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
> +	if (!ret && write)
> +		sysctl_stat_interval = interval * HZ;
> +
> +	return ret;
> +}
> +
>  static int vmstat_refresh(const struct ctl_table *table, int write,
>  		   void *buffer, size_t *lenp, loff_t *ppos)
>  {
> @@ -2236,7 +2257,7 @@ static const struct ctl_table vmstat_table[] = {
>  		.data		= &sysctl_stat_interval,
>  		.maxlen		= sizeof(sysctl_stat_interval),
>  		.mode		= 0644,
> -		.proc_handler	= proc_dointvec_jiffies,
> +		.proc_handler	= vmstat_stat_interval_handler,
>  	},
>  	{
>  		.procname	= "stat_refresh",
> -- 
> 2.39.5 (Apple Git-154)

-- 
Michal Hocko
SUSE Labs

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

end of thread, other threads:[~2026-04-10 12:32 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-10 11:25 [PATCH] mm/vmstat: reject invalid stat_interval values Cao Ruichuang
2026-04-10 12:32 ` Michal Hocko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox