ipoib_ib_dev_flush_light() temporarily clears IPOIB_FLAG_OPER_UP to
prevent multicast joins while ipoib_mcast_dev_flush() is running, and
restores the flag afterwards if it was previously set.
This restore races with ipoib_ib_dev_down(). If the interface is brought
down while the flush is in progress, ipoib_ib_dev_down() clears
IPOIB_FLAG_OPER_UP, but the flush path may set it again after the device
has already gone down.
Since commit 894021a752 ("IB/ipoib: Make the carrier_on_task race
aware"), ipoib_mcast_carrier_on_task() relies on IPOIB_FLAG_OPER_UP
being cleared to terminate its rtnl_trylock() retry loop. If the flag is
left set after shutdown, the workqueue retries forever, causing teardown
to deadlock when ipoib_ndo_uninit() waits in destroy_workqueue() while
holding RTNL.
Instead of overloading IPOIB_FLAG_OPER_UP to block multicast joins
during a light flush, introduce a dedicated IPOIB_FLAG_MCAST_FLUSH flag.
Use it together with IPOIB_FLAG_OPER_UP to determine whether multicast
joins are allowed, avoiding the race with device shutdown.
Fixes: 344bacca8c ("IB/ipoib: Don't allow MC joins during light MC flush")
Reported-by: Ben Davies <ben.davies@gresearch.co.uk>
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
Link: https://patch.msgid.link/20260902-avoid-rest-oper-up-v1-1-04fcd4916cae@nvidia.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
rdma_join_multicast() queues RoCE work that later reads the ucma_multicast
through event->param.ud.private_data, then list_add()s the CMA multicast
at the head of id_priv->mc_list. rdma_leave_multicast() matches only by
sockaddr and destroys the first hit.
ucma_process_join() used to drop ctx->mutex after a successful join and
retake it only if copy_to_user() failed. Two concurrent JOIN_MCAST calls
with the same address can therefore insert a second CMA entry before the
first thread's leave. leave then cancels the newer work and the older
worker still dereferences the ucma_multicast that the first thread frees.
Keep ctx->mutex held from rdma_join_multicast() through copy_to_user() and,
on -EFAULT, through rdma_leave_multicast() so leave cannot miss this join.
Do not leave if join itself failed: that path never published this address
on mc_list, and a leave-by-addr would destroy an earlier successful join.
Reported-by: syzbot+a6ffe86390c8a6afc818@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=a6ffe86390c8a6afc818
Fixes: fe454dc31e ("RDMA/ucma: Fix use-after-free bug in ucma_create_uevent")
Cc: stable@vger.kernel.org
Signed-off-by: Quanye Yang <quanyeyang@proton.me>
Link: https://patch.msgid.link/20260831-rdma-ucma-mc-uaf-v1-1-b8eeb7046aff@proton.me
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Add a verifier test that leaves the raw tracepoint context pointer in R1
when calling bpf_loop(). This is the smallest trigger for the incorrect
precision backtracking: it reuses an existing callback and needs no maps or
userspace setup.
Expect an ordinary scalar-type rejection. Without the verifier fix, the
test instead reaches precision backtracking and reports an internal
"backtracking misuse" error.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260905014735.1452988-3-memxor@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
bpf_loop() declares its nr_loops argument as ARG_ANYTHING. Privileged
programs may pass pointer values to such arguments, so check_func_arg()
lets a pointer-valued R1 reach the helper-specific checks.
Since commit bb124da69c ("bpf: keep track of max number of bpf_loop
callback iterations"), the verifier marks R1 precise and reads its upper
bound to limit callback simulation. Precision backtracking only accepts
scalar registers, so passing a pointer instead triggers the "backtracking
misuse" verifier warning. Kernels with panic_on_warn enabled subsequently
panic.
Introduce ARG_SCALAR for helper arguments that only accept scalar values
and use it for bpf_loop() nr_loops. Generic helper argument validation then
rejects pointers before loop inlining and precision processing.
Fixes: bb124da69c ("bpf: keep track of max number of bpf_loop callback iterations")
Reported-by: syzbot+7b47f87674e9a1569110@syzkaller.appspotmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://patch.msgid.link/20260905014735.1452988-2-memxor@gmail.com
Closes: https://lore.kernel.org/bpf/6a9ad24c.b5d4176b.238c3e.0001.GAE@google.com/
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
- Run scripts/coccinelle/api/kmalloc_objs.cocci for v7.3
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQRSPkdeREjth1dHnSE2KwveOeQkuwUCapuwVwAKCRA2KwveOeQk
u5EeAP9TS7K4iVlw3KlZHuLIK2q+CQfALPepcu+ME2lO5dta4gEAxCTi0ZXmU7OT
XbmWUd+DTkKNYCBW8E6Lvn72Er13uQs=
=ZtN4
-----END PGP SIGNATURE-----
Merge tag 'kmalloc_obj-v7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull kmalloc_obj conversions from Kees Cook:
"Another run of the Coccinelle script for converting kmalloc()
family of allocations to kmalloc_obj() via the existing rules
in scripts/coccinelle/api/kmalloc_objs.cocci"
* tag 'kmalloc_obj-v7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
treewide: refresh kmalloc_obj() conversions
drm/amd/display: Fix harmless type mismatch in allocation
Bounded relies on Integer implementations to describe primitive integer
semantics correctly. In particular, it uses Integer::BITS and Signedness
to justify unchecked operations.
Integer is currently safe and externally implementable, so an
implementation can violate those assumptions and make safe Bounded
operations reach undefined behavior.
For example, an Integer implementation for a u8 wrapper can report
BITS = 16. Safe code can then cast a Bounded<u16, 9> containing 256
to that wrapper. Its TryFrom<u16> implementation returns Err, and
Bounded::cast() calls unwrap_unchecked() on it, causing undefined
behavior.
Seal Integer so only the primitive implementations provided by the
kernel crate can satisfy it.
Fixes: 01e345e82e ("rust: num: add Bounded integer wrapping type")
Reported-by: Miguel Ojeda <ojeda@kernel.org>
Closes: https://lore.kernel.org/rust-for-linux/CANiq72mOfR33s4y+Ueivd5NrC5yre+Pcp57ZOBz0msw9A4AP1Q@mail.gmail.com/
Cc: stable@vger.kernel.org
Suggested-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Younes Akhouayri <git@younes.io>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260905-feature-rust-num-seal-integer-v2-1-f1311ffbe6e7@younes.io
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
qmap decides placements from self_cids, which redistribute() derives from
the caps view at ops.sub_caps_updated() time. That view runs ahead of the
cpus: a granted cid can be in self_cids before its cpu has reported the caps
in effect through ops.sub_ecaps_updated(). ops.update_idle() only comes once
BASE is in effect, so the idle-gated placements reach such a cid only
through an idle bit left over from an earlier hold. The highpri scan has no
gate at all:
parent cpu Y, qmap cpu X
grants ENQ on X to qmap
sub_caps_updated() adds X
to self_cids
highpri scan moves a task
to X with PREEMPT
caps not in effect,
move denied, task
bounced with REENQ_CAP
reject drain, enqueue
the scan moves it to X
again
denied again
dispatch syncs ecaps,
sub_ecaps_updated(X)
Every highpri move to X in that window is denied and bounced. The two
callbacks are meant to split the roles: ops.sub_caps_updated() tracks what
the node holds and drives what it delegates to its children, while
ops.sub_ecaps_updated() says whether a task can run on a cpu now. qmap used
the first for both. Track the caps in effect from ops.sub_ecaps_updated() as
avail_cids and place only on self_cids & avail_cids, so that self_cids stays
the delegation split and avail_cids gates the placement.
The stranded tests keep self_cids, as they ask whether the split gives the
task anywhere at all. A highpri task whose self_cids lack caps in effect
waits for them instead of being moved and bounced.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
qmap's stranded fallback forces a task that can run on none of its self cids
onto its first allowed cid with SCX_ENQ_RESCUE, and adds SCX_ENQ_IMMED when
that cid is a time-share it holds. On such a cid the insert stops being a
rescue request:
1. A task is enqueued while none of its allowed cids is in self_cids. At
attach self_cids is still empty.
2. qmap inserts it into cid 0's local DSQ with SCX_ENQ_RESCUE |
SCX_ENQ_IMMED.
3. The kernel finds ENQ_IMMED held on cid 0, admits the insert and skips the
rescue diversion.
4. cid 0's cpu is busy, so the IMMED task is bounced back to qmap with
SCX_ENQ_REENQ.
5. qmap's enqueue sees the same inputs and repeats step 2. Nothing runs in
between.
6. The reenqueue limit ejects qmap with SCX_EXIT_ERROR_REENQ.
The caps granted during the parent's ops.sub_attach() are delivered after
the sub already holds its tasks, while the per-cid effective caps that mark
the time-shares are delivered from the first dispatch after bypass lifts, so
every attach that receives a time-share on a task's first allowed cid starts
the loop. Drop IMMED from the rescue inserts so that step 3 diverts to the
rescue path.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
dispatch_one() tests ops flags and bypass state against the root scheduler
in both places where it decides to keep running @prev: the early keep of a
@prev with slice left tests the root's bypass state, and the keep-last at
the end tests the root's SCX_OPS_ENQ_LAST and bypass state. Both are
properties of the scheduler @prev belongs to, and put_prev_task_scx(), which
acts on the outcome, reads them from that scheduler. When @prev belongs to a
sub-scheduler the two sides disagree.
The keep-last case is visible. The root set SCX_OPS_ENQ_LAST, so a lone
@prev of a sub-scheduler is not kept and is enqueued with SCX_ENQ_LAST to a
sub-scheduler that never opted in. This trips the WARN_ON_ONCE in
put_prev_task_scx() for the missing flag, and the sub-scheduler queues the
task like any other and triggers no follow-up scheduling event, which can
lead to stalls.
Test SCX_OPS_ENQ_LAST and bypass state on @prev's sched in both places and
charge SCX_EV_DISPATCH_KEEP_LAST to it. Read the sched at each decision, as
the dispatch in between can drop the rq lock.
Fixes: 88234b075c ("sched_ext: Introduce scx_task_sched[_rcu]()")
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
dispatch_one() uses the root scheduler for everything it does, including the
two decisions to keep running @prev, which are wrong when @prev belongs to a
sub-scheduler. The function has to deal with @prev's scheduler too. Rename
the root's local from sch to root_sch for clarity and to make room for it.
No functional change.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
When the device tree describes a fixed-link and has no "mdio" child
node, macb_mii_init() returns early without allocating the MDIO bus,
leaving bp->mii_bus as NULL.
Two cleanup paths then dereference this NULL bus:
1. On driver unbind, macb_remove() unconditionally calls
mdiobus_unregister(bp->mii_bus), which oopses:
Unable to handle kernel NULL pointer dereference at virtual address 00000000000004a8
pc : mdiobus_unregister+0x14/0xa4
lr : macb_remove+0x38/0xa4
Call trace:
mdiobus_unregister+0x14/0xa4 (P)
macb_remove+0x38/0xa4
platform_remove+0x20/0x30
device_release_driver_internal+0x1c8/0x224
unbind_store+0xb4/0xbc
2. On the probe error path in macb_probe(), reached when
macb_mii_init() has succeeded but a subsequent step fails, the
err_out_unregister_mdio label runs the same unconditional cleanup.
mdiobus_unregister() and mdiobus_free() do not guard against a NULL
bus, so guard the calls in both macb_remove() and the probe error
path.
Fixes: d0c3601f2c ("net: macb: Avoid 20s boot delay by skipping MDIO bus registration for fixed-link PHY")
Signed-off-by: Vineeth Karumanchi <vineeth.karumanchi@amd.com>
Reviewed-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Link: https://patch.msgid.link/20260902102836.2019355-1-vineeth.karumanchi@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Jamal Hadi Salim says:
====================
net/sched: clamp quantum/psched_mtu in change paths
This is a followup to commit 709f34f7c2 ("net/sched: fq: add overflow
bounds to quantum and initial quantum").
The quantum_backlog_overflow series and the five siblings that followed
clamped the init-path quantum in fq, fq_codel, fq_pie, hhf, sfq. The
change() paths were not clamped but it is the same pattern, same writer
of q->quantum, same privilege level (CAP_NET_ADMIN in a user namespace).
A user can override the init clamp via tc qdisc change, restoring the
small-quantum deficit spin that the init clamp was meant to prevent.
This series also covers two siblings that were missed entirely by the
original series: sch_dualpi2 and sch_pie call psched_mtu() without any
clamp at all. With a crafted size table qdisc_pkt_len reaches ~2 GiB,
so quantum=1 (or a zero psched_mtu on a headerless device) makes the
deficit-refill loop spin ~2^31 times under the qdisc lock (a soft
lockup / denial of service).
Each patch fixes one qdisc with its own Fixes: tag so they can be
backported independently - the commits they fix shift differently in
the git tree.
Patch 1: fq - clamp TCA_FQ_QUANTUM and TCA_FQ_INITIAL_QUANTUM in change
Patch 2: fq_pie - clamp quantum in change path
Patch 3: sfq - clamp quantum and reject > 1<<20 in change path
Patch 4: hhf - clamp quantum in change and init paths
Patch 5: dualpi2 - clamp psched_mtu at all 3 call sites
Patch 6: pie - clamp psched_mtu in pie_drop_early
Patch 7: drr - clamp quantum in change class
Patch 8: ets - clamp quantum in parse and fallback paths
Patch 9: selftests - update ETS test 41f5 for clamped quanta
Conditions to recreate (applies to all): create the qdisc, then
tc qdisc change ... quantum 1 with a STAB size table inflating
qdisc_pkt_len. Requires CAP_NET_ADMIN in a user namespace (unshare -Urn).
====================
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Commit "net/sched: ets: clamp quantum in parse and fallback paths"
moved the quantum floor into ets_quantum_parse(), so every explicitly
configured quantum is now clamped to [256, 1 << 20], not just the
psched_mtu() fallback.
Test 41f5 passes "quanta 4294967294 1 1" and matches the values back
verbatim, so all three bands now differ from what it expects:
before: bands 3 quanta 4294967294 1 1
after: bands 3 quanta 1048576 256 256
Update the match pattern accordingly.
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com.10
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
ets_qdisc_change() falls back to psched_mtu() with no floor for bands
without an explicit quantum. With a crafted size table qdisc_pkt_len
reaches ~2 GiB, so a zero psched_mtu on a headerless device makes the
deficit-refill loop spin under the qdisc lock.
Move the floor into ets_quantum_parse() so explicitly configured quanta
are also clamped to [256, 1<<20], not just the fallback path.
Conditions to recreate the bug:
CONFIG_NET_SCH_ETS=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root ets bands 3 strict 2 quanta 1 1
Fixes: dcc68b4d80 ("net: sch_ets: Add a new Qdisc")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com.9
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drr_change_class() rejects explicit quantum==0 but falls back to
psched_mtu() with no floor. With a crafted size table qdisc_pkt_len
reaches ~2 GiB, so quantum=1 (or a zero psched_mtu on a headerless
device) makes the deficit-refill loop spin under the qdisc lock.
Add clamp_t(u32, quantum, 256, 1<<20) after the zero reject and on the
fallback path. The explicit-zero reject is preserved.
Conditions to recreate the bug:
CONFIG_NET_SCH_DRR=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root drr
tc class add dev dummy0 parent 1: classid 1:1 drr quantum 1
Fixes: 13d2a1d2b0 ("pkt_sched: add DRR scheduler")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com.8
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
pie_drop_early() calls psched_mtu() with no clamp. With mtu=0x80000000
the bytemode divide silently zeroes the drop probability, disabling AQM.
Clamp to [1, 1<<20].
Conditions to recreate the bug:
CONFIG_NET_SCH_PIE=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root pie
tc qdisc change dev dummy0 root pie stab data 32768 size_log 15 cell_log 0
Fixes: d4b36210c2 ("net: pkt_sched: PIE AQM scheme")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com.7
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
dualpi2_calculate_c_protection(), must_drop(), and get_memory_limit()
call psched_mtu() with no clamp. A huge MTU makes (s32)psched_mtu()
overflow in the signed multiply for c_protection_init, and 2 *
psched_mtu() wraps in get_memory_limit(). With a crafted size table
qdisc_pkt_len reaches ~2 GiB, causing a soft lockup / denial of service.
Clamp psched_mtu() to [1, 1<<20] at all three call sites.
Conditions to recreate the bug:
CONFIG_NET_SCH_DUALPI2=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root dualpi2
tc qdisc change dev dummy0 root dualpi2 stab data 32768 size_log 15 cell_log 0
Fixes: 320d031ad6 ("sched: Struct definition and parsing of dualpi2 qdisc")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com.6
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
hhf_change() accepts any quantum from userspace, including 1. With a
crafted size table qdisc_pkt_len reaches ~2 GiB, so quantum=1 makes
the deficit-refill loop spin ~2^31 times under the qdisc lock
(a soft lockup / denial of service).
Add max(256U, ...) in hhf_change() matching fq_codel_change(). Clamp
hhf_init() to [256, 1<<20] matching the siblings, and remove the old
fallback that only set quantum=256 on overflow.
Conditions to recreate the bug:
CONFIG_NET_SCH_HHF=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root hhf
tc qdisc change dev dummy0 root hhf quantum 1 stab data 32768 size_log 15 cell_log 0
Fixes: 10239edf86 ("net-qdisc-hhf: Heavy-Hitter Filter (HHF) qdisc")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com.5
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
fq_pie_change() accepts any quantum value from userspace, including 1.
With a crafted size table qdisc_pkt_len reaches ~2 GiB, so quantum=1
makes the deficit-refill loop spin ~2^31 times under the qdisc lock
(a soft lockup / denial of service).
Add max(256U, ...) matching fq_codel_change().
Conditions to recreate the bug:
CONFIG_NET_SCH_FQ_PIE=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root fq_pie
tc qdisc change dev dummy0 root fq_pie quantum 1 stab data 32768 size_log 15 cell_log 0
Fixes: ec97ecf1eb ("net: sched: add Flow Queue PIE packet scheduler")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com.3
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The fq change path accepts TCA_FQ_QUANTUM in [1, INT_MAX] and
TCA_FQ_INITIAL_QUANTUM up to INT_MAX, while fq_init() already clamps to
[1, 1<<20]. A user can override the init clamp via tc qdisc change,
restoring the small-quantum deficit spin that the init clamp prevents.
Narrow iq_range.max to 1<<20 so TCA_FQ_INITIAL_QUANTUM is rejected at
parse time. Clamp TCA_FQ_QUANTUM to [256, 1<<20] in fq_change() and
fq_init() quantum to [256, 1<<20] for tiny-MTU devices.
Conditions to recreate the bug:
CONFIG_NET_SCH_FQ=y. Requires CAP_NET_ADMIN (namespace-local via
unshare -Urn suffices).
tc qdisc add dev dummy0 root fq
tc qdisc change dev dummy0 root fq quantum 1 stab data 32768 size_log 15 cell_log 0
Fixes: 709f34f7c2 ("net/sched: fq: add overflow bounds to quantum and initial quantum")
Reported-by: Vega <vega@nebusec.ai>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-0CFC.v3.20260901204856@mojatatu.com.2
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
`mlx5e_stats_ts_get()` currently selects either DMA or port timestamp
counters based on `tx_ptp_opened`. This flag is intentionally kept set
once the PTP TX queues have been opened so their statistics remain
available after queue teardown. As a result, DMA timestamps are no
longer reported after switching from port timestamping back to DMA
timestamping.
The function also reads statistics only from the currently active
channels and TCs. Reducing the number of channels or TCs can therefore
drop previously accumulated timestamp counters from the reported value.
Read the persistent channel statistics instead and always include DMA
timestamp counters. Once the PTP TX queues have been opened, also
include the port timestamp counters.
This also drops state_lock. It previously protected live channel/PTP
pointers, the new code only reads persistent channel_stats and
ptp_stats via mlx5e_stats_nch_read(), which is already safe for
lockless stats access.
Fixes: 3579032c08 ("net/mlx5e: Implement ethtool hardware timestamping statistics")
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Shahar Shitrit <shshitrit@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902193731.3668958-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
In mlx5_esw_vport_disable(), move esw_apply_vport_rx_mode() ahead
of esw_vport_change_handle_locked() so vport->allmulti_rule is
NULL before the change handler observes it.
During FW-fatal recovery the disable runs while dev->state ==
INTERNAL_ERROR. The promisc query inside esw_update_vport_rx_mode()
fails and returns early, leaving vport->allmulti_rule intact, so
esw_update_vport_mc_promisc() runs and adds MLX5_ACTION_ADD entries
to vport->mc_list whose flow rules are then installed in the FDB
by esw_add_mc_addr(). esw_destroy_legacy_table() tears down the
FDB with those refs still held, corrupting the sub-tree and
leaving dangling flow_rule pointers in vport->mc_list.
Two-stage failure on `echo 1 > /sys/bus/pci/devices/<bdf>/reset`:
refcount_t: underflow; use-after-free.
tree_put_node+0xef/0x110 [mlx5_core]
clean_tree+0x44/0xd0 [mlx5_core] (x5)
mlx5_fs_core_cleanup+0x57/0x1c0 [mlx5_core]
mlx5_unload+0x65/0xd0 [mlx5_core]
... mlx5_health_try_recover
BUG: unable to handle page fault for address: 0000000003000055
down_write+0x1c/0x60
mlx5_del_flow_rules+0x33/0x1f0 [mlx5_core]
esw_del_mc_addr+0x7b/0x170 [mlx5_core]
esw_apply_vport_addr_list+0x56/0xf0 [mlx5_core]
esw_vport_change_handle_locked+0x28b/0x310 [mlx5_core]
mlx5_esw_vport_enable+0x270/0x4a0 [mlx5_core]
... mlx5_load ... mlx5_health_try_recover
esw_apply_vport_rx_mode(false, false) clears vport->allmulti_rule
via its local state machine even when the FW del fails. With the
rule NULL the !IS_ERR_OR_NULL(allmulti_rule) gate in the change
handler closes, no rules are installed during disable, and the
reload starts with a clean mc_list.
Fixes: 922f56e9a7 ("net/mlx5: Fix steering rules cleanup")
Signed-off-by: Lama Kayal <lkayal@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902193854.3669035-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
In mlx5_eswitch_termtbl_put(), the zero-ref cleanup check reads
tt->ref_count after termtbl_mutex has been released. Two concurrent
callers on the same mlx5_termtbl_handle race: one decrements ref_count
to zero, removes the hash entry, and calls kfree(tt) while the other
has already dropped the mutex and is about to evaluate
if (!tt->ref_count), producing a use-after-free.
Fix this by capturing the result of the decrement into a stack-local
last variable before dropping the mutex. The cleanup decision is now
made entirely under termtbl_mutex, and tt is not touched after
kfree.
Fixes: 10caabdaad ("net/mlx5e: Use termination table for VLAN push actions")
Signed-off-by: Yael Chemla <ychemla@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902193514.3668880-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Concurrent teardown of TC sample rules sharing the same restore
context may re-read restore->count after dropping restore_lock.
At that point another thread may already have completed cleanup and
freed the restore object.
Use the result of the refcount decrement while holding restore_lock to
determine whether cleanup is needed.
Fixes: 36a3196256 ("net/mlx5e: TC, Add sampler restore handle API")
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Shahar Shitrit <shshitrit@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902193341.3668809-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
When ETS TCs with zero bandwidth are configured, the driver programs the
firmware using an alternate representation. On get, it needs
to recognize that representation so those TCs can be translated back and
reported as 0% bandwidth.
The existing detection relied on the programmed bandwidth because it was
enough to identify this representation. However, when a single ETS TC
owns 100% of the bandwidth, its firmware representation becomes the
same as a strict-priority TC, causing zero-bandwidth ETS TCs to be
reported with non-zero bandwidth values.
Use the cached TSA instead to distinguish the ETS and strict-priority
cases.
Fixes: be0f161ef1 ("net/mlx5e: DCBNL, Implement tc with ets type and zero bandwidth")
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Alex Lazar <alazar@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902193224.3668743-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The CREATE_LAG command is handled asynchronously by queuing a work,
which stores a local copy of ldev->tracker. When the work is processed,
it is possible that the values of the local copy and ldev->tracker have
diverged.
A single CREATE_LAG command programs two related fields into the
firmware: the v2p (virtual-to-physical) map, which selects the physical
egress port for each hash bucket, and the active_port bitmask, which
tells the firmware which physical ports are currently up so it can
redirect QP/TIS away from inactive ports. For the firmware to steer
traffic correctly, both must be derived from the same view of the ports'
link state.
The v2p map is computed by mlx5_infer_tx_affinity_mapping() from the
local tracker snapshot, but lag_active_port_bits() called
mlx5_infer_tx_enabled() on the live ldev->tracker instead. If
ldev->tracker changed between the snapshot and command execution, the
two fields reflect different port states: the v2p map may steer a bucket
to a port that the active_port mask marks as inactive (or vice versa).
The firmware then receives a self-contradictory configuration and can
redirect or drop traffic on a port the mapping still points at, until a
later event happens to reconcile the state.
Update lag_active_port_bits so that it receives the local version of the
tracker from when the work was queued, effectively closing the window
for injecting an inconsistency.
Fixes: c5c13b456c ("net/mlx5: Lag, set active ports if support bypass port select flow table")
Signed-off-by: Akiva Goldberger <agoldberger@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902192740.3665435-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Tariq Toukan says:
====================
net/mlx5e: RS FEC variant fixes
This series by Shahar fixes three related bugs in the RS FEC handling
for mlx5e, all stemming from incomplete coverage of the three RS FEC
hardware variants: RS_528_514 (bit 2), RS_544_514_INTERLEAVED_QUAD
(bit 4), and RS_544_514 (bit 7).
====================
Link: https://patch.msgid.link/20260902164634.3657606-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
get_fec_supported_advertised() populates the FEC modes reported as
supported to userspace. The MLX5E_ADVERTISE_SUPPORTED_FEC macro only
checked MLX5E_FEC_RS_528_514, causing devices that support only the
other RS variants (RS_544_514_INTERLEAVED_QUAD or RS_544_514) to not
advertise RS as supported to ethtool at all.
Introduce MLX5E_FEC_RS_MASK covering all three RS bit positions,
update the macro to accept a bitmask directly rather than a single
enum value, and pass MLX5E_FEC_RS_MASK for the RS entry.
Fixes: b5ede32d33 ("net/mlx5e: Add support for FEC modes based on 50G per lane links")
Fixes: 4e343c11ef ("net/mlx5e: Support FEC settings for 200G per lane link modes")
Signed-off-by: Shahar Shitrit <shshitrit@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Reviewed-by: Yael Chemla <ychemla@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902164634.3657606-4-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
When a user sets a FEC mode via ethtool, the driver maps the ethtool
FEC type to the lowest mlx5 bit of that type. For RS FEC, this is
MLX5E_FEC_RS_528_514 (bit 2). The driver then checks whether this
bit is supported by at least one link mode by inspecting the
fec_override_cap fields via mlx5e_fec_in_caps(), and returns
-EOPNOTSUPP if not.
This check is incorrect. RS FEC has three supported hardware variants:
RS_528_514 (bit 2), RS_544_514_INTERLEAVED_QUAD (bit 4), and
RS_544_514 (bit 7). mlx5e_remap_fec_conf_mode() already remaps bit 2
to the appropriate RS variant per link mode when writing the admin
fields, but the early capability check is done against the raw
unmapped bit. As a result, a device that supports RS_544_514 or
RS_544_514_INTERLEAVED_QUAD but not RS_528_514 will incorrectly reject
the user's RS FEC request.
Remove the early support check from mlx5e_set_fec_mode() and fold
it into the existing write loop, checking caps against the remapped
policy per link mode. Return -EOPNOTSUPP before the final register
write if no link mode accepted the policy.
Fixes: 2608a2f831 ("net/mlx5e: Fix return status when setting unsupported FEC mode")
Signed-off-by: Shahar Shitrit <shshitrit@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Reviewed-by: Yael Chemla <ychemla@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902164634.3657606-3-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD is missing from
pplm_fec_2_ethtool_linkmodes[], leaving index 4 zero-initialized.
As a result, when this FEC mode is active, find_first_bit() returns
index 4, causing __set_bit() to set bit 0
(ETHTOOL_LINK_MODE_10baseT_Half_BIT) instead of
ETHTOOL_LINK_MODE_FEC_RS_BIT. Consequently, ethtool reports:
Advertised FEC modes: Not reported
Add the missing mapping to ETHTOOL_LINK_MODE_FEC_RS_BIT.
Fixes: 4e343c11ef ("net/mlx5e: Support FEC settings for 200G per lane link modes")
Signed-off-by: Shahar Shitrit <shshitrit@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Reviewed-by: Yael Chemla <ychemla@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260902164634.3657606-2-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
An RTM_NEWQDISC request can make clsact bind a populated shared ingress
block during ->init(), publishing an embedded mini_Qdisc to lockless
readers. If the same request has an invalid TCA_RATE, estimator setup
fails after ->init(); the unwind removes the pointer but synchronously
frees its containing qdisc while tc_run() may still hold it.
Retire failed qdiscs through the same RCU helper as normal destruction.
Inline the synchronous free into the callback now that no direct callers
remain.
Fixes: 51ab2994c3 ("net: sched: allow ingress and clsact qdiscs to share filter blocks")
Reported-by: Xiang Mei <xmei5@asu.edu>
Link: https://lore.kernel.org/netdev/20260805102505.740806-1-david.lee@trailofbits.com/
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Link: https://patch.msgid.link/20260902155231.2149915-2-bestswngs@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
- Fix kernfs listxattr() not returning security xattr names (e.g.
SELinux labels) when the kernfs node has no allocated kernfs_iattrs
- Fix silent truncation of IRQ vector indices in the Rust PCI
abstractions
- Don't select OF from DRIVER_PE_KUNIT_TEST; skip the test when OF is
disabled instead of silently enabling extra kernel functionality
- Russ Weight is retiring from kernel development; update the Firmware
Loader sysfs contact to the driver-core mailing list, add a CREDITS
entry for Firmware Upload, and update MAINTAINERS accordingly
-----BEGIN PGP SIGNATURE-----
iHQEABYKAB0WIQS2q/xV6QjXAdC7k+1FlHeO1qrKLgUCapxQTQAKCRBFlHeO1qrK
Lr1NAQD09hhWzsAkRvdDgf/rd3iUW4Fxro/KOIf+OThNRgWpRQD4+hMNQqxzk3OB
QT3xFMqLPFtLf+voWTcWniC6UsLfCA==
=k/Gx
-----END PGP SIGNATURE-----
Merge tag 'driver-core-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core
Pull driver core fixes from Danilo Krummrich:
- Fix kernfs listxattr() not returning security xattr names (e.g.
SELinux labels) when the kernfs node has no allocated kernfs_iattrs
- Fix silent truncation of IRQ vector indices in the Rust PCI
abstractions
- Don't select OF from DRIVER_PE_KUNIT_TEST; skip the test when OF is
disabled instead of silently enabling extra kernel functionality
- Russ Weight is retiring from kernel development; update the Firmware
Loader sysfs contact to the driver-core mailing list, add a CREDITS
entry for Firmware Upload, and update MAINTAINERS accordingly
* tag 'driver-core-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core:
MAINTAINERS: Remove Russ Weight from Firmware Loader
CREDITS: Add CREDITS entry for Firmware Upload
firmware_loader: Change contact for sysfs nodes
rust: pci: reject IRQ vector indices that do not fit in u32
kernfs: preserve security xattrs without allocating iattrs
drivers: base: test: DRIVER_PE_KUNIT_TEST should not select OF
NR_MLOCK is updated from interrupt context. __free_pages_prepare() clears
a stray PG_mlocked and adjusts NR_MLOCK, and a folio can reach it with the
flag still set from a bio completion handler:
__free_pages_ok+0x6af/0x7a0
<IRQ>
__bio_release_pages+0xde/0x260
__iomap_dio_bio_end_io+0x16e/0x1a0
blk_update_request+0x14b/0x3d0
blk_mq_end_request+0x18/0x30
blk_done_softirq+0x49/0x60
The folio gets there like this. A MAP_SHARED file mapping is mlocked, so
its page cache folios carry PG_mlocked, and an O_DIRECT write sourced from
that mapping GUP-pins those same folios. munlock() then runs
mlock_vma_pages_range(), which clears VM_LOCKED before walking the page
tables to munlock each folio. A concurrent hole punch reaches the folio
through the rmap (i_mmap_rwsem, not mmap_lock) and can land inside that
window: __folio_remove_rmap() -> munlock_vma_folio() sees VM_LOCKED
already clear, so it neither queues the folio on the mlock batch nor takes
a reference, and the pte it clears makes the pending mlock_pte_range()
walk skip the folio at its !pte_present() check. filemap_remove_folio()
then drops the page cache reference, leaving the bio's pin as the last
one, released from the completion handler above.
So __zone_stat_mod_folio() here needs interrupts disabled, not merely
preemption, and __munlock_folio() has a path where they are not: when the
folio has already been taken off the LRU by somebody else the function
jumps straight to the counter update without taking the lruvec lock. The
read-modify-write of the per-CPU NR_MLOCK diff can then be interrupted by
the softirq above, and one of the two decrements is lost, leaving Mlocked
in /proc/meminfo permanently overstated.
Use zone_stat_mod_folio(). mod_zone_state()'s this_cpu_try_cmpxchg() is
atomic against a same-CPU interrupt and retries, and on the path where the
lruvec lock is held its cost is negligible next to the lock itself.
The UNEVICTABLE_PG* events are deliberately left on the __ accessors: they
occupy different vm_event_states slots from the UNEVICTABLE_PGCLEARED that
__free_pages_prepare() bumps, and nothing updates those two from interrupt
context.
Link: https://lore.kernel.org/20260901180109.3797944-1-shakeel.butt@linux.dev
Fixes: 2fbb0c10d1 ("mm/munlock: mlock_page() munlock_page() batch by pagevec")
Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
Reported-by: syzbot+cd2073ee6d958a8d0fcd@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/linux-mm/6a931c5a.08e933ee.dbf97.0093.GAE@google.com/
Acked-by: Hugh Dickins <hughd@google.com>
Cc: Jann Horn <jannh@google.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This was moved into mm/, but the original lib/ file somehow remained.
Remove it.
Reported-by: Suren Baghdasaryan <surenb@google.com>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Commit 0ef8faff49 ("fs: push nr_cached_objects memcg gating into
individual filesystems") was meant to drop the blanket memcg gate in
fs/super.c and let each ->nr_cached_objects() implementation decide for
itself whether it is meaningful in per-memcg reclaim. However, when
that patch was applied the removal of super_fs_objects_eligible() and
its two call sites in super_cache_scan() / super_cache_count() was
lost, so the helper is still gating every ->nr_cached_objects() hook
and 0ef8faff49 is effectively a no-op.
Consequences of the leftover gate:
- XFS's inode-reclaim hook, which is intentionally driven from
per-memcg contexts to free memcg-charged slab, is still
short-circuited in fs/super.c exactly the regression from
commit 0baad6f9b9 ("fs/super: skip non-memcg-aware
nr_cached_objects in memcg slab shrink") that 0ef8faff49 was
written to undo. Memcg-charged XFS inode slab therefore keeps
piling up under per-memcg pressure until global reclaim kicks in.
- Any future ->nr_cached_objects()/->free_cached_objects() that
grows memcg awareness is likewise blocked before it can run, so
filesystems cannot opt in to per-memcg reclaim on their own
defeating the whole point of pushing the gating decision down
into the callbacks.
Drop the leftover helper and its call sites so the intent of
0ef8faff49 actually takes effect.
Link: https://lore.kernel.org/cover.1786955972.git.zhengqi.arch@bytedance.com
Link: https://lore.kernel.org/3b038d373c70ebac7cdabfb0035bb91d1d6e6cfe.1786955972.git.zhengqi.arch@bytedance.com
Link: https://lore.kernel.org/all/20260715103516.2410175-1-usama.arif@linux.dev/ [0]
Fixes: 0ef8faff49 ("fs: push nr_cached_objects memcg gating into individual filesystems")
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Acked-by: Usama Arif <usama.arif@linux.dev>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Fault-around can map ready dropbehind folios without going through the
normal page-cache lookup that clears dropbehind. A mapping represents a
competing cached user, so retain the folio instead of forcibly unmapping
it when writeback completes.
For a mapped folio, folio_unmap_invalidate() can call
unmap_mapping_folio(), which takes i_mmap_rwsem and may sleep. Retaining
mapped folios avoids this path when folio_end_dropbehind() runs in
non-preemptible task context.
Tal was able to trigger a sleeping-in-atomic warning due to this [1].
Unmapped dropbehind folios continue through the existing invalidation path.
Link: https://lore.kernel.org/4aba05e1a2c3b61cb337d373eb9b7a8db4ddd822.1788024049.git.qiwenjie@xiaomi.com
Link: https://lore.kernel.org/076bb01b-6fcf-4691-be8c-0e8507c9fe64@columbia.edu [1]
Fixes: fb7d3bc414 ("mm/filemap: drop streaming/uncached pages when writeback completes")
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Tal Zussman <tz2294@columbia.edu>
Tested-by: Tal Zussman <tz2294@columbia.edu>
Cc: Barry Song <baohua@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
obj_cgroup_charge_pages() resolves the objcg to its memcg and calls
try_charge_memcg(), which does not short circuit the root memcg. That
memcg can be the root memcg: obj_cgroup_is_root() reflects the memcg the
objcg was created for and is never updated, while memcg_reparent_objcgs()
does redirect objcg->memcg to the parent on rmdir. An objcg of a dying
child of root therefore passes every obj_cgroup_is_root() filter but
resolves to the root memcg.
Folios keep the objcg they were charged with, so this is easy to reach
through zswap: allocate anon memory in a cgroup, move the task out, remove
the cgroup, then write to the root cgroup's memory.reclaim. The reclaimed
folios are charged through the reparented objcg and end up in
refill_stock() with the root memcg:
WARNING: mm/memcontrol.c:2198 at refill_stock+0x644/0x940
refill_stock+0x644/0x940
try_charge_memcg+0x12d6/0x1570
__obj_cgroup_charge+0x35/0xf0
obj_cgroup_charge+0x1de/0x210
obj_cgroup_charge_zswap+0x83/0x270
zswap_store+0x1620/0x2000
swap_writeout+0x94c/0x14c0
shrink_folio_list+0x3388/0x52b0
[...]
try_to_free_mem_cgroup_pages+0x30d/0x830
user_proactive_reclaim+0x504/0x840
memory_reclaim+0x1f/0x30
Beyond the warning, the charge is asymmetric: obj_cgroup_uncharge_pages()
skips refill_stock() for the root memcg, so the root's page counter grows
and is never uncharged. It is not user visible, since memory.current is
not exposed on the root, but it is a leak.
Use try_charge(), which returns early for the root memcg, restoring the
symmetry with obj_cgroup_uncharge_pages().
The above sequence was scripted into a standalone reproducer (zswap on,
swap on a virtio disk, 512MB of anon memory faulted in inside a child of
the root cgroup, the task then migrated to the root cgroup, the child
removed, followed by "echo 600M swappiness=max > memory.reclaim" on the
root) and run in a CONFIG_DEBUG_VM=y VM. It reproduces the splat on the
first zswap store of a reparented folio, with the same call chain as the
report. With this patch applied the splat is gone while the zswap store
count over the run is unchanged, so the same path is still exercised.
cgroup selftests test_zswap, test_kmem and test_memcontrol show no new
failures.
Link: https://lore.kernel.org/20260829023251.474083-1-shakeel.butt@linux.dev
Fixes: 20d6c17252 ("memcg: avoid refill_stock for root memcg")
Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu>
Closes: https://lore.kernel.org/all/CA+0ovCgWzUMK+nNbbtH7eV65Ca=fDN4Ozu7iASgryjvv8Tk8zQ@mail.gmail.com/
Reviewed-by: Muchun Song <muchun.song@linux.dev>
Reviewed-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
SWAP_USAGE_OFFLIST_BIT is embedded in the si->inuse_pages usage counter,
and is meant to sit above any value that counter can reach. However, it
is defined from BITS_PER_TYPE(atomic_t), so it is bit 30. On a system
with 4 KiB pages the flag collides with the usage count once that count
reaches 4 TiB.
swap_usage_in_pages() masks bit 30 out, so whenever the real count has
that bit set, every caller of it reads 4 TiB low:
* /proc/swaps understates Used by 4 TiB.
* A raw count of exactly 2^30 masks to zero, so try_to_unuse() takes its
"if (!swap_usage_in_pages(si)) goto success;" early exit and swapoff
tears the device down while pages are still swapped out. Nothing in
the rest of swapoff aborts the teardown, so those pages are lost.
Independently of swapoff, the collision also corrupts the counter and the
plist. On a device in normal use, a free that leaves bit 30 set in the
count makes swap_usage_sub() see the flag where there is only count, and
call add_to_avail_list(). It clears the bit with
fetch_and(~SWAP_USAGE_OFFLIST_BIT), leaving the stored count 4 TiB below
the real one, and calls plist_add() on a device that is already listed,
tripping the WARN_ON(!plist_node_empty(node)) in plist_add() and linking
the node a second time.
Change the definition of SWAP_USAGE_OFFLIST_BIT to be based on
atomic_long_t instead. Note that the usage counter field itself is of
this same type, so it is still a valid bit.
Link: https://lore.kernel.org/20260828191433.3304458-1-nphamcs@gmail.com
Fixes: b228386cf2 ("mm, swap: clean up plist removal and adding")
Signed-off-by: Nhat Pham <nphamcs@gmail.com>
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260825153238.2695446-1-nphamcs%40gmail.com
Suggested-by: Andrew Morton <akpm@linux-foundation.org>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Kairui Song <kasong@tencent.com>
Cc: Baoquan He <baoquan.he@linux.dev>
Cc: Barry Song <baohua@kernel.org>
Cc: Chris Li <chrisl@kernel.org>
Cc: Gregory Price <gourry@gourry.net>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
Cc: Kemeng Shi <shikemeng@huaweicloud.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Youngjun Park <youngjun.park@lge.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
When a VMA is mremap()'d with MREMAP_DONTUNMAP set, that results in the
VMA being copied, but the source VMA not being unmapped.
If the VMA is mlock()'d this is a legal operation, though the source VMA
has its VMA_LOCKED_BIT cleared.
However this is done in dontunmap_complete(), after mm->locked_vm was
incremented via vrm_stat_account(), resulting in double-counting.
Worse, this is not even corrected when source VMA is unmapped, due to the
VMA_LOCKED_BIT flag having been cleared.
This all works fine in the usual mremap() case (without MREMAP_DONTUNMAP),
as the source VMA is unmapped with VMA_LOCKED_BIT intact, at which time
mm->locked_vm is decremented accordingly.
Resolve the issue by invoking vrm_stat_account() only after
dontunmap_complete() has run.
Note that MREMAP_DONTUNMAP requires old_len == new_len, so no need to
account for a delta in size in this case.
The bug was introduced by commit b714ccb02a ("mm/mremap: complete
refactor of move_vma()") which incorrectly reordered the accounting and
the clearing of the VMA_LOCKED_BIT flag.
Link: https://lore.kernel.org/20260828-mremap-fix-locked-vm-v1-1-c80be7505d1e@kernel.org
Fixes: b714ccb02a ("mm/mremap: complete refactor of move_vma()")
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260825-fix-mremap-dontunmap-pgoff-v1-1-39a40b2c98b3@kernel.org
Reported-by: Kunwu Chan <kunwu.chan@gmail.com>
Closes: https://lore.kernel.org/all/20260828094823.594279-1-kunwu.chan@linux.dev/
Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Tested-by: Kunwu Chan <kunwu.chan@gmail.com>
Reviewed-by: Kunwu Chan <kunwu.chan@gmail.com>
Cc: Jann Horn <jannh@google.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
The sysfs THP tuneables at /sys/kernel/mm/transparent_huge_pages/ rather
confusingly only control the behaviour of THP in some instances.
They are not applicable to MADV_COLLAPSE operations, nor to DAX mappings.
Long-term, THP is predicated upon compaction being able to obtain large
folios to populate THP ranges.
However, vm_normal_folio() returns NULL for PFN map mappings, thus their
reference count is maintained by the driver, not core mm.
As a consequence, the folios are not subject to reclaim nor compaction, so
are not truly part of the THP mechanism at all.
However, since commit 5dd40721f1 ("mm: allow THP orders for PFNMAPs")
introduced the ability to establish huge PFN maps, they have been subject
to THP tuneables.
This is incorrect - if a huge PFN map is available (defined by
vma->vm_ops->huge_fault being non-NULL for a VMA_PFNMAP_BIT VMA), then it
should be mapped huge upon fault-in.
Correct this by explicitly checking for this while ensuring that smaps
continues to accurately report THPeligible statistics.
While here, abstract the entire file-backed THP check in
vma_can_map_huge_file(), with sensible separation of logic into helper
functions.
Note that drm_gem_shmem_mmap() and panthor_gem_mmap() establish huge PFN
maps of shmem folios, however they are marked unevictable in
drm_gem_get_pages(), and in any case would fail the reference check in
__remove_mapping() even if they weren't.
Failing to map huge PFN maps has resulted in significant real-world
performance degradation, see links for details.
[ziy@nvidia.com: rename some functions]
Link: https://lore.kernel.org/DL1HIHWYJ7TB.1CY76SJS0V03L@nvidia.com
Link: https://lore.kernel.org/20260827-hugepfn-allowable-orders-v1-1-94819c8807c8@kernel.org
Fixes: 5dd40721f1 ("mm: allow THP orders for PFNMAPs")
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Signed-off-by: Zi Yan <ziy@nvidia.com>
Reported-by: Cedric Le Goater <clg@redhat.com>
Closes: https://lore.kernel.org/linux-mm/20260805055544.1568534-1-clg@redhat.com/
Reported-by: Saravanan D <saravanand@crusoe.ai>
Closes: https://lore.kernel.org/linux-mm/20260821070520.25759-1-saravanand@crusoe.ai/
Reviewed-by: Zi Yan <ziy@nvidia.com>
Tested-by: Saravanan D <saravanand@crusoe.ai>
Tested-by: Lance Yang <lance.yang@linux.dev>
Reviewed-by: SJ Park <sj@kernel.org>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Peter Xu <peterx@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-----BEGIN PGP SIGNATURE-----
iQJKBAABCAA0FiEEzOlt8mkP+tbeiYy5AoYrw/LiJnoFAmqb6gQWHGNoZW5odWFj
YWlAa2VybmVsLm9yZwAKCRAChivD8uImeuBkD/9SNpBtFcumYkl1S3FUSTC8Up5k
8exUSd6bJr/lc5+cPJcY4VZLOus8ueKjJuKXQE0C3Id6Cd8g1MGZUQVGXIWYz2Sx
69z2rhYkE4b386ivNutwCzA7Bjlb/rMZEeDGfEuRe2eVOH2o8ADiLG+ANNUHbpWt
zTbLUiBOFD2sfWL2fSShcBJthYF7QTBh54jlL56HBleWMdq6y4ii7rh1X+6RFgNg
xRi7s/4+FLxh+F+1GOVrPvIuNrqQaTgWVASsmmRE56n66WOFeVgsG4NVi0/i0f9Z
MLHp/QeSx5/OtIhjjt9BkV+0E2tXAUMEOalj0HpaDBxsfAjAFLDt7TRra9BhV+aI
FrEnbIwG809BYAjRO2scf4khtrLofZpIv+STt+vbKjFYEv2Z03x/2JS6Tg9gGmtN
wP1GfzfPgk8FgdbQ4pgT354COYr1Ey+OU1tjNTmmYMYN7WmXmGG9Yx7LfrtvsNU9
ohFeHyTygAcw/bE1/IdWqFK7DP6V5LuOoeOtfuEnRC/SFHdGbr2fvu3dfZSK06kE
CWY9QSF7J8MfLNhgRi4/Q0QxRtdekDyANZezS2uwNv1Hn6Pwt9rXMScMiyWkNSg7
6oltWiIrXx5lMBCHDciNWyAR+mQe3/G8YUPnrpPWsfMcOelvfMN/RWtYWMalevZ5
YY9ufXSCGMQQDBPFDQ==
=SgJ4
-----END PGP SIGNATURE-----
Merge tag 'loongarch-fixes-7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch fixes from Huacai Chen:
- Fix build errors when RUST and KASAN enabled
- fix a typo in comment of vmlinux.lds.S
- fix several bugs in Kprobes, BPF JIT and KVM support
* tag 'loongarch-fixes-7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
perf build: Add clang and rust target flags for LoongArch
LoongArch: KVM: Fix TOCTOU race on pv_features
LoongArch: KVM: Validate MSI data before routing it to EIOINTC
LoongArch: KVM: Preserve memslot arch flags on KVM_MR_FLAGS_ONLY
LoongArch: KVM: Remove unused function kvm_arch_flush_remote_tlbs_memslot()
LoongArch: KVM: Fix resource leak in kvm_loongarch_env_init() error path
LoongArch: KVM: Add unregister helpers for the KVM interrupt devices
LoongArch: KVM: Free init resources if kvm_init() fails
LoongArch: BPF: Fix off-by-one error for insn_is_cast_user()
LoongArch: Avoid preempt count underflow without probe
LoongArch: Do not save/restore percpu base register in rethook trampoline
LoongArch: Remove unused setup_profiling_timer() function
LoongArch: Fix typo "avaliable" in comment of vmlinux.lds.S
LoongArch: Do not select HAVE_RUST when KASAN is enabled
put_chars() runs from the hvc console write path with preemption
disabled, so it asks alloc_buf() for GFP_ATOMIC. Only the data buffer
gets it: the struct port_buffer itself keeps the GFP_KERNEL default, so
the allocation can enter direct reclaim and sleep. A write to /dev/kmsg
on a CONFIG_DEBUG_ATOMIC_SLEEP kernel splats:
BUG: sleeping function called from invalid context at ./include/linux/sched/mm.h:320
in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 1, name: virtme-ng-init
preempt_count: 1, expected: 0
Preemption disabled at:
[<ffffffff813fd90d>] vprintk_emit+0x17d/0x510
Call Trace:
<TASK>
dump_stack_lvl+0x69/0xa0
__might_resched+0x37a/0x4d0
__kmalloc_cache_noprof+0x94/0x5f0
put_chars+0x209/0x3e0
hvc_console_print+0x234/0x640
console_flush_all+0x4fc/0x950
console_unlock+0xbf/0x1b0
vprintk_emit+0x312/0x510
devkmsg_emit+0xba/0x110
devkmsg_write+0x21b/0x2e0
vfs_write+0x4dc/0x9d0
ksys_write+0x108/0x1e0
do_syscall_64+0xfa/0x460
</TASK>
Pass gfp on to that allocation too.
Fixes: fc220d6be3 ("virtio_console: refactor __send_to_port() buffer ownership")
Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Sungho Bae <baver.bae@lge.com>
Tested-by: Florian Westphal <fw@strlen.de>
Link: https://patch.msgid.link/20260810-serial-v1-1-abbe51602c13@debian.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-----BEGIN PGP SIGNATURE-----
iQJPBAABCgA5FiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmqcOFUbFIAAAAAABAAO
bWFudTIsMi41KzEuMTIsMiwyAAoJEMVl1fnXbVg7DwAP/i5lmUS85n22uWD7wkmU
5ocMbdl9cKprtcpi8axR9kbtBIC5bq0j3sUwmiFgR6KI774v7FnxJ3AIrey3GwtF
okiaWLffKOYROCDvmLg36ciSbFGEqjS8lwOPl1geBX7tZhhnGgcV+XRXcMv4ehj8
HiOtjN8a+8kXrYTMB73JhBkzku7Hojb/vA9ZHXeCLjP4nfzlXneqltSQw/+3uVvf
jrLfOX3a1lgLkz0Q7AlfAO7ppXv5msrZYu7E1aILYtLA5K6J6Gh1jyK+Y8OZlvdg
hukhU3mAw2pCV5dg6rAurYWzVhE/tNmKmlg2s1LiW3K1Q2NNSPGvR0ArmAnd9bPY
6ZwoK47m98xuZgIAO7v+ej9LYI3XANGwdupTmrKhQ7shLYtzvSsob7kWRYfjCMWu
UaTGshMsrfMXZNznXm2Ydy1Gmr3TBI2J1HpUFiibRL4XgsQ7u9hLUFwiFUiMEi9V
g9oqTN/1VUMsImADlnrdAf30pLtOe8PHV1naFLdmdl+iCPc9o0cX9X5m2fHWtkpt
Cjz/au8Z0zMVJMIDUZuBgCX4mWNSx7pWYKQYvlGOLQEehXNLRVcY5SnIqRman8WF
gnUPaaTb6KDS+SJjRDPkRH9ihGlNEd2c/tzrxek4/42CF842PGeMvGK06PtPyzxW
LWtmCtBWRArSHUq09NZbboim
=z6qW
-----END PGP SIGNATURE-----
Merge tag 'for-7.3-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba:
- preserve inode compression level when changing attributes
- fix lost wakeup when waiting for a zstd workspace
- fix bio context leaks after ordered extent processing errors
- in send, handle unexpected extents for non-regular inodes
- handle edge case in creation of reloc tree with enabled quotas
- in scrub report the exact failing offset, not the stripe base
- error handling fixes
- error code propagation in send, zoned mode and raid-stripe-tree
- restore active device pointer after seeding device addition error
- transaction abort fixups
- update Chris' email address
* tag 'for-7.3-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
MAINTAINERS: update Chris Mason's email address
btrfs: tests: do not touch page cache if root/inode allocation failed
btrfs: zstd: fix lost wakeup when waiting for a workspace
btrfs: do not force reloc root creation during qgroup_account_snapshot()
btrfs: send: fix lost error return value in will_overwrite_ref()
btrfs: abort transaction before releasing tree_log_mutex on commit failure
btrfs: zoned: propagate do_zone_finish() error in btrfs_zone_finish_endio()
btrfs: zoned: finish active block group cleanup if call_zone_finish() fails
btrfs: send: reject extents for non-regular inodes
btrfs: return proper negative error code for update_raid_extent_item()
btrfs: fix the possible bioc_list memory leak during error
btrfs: fix transaction use-after-free in raid stripe insertion
btrfs: scrub: report the failing sector's address, not the stripe base
btrfs: preserve the compression property when other inode flags change
btrfs: restore active device pointers after failed sprout
btrfs: detach failed sprout device from transaction update list
btrfs: clean up target device if block group marking fails
When cifs_close() defers a close, it hands the cifsFileInfo reference
of the closing struct file to the queued work. Each execution of
smb2_deferred_work_close() drops one such reference.
deferred_close_scheduled can be false while the work is pending: the
workqueue clears PENDING when the callback starts to run, before the
callback clears the flag under deferred_lock. A close in that
interval requeues the running work, and the callback then clears the
flag, leaving the requeued work pending with the flag down. A later
cifs_open() can reuse the handle and its cifs_close() reaches the
same branch: queue_delayed_work() fails because the work is still
pending, but cifs_close() returns without dropping the closing file's
reference. The cifsFileInfo count stays pinned and its tlink, dentry
and server handle are leaked.
Check the return value and hand off the reference only when work was
actually queued. Otherwise, use the shared _cifsFileInfo_put(), like
the mod_delayed_work() branch above: the pending execution already
owns its reference.
This issue was found by an in-house static analysis tool.
Fixes: c3f207ab29 ("cifs: Deferred close for files")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5.6
Co-developed-by: Song Li <songl@zju.edu.cn>
Signed-off-by: Song Li <songl@zju.edu.cn>
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
cifs_oplock_break() takes over the reference that
cifs_queue_oplock_break() acquired when it queued the work, and drops it
with _cifsFileInfo_put() once the break has been processed.
Only in setups with "-o multiuser", cifs_sb_tlink() may fail, at which
point cifs_oplock_break() returns without putting the file reference,
mirroring the reference leak we already fixed in the companion patch to
cifs_queue_oplock_break().
This would trigger a crash due to busy inodes on the next unmount:
BUG: Dentry ... still in use (1) [unmount of cifs cifs]
VFS: Busy inodes after unmount of cifs (cifs)
Drop the reference on that path as well. Doing so before the out label
mirrors the normal path, which also puts the reference before
cifs_done_oplock_break().
Found by Sashiko code review. The failure path was not exercised at
runtime.
Fixes: e8f5f849ff ("cifs: fix potential oops in cifs_oplock_break")
Cc: stable@vger.kernel.org
Assisted-by: Kiro:claude-opus-5
Signed-off-by: Bjoern Doebel <doebel@amazon.de>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>