From: Furkan Caliskan Date: Sun, 31 May 2026 08:36:58 +0000 (+0300) Subject: uclampset: fix lost-update race in set_uclamp_one() X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=9da4183594dfd9e816e8db00f0c9c9fef239a175;p=thirdparty%2Futil-linux.git uclampset: fix lost-update race in set_uclamp_one() The function unconditionally sets both SCHED_FLAG_UTIL_CLAMP_MIN and SCHED_FLAG_UTIL_CLAMP_MAX in sa.sched_flags regardless of which values the user actually requested to change. This creates a lost-update race: sched_getattr() fetches the current clamp values, but between that call and sched_setattr(), another thread may legitimately update the value we did not intend to touch. Because both flags are always set, sched_setattr() forces the kernel to apply the stale cached value, silently overwriting the concurrent update. Fix by setting the flags conditionally. Signed-off-by: Furkan Caliskan --- diff --git a/schedutils/uclampset.c b/schedutils/uclampset.c index dc912faee..3998d3a0a 100644 --- a/schedutils/uclampset.c +++ b/schedutils/uclampset.c @@ -157,16 +157,16 @@ static int set_uclamp_one(struct uclampset *ctl, pid_t pid) if (sched_getattr(pid, &sa, sizeof(sa), 0) != 0) err(EXIT_FAILURE, _("failed to get pid %d's uclamp values"), pid); - if (ctl->util_min_set) + sa.sched_flags = SCHED_FLAG_KEEP_POLICY | SCHED_FLAG_KEEP_PARAMS; + + if (ctl->util_min_set) { sa.sched_util_min = ctl->util_min; - if (ctl->util_max_set) + sa.sched_flags |= SCHED_FLAG_UTIL_CLAMP_MIN; + } + if (ctl->util_max_set) { sa.sched_util_max = ctl->util_max; - - sa.sched_flags = SCHED_FLAG_KEEP_POLICY | - SCHED_FLAG_KEEP_PARAMS | - SCHED_FLAG_UTIL_CLAMP_MIN | - SCHED_FLAG_UTIL_CLAMP_MAX; - + sa.sched_flags |= SCHED_FLAG_UTIL_CLAMP_MAX; + } if (ctl->reset_on_fork) sa.sched_flags |= SCHED_FLAG_RESET_ON_FORK;