Commit 88da0ed4 authored by Cyril Hrubis's avatar Cyril Hrubis Committed by Cheng Yu
Browse files

sched/rt: Disallow writing invalid values to sched_rt_period_us

stable inclusion
from stable-v4.19.308
commit 2d931472d4740d3ada7011cc4c3499948d3a22fa
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9K4JZ

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.19.y&id=2d931472d4740d3ada7011cc4c3499948d3a22fa

--------------------------------

[ Upstream commit 079be8fc630943d9fc70a97807feb73d169ee3fc ]

The validation of the value written to sched_rt_period_us was broken
because:

  - the sysclt_sched_rt_period is declared as unsigned int
  - parsed by proc_do_intvec()
  - the range is asserted after the value parsed by proc_do_intvec()

Because of this negative values written to the file were written into a
unsigned integer that were later on interpreted as large positive
integers which did passed the check:

  if (sysclt_sched_rt_period <= 0)
	return EINVAL;

This commit fixes the parsing by setting explicit range for both
perid_us and runtime_us into the sched_rt_sysctls table and processes
the values with proc_dointvec_minmax() instead.

Alternatively if we wanted to use full range of unsigned int for the
period value we would have to split the proc_handler and use
proc_douintvec() for it however even the
Documentation/scheduller/sched-rt-group.rst describes the range as 1 to
INT_MAX.

As far as I can tell the only problem this causes is that the sysctl
file allows writing negative values which when read back may confuse
userspace.

There is also a LTP test being submitted for these sysctl files at:

  http://patchwork.ozlabs.org/project/ltp/patch/20230901144433.2526-1-chrubis@suse.cz/



Signed-off-by: default avatarCyril Hrubis <chrubis@suse.cz>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20231002115553.3007-2-chrubis@suse.cz


[ pvorel: rebased for 4.19 ]
Reviewed-by: default avatarPetr Vorel <pvorel@suse.cz>
Signed-off-by: default avatarPetr Vorel <pvorel@suse.cz>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>

Conflicts:
        kernel/sysctl.c
Signed-off-by: default avatarCheng Yu <serein.chengyu@huawei.com>
parent 5d7f26cf
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -2655,9 +2655,6 @@ static int sched_rt_global_constraints(void)

static int sched_rt_global_validate(void)
{
	if (sysctl_sched_rt_period <= 0)
		return -EINVAL;

	if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
		(sysctl_sched_rt_runtime > sysctl_sched_rt_period))
		return -EINVAL;
@@ -2687,7 +2684,7 @@ int sched_rt_handler(struct ctl_table *table, int write,
	old_period = sysctl_sched_rt_period;
	old_runtime = sysctl_sched_rt_runtime;

	ret = proc_dointvec(table, write, buffer, lenp, ppos);
	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);

	if (!ret && write) {
		ret = sched_rt_global_validate();
+5 −0
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ static int __maybe_unused three = 3;
static int __maybe_unused four = 4;
static int __maybe_unused five = 5;
static int __maybe_unused uce_kernel_recovery_max = 31;
static int int_max = INT_MAX;
static unsigned long zero_ul;
static unsigned long one_ul = 1;
static unsigned long long_max = LONG_MAX;
@@ -463,6 +464,8 @@ static struct ctl_table kern_table[] = {
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= sched_rt_handler,
		.extra1		= &one,
		.extra2		= &int_max,
	},
	{
		.procname	= "sched_rt_runtime_us",
@@ -470,6 +473,8 @@ static struct ctl_table kern_table[] = {
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= sched_rt_handler,
		.extra1		= &neg_one,
		.extra2		= &int_max,
	},
	{
		.procname	= "sched_rr_timeslice_ms",