[PATCH] sched: Preserve reset-on-fork across concurrent sched_setparam()

Andrea Righi <[email protected]>
Newsgroups gmane.linux.kernel
Message-ID <[email protected]>
SCHED_RESET_ON_FORK prevents scheduling attributes from propagating to a
new child. The request is stored in p->sched_reset_on_fork; at fork
time, the scheduler uses it to reset inherited DL/RT policy, negative
nice values, custom slices and utilization clamps, then clears the flag
in the child.

sched_setparam() uses SETPARAM_POLICY to update scheduler parameters
while preserving both the current policy and the reset-on-fork setting.

However, __sched_setscheduler() samples p->sched_reset_on_fork before
acquiring the task's rq lock. A concurrent sched_setscheduler() can
change the flag after that snapshot and the lagging sched_setparam()
call can overwrite it with the stale value.

Remember when the caller requested to keep the policy and refresh
reset_on_fork after acquiring the rq lock. Both the early-exit and full
update paths then preserve the most recent serialized setting.

Fixes: ca94c442535a ("sched: Introduce SCHED_RESET_ON_FORK scheduling policy flag")
Reported-by: K Prateek Nayak <[email protected]>
Link: https://lore.kernel.org/[email protected]
Signed-off-by: Andrea Righi <[email protected]>
---
 kernel/sched/syscalls.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c
index 8fb8474d0a0ec..b149aeb2fd490 100644
--- a/kernel/sched/syscalls.c
+++ b/kernel/sched/syscalls.c
@@ -503,6 +503,7 @@ int __sched_setscheduler(struct task_struct *p,
 	int queue_flags = DEQUEUE_SAVE | DEQUEUE_MOVE | DEQUEUE_NOCLOCK;
 	struct rq *rq;
 	bool cpuset_locked = false;
+	bool keep_policy = policy < 0;
 
 	/* The pi code expects interrupts enabled */
 	BUG_ON(pi && in_interrupt());
@@ -571,6 +572,10 @@ int __sched_setscheduler(struct task_struct *p,
 	rq = task_rq_lock(p, &rf);
 	update_rq_clock(rq);
 
+	/* Preserve reset_on_fork changes made while the rq lock was not held. */
+	if (keep_policy)
+		reset_on_fork = p->sched_reset_on_fork;
+
 	/*
 	 * Changing the policy of the stop threads its a very bad idea:
 	 */
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.