From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-172.mta0.migadu.com (out-172.mta0.migadu.com [91.218.175.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 35CF91F0995 for ; Sat, 18 Jul 2026 09:49:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.172 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784368155; cv=none; b=bqTOiAdo9HEwSzLCqLbyuQ4sOpBW8nFOTql+ngFXvZaM7iQ/yIyxEY3GgUlXGXG8XAfOvYwUmM8Vyo65Jj6yG5dhWB6b/zPkvdghlzNMTljKa23Hhw3reK0Pz6zgKFV+7UkiPFKWh6RXUD1z4ybfxTrDDe61PvYSo3298FmAh/M= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784368155; c=relaxed/simple; bh=fS3CatBIZMxELm3GzTTaMK9EFz2GdDMHNAcgEXEfbkE=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=NLku0jN9RvOEGFIqB+OcxKZDNtbeOVnam9JVg791cbNHfFDGpQrr3YoZNEYspZWPsNFZEjo0LiVzuTRQ0pcsu2umv2GsBPZEk7fufRJMY7an/JqvdUrxT0N6li/bD5tWzL9DNDXTrtJZbYkWtbugV6OIT96ewdh9cVXvKN7OcmU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=sFOgOoyx; arc=none smtp.client-ip=91.218.175.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="sFOgOoyx" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1784368150; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=t9uKwazICqvpP9D2rn42bPjL9mI9x+27Lsc03Z+RKmI=; b=sFOgOoyxBlJ3SqWjGkO3RT7rC8TfQHqZ9QZJ+/1+YG4n9P6L0uCJZojAYroEvGQI38fStO 2z7o9vzjEA1jLg/bmyKDOkqCG7bDqgUR1TO73+zfqminbVsB+Swwhpchq1BTt2QwTg0e6c VwqWu0DTyoPIsRsll1I1t6LGS6jfBtQ= From: Guopeng Zhang To: Ingo Molnar , Peter Zijlstra , Juri Lelli Cc: Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , K Prateek Nayak , Tommaso Cucinotta , linux-kernel@vger.kernel.org, Guopeng Zhang Subject: [PATCH] sched/deadline: Lock the task's runqueue for dynamic sched_getattr() Date: Sat, 18 Jul 2026 17:48:47 +0800 Message-ID: <20260718094847.1239114-1-guopeng.zhang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT From: Guopeng Zhang SCHED_GETATTR_FLAG_DL_DYNAMIC reads task_rq(p) before taking the rq lock. If p migrates between the lookup and lock acquisition, the old rq lock does not protect p->dl and the absolute deadline is converted with the wrong rq clock. Directly locking rq->__lock also bypasses the rq lock indirection used by core scheduling. The policy can also change after the initial check. Use task_rq_lock() to stabilize p's runqueue, recheck its policy, and read the dynamic deadline fields while holding the lock. Update deadline accounting first when p is the current donor. Under proxy execution, update_curr_dl() accounts rq->donor rather than rq->curr. Fixes: 2e7af192697e ("sched/deadline: Add reporting of runtime left & abs deadline to sched_getattr() for DEADLINE tasks") Signed-off-by: Guopeng Zhang --- kernel/sched/deadline.c | 36 +++++++++++++++++++++++++++--------- kernel/sched/sched.h | 2 +- kernel/sched/syscalls.c | 20 +++++++++++++++----- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index a3003b0f4522..de5057680da9 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -3853,29 +3853,47 @@ void __setparam_dl(struct task_struct *p, const struct sched_attr *attr) dl_se->dl_density = to_ratio(dl_se->dl_deadline, dl_se->dl_runtime); } -void __getparam_dl(struct task_struct *p, struct sched_attr *attr, unsigned int flags) +int __getparam_dl(struct task_struct *p, struct sched_attr *attr, unsigned int flags) { struct sched_dl_entity *dl_se = &p->dl; - struct rq *rq = task_rq(p); - u64 adj_deadline; + struct rq_flags rf; + struct rq *rq; - attr->sched_priority = p->rt_priority; if (flags & SCHED_GETATTR_FLAG_DL_DYNAMIC) { - guard(raw_spinlock_irq)(&rq->__lock); + u64 adj_deadline; + + rq = task_rq_lock(p, &rf); + if (!task_has_dl_policy(p)) { + task_rq_unlock(rq, p, &rf); + return -EINVAL; + } + update_rq_clock(rq); - if (task_current(rq, p)) + if (task_current_donor(rq, p)) update_curr_dl(rq); + attr->sched_policy = p->policy; + attr->sched_priority = p->rt_priority; attr->sched_runtime = dl_se->runtime; adj_deadline = dl_se->deadline - rq_clock(rq) + ktime_get_ns(); attr->sched_deadline = adj_deadline; - } else { - attr->sched_runtime = dl_se->dl_runtime; - attr->sched_deadline = dl_se->dl_deadline; + attr->sched_period = dl_se->dl_period; + attr->sched_flags &= ~(SCHED_FLAG_RESET_ON_FORK | SCHED_DL_FLAGS); + if (p->sched_reset_on_fork) + attr->sched_flags |= SCHED_FLAG_RESET_ON_FORK; + attr->sched_flags |= dl_se->flags; + task_rq_unlock(rq, p, &rf); + return 0; } + + attr->sched_priority = p->rt_priority; + attr->sched_runtime = dl_se->dl_runtime; + attr->sched_deadline = dl_se->dl_deadline; attr->sched_period = dl_se->dl_period; attr->sched_flags &= ~SCHED_DL_FLAGS; attr->sched_flags |= dl_se->flags; + + return 0; } /* diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index e3e4e68bb0c5..500163f81a9e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -356,7 +356,7 @@ extern int sched_dl_global_validate(void); extern void sched_dl_do_global(void); extern int sched_dl_overflow(struct task_struct *p, int policy, const struct sched_attr *attr); extern void __setparam_dl(struct task_struct *p, const struct sched_attr *attr); -extern void __getparam_dl(struct task_struct *p, struct sched_attr *attr, unsigned int flags); +extern int __getparam_dl(struct task_struct *p, struct sched_attr *attr, unsigned int flags); extern bool __checkparam_dl(const struct sched_attr *attr); extern bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr); extern int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial); diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c index b215b0ead9a6..c5ff37e083db 100644 --- a/kernel/sched/syscalls.c +++ b/kernel/sched/syscalls.c @@ -911,16 +911,21 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a return -E2BIG; } -static void get_params(struct task_struct *p, struct sched_attr *attr, unsigned int flags) +static int get_params(struct task_struct *p, struct sched_attr *attr, unsigned int flags) { + if (flags) + return __getparam_dl(p, attr, flags); + if (task_has_dl_policy(p)) { - __getparam_dl(p, attr, flags); + return __getparam_dl(p, attr, flags); } else if (task_has_rt_policy(p)) { attr->sched_priority = p->rt_priority; } else { attr->sched_nice = task_nice(p); attr->sched_runtime = p->se.slice; } + + return 0; } /** @@ -979,8 +984,11 @@ SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, if (!p) return -ESRCH; - if (attr.sched_flags & SCHED_FLAG_KEEP_PARAMS) - get_params(p, &attr, 0); + if (attr.sched_flags & SCHED_FLAG_KEEP_PARAMS) { + retval = get_params(p, &attr, 0); + if (retval) + return retval; + } return sched_setattr(p, &attr); } @@ -1086,7 +1094,9 @@ SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, kattr.sched_policy = p->policy; if (p->sched_reset_on_fork) kattr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; - get_params(p, &kattr, flags); + retval = get_params(p, &kattr, flags); + if (retval) + return retval; kattr.sched_flags &= SCHED_FLAG_ALL; #ifdef CONFIG_UCLAMP_TASK -- 2.43.0