From: Qing Wang <wangqing7171@gmail.com>
To: xuhx@hust.edu.cn, Vlastimil Babka <vbabka@kernel.org>,
Harry Yoo <harry@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
Hao Li <hao.li@linux.dev>, Christoph Lameter <cl@gentwo.org>,
David Rientjes <rientjes@google.com>,
Roman Gushchin <roman.gushchin@linux.dev>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: mm/slub: has_pcs_used() reads remote per-CPU sheaf state from flush_all_cpus_locked() without synchronization (data race; KCSAN blind spot: slub.o is uninstrumented)
Date: Wed, 4 Nov 2026 17:41:32 +0800 [thread overview]
Message-ID: <20261104094132.2665206-1-wangqing7171@gmail.com> (raw)
In-Reply-To: <363227fe.1d637.1a1a124c2b0.Coremail.xuhx@hust.edu.cn>
On Tue, 03 Nov 2026 at 19:21, 徐晗翔 <xuhx@hust.edu.cn> wrote:
> flush_all_cpus_locked() calls has_pcs_used() for every CPU to decide
> which flush work to skip, reading each remote CPU's pcs->spare /
> pcs->rcu_free and dereferencing pcs->main->size -- all locklessly
> (mm/slub.c:4041-4051, inlined into flush_all_cpus_locked) -- while
> the owning CPU's alloc/free fast paths mutate exactly those fields
> under only the per-CPU sheaf lock (pcs->main->size++/--, the
> pcs->main pointer swap in __pcs_replace_empty_main, etc.). The
> reader runs from kmem_cache_shrink() (sysfs shrink attribute, memory
> offline) and is, as far as I can enumerate, the only cross-CPU
> consumer of this state outside the sysfs slabinfo walkers (excluded
> -- they read other fields under a different protocol). I verified
> the race with KCSAN after discovering why nobody has ever seen it
> reported: mm/Makefile sets KCSAN_SANITIZE_slub.o := n, so BOTH sides
> of this race are structurally invisible to KCSAN on any stock kernel
> (verified at the disassembly level: the four accesses in
> flush_all_cpus_locked compile to bare cmp/mov with zero __tsan
> calls). On a diagnostic build that only flips that Makefile switch
> (no source change), a shrink+churn workload on a dedicated cache
> produces 436 reader-pair reports covering all five writer families,
> including an 8-byte pcs->main pointer swap with an explicit "value
> changed" line -- the snapshot prerequisite of the (extremely
> unlikely, source-argued) use-after-free chain: a stale pcs->main can
> outlive its sheaf's retirement (spare -> rcu_free -> call_rcu ->
> kfree) if the reader is preempted between load and dereference. The
> practical impact of the race itself is a wrong skip decision in
> sfw->skip; the fix is to move the emptiness check into the target
> CPU's flush callback, where the state is local and locked.
You're right, there is a data race in has_pcs_used() reading the pcs
fields. The possible consequences:
1. has_pcs_used() observes an empty pcs and sets sfw->skip, so the
flush is skipped and the memory is not freed in time.
2. A very unlikely UAF: the reader loads pcs->main, and the old sheaf
is freed before ->size is dereferenced.
For the fix: could we simply drop the has_pcs_used() check? The cost
is some extra workqueue overhead — flush work would be queued even on
CPUs whose sheaves are empty.
--
Best regards,
Qing
next prev parent reply other threads:[~2026-11-04 9:41 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 12:35 usb: devio: usbdev_release() has no barrier against an in-flight async_completed() callback (use-after-free window on struct usb_dev_state)gregkh@linuxfoundation.org 徐晗翔
2026-10-27 14:12 ` Greg KH
2026-11-03 11:21 ` mm/slub: has_pcs_used() reads remote per-CPU sheaf state from flush_all_cpus_locked() without synchronization (data race; KCSAN blind spot: slub.o is uninstrumented) 徐晗翔
2026-11-04 9:41 ` Qing Wang [this message]
2026-11-04 10:07 ` Qing Wang
2026-11-03 11:30 ` futex/hrtimer: hrtimer_sleeper::task is read unsynchronized in 16 places on v7.3 -- the accessor series that fixes this is not in 7.3; please make sure it reaches the affected trees (backport nudge + stock-kernel KCSAN evidence) 徐晗翔
2026-11-03 11:48 ` cgroup: fork vs cgroup.procs write race in favordynmods mode -- v7.3 is affected; please make sure bf6fbf46b5ff reaches the stable trees (repro incl. uninstrumented natural hit) 徐晗翔
2026-11-03 14:51 ` Sasha Levin
2026-11-03 11:57 ` net: rtnetlink: rtnl_link_unregister() vs in-flight RTM_GETLINK dump readers -- v7.3 lacks the synchronize_rcu() fix (Fixes: 6b57ff21a310 family); A/B reproduction on stock 7.3 徐晗翔
2026-11-03 15:49 ` Eric Dumazet
2026-11-04 15:03 ` Sasha Levin
2026-11-03 12:07 ` wifi: wilc1000: SDIO/SPI remove destroys the srcu_struct before wiphy_unregister() -- late cfg80211 callbacks write through dangling srcu state (unfixed upstream; controlled + natural Oops) 徐晗翔
2026-11-03 12:10 ` gpio: gpiolib: final put of the gpio_device happens inside the SRCU read critical section on the setup-failure path -- deterministic use-after-free read at guard release (unfixed upstream) 徐晗翔
2026-11-04 12:54 ` soc: qcom: pmic_glink_altmode: fix use-after-free on unbind (no cancel_work_sync for port work and enable_work) 徐晗翔
2026-11-04 13:04 ` Greg KH
2026-11-04 12:57 ` usb: typec: anx7411: unregister partner/altmodes before stopping the IRQ work -- use-after-free, double unregister, orphan partner on remove 徐晗翔
2026-11-04 13:28 ` Greg KH
2026-11-04 12:58 ` usb: typec: ucsi: deadlock on cros_ec unbind -- connector lock held across cancel_delayed_work_sync vs the mode-selection work's unbounded trylock polling 徐晗翔
2026-11-04 13:00 ` usb: typec: stusb160x/rt1719/hd3ss3220: IRQ thread vs remove -- double unregister / use-after-free on the partner and port 徐晗翔
2026-11-04 13:01 ` usb: typec: ucsi: displayport: data race on dp->header/ vdo_data/vdo_size -- work reads them unlocked while writers hold con->lock (VDM mismatch) 徐晗翔
2026-11-04 13:02 ` usb: typec: class: three lifetime/locking gaps around the mux/switch handles and mode_selection (drvdata UAF after provider unbind; no concurrent protocol for set/put; unlocked state_update vs delete) 徐晗翔
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=20261104094132.2665206-1-wangqing7171@gmail.com \
--to=wangqing7171@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=cl@gentwo.org \
--cc=hao.li@linux.dev \
--cc=harry@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=vbabka@kernel.org \
--cc=xuhx@hust.edu.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
all inboxes | Powered by JetHome®