Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jianyong Wu" <wujianyong@hygon.cn>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Juri Lelli" <juri.lelli@redhat.com>,
	"Vincent Guittot" <vincent.guittot@linaro.org>,
	"Chen Yu" <yu.c.chen@intel.com>,
	"Tim Chen" <tim.c.chen@linux.intel.com>
Cc: "Dietmar Eggemann" <dietmar.eggemann@arm.com>,
	"Steven Rostedt" <rostedt@goodmis.org>,
	"Ben Segall" <bsegall@google.com>, "Mel Gorman" <mgorman@suse.de>,
	"Valentin Schneider" <vschneid@redhat.com>,
	"K Prateek Nayak" <kprateek.nayak@amd.com>,
	"Shrikanth Hegde" <sshegde@linux.ibm.com>,
	"Phil Auld" <pauld@redhat.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"David Hildenbrand" <david@kernel.org>,
	maddy@linux.ibm.com, "Michael Ellerman" <mpe@ellerman.id.au>,
	ljs@kernel.org, linux-mm@kvack.org, jianyong.wu@outlook.com,
	zhongyuan@hygon.cn, huangsj@hygon.cn, wangfengyu@hygon.cn,
	yingzhiwei@hygon.cn
Subject: Re: [RFC PATCH v3 12/17] sched/cache: Apply multi-LLC aggregation policy to task migration
Date: Fri, 30 Oct 2026 03:05:03 +0000	[thread overview]
Message-ID: <sashiko-outbox-190206@kernel.org> (raw)
In-Reply-To: <20261029022036.4002331-13-wujianyong@hygon.cn>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] sched/fair: NULL deref and mm_struct UAF in alb_break_llc()
- [High] sched/fair: alb_break_llc() blocks active balance when pref_llc < 0
- [Medium] sched/fair: active balance bypasses migrate_degrades_llc() when degrades > 0
--

commit 7bd76e4bf626d210dfac7f3c5332cbe2a77e81f9
Author: Jianyong Wu <wujianyong@hygon.cn>

sched/cache: Apply multi-LLC aggregation policy to task migration

This commit updates cache-aware task migration and active load balancing to
use if_to_prefer() and can_migrate_llcs() across all LLC pairs, removes the
can_migrate_llc() helper, and moves the LBF_ACTIVE_LB check in
can_migrate_task() after the locality check.

> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index 03bb5c85a8b7b..c3f9ef8798d6c 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c

[ ... ]

> @@ -10827,55 +10779,52 @@ static enum llc_mig can_migrate_llc_task(int src_cpu, int dst_cpu,

[ ... ]

>  static inline bool
>  alb_break_llc(struct lb_env *env)
>  {
> +	int pref_llc = -1;
> +	bool to_pref = false;
> +
>  	if (!sched_cache_enabled())
>  		return false;
>  
>  	if (cpus_share_cache(env->src_cpu, env->dst_cpu))
>  		return false;
>  	/*
> -	 * All tasks prefer to stay on their current CPU.
> -	 * Do not pull a task from its preferred CPU if:
> -	 * 1. It is the only task running and does not exceed
> -	 *    imbalance allowance; OR
> -	 * 2. Migrating it away from its preferred LLC would violate
> -	 *    the cache-aware scheduling policy.
> +	 * We need the preferred LLC to decide whether we can perform migration.
> +	 * Therefore, we need to obtain task_struct, which is only meaningful
> +	 * in the case that only one task on the rq.
> +	 * For cases with more than one task on the rq, we need to check
> +	 * this in can_migrate_task().
>  	 */
> -	if (env->src_rq->nr_pref_llc_running &&
> -	    env->src_rq->nr_pref_llc_running == env->src_rq->cfs.h_nr_runnable) {
> -		unsigned long util = 0;
> +	if (env->src_rq->nr_running == 1) {
>  		struct task_struct *cur;
>  
> -		if (env->src_rq->nr_running <= 1)
> -			return true;
> -
>  		cur = rcu_dereference_all(env->src_rq->curr);
> -		if (cur && cur->sched_class == &fair_sched_class)
> -			util = task_util(cur);
> +		if (!cur || !cur->mm)
> +			return false;
> +
> +		if (cur->sched_class == &fair_sched_class)
> +			pref_llc = llc_id(cur->mm->sc_stat.cpu);

[Severity: Critical]
Can this dereference of cur->mm cause a NULL pointer dereference or a
use-after-free on struct mm_struct?

In sched_balance_rq(), need_active_balance() -> alb_break_llc() is called
before locking busiest (env->src_rq) and again after unlocking it, holding
only rcu_read_lock():

kernel/sched/fair.c:sched_balance_rq() {
	...
	if (need_active_balance(&env)) {
		unsigned long flags;

		raw_spin_rq_lock_irqsave(busiest, flags);
	...
}

Because cur is actively running on env->src_cpu and neither the runqueue lock
nor task_lock(cur) is held, cur can concurrently execute exit_mm() or
kthread_unuse_mm() and clear current->mm = NULL between the cur->mm check and
the reload in cur->mm->sc_stat.cpu:

kernel/exit.c:exit_mm() {
	...
	local_irq_disable();
	current->mm = NULL;
	membarrier_update_current_mm(NULL);
	enter_lazy_tlb(mm, current);
	local_irq_enable();
	task_unlock(current);
	mmap_read_unlock(mm);
	mm_update_next_owner(mm);
	mmput(mm);
}

Even if the mm pointer is loaded only once, rcu_read_lock() only protects
struct task_struct, whereas mm_cachep does not use SLAB_TYPESAFE_BY_RCU and
__mmdrop() frees struct mm_struct immediately via free_mm(). If cur replaces
its mm in exec_mmap() or exits and switches out on the unlocked remote
runqueue, can alb_break_llc() and can_migrate_llcs() end up reading from a
freed struct mm_struct?

>  
> -		if (can_migrate_llc(env->src_cpu, env->dst_cpu,
> -				    util, false) == mig_forbid)
> +		to_pref = if_to_prefer(env->src_cpu, env->dst_cpu, pref_llc);
> +
> +		if (can_migrate_llcs(env->src_cpu, env->dst_cpu,
> +				    cur, to_pref) == mig_forbid)
>  			return true;
>  	}

[Severity: High]
When pref_llc is negative (for instance, when cur->mm->sc_stat.cpu is -1 on
single-threaded tasks, or when cur is not in fair_sched_class), shouldn't
alb_break_llc() return false instead of calling can_migrate_llcs()?

When pref_llc < 0, if_to_prefer() returns false, and can_migrate_llcs() falls
back to using src_cpu as target_cpu:

kernel/sched/fair.c:can_migrate_llcs() {
	...
	if (p) {
		struct mm_struct *mm = p->mm;

		if (mm)
			target_cpu = READ_ONCE(mm->sc_stat.cpu);
		target_cpu = target_cpu >= 0 ? target_cpu : src_cpu;

		tsk_util = task_util(p);
	}
	...
}

With to_pref == false and target_cpu == src_cpu, can_migrate_llcs() treats
src_cpu as the task's preferred cache location and returns mig_forbid whenever
fits_llc_capacity() is true on the source LLC or node:

kernel/sched/fair.c:can_migrate_llcs() {
	...
			if (src_node == dst_node) {
				/* Leave the source LLC at or above the threshold. */
				if (fits_llc_capacity(src_util, src_cap, false))
					return mig_forbid;
	...
}

Unlike can_migrate_llc_task(), which returns mig_unrestricted when cpu < 0,
won't this regression cause alb_break_llc() to block cross-LLC active balance
for tasks that have no preferred LLC?

[ ... ]

> @@ -11027,14 +10976,11 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)
>  
>  	/*
>  	 * Aggressive migration if:
> -	 * 1) active balance
> -	 * 2) destination numa is preferred
> +	 * 1) destination numa is preferred
> +	 * 2) active balance
>  	 * 3) task is cache cold, or
>  	 * 4) too many balance attempts have failed.
>  	 */
> -	if (env->flags & LBF_ACTIVE_LB)
> -		return 1;
> -
>  	degrades = migrate_degrades_locality(p, env);
>  	if (!degrades) {
>  		/*
> @@ -11060,6 +11006,13 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)
>  		hot = degrades > 0;
>  	}
>  
> +	/*
> +	 * Keep this after the cache-aware check so active balance respects its
> +	 * migration veto when NUMA locality is neutral.
> +	 */
> +	if (env->flags & LBF_ACTIVE_LB)
> +		return 1;

[Severity: Medium]
What happens during cross-node active load balancing when
migrate_degrades_locality() returns a positive value (degrades > 0)?

In active_load_balance_cpu_stop(), the stopper task is queued on env->src_rq,
so env->src_rq->nr_running > env->src_rq->nr_preferred_running is true in
migrate_degrades_locality():

kernel/sched/fair.c:migrate_degrades_locality() {
	...
	/* Migrating away from the preferred node is always bad. */
	if (src_nid == p->numa_preferred_nid) {
		if (env->src_rq->nr_running > env->src_rq->nr_preferred_running)
			return 1;
		else
			return 0;
	}
	...
}

When a task is on its preferred NUMA node, migrate_degrades_locality() returns
1, which skips the if (!degrades) block containing migrate_degrades_llc() and
sets hot = 1. Because the LBF_ACTIVE_LB check right after that block returns 1
unconditionally, won't active balance bypass migrate_degrades_llc() whenever
migrating the task also degrades NUMA locality?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261029022036.4002331-1-wujianyong@hygon.cn?part=12


  reply	other threads:[~2026-10-30  3:05 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-29  2:20 [RFC PATCH v3 00/17] sched: Scale cache-aware aggregation at LLC granularity Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 01/17] sched/topology: Add llc_to_node() to translate LLC ID to NUMA node Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 02/17] sched/topology: Build NUMA node affinity sequences Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 03/17] sched/topology: Add an iterator for cached NUMA node affinity rows Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 04/17] sched/topology: Build triangular affinity orders for LLCs in a node Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 05/17] sched/topology: Walk LLCs in NUMA node Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 06/17] sched/cache: Prioritize cache-preferred node selection over LLC selection Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 07/17] sched/topology: Add per-sd scratch for cache-aware load balancing Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 08/17] sched/cache: Introduce helpers for task migration decisions Jianyong Wu
2026-10-30  3:04   ` sashiko-bot
2026-10-29  2:20 ` [RFC PATCH v3 09/17] sched/cache: Introduce rq affinity gain calculation Jianyong Wu
2026-10-30  3:05   ` sashiko-bot
2026-10-29  2:20 ` [RFC PATCH v3 10/17] sched/cache: Pick the source rq/group with the highest affinity gain Jianyong Wu
2026-10-30  3:05   ` sashiko-bot
2026-10-29  2:20 ` [RFC PATCH v3 11/17] sched/cache: Drop prefer_sibling restriction for llc_balance Jianyong Wu
2026-10-29  2:20 ` [RFC PATCH v3 12/17] sched/cache: Apply multi-LLC aggregation policy to task migration Jianyong Wu
2026-10-30  3:05   ` sashiko-bot [this message]
2026-10-29  2:45 ` [RFC PATCH v3 13/17] sched/cache: Allow active balance to spread load from a full LLC Jianyong Wu
2026-10-30  3:05   ` sashiko-bot
2026-10-29  2:50 ` [RFC PATCH v3 14/17] sched/cache: Consider LLC load when selecting a single-task source rq Jianyong Wu
2026-10-29  2:56 ` [RFC PATCH v3 15/17] sched/cache: Include recently used preferred nodes in LLC scans Jianyong Wu
2026-10-30  3:05   ` sashiko-bot
2026-10-29  2:58 ` [RFC PATCH v3 16/17] sched/cache: Drop stale preferred LLC checks Jianyong Wu
2026-10-30  3:05   ` sashiko-bot
2026-10-29  2:59 ` [RFC PATCH v3 17/17] sched/debug: Show cache placement and preferred LLC in /proc/<pid>/sched Jianyong Wu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-190206@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=bsegall@google.com \
    --cc=david@kernel.org \
    --cc=dietmar.eggemann@arm.com \
    --cc=huangsj@hygon.cn \
    --cc=jianyong.wu@outlook.com \
    --cc=juri.lelli@redhat.com \
    --cc=kprateek.nayak@amd.com \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=maddy@linux.ibm.com \
    --cc=mgorman@suse.de \
    --cc=mingo@redhat.com \
    --cc=mpe@ellerman.id.au \
    --cc=pauld@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=sshegde@linux.ibm.com \
    --cc=tim.c.chen@linux.intel.com \
    --cc=vincent.guittot@linaro.org \
    --cc=vschneid@redhat.com \
    --cc=wangfengyu@hygon.cn \
    --cc=wujianyong@hygon.cn \
    --cc=yingzhiwei@hygon.cn \
    --cc=yu.c.chen@intel.com \
    --cc=zhongyuan@hygon.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox