check_kfunc_arg() allows bpf_register_is_null() for nullable arguments
w/o marking the underlying scalar register precise. Hence a checkpoint
created on such a path would prune against arbitrary scalar value.
Fixes: 3bda08b636 ("bpf: Allow NULL buffers in bpf_dynptr_slice(_rw)")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-5-0f5a360ff15d@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Check that mark_chain_precision() is called for a NULL pointer passed
as a nullable pointer argument of a global subprogram.
(Pointer arguments of the global subprograms are nullable by default).
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-4-0f5a360ff15d@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
check_mem_reg() allows bpf_register_is_null() for nullable arguments
w/o marking the underlying scalar register precise. Hence a checkpoint
created on such a path would prune against arbitrary scalar value.
The argument may live on the stack rather than in a register when a
call has more than MAX_BPF_FUNC_REG_ARGS arguments, hence the new
mark_arg_precision() helper.
Fixes: e5069b9c23 ("bpf: Support pointers in global func args")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-3-0f5a360ff15d@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
check_func_arg() allows bpf_register_is_null() for nullable arguments
w/o marking the underlying scalar register precise. Hence a checkpoint
created on such a path would prune against arbitrary scalar value.
check_helper_call() enforces second parameter of the
bpf_get_local_storage() to be zero, w/o marking the underlying scalar
register precise. Hence a checkpoint created on such a path would
prune against arbitrary scalar value.
Grouping these two into one patch, as they share the same fixes tag.
Fixes: b5dc0163d8 ("bpf: precise scalar_value tracking")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-1-0f5a360ff15d@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Nikhil P. Rao says:
====================
pds_core: fixes for the PCI reset path [part]
Patch 1 is the v2 patch with the pdsc_core_init() and
pdsc_identify_ver() checks removed. Those checks are dead code. commit
cd09971dcc ("pds_core: keep the health thread stopped during reset")
disables health_work across the reset, so the health thread can no
longer reach pdsc_setup() with the BARs unmapped. The only other callers
are probe and pdsc_reset_done(), and both map the BARs earlier in the
same call, so cmd_regs cannot be NULL by the time they get there.
The pdsc_core_init() check is also worse than what it replaces. Its
bail-out jumps to err_out_uninit, which ends up in pdsc_intr_free() and
writes to pdsc->intr_ctrl, also NULL at that point.
On v2 I said I would convert pdsc_identify() and pdsc_core_init() to
pdsc_devcmd_with_data() once the PLDM series landed. Dropping that: the
helper has no read-back path and both callers need one, and giving them
an -ENXIO return means hardening pdsc_intr_free() against a NULL
intr_ctrl on the err_out_uninit path. That is a lot of churn to
deduplicate two call sites.
Patch 2 is the VF pci_release_regions() fix, older than the cmd_regs
race, so it carries its own Fixes tag.
The v2 changelog claim that pdsc_unmap_bars() clears db_pages was wrong.
It clears info_regs, cmd_regs, intr_status and intr_ctrl; db_pages is
never mapped.
v2: https://lore.kernel.org/20260804235946.177762-1-nikhil.rao@amd.com
v1: https://lore.kernel.org/20260729055258.1416225-1-nikhil.rao@amd.com
====================
Link: https://patch.msgid.link/20260901044219.1361466-1-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
pdsc_reset_prepare() and pdsc_reset_done()'s pdsc_map_bars() error path
clear/iounmap cmd_regs without devcmd_lock, and
pdsc_legacy_firmware_update()'s download loop derefs cmd_regs after
dropping and retaking the lock without re-checking. An FLR concurrent
with a devlink flash can unmap cmd_regs under an in-flight devcmd,
causing a NULL deref or a write to unmapped MMIO.
Take devcmd_lock across the BAR unmap/remap, and re-check cmd_regs in
the download loop. Only the PF maps cmd_regs and runs devcmd, so skip
the unmap on a VF, as pdsc_remove() and pdsc_reset_done() already do.
A reset that completes entirely within the unlocked window is not a
correctness problem for the image: the device clears its update session,
so a resumed download is rejected, and it verifies the staged image
before writing a flash slot, reporting PDS_RC_BAD_FW rather than
activating it.
pdsc_unmap_bars() also clears info_regs, intr_status and intr_ctrl. The
interrupt and start/stop readers of those are quiesced before the unmap
by pdsc_fw_down(), which frees the interrupts and tears down the queues.
The debugfs readers are not, since those files outlive a reset; that is
pre-existing and out of scope here.
Fixes: e96094c1d1 ("pds_core: Clear BARs on reset")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260708212222.296202-1-nikhil.rao%40amd.com?part=3
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Link: https://patch.msgid.link/20260901044219.1361466-2-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Jamal Hadi Salim says:
====================
net: cap tx_queue_len at S16_MAX to prevent oversized ring allocations
An unprivileged user (via unshare -Urn) can set a huge tx_queue_len
and exhaust global memory through ring allocations sized from it
(pfifo_fast skb_arrays, tun/tap ptr_rings).
The reproducer from vega@nebusec.ai set the following params for
illustration: txqlen of 500000 -> ~32 GiB/ring attempts, 1.6 GB tun,
~960 MB tap. Gets worse when you consider qdiscs like mq.
What we fix: every path an unprivileged user can use to install
an oversized tx_queue_len is rejected with -ERANGE before any ring is
allocated; per-ring memory is bounded at 256 KiB.
This is for you sashikos: What we deliberately _do not fix_
bound the NUMBER of rings. With the cap in place the worst case moves
from "one knob" to the aggregate of ring x queues x devices, example:
ip link add v0 numtxqueues 4096 txqueuelen 32767 type veth
tc qdisc add dev v0 root mq
-> 4096 * 3 * 32767 * 8 = ~3.0 GiB (one command)
50 tun devices x 256 queues x 32767 x 8 = ~3.1 GiB
Unfortunately tx_queue_len is a bit ambigious in meaning:
In some cases it means a ring size (which is pre-allocated, ex:
tun, tap, and pfifo_fast); a cap of 4096 seems reasonable here.
but in other cases it is used to indicate a queue limit ex:
the qdisc consumers that allocate nothing (pfifo/bfifo/gred/plug/sfb,
htb direct_qlen, qfq, teql). 32767 is a legitimate high-BDP queue
length, so we are going to keep that value.
Getting back to you sashikos, after this is merged and shows up
in net-next we will send followup patches as follows:
this series is not misread as "closes the OOM class"):
a) Per-site ring limits at six identified locations
- pfifo_fast init/resize,
- tun attach/resize,
- tap minor/resize)
if you can spot more in your review we will take care of those as well.
b) memcg accounting (GFP_KERNEL_ACCOUNT) for those ring
allocations: contains a memcg-limited container's ring memory.
Not GFP_KERNEL_ACCOUNT has no effect on the unshare attacker
but will protect against containers (memory.max in its cgroup)
====================
Link: https://patch.msgid.link/QDISC-2899.v2.20260901233641@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Add nine test cases for the S16_MAX tx_queue_len cap to the
pfifo_fast suite. Netlink cases exercise the ifla_policy bound
(2/3); the two new sysfs cases exercise the netif_change_tx_queue_len()
choke point that 1/3 owns (SIOCSIFTXQLEN shares it; the ioctl is not
portably reachable from tdc):
- dbe3: set txqueuelen 32767 (S16_MAX) - accepted, pins the exact
boundary value.
- b50e: set txqueuelen 32768 - rejected with -ERANGE.
- 40f8: write 32768 to /sys/class/net/*/tx_queue_len - rejected
(covers patch 1/3 directly; netlink cannot reach this path).
- 4b6e: write 32767 via sysfs - accepted, boundary positive control
for the patch-1 path.
- b90d: create a dummy with txqueuelen 32767 - accepted.
- 57ab: create a dummy with txqueuelen 32768 - rejected at netlink
parse time.
- e777: create a dummy with txqueuelen 500000 - rejected (the v1
bypass path flagged by review).
- 31ac: create a veth with an oversized txqueuelen on the peer nest -
rejected (the peer nest is parsed against ifla_policy too).
- b567: create a veth with txqueuelen on both ends within the cap -
accepted (positive control for the peer nest).
The three negative-creation verifies assert device absence
("ip -o link show" must not contain the device), not merely absence
of a qlen pattern - the device does not exist when creation fails, so
the exit code carries the signal and the verify adds content.
The v1 04b5 "resize rollback" case is dropped: with the cap checked
first, netif_change_tx_queue_len() returns -ERANGE before the write,
the notifier or any qdisc resize, so the case exercised no resize and
no rollback. It was also nondeterministic: pre-patch, the resize
issues three ~11 MB kvmallocs for qlen 500000 which normally succeed,
so the case passed on an unfixed kernel only under memory pressure -
its outcome depended on the test host's free memory.
Test commands run inside the netns, but nsPlugin creates the veth
peer in the root namespace, so the teardown deletes the in-ns end
only; deleting the peer via the pair is implicit.
Note: iproute2 treats "txqueuelen" appearing after "type X" as a
link-type attribute and silently drops it, so the creation cases
place it before "type" to actually reach the kernel.
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-2899.v2.20260901233641@mojatatu.com.3
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
rtnl_create_link() assigns IFLA_TXQLEN directly to dev->tx_queue_len
without going through netif_change_tx_queue_len(), so a device created
with "ip link add ... txqueuelen 500000" bypasses the S16_MAX cap and
still triggers the oversized ring allocations in pfifo_fast, tun and
tap. The veth peer nest (rtnl_nla_parse_ifinfomsg()) and the
RTM_NEWLINK-on-existing-device path reach the same sinks.
Enforce the cap in ifla_policy instead: IFLA_TXQLEN becomes
NLA_POLICY_FULL_RANGE(NLA_U32, &txqlen_range) with
txqlen_range = { .min = 0, .max = S16_MAX }. All netlink consumers
parse against this policy - rtnl_setlink(), rtnl_newlink() (create
and change), and the veth peer nest - so every netlink path is capped
at parse time and rejects the attribute with -ERANGE plus a proper
"integer out of range" extack message before any device state is
modified (the RTM_SETLINK half-application wart is gone with it).
Document the bound in the rt-link.yaml netlink spec.
Conditions to recreate the bug:
- CONFIG_NET_SCHED=y, CONFIG_VETH=y, CONFIG_USER_NS=y, CONFIG_NET_NS=y.
- Unprivileged user in a fresh user+net namespace (unshare -Urn):
ip link add v0 txqueuelen 500000 type veth peer name v1
-> on the fixed kernel this is rejected with -ERANGE ("integer out
of range" extack) instead of installing an oversized tx_queue_len
that later inflates pfifo_fast/tun/tap ring allocations.
- ip link set v0 txqueuelen 500000 is likewise rejected at parse time.
Fixes: 38f7b870d4 ("[RTNETLINK]: Link creation API")
Reported-by: Vega <vega@nebusec.ai>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-2899.v2.20260901233641@mojatatu.com.2
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Several subsystems allocate ring buffers sized by dev->tx_queue_len
with no upper bound. An unprivileged user (via unshare -Urn) can set a
huge tx_queue_len and exhaust global memory with ring allocations:
- pfifo_fast: pfifo_fast_init() and pfifo_fast_change_tx_queue_len()
allocate 3 skb_array rings of tx_queue_len entries each.
- tun: tun_queue_resize() and the queue-attach path resize ptr_rings
to tx_queue_len on the NETDEV_CHANGE_TX_QUEUE_LEN notifier.
- tap (macvtap/ipvtap): tap_queue_resize() and tap_init() resize/init
ptr_rings to tx_queue_len on the same notifier.
netif_change_tx_queue_len() is the single entry point for IFLA_TXQLEN,
sysfs, and the SIOCSIFTXQLEN ioctl. Cap new_len at S16_MAX (32767)
there so the oversized value is rejected at set time. This takes
effect whether the device is up or down, before dev->tx_queue_len is
written, before any notifier fires, and before any ring is allocated.
The "> S16_MAX" check also subsumes the previous unsigned-long
truncation test, and a negative ifr_qlen from the ioctl lands far
above the cap after conversion, so both old failure modes are covered
by the one comparison.
tx_queue_len is ambigious: both a per-ring sizing multiplier and a
default queue-length/limit knob for consumers that allocate
nothing at set time (pfifo/bfifo/gred/plug/sfb limits, htb
direct_qlen, qfq max_classes, teql). 32767 is chosen as the largest
value NLA_POLICY_FULL_RANGE can express for the u32 IFLA_TXQLEN
policy in patch 2/3 while staying a legitimate queue length on
high-BDP paths; the ring-memory trade-off of a shared knob is
disclosed below.
Conditions to recreate the bug:
- CONFIG_NET_SCHED=y, CONFIG_VETH=y, CONFIG_USER_NS=y, CONFIG_NET_NS=y.
- Unprivileged user in a fresh user+net namespace (unshare -Urn).
- pfifo_fast: create veth pairs, set tx_queue_len to 500000, attach
mq+pfifo_fast. ~28 iterations OOMs a 2GB guest.
- tun: create 50 tun devices with IFF_MULTI_QUEUE, set tx_queue_len to
500000, open 8 queues each. ~1.6GB of ptr_ring allocations OOMs a
512MB guest.
- tap: same as tun with IFF_TAP. ~960MB OOMs a 512MB guest.
- On the fixed kernel the oversized tx_queue_len is rejected with
-ERANGE at set time (all four paths: RTM_SETLINK, RTM_NEWLINK
create, sysfs, ioctl - the latter two via this check, the former
two via this check and the 2/3 parse policy respectively).
Fixes: 6a643ddb56 ("net: introduce helper dev_change_tx_queue_len()")
Reported-by: Vega <vega@nebusec.ai>
Closes: https://lore.kernel.org/netdev/20260828121902.66837-1-jhs@mojatatu.com/
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/QDISC-2899.v2.20260901233641@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The commit cited in the Fixes tag allowed VXLAN FDB entries to point to
FDB nexthops so that overlay traffic could be load balanced across
multiple VTEPs. Such entries can only be configured from user space,
cannot be learned and cannot roam. They only make sense with a user space
control plane such as E-VPN where data plane learning is disabled.
Despite that, the VXLAN driver does not currently prevent such entries
from being configured with the "dynamic" flag. The per-nexthop FDB list
is only protected by the per-device hash lock, which is not sufficient
when two VXLAN devices point to the same FDB nexthop and therefore share
the list. Aging runs in softirq context without RTNL, so an entry deleted
by one device can race with an addition or deletion from the other,
leading to list corruption:
list_del corruption. next->prev should be ffff8881069d9548, but was
dead000000000122. (next=ffff8881069d9448)
WARNING: CPU: 0 PID: 90 at lib/list_debug.c:65
__list_del_entry_valid_or_report+0x1aa/0x210
...
vxlan_fdb_destroy+0x5b8/0xad0
vxlan_cleanup+0x328/0x450
call_timer_fn+0x2a/0x1c0
run_timer_softirq+0x18c/0x210
BUG: KASAN: slab-use-after-free in vxlan_fdb_destroy
Fix this by rejecting the bogus configuration of dynamic FDB entries that
point to FDB nexthops, both when created and when an existing entry is
updated. As such, the per-nexthop FDB list is only ever mutated under the
RTNL lock. Add test cases to make sure that this does not regress in the
future.
Fixes: 1274e1cc42 ("vxlan: ecmp support for mac fdb entries")
Suggested-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Seungwon Bae <qotmddnjs@ajou.ac.kr>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260902155956.296699-1-qotmddnjs@ajou.ac.kr
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
dmb->cpu_addr was allocated via folio_alloc(). Use folio_put() instead of
kfree() in the error exit of ism_alloc_dmb() to avoid slab allocator
corruption.
While at it, reset dmb->cpu_addr after folio_put to avoid unintentional UAF
by future callers.
Fixes: 83781384a9 ("s390/ism: Properly fix receive message buffer allocation")
Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Reviewed-by: Gerd Bayer <gbayer@linux.ibm.com>
Link: https://patch.msgid.link/20260902143733.433574-1-wintera@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
In case dibs_loopback_init() fails, e.g. because of -ENOMEM, dibs_init()
must unregister dibs_class. Otherwise dibs_class and /sys/class/dibs exist
even though the functionality is not available. A retry to load the module
fails with -EEXIST.
Unregister dibs_class in the error path of dibs_init.
Note that before
commit ad3dfa80be ("dibs: change dibs_class to a const struct")
class_destroy(dibs_class) is required instead of
class_unregister(&dibs_class).
Fixes: 8047373498 ("dibs: Create class dibs")
Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Link: https://patch.msgid.link/20260902143438.426664-1-wintera@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
The 0xffff length sentinel detects a router reboot and schedules
re-enabling of ethernet mode, but then falls through to the rest
of the loop body. The next check is
} else if (len > CX82310_MTU) {
which is the else of the just-matched if -- it never fires for
len == 0xffff. The MTU bound that normally caps the
incomplete-packet save path is silently bypassed.
With 0xffff > skb->len always true (rx_urb_size is 4096), the
incomplete-packet branch saves dev->partial_len = skb->len bytes
into dev->partial_data. partial_data is kmalloc(hard_mtu) =
kmalloc(CX82310_MTU + 2) = 1516 bytes, but skb->len after the
2-byte header pull can be up to 4094. A device that sends a
4096-byte URB starting with [0xff 0xff] therefore copies 4094
device-provided bytes into a buffer allocated for 1516 bytes,
exceeding its requested size by 2578 bytes.
The next URB then reads dev->partial_len (4094) back from the same
1516-byte buffer and dev->partial_rem (65535 - 4094 = 61441) from
the new URB's ~4KB skb, both well past their allocations, and
delivers the spliced result as a 64KB "frame" to the network
stack.
Bail out of rx_fixup after scheduling the re-enable work; the
remainder of a reboot-marker URB is not meaningful packet data.
This restores the invariant that partial_len < CX82310_MTU + 2 on
the save path, since every other route there has already passed
the MTU check.
Fixes: ca139d76b0 ("cx82310_eth: re-enable ethernet mode after router reboot")
Signed-off-by: Jason Winter <jjx@live.nl>
Link: https://patch.msgid.link/BESP194MB283265DDDC63B6B78D8D34FBB8B72@BESP194MB2832.EURP194.PROD.OUTLOOK.COM
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
skb_mpls_push() records the pre-encapsulation network header once, gated
on !skb->inner_protocol. skb_mpls_pop() never clears that record, so it
outlives the encapsulation it describes.
Open vSwitch can then re-push MPLS onto a packet whose
inner_network_header still points at the older, deeper offset: push a
label, pop every label, recirculate (ovs_flow_key_update() re-derives
key->eth.type and resets network_header, but leaves inner_*), then push
again. ovs_fragment() trusts the record:
skb->network_header = skb->inner_network_header;
so skb_network_offset() goes negative. The bound check is signed:
if (skb_network_offset(skb) > MAX_L2_LEN)
a negative offset passes it, and prepare_frag() widens the value:
unsigned int hlen = skb_network_offset(skb);
memcpy(&data->l2_data, skb->data, hlen);
which is a ~4GiB memcpy out of a 30-byte per-CPU buffer.
Reproduced on v7.3-rc1. RDX is the truncated length, (unsigned int)(-8):
BUG: unable to handle page fault for address: ffffe8ffffc16000
#PF: supervisor write access in kernel mode
Oops: 0002 [#1] SMP KASAN NOPTI
RIP: 0010:memcpy+0x8/0x20
RDX: 00000000fffffff8 RSI: ffff888105d732db RDI: ffffe8ffffc16000
prepare_frag+0x3df/0x4e0
ovs_fragment+0x589/0x7e0
do_output+0x4ce/0x5e0
do_execute_actions+0x55d2/0x7b30
ovs_execute_actions+0xea/0x450
Same root-cause shape as commit 975b5b067f ("ipv6: sr: restore network
header before routing and forwarding"): a stale network header offset
reaching a consumer that widens it. Here it originates in the MPLS
push/pop path.
Clear inner_protocol once the packet is no longer MPLS, so a later push
re-records the current header. net/sched/act_mpls.c is the only other
skb_mpls_pop() caller and gets the same fix; sch_frag.c saves and
restores inner_protocol around fragmentation in the same way OVS does.
Fixes: 48d2ab609b ("net: mpls: Fixups for GSO")
Cc: stable@vger.kernel.org
Signed-off-by: Fourie Zhang <fouriezhang@tencent.com>
Acked-by: Jiri Benc <jbenc@redhat.com>
Link: https://patch.msgid.link/20260902092719.2874481-1-fouriezhang@tencent.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Commit 061b9bedbe ("ionic: Rework Tx start/stop flow") replaced
ionic_maybe_stop_tx() with netif_txq_maybe_stop() to get the memory
barriers around the stop/start bits right, but did not cover the stop
in ionic_tx() added by commit 138506ab24 ("ionic: Check stop no
restart"). Convert the remaining site.
netif_txq_maybe_stop() requires the ring indexes to be updated before
it is invoked, so the post has to come first. But ring_dbell comes
from __netdev_tx_sent_queue(), which runs after that and reads the
stop bit, so it is not known in time to pass to ionic_txq_post(). Post
without the doorbell and ring it separately.
The stop condition is unchanged. The re-check only clears the stop bit
when space has become available, so the doorbell starvation fixed by
commit 138506ab24 ("ionic: Check stop no restart") cannot recur.
Fixes: 138506ab24 ("ionic: Check stop no restart")
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Reviewed-by: Brett Creeley <brett.creeley@amd.com>
Link: https://patch.msgid.link/20260901055627.1373129-1-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Some firmware versions leave MCSX_MIL_GLOBAL bit 5 set on boot.
If the bit is already set when the driver attempts X2P calibration,
the hardware sees no rising edge and calibration never triggers.
Clear the bit and wait briefly before starting calibration to ensure
a clean rising edge.
Fixes: ca7f49ff88 ("octeontx2-af: cn10k: Introduce driver for macsec block.")
Signed-off-by: Nitin Shetty J <nshettyj@marvell.com>
Signed-off-by: Viswajith Murali <viswajithm@marvell.com>
Link: https://patch.msgid.link/20260901094318.1395356-1-nshettyj@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Sashiko reported a bug [1] that br_multicast_del_port_group unlists the
port group not using proper rcu helper that preserves the next pointer and
after that immediately frees the port group without waiting for rcu grace
period. The only rcu walker of mglist is br_multicast_list_adjacent() and
it turns out that function has always been buggy because mglist was never
properly converted to RCU. Fix it by converting it to rcu and moving its
initialization after eth_addr's. Initializing p->next can use
RCU_INIT_POINTER because we have a barrier from the hlist_add_head_rcu call
later, besides we're initializing an unpublished structure anyway.
[1] https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260826014200.362304-1-littleddfu%40gmail.com
Fixes: 07f8ac4a1e ("bridge: add export of multicast database adjacent to net_dev")
Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260903093851.1494297-1-razor@blackwall.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Three drivers have shipped a get_rxnfc() which dumps its entire rule
table into rule_locs, reading rule_cnt as "how many rules do I have"
rather than "how many entries did the caller allocate". Nothing in the
callback's documentation contradicted that reading. The distinction only
matters because the ioctl lets an unprivileged caller pick rule_cnt
directly, so getting it wrong is a heap overflow rather than a truncated
dump.
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260903032611.3000029-6-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
mv88e6xxx_get_rxnfc() uses rxnfc->rule_cnt as the write index while
dumping the policy IDR, clobbering the input value before it has been
looked at. That input is the number of entries the caller had room for.
ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN and the ioctl sizes the
buffer from the rule_cnt userspace passes in, so once an admin has
installed policy rules any user can ask for fewer slots than there are
rules and run off the end of the allocation. A rule_cnt of 0 leaves the
buffer pointer NULL and the walk dereferences it.
Count into a local so the caller's limit survives the walk, and stop with
-EMSGSIZE once it is reached.
Fixes: da7dc87553 ("net: dsa: mv88e6xxx: add RXNFC support")
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260903032611.3000029-5-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
nfp_net_fs_add() replaces an existing rule by deleting it from the
hardware, decrementing nn->fs.count and programming the new one. If
nfp_net_fs_add_hw() fails the old entry stays on nn->fs.list - only the
success path reaches list_replace() - so the list is one longer than
nn->fs.count, and it advertises a rule whose hardware entry has already
been torn down.
nn->fs.count is what ETHTOOL_GRXCLSRLCNT reports, so userspace then sizes
its buffer one entry short of what the GRXCLSRLALL walk wants to write.
That used to overwrite one u32 past the allocation; since the walk is
bounded it is a permanent -EMSGSIZE instead, as nothing ever resyncs the
counter.
Fixes: 9eb03bb1c0 ("nfp: add ethtool flow steering callbacks")
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260903032611.3000029-4-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
nfp_net_get_fs_loc() dumps every entry of nn->fs.list into rule_locs[]
without consulting cmd->rule_cnt, which is how many entries the caller
had room for. ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN and the
ioctl sizes the buffer from the rule_cnt userspace passes in, so once an
admin has installed flow steering rules any user can ask for fewer slots
than there are rules and run off the end of the allocation. A rule_cnt
of 0 leaves the buffer pointer NULL and the walk dereferences it.
Bail out with -EMSGSIZE when the buffer fills up, the way the other
ntuple capable drivers do, and report how many locations were filled so
a shrinking rule list does not leave the caller reading stale slots.
Reported-by: VEGA <vega@nebusec.ai>
Fixes: 9eb03bb1c0 ("nfp: add ethtool flow steering callbacks")
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260903032611.3000029-3-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
bcm_sf2_cfp_rule_get_all() walks the whole cfp.unique bitmap into
rule_locs[] without consulting nfc->rule_cnt, which is how many entries
the caller had room for. ETHTOOL_GRXCLSRLALL requires no CAP_NET_ADMIN
and the ioctl sizes the buffer from the rule_cnt userspace passes in, so
once an admin has installed CFP rules any user can ask for fewer slots
than there are rules and run off the end of the allocation. A rule_cnt
of 0 leaves the buffer pointer NULL and the walk dereferences it.
Fixes: 7318166cac ("net: dsa: bcm_sf2: Add support for ethtool::rxnfc")
Reviewed-by: Jonas Gorski <jonas.gorski@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260903032611.3000029-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
In bond_do_alb_xmit() and rlb_arp_xmit(), make sure to unclone
skb head via skb_cow_head() before modifying the source MAC address
(Ethernet header and ARP payload) to avoid silent corruption if
the skb is shared or cloned. Avoid caching the header pointers
across skb_cow_head().
In rlb_arp_xmit(), only modify arp->mac_src if it differs from
tx_slave->dev->dev_addr to avoid an unnecessary copy and head
reallocation.
Also, we should not assume mac header is set in output path.
Use skb_eth_hdr() instead of eth_hdr() to fix the issue,
and remove now redundant skb_reset_mac_header() calls.
Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn>
Cc: Jay Vosburgh <jv@jvosburgh.net>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/20260903143940.1180513-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
remove_nh_grp_entry() prints the extack message when a listener fails
to replace the reduced nexthop group. However, extack is not
initialized and listeners are not required to set a message when
returning an error. Neither netdevsim nor mlxsw do so when an
allocation fails, resulting in the dereference of an uninitialized
stack pointer.
Fix by zero-initializing extack, as was done in commit 6347c5314c
("nexthop: initialize extack in nh_res_bucket_migrate()").
Fixes: 833a1065ee ("nexthop: Emit a notification when a nexthop group is reduced")
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260903080259.10378-1-idosch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stefan Schmidt says:
====================
pull-request: ieee802154 for net 2026-09-03
Zhiling Zou fixed a NULL deref when coming from a TUN device.
Fan Wu fixed a UAF in the cc2520 driver.
Chenguang Zhao fixed up some out of date comments in 6lowpan.
David Carlier fixed a potential double free in the hwsim driver.
Ibrahim Hashimov reworked the queuing in the RX path to fix a UAF on beacon
and MAC frames.
* tag 'ieee802154-for-net-2026-09-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wpan/wpan:
mac802154: fix use-after-free of sdata via queued RX frames
ieee802154: hwsim: serialize pib updates to fix double-free
ieee802154: 6lowpan: fix NULL dereference in lowpan_newlink
ieee802154: cc2520: fix FIFOP work use-after-free
net: 6lowpan: fix mismatched comments
====================
Link: https://patch.msgid.link/20260903093012.4032586-1-stefan@datenfreihafen.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
core:
- Fix drm_crtc_commit leak when PAGE_FLIP_EVENT is used,
dma-buf:
- Publish the dma-buf only after copy_to_user succeeds
- fix some kernel-doc warnings
atomic-state-helpers:
- set pixel_blend_mode to prop default on reset
sysfb:
- Fix integer overflow
- fix constant comparison bug
pagemap:
- Prevent double migration of device pages
- Reset migration page count on eviction retry
- dma-unmap pages before handling migration errors
- use after free fixes
prime:
- fix prime exports tracing
amdgpu:
- Fix for drm_amdgpu_info_device with mixed 64 bit kernel and 32 bit userspace
- plane blend mode fixes
- SR-IOV fix
- GFX8 fix
- MES queue reset fix
- GPUVM fixes
- DCN 6 warning fix
- DCN 3.5/3.6 fix
- DML fix
- Backlight fix
- Colorop fix
- DC get_estimated_bw() fix
- devcoredump fix
- Userq fixes
- APU PSP fix
- Cursor fix
amdkfd:
- MES queue eviction fix
- MQD debugfs fix
xe:
- oa uapi error handling fix
- drm info message to report FLAT_CSS base misalignment.
i915:
- Drop an accidentally duplicated panel fitter call in DP MST
- Fix DDI clock programming for Cx0 and LT PHY
- Fix PTL CDCLK handling at probe, causing a glitch
- Fix dg2_power_well_count() return type
- Fix a NULL pointer deref at forced probe
- Fix selective fetch disable
amdxdna:
- out-of-bounds access fix
- reject commands chains with no commands
- handle chained mapping BO failures
- refuse to flush an imported BO
ethosu:
- handle mmio mapping failures
- handle storage modes only on hardware that supports it
- fix job completion fence cleanup
fastrpc:
- Publish the dma-buf only after copy_to_user succeeds
gud:
- Improve TV modes and rotation handling
nouveau:
- use-after-free fixes
- add missing scanline position support
- HDMI and DP fixes
- null pointer dereference fix
- dmem accounting fixes for large folios
- use write-combined maps for coherent
qaic:
- out-of-bounds access fix
tegra:
- Add blend mode properties
virtio:
- exit path and error handling fixes
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmqbH88ACgkQDHTzWXnE
hr7stA//SAJOADL8CuoBzSyAX7zoqhVErYk798+4r5tPFJ5CzjkZVxGRGur7XWbm
atezEEKaMTEz2BDVb1JDNRI1X1Yq9GtfWM860hUXmYHCegeO49B9lDnS1v0HZweD
PQvPhCqvJpOOF6D8sjYFjVNvi0OrY0JVRlzsnMNmTIlw0xbg01lqn/oWgRA7qdvq
Zo1k1yEPlK3jV2YuX674n7NoioFqeiSWBo9PzIX+yghagg2LrrS1Plx4RFA/B6bm
Czt/x7WPE7lvoZqyDGBwlAY/dta3bagCFkGoDwb2Q1B3MjYXKcKBS0aGL9PyOgu/
/9dNqvR4aDu9CXvNwb3kNbqjJL7DdFBCzwm78PNc43TizkR4WXCBXCNxJOf93e6h
Bwx0GamXQJeGI6xNvQpEssUxezuS3wdoNZ0Rbk3nxMXlvf7OB/sgwkNYVCNKkk/V
dSMOr1XB9pBGmtuWFPOf1kq/is4P4Ns/m8Rutfp5SBJNU9Air5ECblRNNkqFuOtS
582QAM+7xp6zIbepWALu8TTNQMsNKlDwiNc3JOH3Ks3wZ0wExXMTIaSJ7NHOxYj/
B9gWEN+g1LreFHDaCzR1xRetO1bIHNGMNhuqChXj8K8vuDoVPP8FAvKzKEy/iyIl
CRQXLPSV8LjqKL5d5YW3QFvwUSwJwGr3fXCWd1Voo26dL4DOEx0=
=vHdE
-----END PGP SIGNATURE-----
Merge tag 'drm-fixes-2026-09-05' of https://gitlab.freedesktop.org/drm/kernel
Pull drm fixes from Dave Airlie:
"Lots of scattered fixes: nouveau has a bunch of display fixes for
blackwell GPUs that should mean we light up monitors properly and fix
some desktop rendering problems, amdgpu and intel display changes as
usual.
There also changes to the core pagemap, then the usual amouny of AI
inspired validation fixes.
core:
- Fix drm_crtc_commit leak when PAGE_FLIP_EVENT is used
dma-buf:
- Publish the dma-buf only after copy_to_user succeeds
- fix some kernel-doc warnings
atomic-state-helpers:
- set pixel_blend_mode to prop default on reset
sysfb:
- Fix integer overflow
- fix constant comparison bug
pagemap:
- Prevent double migration of device pages
- Reset migration page count on eviction retry
- dma-unmap pages before handling migration errors
- use after free fixes
prime:
- fix prime exports tracing
amdgpu:
- Fix for drm_amdgpu_info_device with mixed 64 bit kernel and 32 bit
userspace
- plane blend mode fixes
- SR-IOV fix
- GFX8 fix
- MES queue reset fix
- GPUVM fixes
- DCN 6 warning fix
- DCN 3.5/3.6 fix
- DML fix
- Backlight fix
- Colorop fix
- DC get_estimated_bw() fix
- devcoredump fix
- Userq fixes
- APU PSP fix
- Cursor fix
amdkfd:
- MES queue eviction fix
- MQD debugfs fix
xe:
- oa uapi error handling fix
- drm info message to report FLAT_CSS base misalignment
i915:
- Drop an accidentally duplicated panel fitter call in DP MST
- Fix DDI clock programming for Cx0 and LT PHY
- Fix PTL CDCLK handling at probe, causing a glitch
- Fix dg2_power_well_count() return type
- Fix a NULL pointer deref at forced probe
- Fix selective fetch disable
amdxdna:
- out-of-bounds access fix
- reject commands chains with no commands
- handle chained mapping BO failures
- refuse to flush an imported BO
ethosu:
- handle mmio mapping failures
- handle storage modes only on hardware that supports it
- fix job completion fence cleanup
fastrpc:
- Publish the dma-buf only after copy_to_user succeeds
gud:
- Improve TV modes and rotation handling
nouveau:
- use-after-free fixes
- add missing scanline position support
- HDMI and DP fixes
- null pointer dereference fix
- dmem accounting fixes for large folios
- use write-combined maps for coherent
qaic:
- out-of-bounds access fix
tegra:
- Add blend mode properties
virtio:
- exit path and error handling fixes
* tag 'drm-fixes-2026-09-05' of https://gitlab.freedesktop.org/drm/kernel: (83 commits)
drm/xe/vram: report FLAT_CCS base misalignment
MAINTAINERS, mailmap: use Aditya Garg's linux.dev account
drm/amd/display: use plane color_mgmt_changed to track colorop changes
drm/amdgpu/userq: fix struct drm_amdgpu_info_device padding for 32bit compile
drm/amd/display: Fix cursor disable with horizontally split planes
drm/amdgpu/userq: dont overwrite the error of subsequent map call
drm/amdgpu: Skip accessing psp rum time db for APUs
drm/amdgpu: update the fw version for gfx12 userqueues
drm/amdgpu: update the fw version for gfx11 userqueues
drm/amdgpu: fix byte/dword unit mismatch in coredump IB dump
drm/amdkfd: fix scope of mqd_mgr dereference in pqm_debugfs_mqds
drm/amd/display: fix division by zero in get_estimated_bw()
drm/amd/display: use halving distribution for all encode-to-linear curves
drm/amd/display: Fix backlight control for luminance-capable OLED
drm/amd/display: Remove const Qualifier From Non-Pointer Fields
drm/amd/display: Set gpuvm min page size to 4K on dcn35/36
drm/amd/display: Fix DCN5/6 DML2 compilation warnings
drm/amdgpu: fix Idle BOs list in VM debugfs status info
drm/amdgpu: use AMDGPU_GPU_PAGE_SHIFT instead of PAGE_SHIFT
drm/amdgpu: Update queue reset support version
...
- Disable interrupts during page-table walk in show_pte()
- Fix kexec_file_load() with 52-bit capable kernels on machines without
52-bit addressing
- Fix MIDR matching in CPU errata handling for KVM guests
- Avoid reading MTE-specific ID registers when MTE support is disabled
-----BEGIN PGP SIGNATURE-----
iQFEBAABCgAuFiEEPxTL6PPUbjXGY88ct6xw3ITBYzQFAmqayVUQHHdpbGxAa2Vy
bmVsLm9yZwAKCRC3rHDchMFjNIG6B/47THEr7Wqq00c1s7loGtwGJiN8dMcfSMpp
r86zeLL37erJQ9K/OeaUFR0bQEgfh7gXSqXXJ8N1wqAObrAfzek7X0lxxXMkVz4p
tpNPFgEgP9jwvtYbKH2W9apmP8xxT7MJHF/FnLQVkdVdJBBU+nmrpYcEz37e7O6a
PmSdl4grWL6AG/CifSCnGvyVFsWVzLeaDgJSAXQWgalefZJzar8dki6W7HfZULo0
I9uizj52+lG2tVpIz6MUcy9k1cwOyTDl061qrD4/oD6aC67U6aS3tRPmwX3qKF7a
rvuwEBwRckmKoK1bxzd3wjzkEH/Urhom1Op8SwJ72s1ex6m5EUJ4
=QWAE
-----END PGP SIGNATURE-----
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon:
"Nothing Earth-shattering, but worthwhile fixes nonetheless:
- Disable interrupts during page-table walk in show_pte()
- Fix kexec_file_load() with 52-bit capable kernels on machines
without 52-bit addressing
- Fix MIDR matching in CPU errata handling for KVM guests
- Avoid reading MTE-specific ID registers when MTE support is
disabled"
* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: Don't read GMID_EL1 when MTE is disabled
arm64: errata: pass REVIDR when matching target implementation CPUs
arm64: trans_pgd: clone only the linear map that exists at runtime
arm64: mm: Fix the lockless page-table walk in show_pte()
use-after-free fix (marked for stable) and a patch that eliminates
the last use of PageWriteback macro in the tree.
-----BEGIN PGP SIGNATURE-----
iQFHBAABCgAxFiEEydHwtzie9C7TfviiSn/eOAIR84sFAmqa/nETHGlkcnlvbW92
QGdtYWlsLmNvbQAKCRBKf944AhHzi7qLB/4gfbxdP5lystLHoDbwSo+ceM15Apl+
THXVTBGspHNe5w07/fk1NfSk8KccqN66cCh9W23JMZt2PQr+n5/0Azp+ZkcL+koO
CNNhvachvs+E3J5cRNHvvP3PCQurOO0tCO4vGGHRt6j3VTrWdwKkgVHGHu2hZ49q
GLkm82eUKYkZdV80FV31q1ZdXHQBCAuxkBgRQNbqlc9yj3OA6UoxLsAaB3uxvmKq
sifdvIyWFt/+SdntzoM6Dt4vo6P0/RiQJdIXKLj+fxHFiJEeX0IJaTpZvA7FOHOt
DyRMhb3lTzQBDjZydNQO15XcjfifskuqeQxxSQmISv7lASiUkq5Tn+uj
=p61q
-----END PGP SIGNATURE-----
Merge tag 'ceph-for-7.3-rc2' of https://github.com/ceph/ceph-client
Pull ceph fixes from Ilya Dryomov:
"A small fixup for the new nearfull_sync mount option, a potential
use-after-free fix (marked for stable) and a patch that eliminates
the last use of PageWriteback macro in the tree"
* tag 'ceph-for-7.3-rc2' of https://github.com/ceph/ceph-client:
ceph: apply nearfull_sync option on remount
libceph: remove pinning assertion in ceph_msg_data_iter_next()
ceph: lock mutex in ceph_mds_check_access()
Instead of hard coding 30 for the number of bits used for the static
buffer ids in two places, create a macro. This way if it changes in the
future, it will change in all the locations that use it.
Link: https://patch.msgid.link/20260904151641.17eae0aa@gandalf.local.home
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
The comment about returning an error if the read fails on the first
iteration is slightly incorrect. It makes it sound like the only reason it
could fail on a later iteration is if the subbuf order changed. That is
incorrect, it could also fail if the length passed in was not a multiple
of the subbuf size. Fix the comment.
Link: https://lore.kernel.org/all/20260904143527.40e73d36@gandalf.local.home/
Link: https://patch.msgid.link/20260904144902.506862a1@gandalf.local.home
Fixes: dae8dda341 ("tracing: Fix subbuf resize races with trace_pipe_raw readers")
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Although ring_buffer_per_cpu::nr_pages is defined as unsigned long, it
is capped to 32-bits in a few places, limiting the operations possible
on a very large buffer. Use `unsigned long` where appropriate and
prevent truncation of values using nr_pages (or nr_subbufs).
While at it, subbuf_size must be at least `unsigned int`.
Note that persistent, remote and user-mapped ring buffers are capping
the number of pages to 30 bits already, making "int" safe in many
places.
Link: https://patch.msgid.link/20260904164450.1345852-5-vdonnefort@google.com
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Static ring buffers (i.e. persistent, user-mapped and remote) rely on
the bpage::id field. The number of pages for those ring buffers must fit
into that variable. Enforce this limit on ring buffer creation or
user-mapping.
While at it, prevent nr_pages underflow when allocating a persistent
buffer.
Link: https://patch.msgid.link/20260904164450.1345852-4-vdonnefort@google.com
Fixes: be68d63a13 ("ring-buffer: Add ring_buffer_alloc_range()")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Concurrent subbuffer resizes may crash trace_pipe_raw readers or leak
uninitialized memory to userspace due to stale size values.
Modify ring_buffer_alloc_read_page() to handle the resizing of an
existing buffer_data_read_page if necessary and add a new
ring_buffer_read_page_size(). This new function enables ring-buffer
buffer_data_read_page users to not call the racy
ring_buffer_subbuf_size_get(). This makes the spare_size member of
ftrace_buffer_info redundant.
Finally, handle buffer_data_read_page/reader_page order discrepancy in
ring_buffer_read_page(). On a mismatch simply copy manually the data to
the buffer_data_read_page.
Link: https://lore.kernel.org/all/20260817140812.2C7D41F00A3A@smtp.kernel.org/
Link: https://patch.msgid.link/20260904164450.1345852-3-vdonnefort@google.com
Fixes: bce761d757 ("ring-buffer: Read and write to ring buffers with custom sub buffer size")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Kumar Kartikeya Dwivedi says:
====================
Misc bug fixes - part 4
A set of miscellaneous fixes for bugs reported by Nicholas, and GPT-5.6
when analyzing those fixes, batched together again. See commit logs for
details. Related rhtab fixes from Yuan Chen and Nuoqi Gui have been
folded into the series.
====================
Link: https://patch.msgid.link/20260904104203.345917-1-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Add load-only timer_mim coverage for inner map identities propagated
through nested timer and bpf_for_each_map_elem() callbacks.
The negative case initializes a timer in the second inner map with the map
saved from the first inner map timer callback. The positive case pairs the
timer value with the map supplied to the same for-each callback.
Without the verifier fix, the mismatched-map program is accepted while the
same-map control is rejected. Preserving map_uid reverses both verdicts.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904104203.345917-9-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Callback frame constructors initialize map-typed argument registers with
__mark_reg_known_zero() and then restore map_ptr. This clears map_uid,
which is the only field distinguishing inner maps that share an
inner_map_meta template.
When a timer callback invokes bpf_for_each_map_elem() on a second inner
map, both the saved first map and the second map value can reach the nested
callback as the same template with map_uid zero. bpf_timer_init() then
accepts pairing the timer from the second map with the first map.
The runtime records the first map in the timer without taking a reference.
Freeing that map does not find the timer stored in the second map, so a
later timer callback dereferences the freed map.
Copy map_uid from the same caller register as map_ptr when constructing
for-each, timer/workqueue, and task-work callback arguments. The existing
identity check can then reject mismatched inner maps while allowing a
callback value to be paired with its actual map.
Fixes: 3e8ce29850 ("bpf: Prevent pointer mismatch in bpf_timer_init.")
Fixes: 69c087ba62 ("bpf: Add bpf_for_each_map_elem() helper")
Fixes: 5c8fd7e2b5 ("bpf: bpf task work plumbing")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904104203.345917-8-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Add a verifier regression where an imprecise zero scalar reaches a kptr
store first and a nonzero scalar reaches the same instruction on a second
path.
Without the corresponding verifier fix, the second path is pruned and the
program is unexpectedly accepted. With the fix, the scalar range is
compared and the invalid store is rejected.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904104203.345917-7-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
check_map_kptr_access() permits a scalar store into an untrusted kptr
field only when the register is known to contain zero. Unlike other
verifier checks whose outcome depends on a scalar value, it does not mark
that register precise.
A state checkpoint reached with an imprecise zero can therefore prune a
second path that reaches the store with an arbitrary nonzero scalar. The
program can write attacker-controlled bits into the kptr field and load
them back as a PTR_TO_BTF_ID.
Call mark_chain_precision() before accepting a known-zero register. This
forces state equivalence to compare its scalar range and makes the verifier
visit and reject a path carrying a nonzero value.
Fixes: 61df10c779 ("bpf: Allow storing unreferenced kptr in map")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260904104203.345917-6-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Resizable hash-map updates and deletions must not perform full special-field
destruction in their caller context. In particular, a referenced kptr must
remain attached to the allocation until the memory allocator destructor can
release it safely.
Add separate coverage for both affected paths. The update test stores a task
kptr, replaces the ordinary value bytes with BPF_EXIST, and verifies that the
kptr survived. The delete test removes an element and exchanges its kptr
through the still-valid map-value pointer before the allocation is reclaimed.
Both cases observe a NULL kptr when rhtab uses bpf_obj_free_fields(). They
recover and release the reference after rhtab switches to cancellation
semantics.
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
[ kkd: Split update and delete coverage and rewrote the commit log ]
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904104203.345917-5-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
rhtab_map_update_existing() and rhtab_delete_elem() call
bpf_obj_free_fields() when replacing or deleting a value. These map
operations can run from BPF programs in NMI context, where releasing a
referenced kptr or another complex field is not generally safe.
Array and hash maps avoid that problem by cancelling only the asynchronous
fields which can be stopped safely in the caller context. Other ownership
state remains attached to the allocation until its memory allocator
destructor performs the final cleanup.
Use bpf_obj_cancel_fields() for the corresponding rhtab paths as well. This
cancels timers, workqueues, and task work while allowing rhtab_mem_dtor() to
release referenced kptrs when the allocation is eventually destroyed.
Fixes: 6905f86012 ("bpf: Allow special fields in resizable hashtab")
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
[ kkd: Rebased, used direct helper calls, and rewrote the commit log ]
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904104203.345917-4-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Exercise the rhtab special-field lifecycle with the sequence from the
original report. A bpf_for_each_map_elem() callback deletes the sole
element, then initializes and arms a timer through the callback value
pointer while it remains valid.
Use a one-element map and pin userspace and BPF execution to one CPU.
Repeated delete-and-replace cycles drain the per-CPU allocator cache, and
periodic RCU synchronization makes the deleted units available for
recycling.
After each replacement, a second BPF program calls bpf_timer_cancel()
on its value. A successful cancellation proves both that a timer-bearing
unit was recycled and that insertion preserved the timer field. Without
the fix, insertion clears that field and cancellation keeps returning
-EINVAL. A long expiration keeps the timer callback out of the test, so
the regression is detected without accessing freed memory.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904104203.345917-3-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
rhtab_map_update_elem() initializes special fields after obtaining an
element from bpf_mem_cache_alloc(). The allocator can return a fresh,
zeroed unit, or recycle one from its RCU-pending lists before the
registered destructor has run.
A BPF program can retain a map-value pointer after deleting its element
and initialize and arm a timer through that pointer. If the deleted unit
is recycled, check_and_init_map_value() clears the only pointer to the
timer. Neither a later deletion nor rhtab_mem_dtor() can then cancel it,
and the callback can run with its key and value pointing into freed memory.
Do not reinitialize special fields on insertion. Fresh allocator units are
already zeroed. For recycled units, the special fields are ownership state
that must remain visible to the eventual destructor. copy_map_value()
already skips those fields, matching the non-preallocated hash-map path and
the lifecycle established by commit 275c30bcee ("bpf: Don't reinit map
value in prealloc_lru_pop").
Fixes: 6905f86012 ("bpf: Allow special fields in resizable hashtab")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Suggested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
[ kkd: Split out the fix and rewrote the commit log ]
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904104203.345917-2-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
The Cadence NAND interrupt handler uses both the IRQ lock and completion
object. Registering the IRQ before initializing them leaves a window in
which a pending interrupt can access uninitialized synchronization state.
Initialize them before registering the handler.
Fixes: ec4ba01e89 ("mtd: rawnand: Add new Cadence NAND driver to MTD subsystem")
Cc: stable@vger.kernel.org
Assisted-by: Codex:GPT-5
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
When the ECC engine fails to decode a page, the driver re-reads the OOB
area with the engine bypassed, but runs the erased-page check for the
data area on the buffer left in the controller SRAM by the failed
transfer.
That buffer does not hold what is on the flash: the failing engine
writes a bogus single-bit "correction" into it. In the 60-byte ECC mode
the all-0xff content of an erased page always decodes to the same error
location, so every erased page shows one stale zero bit at data offset
0x5FD, which the erased-page check then reports as a corrected bitflip.
Edward Karpicz discovered this behaviour and identified the offset on a
Colibri VF61; the analysis and the fix build on his finding. Measured
with an instrumented driver on a Colibri VF50 (MX30LF1G18AC, 32-bit
ECC): reading a 126 MiB partition with nanddump increased the corrected
counter by 18035, exactly one per erased page, while raw reads of the
same pages return clean 0xff. A v4.4 kernel on the VF61 (MX30LF4G28AC)
accumulates the same false counts, so the behaviour follows the
controller rather than the chip or the driver generation. Neither the
Vybrid reference manual nor the published mask set errata (VFXXX_2N02G)
document it. The 45-byte ECC mode is not affected.
Restoring the known byte is not enough: on pages that fail to decode
with content other than all-0xff the engine writes its correction
wherever the syndrome points (measured at a different offset on such a
page), so the check has to run on what the flash holds. Re-read the data
area with the ECC engine bypassed, exactly as already done for the OOB
area. The corrected counter then stays at zero on both boards.
Reported-by: Edward Karpicz <webmaster@toradex.com>
Link: https://community.toradex.com/t/colibri-vf50-vf61-on-the-current-bsp-mainline-u-boot-v2026-07-and-linux-6-18-lts/30735
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
The controller transfers 64 spare bytes per page and the driver only
implements the matching 64-byte ECC layout, so attach_chip() shrinks
mtd->oobsize when the chip provides more. That clamp does not survive:
nand_scan_tail() runs nanddev_init() after ->attach_chip(), and it
restores mtd->oobsize from the memory organization, which still holds
the value detected from the chip. The driver then transfers writesize
plus the chip's full OOB size, the hardware ECC parity ends up at a
different offset than the layout the controller was set up for, and
every ECC-protected read fails with -EBADMSG.
Measured on a Colibri VF61 (MX30LF4G28AC, 2048-byte pages, 112 bytes of
OOB): with the clamp lost, UBI cannot read the erase counter headers of
the pages U-Boot has just written, and the on-flash bad block table
written by an older kernel reads back with ECC errors, so the board
does not boot. Kernels before commit a7ab085d7c ("mtd: rawnand:
Initialize the nand_device object") are not affected because nothing
overwrote the clamp there, which is why the same chip works with a v4.4
kernel and with U-Boot, whose copy of this driver has no memory
organization to restore the value from. Edward Karpicz reported that
the clamp no longer takes effect on this chip; see the link below.
Instead of modifying the memory organization, keep the detected OOB
size and give the driver its own mtd_ooblayout_ops: the same layout the
NAND core uses for large pages, but computed on the first 64 OOB bytes
instead of the whole OOB, so the ECC bytes stay where U-Boot and the
old kernels put them. The data paths transfer writesize plus those 64
bytes, as the controller always has.
Since mtd->oobsize now reports the chip's real spare size, fill the
tail of oob_poi with 0xff after the 64 transferred bytes on ECC page
reads: the core may copy the full mtd->oobsize from it, which would
otherwise expose whatever the buffer held before. 0xff also matches
what a raw read returns from flash, since the write path only ever
programs the first 64 spare bytes.
Reported-by: Edward Karpicz <webmaster@toradex.com>
Link: https://community.toradex.com/t/colibri-vf50-vf61-on-the-current-bsp-mainline-u-boot-v2026-07-and-linux-6-18-lts/30735
Suggested-by: Miquel Raynal <miquel.raynal@bootlin.com>
Fixes: a7ab085d7c ("mtd: rawnand: Initialize the nand_device object")
Cc: stable@vger.kernel.org
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Commit 00c15b78b4 ("mtd: spinand: Allow the case where there is no
ECC engine") made the OOB free bytes count conditional on having an
ECC engine so that probing would not fail when none is requested.
However mtd->oobavail is still assigned from ret just after that
block, and ret is 0 there, so the device ends up advertising no
available OOB bytes at all.
mtd_oobavail() returns mtd->oobavail for MTD_OPS_AUTO_OOB, so a zero
value makes every automatic OOB access fail with -EINVAL. JFFS2 fares
worse: it keeps its cleanmarker in the OOB area on NAND and refuses to
mount outright, reporting "inconsistent device description".
No ECC engine also means no ooblayout was ever installed, which would
make the count return -ENOTSUPP, so install the same fallback layout
the on-die path already uses before counting unconditionally.
Fixes: 00c15b78b4 ("mtd: spinand: Allow the case where there is no ECC engine")
Cc: stable@vger.kernel.org
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>