Re: [PATCH 17/23] sched/isolation: Extend housekeeping_dereference_check() to cover changes in nohz_full or manged_irqs cpumasks

sashiko-bot
2026-04-22T03:09:06Z

Sashiko AI review found 2 potential issue(s):
- [Critical] Unprotected access to newly dynamic HK_TYPE_KERNEL_NOISE causes lockdep splats and Use-After-Free.
- [Critical] Flawed lockdep exemptions mask genuine Use-After-Free vulnerabilities.
--

commit 7b12dcd17d401c6b135ee53ba4e8384a7bd3d867
Author: Waiman Long <longman@redhat.com>

sched/isolation: Extend housekeeping_dereference_check() to cover changes in nohz_full or manged_irqs cpumasks

This commit extends housekeeping_dereference_check() to apply the same
lockdep exemptions used by HK_TYPE_DOMAIN to HK_TYPE_KERNEL_NOISE and
HK_TYPE_MANAGED_IRQ, preparing them to be runtime changeable.

> diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
> --- a/kernel/sched/isolation.c
> +++ b/kernel/sched/isolation.c
> @@ -38,7 +38,8 @@ EXPORT_SYMBOL_GPL(housekeeping_enabled);
>
> static bool housekeeping_dereference_check(enum hk_type type)
> {
> - if (IS_ENABLED(CONFIG_LOCKDEP) && type == HK_TYPE_DOMAIN) {
> + if (IS_ENABLED(CONFIG_LOCKDEP) &&
> + (BIT(type) & (HK_FLAG_DOMAIN | HK_FLAG_KERNEL_NOISE | HK_FLAG_MANAGED_IRQ))) {

Because HK_TYPE_KERNEL_NOISE is becoming runtime changeable, does this
expose existing readers to concurrent updates and use-after-free?

For example, housekeeping_show() reads this mask without holding
rcu_read_lock(). Similarly, tmigr_isolated_exclude_cpumask() reads it
holding only cpus_read_lock(), not the write lock.

If housekeeping_update() allocates a new mask, calls synchronize_rcu(),
and frees the old mask while these functions are accessing the pointer,
could this result in a use-after-free?

Additionally, does extending this lockdep exemption mask genuine
use-after-free vulnerabilities?

The exemptions below assume that holding cpuset_mutex or cpus_write_lock()
protects the pointer:

> /* Cpuset isn't even writable yet? */
> if (system_state <= SYSTEM_SCHEDULING)
> return true;
>
> /* CPU hotplug write locked, so cpuset partition can't be overwritten */
> if (IS_ENABLED(CONFIG_HOTPLUG_CPU) && lockdep_is_cpus_write_held())
> return true;
>
> /* Cpuset lock held, partitions not writable */
> if (IS_ENABLED(CONFIG_CPUSETS) && lockdep_is_cpuset_held())
> return true;

However, housekeeping_update() explicitly drops cpuset_mutex and
cpus_read_lock() before updating masks and calling synchronize_rcu().

This means housekeeping_update() can run in parallel with readers
holding cpuset_mutex or CPU hotplug callbacks holding cpus_write_lock().

Since these readers are exempted from needing rcu_read_lock(),
synchronize_rcu() will not wait for them. Could this result in a silent
use-after-free on a freed cpumask?

> return false;
> }
>
> return true;
> }

--
Sashiko AI review · https://sashiko.dev/#/patchset/20260421030351.281436-1-longman@redhat.com?part=17