summaryrefslogtreecommitdiff
path: root/net
AgeCommit message (Collapse)Author
45 hoursxprtrdma: fix up the nfs/nfs-anna merge of the Write chunk head trimSasha Levin
Two fixes for the same Write chunk payload corruption meet in linux-next. In the nfs tree, commit a0db57fee35e ("xprtrdma: Fix Write chunk payload corruption on a short reply header") trims head[0].iov_len in rpcrdma_decode_msg(). In the nfs-anna tree, commit 9ee534a75912 ("xprtrdma: trim head iovec when the payload arrives via a Write chunk") trims it in rpcrdma_inline_fixup() and reduces buflen by the same amount. The merge resolution keeps the caller-side trim. By the time rpcrdma_inline_fixup() runs, head[0].iov_len already equals copy_len, so the block added by the nfs-anna commit never runs and its buflen reduction in rq_rcv_buf and rq_private_buf is lost. The helper is also still passed xdr_pad_size(writelist), while its kernel-doc now describes @writelist as the number of bytes conveyed by the Write chunk. Drop the caller-side trim and pass the full Write chunk length, so that rpcrdma_inline_fixup() is the only place that trims head[0] and reduces buflen. Compute the pad with xdr_pad_size() in the helper, so the padding from the nfs commit stays correct for lengths that are not a multiple of four. Its rpclen calculation and empty reply check stay in rpcrdma_decode_msg(). Fixes: 53ab189bdc14 ("Merge branch 'linux-next' of git://git.linux-nfs.org/projects/anna/linux-nfs.git") Link: https://lore.kernel.org/all/as4aacUf2Q78FMvY@sirena.org.uk/ Signed-off-by: Sasha Levin <sashal@kernel.org> Tested-by: Tim Menninger <tmenninger@everpuredata.com> Reviewed-by: Tim Menninger <tmenninger@everpuredata.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2 daysMerge tag 'ceph-for-7.4-rc1' of https://github.com/ceph/ceph-clientLinus Torvalds
Pull ceph updates from Ilya Dryomov: "The two things of note here are the disablement of inline data support and a new lazyio mount option to enable LAZYIO behavior globally (instead of via an ioctl on a per-file basis), both from Xiubo. Despite being over a decade old, the inline data feature never lost its experimental status -- it has always been off by default and required passing --yes-i-really-mean-it flag to be turned on. It was officially deprecated in 2020 and is now in the process of being removed on the MDS side. For now it's still possible to re-enable it in Kconfig, but the code will eventually be dropped from the kernel client entirely. Outside of that we have a number of bug fixes, a series from Tal to help phase out older page APIs, some cleanups from Max and a large pile of LLM-based hardening patches. Xiubo is also back in a maintainer role, replacing Slava" * tag 'ceph-for-7.4-rc1' of https://github.com/ceph/ceph-client: (66 commits) ceph: fix uninitialized err in ceph_netfs_issue_read() MAINTAINERS: update ceph and libceph maintainers ceph: validate encoded xattr name lengths ceph: validate MDS reply fragtree split array length ceph: bound name skips in ceph_mdsmap_decode() by the message end ceph: validate fscrypt auth blob length ceph: check the caps of a closed file after caps_wanted_delay_min ceph: don't fail write_begin with -EAGAIN after flushing old snapc ceph: fail readdir when the MDS reply carries no dirfrag ceph: clamp MDS reply result code to the errno range libceph: initialize CRUSH choose argument weights libceph: fix out-of-bounds reads from repeated CRUSH bucket entries ceph: fix 32-bit overflow in readdir reply count check libceph: reject bad connect_seq in msgr1 READY reply ceph: Fix mds session leak in __open_export_target_session() ceph: Fix xattr buffer leak in __send_cap() ceph: fix integer overflow in the snap trace bounds check libceph: bound mon_command ack decode to front len ceph: use alloc_page() in fill_fscrypt_truncate() libceph: use alloc_page() in ceph_alloc_page_vector() ...
2 daysMerge tag 'vfs-7.4-rc1.fixes' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs fixes from Christian Brauner: - writeback: - Update dirtied_when instead of dirtied_time_when when a wb switch puts an inode at the newest end of the target b_dirty list. The list was left out of order so move_expired_inodes() could stop before older inodes, and the lazytime expiration timestamp was reset - Clear the old wb's dirty-I/O state and bandwidth contribution when a batch of inode switches leaves its dirty lists empty. An empty wb stayed scheduled for periodic writeback and inflated bdi->tot_write_bandwidth - Take wb_switch_rwsem across the inode scan of cleanup_offline_cgwb(). The v7.3-rc5 fix that rotates scanned inodes let a scan racing a sync()'s queue_io() move lazytime inodes past the sync's cutoff, so sync() returned without persisting their timestamps - Don't kick writeback for an IOCB_DONTCACHE write on an inode that has no wb yet. With cgroup writeback an O_DIRECT RWF_DONTCACHE write to a block device dereferenced NULL - statmount/listmount/listns: - Refuse statmount() string requests with a buffer that isn't larger than struct statmount - Don't wrap around with a U64_MAX cursor in listmount() and listns() - Don't end listns() at an inactive namespace - Only add init_ipc_ns and init_net to the namespace trees if CONFIG_IPC_NS and CONFIG_NET_NS are enabled - iomap: - Only mark blocks uptodate in __iomap_write_begin() after reading them and let __iomap_write_end() mark the zeroed blocks uptodate once the copy from userspace succeeded - Check a chunk against max_integrity_io_size() on its own before the bio size check - Only enforce block alignment for direct I/O into holes and unwritten extents if IOMAP_DIO_FSBLOCK_ALIGNED is set - backing-file: - Check S_APPEND and S_IMMUTABLE on the backing inode. FUSE passthrough opens the backing file with vfs_open() which skips may_open(), so anyone who may open the FUSE file for writing could overwrite an append-only backing file anywhere or write to an immutable one. Open, mmap and writes now check the backing inode the way may_open() and do_mmap() do - Always call kiocb_end_write() for a queued write - Let backing files inherit FMODE_NONOTIFY from the user file. The event fds fanotify creates for permission events on a stacked filesystem raised FS_OPEN_PERM on the real path from inside the listener's read() and deadlocked listeners with marks on both layers - pidfs: - Look the task up before checking for exit information in PIDFD_GET_INFO and start over if the task no longer owns the pid once all fields have been read. A caller racing release_task() got neither PIDFD_INFO_PID nor PIDFD_INFO_EXIT or ESRCH although the exit information was available, and a caller racing a sub-thread's exec reported that thread's tid as the pid - Clear the mask bits of fields that lie beyond the struct size the caller passed. The uapi header promises that the mask names no such field but a caller passing PIDFD_INFO_SIZE_VER0 got the coredump and supported mask bits set for fields that were never written - aio: - Give the aio ring a ->read_folio that fails with EIO so a fault on a ring whose file was truncated gets SIGBUS instead of jumping to NULL - Check nr_events against the ring size before doubling it in ioctx_alloc() - splice: - Only write back an implicit file position in do_splice() when the splice helper succeeded. splice doesn't take f_pos_lock so a failed splice restored a stale snapshot over a position that a concurrent getdents() had moved. On ext2 the next readdir then trusted an offset inside a directory entry - Retry tee() when the input pipe was emptied or the output pipe filled between the prep steps and link_pipe() instead of returning 0 while the input pipe still has writers, as splice_pipe_to_pipe() does - ucount: - Take the reference that pins a ucounts level on the 0 -> 1 transition before checking the rlimit - Read the parent ucounts before dropping the rlimit count in do_dec_rlimit_put_ucounts() - inode: - Rotate inodes whose page cache couldn't be dropped to the tail of the LRU - Skip inodes that another LRU walker is isolating - setns: - Set nsset->flags before anything in prepare_nsset() can fail so the error path drops the cred prepared for CLONE_NEWUSER. A failing setns() with CLONE_NEWUSER and CLONE_NEWNS leaked it together with its user namespace - Refuse setns(CLONE_NEWNS) for a task that shares its fs_struct again when more namespaces are requested - minix: - Restore uptodate on the pinned bitmap buffers before redirtying them after a failed writeback instead of tripping the warning in mark_buffer_dirty(), as ext2 and ext4 do for their superblock buffers - Reject rmdir() of a directory with a corrupted link count with EFSCORRUPTED instead of hitting the drop_nlink() warning - userns: Keep the exec securebits and their locks when creating or joining a user namespace. set_cred_user_ns() reset all securebits to SECUREBITS_DEFAULT so anyone who may create a user namespace could shed SECBIT_EXEC_RESTRICT_FILE and SECBIT_EXEC_DENY_INTERACTIVE with a single unshare(CLONE_NEWUSER) - fs: Honor FOP_UNSIGNED_OFFSET in sys_llseek() and in the pread64(), pwrite64(), preadv() and pwritev() wrappers - proc/kcore: Advance the vmalloc retry in read_kcore_iter() by the last vread_iter() copy instead of the running total - eventpoll: Return the error when the wakeup source for EPOLLWAKEUP can't be created in EPOLL_CTL_MOD instead of reporting success without suspend protection - coredump: Mark do_coredump() noinline_for_stack - nsfs: Check the trailing bytes of a namespace file handle in bytes instead of words - netfs: Restore the per-level and per-point decoding of the debug mask - exportfs: Release the directory file get_name() opened with __fput_sync(). From nfsd's kernel threads the deferred fputs arrived faster than delayed_fput retired them and each pinned the directory's readdir state, growing unreclaimable slab by about 90 MB per second under a parallel tree walk - fs: Call ramfs_kill_sb() for a ramfs rootfs. Since rootfs can be unmounted as of v7.0 its struct ramfs_fs_info was leaked - signal: Check the blocked mask for every entry dequeue_synchronous_signal() looks at. The scan could select a blocked synchronous signal and deliver it while blocked - super: Convert the superblock device table from an rhltable to a plain hashtable under a spinlock. This fixes a bug from v7.3 where fs_bdev_freeze() froze a btrfs filesystem through a stale member that open_ctree() had already released while the freeze was waiting for SB_BORN - fork: Leave rcu_users at zero until copy_process() can't fail anymore. bpf_task_acquire() handed out trusted references to the new task from the task_alloc LSM hook and sched_ext's ops.init_task() and a failing fork freed the task behind them - xattr: Always run cap_convert_nscap() for a security.capability write. A zero-length setxattr() skipped it and let an unprivileged caller without CAP_SETFCAP or write permission on the file plant an empty security.capability xattr that made every execve() of the binary fail with EINVAL - namei: Skip the S_ISDIR assertion in - proc: Refuse to mount on entries below /proc/<pid>/net like fd/, fdinfo/ and map_files/. proc_net_d_revalidate() always fails so the first lookup by anyone with search permission ran d_invalidate() on the dentry and detached every mount on it, locked mounts included - libfs: Hold one mount reference for all pins instead of one per pin. The pin count is what keeps the mount alive, so the per-pin reference only cost a mntget() and a mntput() through mntput_no_expire_slowpath() for every debugfs, tracefs, securityfs or configfs file that comes and goes - iov_iter: Return 0 from iov_iter_alignment() for an empty iterator of any type - watch_queue: Give info_id its own storage instead of overlaying it with rcu_head - filelock: Take an active superblock reference while waiting for a delegation break. After a lazy umount closing the delegation holder could shut down the superblock under the waiter whose final iput() then ran shmem_evict_inode() on freed state - fs: Skip the copy_file_range() write limit checks when there is no data to copy - bpf: Allow bpf_d_path() from fentry on filp_close_sync(). Since close_range() became synchronous this cycle close(), close_range() and the closes on exec and exit no longer go through filp_close(). fexit stays rejected since the file may be gone by then - fs_pin: Dequeue the wait entry unconditionally in pin_kill(). A spuriously woken waiter kept its on-stack entry queued, took that as proof that the pin was alive and used the freed acct structure when umount() of the accounting file raced acct(2) - dcache: Don't fail __d_obtain_alias() for an inode without links and aliases. The ESTALE check added this cycle broke open_by_handle_at() and nfsd file handle decoding on NFS and FUSE where i_nlink is just what the server last reported and the handle may well still be valid - selftests/ovl: Fix the mountinfo expectations of the detached layer test which has failed since it was added * tag 'vfs-7.4-rc1.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (60 commits) fs: don't fail __d_obtain_alias() for unlinked inodes ns: don't add init_ipc_ns and init_net without namespace support aio: avoid request count overflow in ioctx_alloc() selftests/ovl: fix detached layer mountinfo expectations bpf: Allow bpf_d_path() from filp_close_sync() fs: skip copy_file_range write limits when there is no data minix: reject rmdir of a directory with a corrupted link count fs_pin: do not trust the pin after a spurious wakeup in pin_kill() ucount: read the parent ucounts before dropping the rlimit count splice: retry tee() instead of returning 0 when it races selftests/pidfd: test that fields beyond the struct size are not reported pidfs: do not report fields that do not fit into the caller's struct fs: let backing files inherit FMODE_NONOTIFY from the user file splice: avoid stale f_pos writeback on error backing-file: always end a queued write filelock: keep superblock active through delegation wait watch_queue: keep info_id separate from rcu_head iomap: only follow dio alignment requirement if specified iov_iter: fix NULL deref in iov_iter_alignment() backing-file: enforce append-only and immutable backing inodes ...
2 daysns: don't add init_ipc_ns and init_net without namespace supportChristian Brauner
When CONFIG_IPC_NS or CONFIG_NET_NS are turned off we still add the initial ipc and network namespace to the namespace trees. ipc_ns_init() calls ns_tree_add(&init_ipc_ns) whenever CONFIG_SYSVIPC is set and setup_net() calls ns_tree_add_raw() on init_net whenever CONFIG_NET is set. But without CONFIG_IPC_NS and CONFIG_NET_NS these aren't namespaces userspace can do anything with. They don't have proc_ns_operations so there's no /proc/<pid>/ns/{ipc,net} for them, nsfs_fh_to_dentry() refuses them with -EOPNOTSUPP, and since ns->ops is NULL __ns_tree_add_raw() doesn't add them to the owner list of init_user_ns either. So they end up half registered. That's also not how we treat any of the other namespace types. Without CONFIG_UTS_NS, CONFIG_PID_NS, CONFIG_TIME_NS or CONFIG_USER_NS the initial namespace is never added to the tree. listns() walks the unified tree and calls is_current_namespace() for every namespace it finds via may_list_ns(). But is_current_namespace() only knows about CLONE_NEWIPC and CLONE_NEWNET if CONFIG_IPC_NS and CONFIG_NET_NS are set. Otherwise we end up in the default case and its VFS_WARN_ON_ONCE(). Any unprivileged caller can trigger that with a plain listns() call: WARNING: CPU: 0 PID: 526 at fs/nsfs.c:508 is_current_namespace+0x12f/0x440 Call Trace: legitimize_ns+0x25f/0x4c0 do_listns+0x185/0x5c0 __do_sys_listns+0x13b/0x300 Instead of teaching is_current_namespace() about namespaces that can't be opened, only add the initial namespaces to the tree if their namespace type is enabled. Move the registration of init_ipc_ns into ipc/namespace.c which is only built with CONFIG_IPC_NS. That also fixes CONFIG_SYSVIPC=n, CONFIG_POSIX_MQUEUE=y, CONFIG_IPC_NS=y where ipc/shm.c isn't built and init_ipc_ns was never added at all. For the network namespace only call ns_tree_add_raw() if CONFIG_NET_NS is set. Without CONFIG_NET_NS cleanup_net() isn't built and init_net is never removed so there's nothing to balance. Fixes: 74b24a582e1f ("ipc: support ns lookup") Fixes: 195f7422298d ("net: support ns lookup") Reported-by: kernel test robot <yi1.lai@intel.com> Closes: https://lore.kernel.org/oe-lkp/202610260917.6248e316-lkp@intel.com Cc: stable@vger.kernel.org # v6.18+ Link: https://patch.msgid.link/20261030-work-nsfs-init_ns_tree-v1-1-7ec0adb47c54@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
3 daysMerge tag 'net-7.4-rc1' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Jakub Kicinski: "Current release - new code bugs: - mctp: usblib: fix assertion breaking esoteric builds Previous releases - regressions: - Revert advertising the TCP MSS from the configured MTU - netlink: check sk_rcvbuf before charging the dump skb - eth: - ti: am65-cpts: fix support for PTP_EXTTS_REQUEST2 ioctl - mlx4: always create the eth and ib auxiliary devices - tg3: invert restart quirk logic to restrict SNP power-down bypass - bnxt: recycle agg buffers when Rx head buffer allocation fails Previous releases - always broken: - net: fix frag_list leak in skb_segment_list() error path - sctp: reject forged cookie peer_addr with unknown address family - vxlan: keep reserved_bits across changelink - net: limit priority VLAN untag depth - inet: frags: prevent acceptance of partially authenticated reassembly - gro: do not GRO GSO packets with inconsistent payload - tcp: avoid double destroy in tcp_abort() of an unaccepted child" * tag 'net-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (137 commits) tun: drop batched packets while the device is down selftests: net: netlink-dumps: start a dump with a notification queued netlink: check sk_rcvbuf before charging the dump skb net/sched: act_ife: do not consume the inner header on egress openvswitch: use eth_type_trans_careful() in internal_dev_recv() net: use eth_type_trans_careful() in __dev_forward_skb2() loopback: use eth_type_trans_careful() net: add eth_type_trans_careful() tcp: initialize mapped children before route lookup tcp: fix reordering addition overflow in MTU probing tcp: avoid double destroy in tcp_abort() of an unaccepted child net: bgmac: fix TX DMA unmapping and slot cleanup gro: do not GRO GSO packets with inconsistent payload net/packet: check TX_RING fragments before memory accounting eth: bnxt: hand XDP frags over to the copybreak skb eth: bnxt: free XDP frags when xdp_do_redirect() fails eth: bnxt: don't leak buffers when XDP agg buffer allocation fails eth: bnxt: resize Rx head buffers when rx-copybreak changes eth: bnxt: recycle agg buffers when Rx head buffer allocation fails netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts ...
3 daysMerge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpfLinus Torvalds
Pull bpf fixes from Alexei Starovoitov: - Remove BPF_F_ARENA_SCALAR flag and .arena.data section in libbpf that were added for rust-bpf in this merge window. We found a cleaner approach that does it on compiler side instead of kernel/libbpf. No released kernel has them (Alexei Starovoitov) - Fix bpf_send_signal_task() returning -EPERM when it is called from a kernel thread (Aditya Sharma) - Various fixes (Alexei Starovoitov): - Use emit_rsb_call() to call bpf_unwind_target() in x86 JIT to fix objtool warning during the build - Fix scalar evolution: clear delta of a widened register, don't widen a pointer to a buffer, don't clamp a register whose type changed in the loop, and reset the range of a clamped packet pointer - Finish the insn in the state that maybe_fork_scalars() splits off, so that pruning doesn't drop it at the head of a counted loop - Preserve the registers that carry stack arguments across arch_bpf_timed_may_goto() on x86-64, arm64 and riscv64 - Don't re-sort subprog_info[] for every new subprogram - Fix flaky map_kptr and rcu_reentry selftests - Use memmove() in bpf_skb_load_bytes(), bpf_skb_load_bytes_relative() and bpf_xdp_load_bytes(), since the destination can be a slice of the same packet (Ayushman Rout) - Fixes and follow-ups for scalar evolution: reject pointer operands in 32-bit recurrences and latches, don't intersect with the current register range on clamp to avoid a false 'verifier bug', avoid false infinite loop reports, and recognize a 32-bit copy of the induction variable (Eduard Zingerman) - Fix out-of-bounds write to btf->types[] for split BTF and propagate btf_add_type() errors in btf_check_all_metas() (Feng Yang) - Fix use-after-free in bpf_timer callback that fires after its inner map was freed (Mani Tofigh) - Fix x86 JIT stopping before jumps converge: size backward jumps by the insns they jump over (Mykyta Yatsenko) - Fix use-after-free of struct_ops trampoline: dissociate struct_ops progs before the grace period of the map (Qiliang Yuan) - Validate stack argument reads against the caller state to fix out-of-bounds read in the verifier, and reject callbacks with stack arguments (Weiming Shi) - Tie borrowed iterator results and pointers loaded from trusted fields to the lifetime of their source, so that iterator next, destroy and reference release invalidate them (Xu Yunxiang) * tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: (48 commits) bpf: Don't re-sort subprog_info[] for every new subprogram bpf: Fix out-of-bounds btf->types write for split BTF selftests/bpf: Test stack arguments across may_goto bpf: Keep stack arguments in arch_bpf_timed_may_goto() selftests/bpf: Test maybe_fork_scalars() at the head of a counted loop bpf: Finish the insn in the state that maybe_fork_scalars() splits off selftests/bpf: Test the clamp of pointers in scalar evolution bpf: Reset the range of a packet pointer that scalar evolution clamps bpf: Don't clamp a register whose type changed in the loop selftests/bpf: Test a loop that moves a pointer to a buffer bpf: Don't widen a pointer to a buffer in scalar evolution selftests/bpf: Avoid a page fault in rcu_reentry while the handler is armed selftests/bpf: Wait for the last maps of map_kptr to be freed selftests/bpf: Test that a widened register is not linked bpf: Clear delta of a register that scalar evolution widens bpf, x86: Remove r0_on_stack from fetching atomics in arena bpf: Remove BPF_F_ARENA_SCALAR selftests/bpf: Remove tests for arena access through numbers libbpf: Keep format strings of bpf_printk() in .rodata libbpf: Remove .arena.data ...
3 daysnetlink: check sk_rcvbuf before charging the dump skbJhonata Poma-Hansen
Since commit ae8f160e7eb2 ("netlink: Fix wraparounds of sk->sk_rmem_alloc."), netlink_dump() charges the dump skb first and queues it only if sk_rmem_alloc is still below sk_rcvbuf. Commit a215b5723922 ("netlink: make sure we allow at least one dump skb") added an exception for an empty socket. A dump that starts while something else is still charged to a socket with a small receive buffer fails with ENOBUFS and stays running. Every recvmsg() retries it, fails again and sets sk_err, so a reader that peeks before reading, as libnl does, gets ENOBUFS on the read after each peek, never consumes the message at the head of the queue and spins forever. I hit this with "iw dev wlan0 scan" hanging at 100% CPU on an arm64 board with a 6.6 based kernel (iw 5.19 sets SO_RCVBUF to 8KiB). A kprobe trace showed the scan dump starting while the NEW_SCAN_RESULTS notification iw had just read was still charged to its socket, because iw had preempted the sender before netlink_broadcast() returned. Check the limit before charging, as before ae8f160e7eb2, which also covers the empty socket. netlink_recvmsg() continues a dump only at or below half of sk_rcvbuf, so the skb is then always queued, and a dump goes over the limit by at most one skb. Refuse a skb that would take sk_rmem_alloc past INT_MAX, so the wraparound stays fixed. Reproduced on net in a KVM guest with a userspace reproducer and the selftest in the next patch; both pass with this fix. Fixes: ae8f160e7eb2 ("netlink: Fix wraparounds of sk->sk_rmem_alloc.") Signed-off-by: Jhonata Poma-Hansen <jhonata.poma@gmail.com> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Link: https://patch.msgid.link/20261027-netlink-dump-livelock-v2-1-c4bb05352a33@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daysnet/sched: act_ife: do not consume the inner header on egressJamal Hadi Salim
The issue: tcf_ife_decode() unconditionally calls eth_type_trans(), which pulls ETH_HLEN. On egress this consumes the inner Ethernet header, and the device receives an skb whose data points to the L3 header: - loopback_xmit() parses L3 data as Ethernet: the "ethertype" comes from the inner IPv4 source address, and the decapsulated packet is dropped or misparsed. - a real NIC transmits the frame without its Ethernet header. (The __skb_pull() BUG this used to trigger in loopback_xmit() when the remaining linear area was short is handled by "loopback: use eth_type_trans_careful()".) The Fix: Parse the inner Ethernet header with eth_type_trans() in both directions, then restore the egress data position and MAC length. On ingress the existing behavior is unchanged. On egress, push the inner Ethernet header back after parsing so the xmit path sees the original frame and later actions see a consistent network header. Conditions to recreate the bug: - egress tc filter on lo: action ife decode pipe; - AF_PACKET SOCK_RAW frame: outer Ethernet with ETH_P_IFE, IFE metadata, inner Ethernet + a valid IPv4 ICMP echo request to a local address; - before this patch, no echo is received; after it, the echo is delivered and answered. Fixes: ef6980b6becb ("introduce IFE action") Cc: stable@vger.kernel.org Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> [edumazet: reworded changelog, the crash is now handled in loopback] Signed-off-by: Eric Dumazet <edumazet@kernel.org> Acked-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20261028122703.2093730-6-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daysopenvswitch: use eth_type_trans_careful() in internal_dev_recv()Eric Dumazet
OVS actions like pop_eth followed by pop_mpls(ETH_P_TEB) or pop_nsh can expose an inner Ethernet header which is not in the linear part of the skb. Output to an internal port then crashes in eth_type_trans(): flow: in_port(0),eth(),eth_type(0x8847),mpls(lse=0x00010140) actions: pop_eth,pop_mpls(0x6558),0 # AF_PACKET SOCK_RAW on dp0: eth / mpls / eth / 4096 bytes of payload kernel BUG at include/linux/skbuff.h:2839! RIP: 0010:eth_type_trans (include/linux/etherdevice.h:635 net/ethernet/eth.c:163) Call Trace: internal_dev_recv (net/openvswitch/vport-internal_dev.c:202) openvswitch do_execute_actions (net/openvswitch/actions.c:1296) openvswitch ovs_execute_actions (net/openvswitch/actions.c:1606) openvswitch ovs_dp_process_packet (net/openvswitch/datapath.c:310) openvswitch ovs_vport_receive (net/openvswitch/vport.c:448) openvswitch internal_dev_xmit (net/openvswitch/vport-internal_dev.c:42) openvswitch dev_hard_start_xmit (include/linux/netdevice.h:5455 include/linux/netdevice.h:5464 net/core/dev.c:4057 net/core/dev.c:4073) __dev_queue_xmit (net/core/dev.c:5066) packet_sendmsg (net/packet/af_packet.c:3157 net/packet/af_packet.c:3189) Use eth_type_trans_careful(), and drop the packet if the Ethernet header can not be pulled. This covers all OVS actions at the consumer, instead of fixing each producer. Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support") Fixes: f66b53fdbb22 ("openvswitch: New MPLS actions for layer 2 tunnelling") Signed-off-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Aaron Conole <aconole@redhat.com> Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com> Tested-by: Jamal Hadi Salim <jhs@mojatatu.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20261028122703.2093730-5-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daysnet: use eth_type_trans_careful() in __dev_forward_skb2()Eric Dumazet
A tc egress BPF program can push a tiny link-layer header with bpf_skb_change_head() on an skb whose head is almost empty, then redirect it to an Ethernet device ingress. __bpf_redirect_common() only checks mac_header < network_header, and __dev_forward_skb2() crashes in eth_type_trans(): tc filter add dev lo egress pref 1 matchall action vlan pop_eth continue tc filter add dev lo egress pref 2 bpf da obj prog.o # prog: bpf_skb_change_head(skb, 1, 0); # return bpf_redirect(veth1_ifindex, BPF_F_INGRESS); # AF_PACKET SOCK_RAW on lo: eth / eth / 8192 bytes of payload kernel BUG at include/linux/skbuff.h:2839! RIP: 0010:eth_type_trans (include/linux/etherdevice.h:635 net/ethernet/eth.c:163) Call Trace: __dev_forward_skb2 (net/core/dev.c:2507) dev_forward_skb_nomtu (net/core/dev.c:2546) __dev_queue_xmit (net/core/dev.c:4738 net/core/dev.c:4998) packet_sendmsg (net/packet/af_packet.c:3157 net/packet/af_packet.c:3189) Use eth_type_trans_careful(), and drop the packet if the Ethernet header can not be pulled. This also covers other dev_forward_skb() users (veth, macvlan, ipvlan, netdevsim, l2tp_eth). Update the empty_skb BPF selftest: at lwt_xmit, BPF_PROG_TEST_RUN strips the Ethernet header, so the "veth ETH_HLEN+1" packet is a 1-byte skb. Redirecting it to veth ingress used to read the Ethernet header past skb->tail and deliver a 1-byte frame; it is now dropped with NET_RX_DROP, as veth_xmit() already does at egress. Fixes: 3a0af8fd61f9 ("bpf: BPF for lightweight tunnel infrastructure") Signed-off-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com> Tested-by: Jamal Hadi Salim <jhs@mojatatu.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20261028122703.2093730-4-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daystcp: initialize mapped children before route lookupKyle Zeng
IPv4 passive opens on a dual-stack listener go through tcp_v4_syn_recv_sock() with tcp_v6_mapped_child_init() as the optional initializer. The callback currently runs after the output route lookup. If that lookup fails, tcp_done() destroys a clone whose pinet6 and ipv6_fl_list still refer to the listener's state. With the flowlabel list head in inet_sock, fl6_free_socklist() walks the clone's list and RCU-frees its nodes without unlinking them from the live listener. Subsequent flowlabel operations can use or free the nodes again. Commit 858d2a4f67ff ("tcp: fix potential race in tcp_v6_syn_recv_sock()") moved the initializer before ehash insertion, but did not cover this error path. Invoke the existing initializer after the IPv4 fields it consumes have been set, but before route lookup can fail. It needs neither the destination nor sk_setup_caps(), and all later disposal paths remain covered. Fixes: 1c17f4373d4d ("ipv6: Move ipv6_fl_list from ipv6_pinfo to inet_sock.") Signed-off-by: Kyle Zeng <kylebot@openai.com> Signed-off-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20261028154101.2153360-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daystcp: fix reordering addition overflow in MTU probingKyle Zeng
Commit efb8763d7bbb ("net: ipv4: bound TCP reordering sysctl writes and MTU probe sizes") widened size_needed and the MSS multiplication, but tp->reordering + 1 is still evaluated as u32. RTAX_REORDERING accepts an unrestricted u32, and tcp_init_metrics() can install U32_MAX. In that case the extra-data requirement becomes zero. A write queue with probe_size - 1 data bytes and a FIN satisfies the sequence-space check. The coalescing walk can pass the queue head to tcp_skb_can_collapse(), and tcp_clone_payload() can produce an skb whose advertised payload exceeds the data in its fragments. Local delivery followed by TCP_ZEROCOPY_RECEIVE can then walk beyond the fragment array. KASAN reports a slab-out-of-bounds read in can_map_frag(). Cast reordering before incrementing it so the arithmetic handles the entire u32 metric range. For U32_MAX, the required size exceeds the 32-bit queue and window limits, so the existing checks skip the probe. The calculation is unchanged for all other reordering values. Fixes: efb8763d7bbb ("net: ipv4: bound TCP reordering sysctl writes and MTU probe sizes") Cc: stable@vger.kernel.org Cc: Wyatt Feng <bronzed_45_vested@icloud.com> Cc: Ren Wei <n05ec@lzu.edu.cn> Signed-off-by: Kyle Zeng <kylebot@openai.com> Signed-off-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Neal Cardwell <ncardwell@google.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev> Link: https://patch.msgid.link/20261028160226.2170244-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daystcp: avoid double destroy in tcp_abort() of an unaccepted childKyle Zeng
tcp_abort() checks for TCP_CLOSE while only owning the socket lock, then grabs the BH lock before calling tcp_done_with_error(). For a child still sitting in a listener accept queue (which can be reached via SOCK_DESTROY or bpf_sock_destroy()), inet_csk_listen_stop() can run in this window: it only holds the child BH lock, and calls inet_child_forget(), which disconnects, orphans and destroys the child. tcp_abort() then calls tcp_done_with_error() -> tcp_done(), which sees SOCK_DEAD and calls inet_csk_destroy_sock() a second time, leading to a double sock_put() and a use-after-free. Recheck TCP_CLOSE after acquiring the BH lock, unless we just closed a listener ourselves, in which case tcp_done_with_error() must still run to report the error. Note that the WARN_ON(sock_owned_by_user(child)) in inet_csk_listen_stop() can still trigger in this window. Fixes: bac76cf89816 ("tcp: fix forever orphan socket caused by tcp_abort") Signed-off-by: Kyle Zeng <kylebot@openai.com> [edumazet: recheck TCP_CLOSE under the BH lock instead of moving the test, smaller diff] Signed-off-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20261028160847.2170959-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daysgro: do not GRO GSO packets with inconsistent payloadKyle Zeng
tcp_gro_receive() excludes empty non-GSO packets with the unsigned len - 1 check, but its GSO branch only checks that gso_size matches the held packet's MSS. A trusted TCP GSO skb can reach GRO again with no payload after TC pedit increases its TCP data offset. If the skb is fully linear, skb_gro_receive() then enters its fragment transfer path with nr_frags == 0. The do-while loop copies skb_frag_t entries backwards beyond both fragment arrays. An unprivileged process using its own user and network namespaces can trigger a KASAN slab-out-of-bounds write and panic through veth, pedit and GRE. More generally, the payload of such a packet can be shrunk to any value, making it inconsistent with its gso_segs, and a GSO packet with gso_segs == 0 contributes no segment to the GRO packet. Do not aggregate GSO packets with gso_segs == 0, and require the payload of GSO packets to be consistent with gso_segs and gso_size, the last segment being allowed to be short. This rejects the empty skb before either TCP merge helper, and covers both IPv4 and IPv6. Fixes: 5eddb24901ee ("gro: add support of (hw)gro packets to gro stack") Signed-off-by: Kyle Zeng <kylebot@openai.com> [edumazet: check payload against gso_segs, refuse gso_segs == 0] Signed-off-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20261028171350.2205175-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daysnet/packet: check TX_RING fragments before memory accountingKyle Zeng
tpacket_fill_skb() adds the full non-linear payload length to skb->truesize and sk_wmem_alloc before checking MAX_SKB_FRAGS. With PACKET_VNET_HDR, userspace can submit a ring-sized frame even when it greatly exceeds the device MTU. A near-INT_MAX frame can saturate sk_wmem_alloc before the fragment loop rejects it. A subsequent refcount_add(0x40000001) can temporarily turn REFCOUNT_SATURATED into 1. A concurrent TX completion can then drop that apparent last reference and free the still-live packet socket before refcount_warn_saturate() restores the counter. Check that the remaining payload fits in MAX_SKB_FRAGS pages before accounting it. Include the initial page offset in the calculation, and move the existing -EFAULT handling out of the fragment loop. This preserves the accepted packet sizes and error code while preventing an invalid frame from injecting an oversized byte charge. Fixes: 69e3c75f4d54 ("net: TX_RING and packet mmap") Cc: stable@vger.kernel.org Cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Signed-off-by: Kyle Zeng <kylebot@openai.com> [edumazet: use net_warn_ratelimited() instead of pr_err(), add a Fixes: tag] Signed-off-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20261028181450.2221013-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daysnetdev-genl: ignore NETDEV_UNREGISTER rebroadcastsNaman Gulati
netdev_wait_allrefs_any() re-sends NETDEV_UNREGISTER every second while it waits for the last references on a device to be dropped. By then netdev_run_todo() has already marked the device NETREG_UNREGISTERED and RTNL has been dropped at least once since the initial notification sent by unregister_netdevice_many_notify(). netdev_genl_netdevice_event() does not tell these rebroadcasts apart from the initial notification and sends a NETDEV_CMD_DEV_DEL_NTF multicast for each of them. At best this spams NETDEV_NLGRP_MGMT listeners with duplicate notifications; at worst the pernet state of the netns the device belongs to is already gone and the handler dereferences a NULL pointer. default_device_exit_batch() only unregisters the devices still listed in the exiting netns; it does not wait for in-flight unregistrations of devices that were already unlisted (the barrier doing that was removed by commit 8a4fc54b07d7 ("net: get rid of rtnl_lock_unregistering()")). So when a device is unregistered by something other than the cleanup_net() of its own netns while references on it are still held, e.g. a veth whose peer in another netns gets deleted, and that netns exits while the device is stuck in netdev_wait_allrefs_any(), the remaining pernet exit handlers run and genl_pernet_exit() sets net->genl_sock to NULL. The next rebroadcast then crashes in genl_has_listeners(): BUG: KASAN: null-ptr-deref in netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 Read of size 8 at addr 0000000000000578 by task syz.0.0/5325 Call Trace: <TASK> netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 genl_has_listeners include/net/genetlink.h:644 [inline] netdev_genl_dev_notify+0x161/0x450 net/core/netdev-genl.c:93 netdev_genl_netdevice_event+0x98/0x3c0 net/core/netdev-genl.c:1491 notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85 netdev_wait_allrefs_any net/core/dev.c:11690 [inline] netdev_run_todo+0x731/0x1060 net/core/dev.c:11808 rtnl_unlock net/core/rtnetlink.c:157 [inline] rtnl_dellink+0x68f/0x810 net/core/rtnetlink.c:3707 syzbot hit this by moving one end of a veth pair into a short-lived netns while netdevsim's deferred FIB event processing still held a reference on it, and then deleting the other end (repro [1]). While the source of this bug is netdevsim deferring FIB processing for and holding onto the device reference for O(seconds) which is being fixed separately [2], any driver may introduce such a delay and trigger the null-ptr-deref. Skip the rebroadcasts, which are the only NETDEV_UNREGISTER events delivered with reg_state == NETREG_UNREGISTERED. The notifications sent by unregister_netdevice_many_notify() and, for a device leaving a netns, by __dev_change_net_namespace() are issued under RTNL in the same critical section that unlists the device, before its netns can be torn down, and keep being handled. This mirrors what ip6_route_dev_notify() already does to cope with the rebroadcasts. This change should not break the UAPI spec as it defines dev-del-ntf as a "Notification about device disappearing." which is a single event. The rebroadcast in netdev_wait_allrefs_any() exists to re-kick in-kernel subsystems holding references; netdev-genl happens to be on the notifier chain and forwards it. [1] https://gist.github.com/NamanGulati/2d1b49b8757f9a88b0bd6e55018c02ae [2] https://lore.kernel.org/r/20261023191517.607834-1-kuniyu@google.com Fixes: d3d854fd6a1d ("netdev-genl: create a simple family for netdev stuff") Reported-by: syzbot+1269fe6cc2016008124e@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/6adf9f64.6200f071.51519.0ed1.GAE@google.com/ Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Signed-off-by: Naman Gulati <namangulati@google.com> Link: https://patch.msgid.link/20261026221306.3151025-1-namangulati@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
3 daystcp: check congestion control restriction firstZhiling Zou
tcp_set_default_congestion_control() takes a reference to an algorithm before checking whether a non-init network namespace may select it. A rejected request returns -EPERM without dropping the reference. This affects module-backed algorithms too; BPF is not required. For example, after root loads tcp_bbr, a user with CAP_NET_ADMIN in a non-init network namespace can repeatedly request it as the default although it is not in tcp_allowed_congestion_control. Each rejected write leaks a module reference. Since module->refcnt is an atomic_t, 2^31 such writes can make it negative; later module_put() calls warn, and rmmod can hit the BUG_ON() in try_release_module_ref(). Check the namespace restriction before acquiring the reference, as tcp_set_congestion_control() already does. Fixes: 8d432592f30f ("net: Only allow init netns to set default tcp cong to a restricted algo") Cc: stable@vger.kernel.org Reported-by: Vega <vega@nebusec.ai> Suggested-by: Eric Dumazet <edumazet@kernel.org> Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev> Link: https://patch.msgid.link/71c142b2d45af6a2fe7fc6cd4a5ca52c53afbe23.1793075984.git.zhilinz@nebusec.ai Signed-off-by: Paolo Abeni <pabeni@redhat.com>
3 daysnet/sched: sch_teql: fix use-after-free on lower qdisc dropowen kwan
The issue: teql_master_xmit() tests the slave's ndo_start_xmit() return value against NETDEV_TX_OK alone. A slave that consumes the skb but returns an error code (rc < NET_XMIT_MASK, e.g. NET_XMIT_DROP) is treated as if the skb were still owned, so the loop restores skb->dev and calls __skb_pull() on it. A VLAN slave returns the result of dev_queue_xmit() from its ndo_start_xmit() (propagated since cbbef5e18307), and when the lower qdisc drops the packet that value is NET_XMIT_DROP after the skb has been freed, giving a use-after-free in teql_master_xmit(). The Fix: test for consumption with dev_xmit_complete(), which accepts NETDEV_TX_OK and every rc < NET_XMIT_MASK, matching other callers that need to distinguish consumed results from busy. Only NETDEV_TX_OK keeps the packet counted in tx_packets/tx_bytes and advances the slave; a consumed result that is neither a success nor NET_XMIT_CN ends the attempt and is charged to tx_dropped, so lower-qdisc drops are no longer reported as good transmits. NET_XMIT_CN is counted like success because it can accompany acceptance of the current packet: pfifo_head_drop drops the old head, enqueues the current skb and returns NET_XMIT_CN. Conditions to recreate the bug: With CONFIG_NET_SCH_TEQL, CONFIG_VLAN_8021Q and CONFIG_DUMMY enabled, add lkrdummy0 (dummy) and lkrvlan0 (VLAN id 37 on lkrdummy0); set a pfifo limit 0 root on lkrdummy0 and a teql0 root on lkrvlan0; bring teql0 up with an address and send one UDP packet to it. The VLAN xmit returns NET_XMIT_DROP from the lower qdisc while holding a freed skb. Fixes: 572a9d7b6fc7 ("net: allow to propagate errors through ->ndo_hard_start_xmit()") Link: https://lore.kernel.org/netdev/179248763469.3135.1739559328868319628@kernel.org/ Link: https://lore.kernel.org/netdev/20261023162821.GN708417@horms.kernel.org/ Cc: stable@vger.kernel.org Signed-off-by: owen kwan <owen@verialabs.com> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/QDISC-Y0BY.v2.r0.20261024060625-2@mojatatu.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
3 daysnet/sched: sch_teql: fix slaves_lock IRQ deadlockJamal Hadi Salim
This is a followup of commit e5b811fe7931 ("net/sched: sch_teql: Introduce slaves_lock to avoid race condition and UAF") as reported by Sashiko. The issue: master->slaves_lock serializes the master's ring of slave qdiscs. The control paths -- teql_dequeue(), teql_destroy() and teql_qdisc_init() -- take it with spin_lock_bh(), while teql_master_xmit() (the master's ndo_start_xmit) takes it with plain spin_lock(). netpoll_send_skb() wraps the transmit in local_irq_save(), and __netpoll_send_skb() asserts lockdep_assert_irqs_disabled(), so teql_master_xmit() reached from netconsole always acquires slaves_lock with hard IRQs disabled. On PREEMPT_RT spinlock_t is an rtmutex, and Documentation/locking/locktypes.rst names local_irq_disable(); spin_lock(&lock); as a sequence that breaks there because the rtmutex requires a fully preemptible context. This is reachable without any panic: the nbcon printer thread calls netconsole's write_thread() callback on every message. The usual remedy -- folding the IRQ disable into the lock with spin_lock_irqsave() -- is unavailable because the local_irq_save() is netpoll's, not ours. On non-RT the same asymmetry leaves slaves_lock acquirable with hard IRQs disabled on one path and held with hard IRQs enabled on another. That is only exploitable during the panic console flush (netconsole is CON_NBCON_ATOMIC_UNSAFE, so console_is_usable() admits its write_atomic() only from nbcon_atomic_flush_unsafe(), which panic() alone calls), and even then an IRQ-saving lock does not help if the holder oopsed inside the section or was stopped by panic_other_cpus_shutdown(). So the non-RT half is hardening; the PREEMPT_RT half is the bug. The Fix: take slaves_lock as a raw spinlock with IRQs saved at every site. Since skb_queue_purge() takes the queue's spinlock_t and may not nest inside a raw lock on PREEMPT_RT, move its call in teql_destroy() outside the raw section; dat->q is the dying qdisc's own queue and was never serialized by slaves_lock, so the move is behaviour-neutral. The new critical sections contain only RCU pointer assignments and netdev_get_tx_queue(); skb_queue_purge(), netif_wake_queue() and dev_reset_queue() are all outside them. teql_destroy()'s ring walk is O(slaves), two pointer loads and a compare per iteration, so even a large ring is microseconds with IRQs off. Keeping the purge conditional rather than dropping it outright is the conservative call for a backport. Some context: commit 6301f6a34ed8 ("net/sched: sch_teql: move rcu_read_lock()/spin_lock() from _bh variants") hardened the parent fix; together they addressed the master->slaves resurrection use-after-free and the xmit-side BH warning but left the reverse direction -- a hard IRQ re-entering xmit while a control path holds the lock -- unaddressed. Conditions to recreate the bug: - CONFIG_PREEMPT_RT, CONFIG_NET_SCH_TEQL, CONFIG_DUMMY and CONFIG_NETCONSOLE. - Run `ip link add dev teqlslave0 type dummy`, bring teqlslave0 up, attach it with `tc qdisc add dev teqlslave0 root teql0`, and bring teql0 up. - Configure a netconsole target on teql0 with explicit local and remote IP addresses and a remote MAC address, then emit a console message. The nbcon printer thread reaches teql_master_xmit() with hard IRQs disabled by netpoll; taking slaves_lock as a spinlock_t is invalid on PREEMPT_RT. No panic or concurrent qdisc change is required. - Reachable by an admin with CAP_NET_ADMIN; teql devices exist only in the initial netns (no per-netns ops), so a user namespace does not suffice. Fixes: e5b811fe7931 ("net/sched: sch_teql: Introduce slaves_lock to avoid race condition and UAF") Reported-by: Sashiko (gemini) <sashiko-bot@kernel.org> Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260630150922.238714-1-jhs%40mojatatu.com Link: https://lore.kernel.org/netdev/20260630150922.238714-1-jhs@mojatatu.com/ Cc: stable@vger.kernel.org Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/QDISC-Y0BY.v2.r0.20261024060625-1@mojatatu.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
3 daysnet: mctp: free reassembly head skb when key_add fails on SOMJoas Antonio dos Santos
When a start-of-message fragment creates a new reassembly key on the broadcast/bind path, mctp_frag_queue() stores the skb as key->reasm_head before the key is made observable with mctp_key_add(). If mctp_key_add() fails (a race with another SOM packet for the same source/dest/tag, or the receiving socket going away), the error path only drops the key reference via mctp_key_unref(). The final key destructor frees the key itself but not key->reasm_head, and since the key was never added to any list, neither the expiry worker nor socket teardown can reach it to release the queued fragment. The skb is leaked. Free key->reasm_head on the key_add failure path before releasing the key. Other teardown paths (__mctp_key_done_in(), EOM delivery) already clear reasm_head before the final unref, so this only affects the failure path. Fixes: 4a992bbd3650 ("mctp: Implement message fragmentation & reassembly") Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com> Reported-by: Guikun Yang <yangguikun19@qq.com> Closes: https://lore.kernel.org/all/tencent_43A65D51143E18518EA968DF9323694EFD08@qq.com/ Acked-by: Jeremy Kerr <jk@codeconstruct.com.au> Link: https://patch.msgid.link/179287946888.17431.11219154409333681184@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
4 daysnet: bridge: netlink: do not clear the vlan info dump errorLinkui Xiao
br_fill_ifinfo() assigns the result of br_fill_vlan_tunnel_info() over the result of br_fill_ifvlaninfo() or br_fill_ifvlaninfo_compressed() instead of only running the second helper when the first one succeeded. When the vlan information no longer fits in the skb but the port has no vlan mapped to a tunnel dst, br_fill_vlan_tunnel_info() walks the vlan list and returns 0 without touching the skb. The -EMSGSIZE is lost, br_fill_ifinfo() completes a message whose IFLA_AF_SPEC is truncated, and the dump carries on to the next interface instead of stopping, so userspace silently sees an incomplete vlan list. Only fill the tunnel information when the vlan information was filled successfully. This was flagged as a pre-existing issue in the Sashiko review of the net-next series, which noted that the VLAN fill result is overwritten before it is tested (see the Link tag below). Not triggered or tested. Fixes: efa5356b0d97 ("bridge: per vlan dst_metadata netlink support") Link: https://lore.kernel.org/bridge/ed1de95e-e112-4076-93f0-6f7668e657ad@blackwall.org/T/#u#5 Signed-off-by: Linkui Xiao <xiaolinkui@kylinos.cn> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Acked-by: Nikolay Aleksandrov <razor@blackwall.org> Link: https://patch.msgid.link/20261027085200.1501599-1-xiaolinkui@126.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
4 daysipv6: Protect multiple routes insertion by table lock.Kuniyuki Iwashima
syzbot reported the warning below. [0] While call_fib6_multipath_entry_notifiers() is called locklessly, fib6_siblings could be changed concurrently, leading to the warning (and later null-ptr-deref). Let's protect multiple routes insertion with tb6_lock. Along with that, __ip6_ins_rt() and ip6_route_del() are changed to fib6_add() and fib6_del(). Note that fib6_del() finally calls rt6_multipath_rebalance(), which requires rcu_read_lock(). [0]: i != fen6_info->nsiblings WARNING: drivers/net/netdevsim/fib.c:831 at nsim_fib6_event_init drivers/net/netdevsim/fib.c:831 [inline], CPU#0: syz.0.157/6279 WARNING: drivers/net/netdevsim/fib.c:831 at nsim_fib6_prepare_event drivers/net/netdevsim/fib.c:947 [inline], CPU#0: syz.0.157/6279 WARNING: drivers/net/netdevsim/fib.c:831 at nsim_fib_event_schedule_work drivers/net/netdevsim/fib.c:1003 [inline], CPU#0: syz.0.157/6279 WARNING: drivers/net/netdevsim/fib.c:831 at nsim_fib_event_nb+0x1029/0x11d0 drivers/net/netdevsim/fib.c:1043, CPU#0: syz.0.157/6279 Modules linked in: CPU: 0 UID: 0 PID: 6279 Comm: syz.0.157 Not tainted syzkaller #0 PREEMPT(full) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026 RIP: 0010:nsim_fib6_event_init drivers/net/netdevsim/fib.c:831 [inline] RIP: 0010:nsim_fib6_prepare_event drivers/net/netdevsim/fib.c:947 [inline] RIP: 0010:nsim_fib_event_schedule_work drivers/net/netdevsim/fib.c:1003 [inline] RIP: 0010:nsim_fib_event_nb+0x1029/0x11d0 drivers/net/netdevsim/fib.c:1043 Code: eb 0d 4d 89 fd e8 b7 c5 6c fa be 01 00 00 00 48 89 df e8 5a 38 85 fd 4d 89 ef 4c 8b 6c 24 20 e9 4a f3 ff ff e8 98 c5 6c fa 90 <0f> 0b 90 e9 db fa ff ff 89 e9 80 e1 07 80 c1 03 38 c1 0f 8c df f0 RSP: 0018:ffffc900047bef10 EFLAGS: 00010293 RAX: ffffffff875b59a8 RBX: 0000000000000002 RCX: ffff888079770000 RDX: 0000000000000000 RSI: 0000000000000002 RDI: 0000000000000001 RBP: ffffc900047bf0a0 R08: ffff88805c0bb02f R09: 1ffff1100b817605 R10: dffffc0000000000 R11: ffffed100b817606 R12: dffffc0000000000 R13: 0000000000000000 R14: 0000000000000001 R15: ffff88802c792000 FS: 00007f334ba076c0(0000) GS:ffff888123ad0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f334ba06ff8 CR3: 000000007a5b2000 CR4: 00000000003526f0 Call Trace: <TASK> notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85 atomic_notifier_call_chain+0xda/0x180 kernel/notifier.c:223 call_fib_notifiers+0x31/0x60 net/core/fib_notifier.c:36 call_fib6_multipath_entry_notifiers+0xf5/0x160 net/ipv6/ip6_fib.c:428 ip6_route_multipath_add net/ipv6/route.c:5542 [inline] inet6_rtm_newroute+0x14f5/0x1a30 net/ipv6/route.c:5664 rtnetlink_rcv_msg+0x802/0xc00 net/core/rtnetlink.c:7163 netlink_rcv_skb+0x226/0x4a0 net/netlink/af_netlink.c:2572 netlink_unicast_kernel net/netlink/af_netlink.c:1335 [inline] netlink_unicast+0x7bd/0x940 net/netlink/af_netlink.c:1361 netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1916 sock_sendmsg_nosec+0x14e/0x190 net/socket.c:800 __sock_sendmsg net/socket.c:818 [inline] ____sys_sendmsg+0x54e/0x850 net/socket.c:2715 ___sys_sendmsg+0x2a5/0x360 net/socket.c:2769 __sys_sendmmsg+0x273/0x4d0 net/socket.c:2858 __do_sys_sendmmsg net/socket.c:2885 [inline] __se_sys_sendmmsg net/socket.c:2882 [inline] __x64_sys_sendmmsg+0xa0/0xc0 net/socket.c:2882 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f334ab9e1d9 Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f334ba07028 EFLAGS: 00000246 ORIG_RAX: 0000000000000133 RAX: ffffffffffffffda RBX: 00007f334ae26090 RCX: 00007f334ab9e1d9 RDX: 04000000000001f2 RSI: 0000200000000000 RDI: 0000000000000004 RBP: 00007f334ac35888 R08: 0000000000000000 R09: 0000000000000000 R10: 00000000000000fc R11: 0000000000000246 R12: 0000000000000000 R13: 00007f334ae26128 R14: 00007f334ae26090 R15: 00007ffd96688aa8 </TASK> Fixes: 169fd62799e8 ("ipv6: Get rid of RTNL for SIOCADDRT and RTM_NEWROUTE.") Reported-by: syzbot+751b587577d0ebca10f2@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/6adbaed6.67317f00.38c4bc.001b.GAE@google.com/T/ Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://patch.msgid.link/20261027065247.2871134-1-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
4 daystls: Honor O_NONBLOCK in tls_sw_splice_read()Chuck Lever
tls_sw_splice_read() takes its blocking behavior from SPLICE_F_NONBLOCK alone. When splicing from a socket to a pipe, do_splice() sets that flag from the pipe's O_NONBLOCK, not the socket's. On a nonblocking socket, a splice(2) call without SPLICE_F_NONBLOCK therefore sleeps in tls_rx_rec_wait() until a record arrives. tcp_splice_read() instead reads sock->file->f_flags and returns -EAGAIN. Polling first does not avoid the sleep once tls_sw_splice_read() consumes zero-length records, as it does after a later patch in this series. tls_sw_sock_is_readable() reports the socket readable while any record sits on rx_list, including a zero-length record that delivers no bytes to the pipe. For TLS 1.3 the strparser announces a record before decryption, when its plaintext length is still unknown, so the readiness test cannot screen such a record out. A splice that consumes the record and waits for the next stalls every connection an event loop multiplexes. An LLM audit of the TLS read paths found this defect. Treat the socket's O_NONBLOCK as nonblocking too. A caller that sets O_NONBLOCK on the socket and splices without SPLICE_F_NONBLOCK now gets -EAGAIN where the splice blocked before. sendfile(2) from a TLS socket changes the same way, because do_sendfile() leaves the input file's O_NONBLOCK out of the splice flags. Both now behave as they do on a plain TCP socket. Fixes: c46234ebb4d1 ("tls: RX path for ktls") Signed-off-by: Chuck Lever <cel@kernel.org> Link: https://patch.msgid.link/20261027015215.605919-2-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
4 daysnet/sched: fix packet reordering on requeueAntonio Quartulli
dev_requeue_skb() appends requeued skbs to the tail of q->gso_skb, while dequeue_skb() takes them back one at a time from the head. If the driver returns NETDEV_TX_BUSY again for the first of them, it moves behind the skbs still parked there and is sent after them. This showed up as heavy TCP reordering while benchmarking over veth, which returns NETDEV_TX_BUSY whenever its ring is full since commit dc82a33297fc ("veth: apply qdisc backpressure on full ptr_ring to reduce TX drops"). Requeue the skbs at the head of gso_skb, keeping their order. With 4 TCP streams over a veth pair with a pfifo qdisc, this removes about 1.3M out-of-order segments and 15-37k retransmits per 15 seconds, and raises throughput from about 40 to 76 Gbit/s. Fixes: a53851e2c321 ("net: sched: explicit locking in gso_cpu fallback") Fixes: 9540d977618c ("net: sched: fix skb leak in dev_requeue_skb()") Cc: stable@vger.kernel.org Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Acked-by: Jesper Dangaard Brouer <hawk@kernel.org> Link: https://patch.msgid.link/20261026153113.3275494-1-antonio@mandelbit.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
4 daysnet: dcb: initialize PFC value before calling getpfccfgJoas Antonio dos Santos
dcbnl_getpfccfg() and dcbnl_cee_fill() pass the address of an uninitialized stack u8 to the driver's getpfccfg() op and then put it into the netlink reply unconditionally. The op returns void, so the core cannot tell whether the driver wrote the value. i40e_dcbnl_get_pfc_cfg() and ice_dcbnl_get_pfc_cfg() return without writing *setting unless the DCBX agent is host managed and in CEE mode. Both drivers normally run with firmware managed DCBX (DCB_CAP_DCBX_LLD_MANAGED), and i40e with FW LLDP disabled runs host managed in IEEE mode, so on a DCB capable i40e/ice port the PFC values in DCB_CMD_PFC_GCFG and DCB_CMD_CEE_GET replies, and in the CEE part of RTNLGRP_DCB notifications, come from uninitialized stack. The same u8 is reused for all eight priorities, so this is one byte per reply. dcb_doit() only requires CAP_NET_ADMIN for RTM_SETDCB, so the GET commands are available to unprivileged users. Set the value to 0 before each call, like the PG config path already presets its outputs to DCB_ATTR_VALUE_UNDEFINED. 0 is also what the reply contains today on kernels built with CONFIG_INIT_STACK_ALL_ZERO, so nothing changes for those. Found by code inspection, compile-tested only (W=1). I don't have i40e/ice hardware to check the reply. Fixes: b94b013eb626 ("ice: Implement DCBNL support") Fixes: 5effa78e7c94 ("i40e: Add netlink callbacks support for software based DCB") Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com> Link: https://patch.msgid.link/179289284460.50470.572724041164324949@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
4 daysRevert "net: advertise TCP MSS from the configured MTU, not the learned PMTU"Yongjian Wang
This reverts commit 2640e6419594 ("net: advertise TCP MSS from the configured MTU, not the learned PMTU"). That commit stopped the learned PMTU from lowering the MSS we advertise in SYN and SYN-ACK. For symmetric paths it argued that "the peer runs its own PMTU discovery and usually already knows the real path MTU". That only holds if ICMP "fragmentation needed" can reach the peer. When the peer sits behind a firewall that drops inbound ICMP, its PMTU discovery is a black hole (RFC 2923, section 2.1), and the smaller MSS we advertised was the only thing keeping its full-size segments off the narrow hop. Inbound ICMP filtering is very common in enterprise and carrier networks, and it is pervasive in mainland China. We hit this in production after the commit was backported to 6.12.111: TCP connections that reach a server through a relay with a smaller-MTU hop complete the handshake, then stall as soon as the client sends full-size segments. Clients on networks that let ICMP through, and connections that bypass the relay, are unaffected, which made it hard to trace back to the kernel. Reproducer, network namespaces on a single host: cli --(1500)-- r1 --(1456)-- r2 --(1500)-- srv r1 drops ICMP frag-needed towards cli. srv has already learned PMTU 1456 towards cli, then cli uploads 1 MB to srv: kernel SYN-ACK MSS 1 MB upload 6.12.107 1416 OK 6.12.111 1460 stalls, times out 7.3-rc7 1460 stalls, times out 7.3-rc7 + this revert 1416 OK The asymmetric case the commit was written for does not need a new default: the advertised MSS can already be set per route with the advmss metric, which takes precedence over default_advmss(). With this revert applied, on an asymmetric path where srv learned PMTU 1456 towards cli while cli->srv is 1500 end to end: srv route to cli SYN-ACK MSS largest cli->srv segment default 1416 1404 advmss 1460 1460 1448 So DSR-style setups can opt in with "ip route ... advmss <mss>", while hosts whose peers cannot complete PMTU discovery keep working by default. Fixes: 2640e6419594 ("net: advertise TCP MSS from the configured MTU, not the learned PMTU") Closes: https://lore.kernel.org/regressions/4F0FAEB6-A13B-47F3-BFF1-C706686C6F64@gmail.com/ Cc: stable@vger.kernel.org Signed-off-by: Yongjian Wang <echoowall@gmail.com> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev> Link: https://patch.msgid.link/20261026-advmss-revert-v1-2-272fa4b7ecb6@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
4 daysnet: sched: em_ipt: validate hook value from netlinkFang Xieyan
em_ipt_change() accepts the user-provided TCA_EM_IPT_HOOK value without validating its range. The value is later used in check_match() as "1 << im->hook". A hook value of 32 or greater causes undefined behavior and may undermine the xt match hook-mask validation. The value is also passed to nf_hook_state_init() as a hook index. Reject hook values outside the supported IPv4/IPv6 Netfilter hook range after checking the required attributes, before loading the xt match or allocating the match state. Reviewed-by: Weibin Liu <liuwb@xiaopeng.com> Signed-off-by: Fang Xieyan <fangxy@xiaopeng.com> Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
4 daysnet: sched: prevent scheduling deactivated qdiscsKyle Zeng
TAPRIO can schedule a deactivated qdisc after some_qdisc_is_busy() has reported it idle. Commit 47e8dbb6e763 ("net/sched: do not reset queues in graft operations") made graft deactivation skip queue reset, leaving TAPRIO's timer armed. A late callback schedules NET_TX softirq work, whose dequeue path can race the unlocked child-queue reset in taprio_reset(). The same skb can be queued for deferred freeing by RTNL and dequeued for transmission. In the reproducer, the TAP reader frees it before __rtnl_unlock() reads its next pointer. KASAN reports a slab-use-after-free in __rtnl_unlock+0xa3/0xd0, with a read of size 8 from the freed skb. Reject deactivated qdiscs in __netif_schedule(). Callers' RCU protection lets the existing grace period join earlier scheduling calls before the busy check. Restart nonempty transmit queues on reactivation so suppressed scheduling does not strand packets. Fixes: 47e8dbb6e763 ("net/sched: do not reset queues in graft operations") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/netdev/20260805102514.740834-1-david.lee@trailofbits.com/ Assisted-by: Codex:gpt-5.6-sol Codex:gpt-5.5-cyber Signed-off-by: Kyle Zeng <kylebot@openai.com> Co-developed-by: David Lee <david.lee@trailofbits.com> Signed-off-by: David Lee <david.lee@trailofbits.com> Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
4 daysinet: frags: prevent acceptance of partially authenticated reassemblyJérémy Jean
A reassembled skb retains the secpath from its first fragment, which makes it possible for the final policy check to accept bytes that were not covered by the transform recorded on the skb. This can affect IPsec tunnel traffic, including AH and ESP, and allow a packet to be accepted even though only part of its payload was authenticated. Reject a fragment when its secpath differs from the fragments already in the queue, and keep overlap statistics limited to actual overlaps. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
5 daystls: keep TX and RX hardware offload on the same deviceRishikesh Jethwani
After TX is offloaded on device A, a route change, or a change in the usable-slave set of an 802.3ad or balance-xor (layer3+4) bond, can make RX setup program device B. tls_device_attach() sees the existing TLS destructor and keeps ctx->netdev pointing at A. The RX driver state on B is then untracked: tls_dev_resync() and tls_dev_del() are invoked on A for a context it never created, and neither socket close nor NETDEV_DOWN on B calls tls_dev_del() for B, so the driver context leaks. The reverse setup order has the same problem. Check the shared device binding under device_offload_lock before each tls_dev_add(). Permit the first attachment and a second direction on the same device. Reject a different device, including when the old binding was cleared by NETDEV_DOWN: the TLS destructor remains installed and tls_device_attach() cannot establish a new binding. Setup then falls back to software for the requested direction. The RX check precedes allocation and software setup. TX uses its existing resource unwind path without calling the driver. Document the shared binding and clarify that fallback is per direction. This issue was discovered during code review and subsequently reproduced on hardware using mlx5 and TLS 1.2 AES-GCM-128. Changing the route between TX and RX setup installed the second direction on a different device. Driver traces showed successful adds on both devices, but both deletes at socket close targeted the first device, leaving an orphaned context on the second. Both setup orders reproduced the leak, even though all current core TLS context counters returned to zero. No crash was observed. With the fix, the same tests correctly fall back to software for the second direction and leave no orphaned hardware context. Fixes: 4799ac81e52a ("tls: Add rx inline crypto offload") Signed-off-by: Rishikesh Jethwani <rjethwani@purestorage.com> Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
5 daystcp: Fix fastreuse cache initialization on first bindZhewei Yuan
inet_csk_update_fastreuse() initializes the reuse caches only when tb->bhash2 is empty, but both inet_csk_get_port() and __inet_inherit_port() link tb2 before calling it, so the first-bind branch is never taken. As a result, SO_REUSEADDR binds never get fastreuse=1 and keep scanning existing owners, and SO_REUSEPORT starts in STRICT instead of ANY. Initialize the caches when tb2 is the only entry in tb->bhash2 and has no owners. Timewait sockets are also linked on tb2->owners, so this is equivalent to the old hlist_empty(&tb->owners) test. Found by manual code inspection and confirmed with GDB. Binding 16000 SO_REUSEADDR sockets to one address/port in a KVM guest takes 4.18 s before and 19.4 ms after this patch. Existing bind/reuse selftests pass. Analysis and testing were assisted by an AI tool (Codex). Fixes: 8002d44fe84d ("tcp: Check hlist_empty(&tb->bhash2) instead of hlist_empty(&tb->owners).") Reviewed-by: Eric Dumazet <edumazet@kernel.org> Signed-off-by: Zhewei Yuan <yzwlhm@gmail.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Jason Xing <kerneljasonxing@gmail.com> Link: https://patch.msgid.link/20261026095208.58504-1-yzwlhm@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
5 daysdevlink: region: fix snapshot id leak on kernel-allocated idsFernando Fernandez Mancera
When DEVLINK_CMD_REGION_NEW is issued without a snapshot id, the kernel allocates one with __devlink_region_snapshot_id_get(). That helper counts the caller as a user of the id, and the caller must release this hold once it is done. devlink_nl_region_new_doit() never drops it. The refcount of the id goes 1 (allocation) -> 2 (snapshot created) and stays at 2. When the snapshot is deleted the count only drops to 1, so the id is never erased from the snapshot_ids xarray. The id then stays in use for the lifetime of the devlink instance: requesting a snapshot with that explicit id fails with -EEXIST, and there is no snapshot left to delete to clean it up. Reproducer steps: # devlink region new pci/0000:13:00.0/device-caps pci/0000:13:00.0/device-caps: snapshot 0 # devlink region del pci/0000:13:00.0/device-caps snapshot 0 # devlink region new pci/0000:13:00.0/device-caps snapshot 0 kernel answers: File exists Drop the caller's reference right after the snapshot has been created, as the snapshot then holds its own. Fixes: 043b3e22768d ("devlink: let kernel allocate region snapshot id") Reported-by: Guikun Yang <yangguikun19@qq.com> Closes: https://lore.kernel.org/netdev/tencent_BE912BA710539F285F9FCF28E854ABEFCD07@qq.com/ Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Link: https://patch.msgid.link/20261026174403.512-1-fmancera@suse.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
5 daysnet-sysfs: reject a one-entry RPS flow tableDudu Lu
store_rps_dev_flow_table_cnt() accepts rps_flow_cnt == 1. For count == 1 the round-up loop leaves mask == 0, which is stored as log == 0 in the tag (tag_ptr |= ilog2(mask) + 1). get_rps_cpu() then calls rfs_slot() -> hash_32(hash, rps_tag_to_log(tag_ptr)) with log == 0: include/linux/hash.h:68 return __hash_32(val) >> (32 - bits); /* bits == 0 -> shift by 32 */ The shift by 32 is undefined and yields the full 32-bit hash, which is used to index the one-entry rps_dev_flow[] table unchecked: UBSAN: shift-out-of-bounds in ./include/linux/hash.h:68:24 shift exponent 32 is too large for 32-bit type 'unsigned int' __ubsan_handle_shift_out_of_bounds+0x11c/0x208 get_rps_cpu+0x12fc/0x1344 netif_rx_internal+0x1e0/0x4d4 rps_dev_flow[] is then read (rflow->cpu) and written (last_qtail) out of bounds on the packet path. Require at least two entries. Fixes: f3483c8e1da6 ("net: rfs: hash function change") Signed-off-by: Dudu Lu <phx0fer@gmail.com> Link: https://patch.msgid.link/20261021155522.67521-1-phx0fer@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
5 daysnet: limit priority VLAN untag depthKamil Sawicki
The priority VLAN receive path can repeatedly remove VID 0 tags and retry packet processing. Unlike the read-only VLAN protocol parser, this path has no limit on the number of nested tags it consumes. Each skb_vlan_untag() advances skb->data and resets header offsets. The offsets are stored in 16-bit fields. With enough nested tags, the network or transport offset can wrap. A later protocol handler can then derive a large pull length from the wrapped offsets and access memory outside the skb allocation. Apply the existing VLAN_MAX_DEPTH limit to the exceptional VID 0 retry. Count the tag already stored in skb VLAN metadata as the first level, then stop before untagging a ninth level. Keep the accounting inside this uncommon branch so the regular VLAN receive path is unaffected. A single VID 0 priority tag before a real VLAN tag is valid. No normal deployment was found that intentionally emits multiple consecutive VID 0 tags; permitting eight levels is therefore conservative. The issue was found while researching the Linux network receive path for Google kvmCTF, with OpenAI Codex (gpt-5.6-sol) assisting the analysis. The affected path, reproducer and fix were manually reviewed and tested. Fixes: 36b2f61a42c2 ("net: handle 802.1P vlan 0 packets properly") Cc: stable@vger.kernel.org Reviewed-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Kamil Sawicki <user148783812897@gmail.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Link: https://patch.msgid.link/20261024004835.17862-1-user148783812897@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
5 daysnet: xps: bound the cleanup loop by the old map's num_tcDudu Lu
__netif_set_xps_queue() walks the OLD dev_maps to free its entries. The per-row trip count uses the NEW num_tc while the row stride uses the OLD dev_maps->num_tc, so when dev->num_tc was raised without rebuilding the XPS map the last row indexes attr_map[] past the allocation: BUG: KASAN: slab-out-of-bounds in __netif_set_xps_queue+0x1458/0x1ee8 Read of size 8 at addr ffff000014f69458 by task insmod/112 The loop frees entries in dev_maps, so both the trip count and the stride must come from dev_maps->num_tc. The map is sized XPS_CPU_DEV_MAPS_SIZE(old num_tc)/XPS_RXQ_DEV_MAPS_SIZE(old num_tc, ...), so iterating the new (larger) num_tc reads past the end. Fixes: 255c04a87f43 ("net: embed num_tc in the xps maps") Signed-off-by: Dudu Lu <phx0fer@gmail.com> Reviewed-by: Antoine Tenart <atenart@kernel.org> Link: https://patch.msgid.link/20261021155538.67867-1-phx0fer@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
5 daysnet: ipv4: add zero check for snd_cwnd_clampKaho Jiang
When RTAX_CWND is locked, user is able to pass 0 into it. This could lead to writing 0 to tp->snd_cwnd, leading to a division by zero error. Oops: divide error: 0000 [#1] SMP KASAN NOPTI Call Trace: <IRQ> tcp_reno_cong_avoid (net/ipv4/tcp_cong.c:510 (discriminator 1)) tcp_ack (net/ipv4/tcp_input.c:3517 net/ipv4/tcp_input.c:3873 net/ipv4/tcp_input.c:4440) tcp_rcv_established (net/ipv4/tcp_input.c:6685) tcp_v4_do_rcv (net/ipv4/tcp_ipv4.c:1854) tcp_v4_rcv (net/ipv4/tcp_ipv4.c:2248) ip_protocol_deliver_rcu (net/ipv4/ip_input.c:207 (discriminator 1)) ip_local_deliver_finish (net/ipv4/ip_input.c:241 (discriminator 1)) ip_local_deliver (./include/linux/netfilter.h:325 ./include/linux/netfilter.h:319 net/ipv4/ip_input.c:262) ip_rcv (./include/net/dst.h:481 (discriminator 6) net/ipv4/ip_input.c:492 (discriminator 6) ./include/linux/netfilter.h:325 (discriminator 6) ./include/li) __netif_receive_skb_one_core (net/core/dev.c:6297 (discriminator 4)) __netif_receive_skb (net/core/dev.c:6410) process_backlog (net/core/dev.c:6761) __napi_poll.constprop.0 (net/core/dev.c:7830) net_rx_action (net/core/dev.c:7893 net/core/dev.c:8050) handle_softirqs (kernel/softirq.c:645) __irq_exit_rcu (kernel/softirq.c:679 kernel/softirq.c:519 kernel/softirq.c:758) irq_exit_rcu (kernel/softirq.c:775) sysvec_apic_timer_interrupt (arch/x86/kernel/apic/apic.c:1062 (discriminator 35) arch/x86/kernel/apic/apic.c:1062 (discriminator 35)) RIP: 0010:tcp_cong_avoid_ai (net/ipv4/tcp_cong.c:482) Fix by checking if user pass in zero as parameter and if lock is present. Fixes: 814d488c6126 ("tcp: fix the timid additive increase on stretch ACKs") Cc: stable@vger.kernel.org Suggested-by: Eric Dumazet <edumazet@kernel.org> Reported-by: co+71b6509cb791e531@bugs.sh Signed-off-by: Kaho Jiang <kj2864@nyu.edu> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Link: https://patch.msgid.link/20261021235732.1313305-2-kj2864@nyu.edu Signed-off-by: Paolo Abeni <pabeni@redhat.com>
5 daysnet/rds: do not initialize transports after rds_init() failedAllison Henderson
rds, rds_rdma and rds_tcp each have their own module_init(). When they are built in, those run in link order, so rds_init() goes first, but do_initcalls() does not stop when it fails. The transports then initialize against a core that has already been torn down: rds_wq has been destroyed, yet rds_ib_dev_put(), rds_ib_unregister_client() and rds_tcp_accept_work() still queue onto or flush it, and rds_trans_register() hands the transports to a core whose socket family may never have been registered. This was seen with CONFIG_SYSCTL=n, where rds_sysctl_init() failed and rds_ib_init()'s error path then flushed the freed rds_wq [1], but any rds_init() failure after rds_threads_init() has the same effect. Record whether rds_init() succeeded and have rds_rdma_init() and rds_tcp_init() bail out with -ENODEV otherwise. Modular builds are unaffected: the transports need symbols exported by rds.ko, so they cannot be loaded unless rds_init() succeeded. [1] https://lore.kernel.org/oe-lkp/202610190310.9737b2e3-lkp@intel.com Fixes: 55b7ed0b582f ("RDS: Common RDMA transport code") Fixes: 70041088e3b9 ("RDS: Add TCP transport to RDS") Suggested-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Allison Henderson <achender@kernel.org> Link: https://patch.msgid.link/20261021195837.142802-3-achender@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
5 daysnet/rds: do not fail init when CONFIG_SYSCTL=nAllison Henderson
With CONFIG_SYSCTL=n, register_net_sysctl() and register_net_sysctl_sz() are inline stubs that return NULL. rds_sysctl_init(), rds_ib_sysctl_init() and rds_tcp_init_net() all treat that NULL as -ENOMEM, so RDS refuses to initialize at all even though every tunable has a sane compiled-in default. When RDS is built in, that is worse than a missing feature: the failed rds_init() destroys rds_wq, but the rds_rdma initcall still runs, and when rds_ib_sysctl_init() fails the same way, the error path in rds_ib_init() flushes the already freed workqueue: BUG: KASAN: slab-use-after-free in touch_wq_lockdep_map ... __flush_workqueue rds_ib_init rds_rdma_init ... Allocated by task 1: alloc_workqueue_noprof rds_threads_init rds_init ... Freed by task 0: kfree rcu_do_batch Only treat the NULL return as a failure when sysctl support is actually compiled in. The exit paths need no change: unregister_net_sysctl_table() is an empty stub with CONFIG_SYSCTL=n and already tolerates a NULL header otherwise. The underlying problem of built-in transports initializing after rds_init() has failed is independent of sysctl and is addressed separately. Reported-by: kernel test robot <yi1.lai@intel.com> Closes: https://lore.kernel.org/oe-lkp/202610190310.9737b2e3-lkp@intel.com Fixes: 3e5048495c85 ("RDS: sysctls") Fixes: e6babe4cc4ce ("RDS/IB: Stats and sysctls") Fixes: c6a58ffed536 ("RDS: TCP: Add sysctl tunables for sndbuf/rcvbuf on rds-tcp socket") Suggested-by: Joel Granados <joel.granados@kernel.org> Signed-off-by: Allison Henderson <achender@kernel.org> Reviewed-by: Joel Granados <joel.granados@kernel.org> Acked-by: Oleg Nesterov <oleg@redhat.com> Link: https://patch.msgid.link/20261021195837.142802-2-achender@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
6 daysxsk: restore UMEM flags after failed pool assignmentPaul Moses
xp_assign_dev() sets XDP_UMEM_SG_FLAG before checking whether the device supports multibuffer zero-copy. If assignment fails, xsk_bind() destroys the pool but retains the registered UMEM. A subsequent bind without XDP_USE_SG inherits the stale flag. The flag also changes RX buffer sizing after DMA mapping. On igc, a failed SG bind followed by a non-SG retry with 4096-byte chunks and 1792 bytes of headroom passes admission with 2048 bytes, but programs a 1024-byte RX buffer. On I225-V hardware, an ordinary 1514-byte frame is truncated to 1024 bytes or 1008 with RX timestamps enabled. Restoring the original flags eliminates the truncation in both cases. Save the UMEM flags before assignment and restore them on failure. Discovered during development of AF_XDP changes for igc. Fixes: d609f3d228a8 ("xsk: add multi-buffer support for sockets sharing umem") Cc: stable@vger.kernel.org Signed-off-by: Paul Moses <p@1g4.org> Acked-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> Link: https://patch.msgid.link/20261021224705.2078753-1-p@1g4.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daystcp: limit tcp_tso_rtt_log to a valid shift countYingjie Wang
tcp_tso_autosize() right-shifts the u32 returned by tcp_min_rtt() by sysctl_tcp_tso_rtt_log. The sysctl uses proc_dou8vec_minmax() without an upper bound, so it accepts values through 255. Values above 31 make the shift undefined. A process with CAP_NET_ADMIN in the target network namespace can set the per-netns sysctl. With CONFIG_UBSAN_SHIFT=y, setting it to 32 and sending TCP data over loopback triggers: UBSAN: shift-out-of-bounds in net/ipv4/tcp_output.c:2264:30 shift exponent 32 is too large for 32-bit type 'unsigned int' Call Trace: __ubsan_handle_shift_out_of_bounds tcp_tso_segs tcp_write_xmit __tcp_push_pending_frames tcp_push tcp_sendmsg_locked Limit the sysctl to 31, the largest valid shift count for a u32, and document the accepted range. Writes of larger values now fail with -EINVAL. On a UBSAN/KASAN build of the net tree, values 0 and 31 remained accepted, values 32 and 255 returned -EINVAL, and TCP traffic with the valid boundary values produced no sanitizer diagnostics. Fixes: 65466904b015 ("tcp: adjust TSO packet sizes based on min_rtt") Cc: stable@vger.kernel.org Signed-off-by: Yingjie Wang <1075151112@qq.com> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev> Reviewed-by: Neal Cardwell <ncardwell@google.com> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Link: https://patch.msgid.link/tencent_31D2FFCCE76C50A695A1270151F825E90906@qq.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daystipc: fix refcount panic in tipc_rcv() when receiving shared skbTung Nguyen
TIPC assumes that the received skb is not shared with other users. However, syzbot reports a bug triggered by receiving a shared skb: ... RIP: 0010:pskb_expand_head+0x135a/0x13a0 net/core/skbuff.c:2308 __pskb_pull_tail+0x111/0x1870 net/core/skbuff.c:2890 skb_cow_data+0x2ed/0xc50 net/core/skbuff.c:5398 tipc_aead_decrypt net/tipc/crypto.c:892 [inline] tipc_crypto_rcv+0x346/0x23d0 net/tipc/crypto.c:1843 tipc_rcv+0x4b7/0x1040 net/tipc/node.c:2119 tipc_l2_rcv_msg+0x2d9/0x470 net/tipc/bearer.c:669 deliver_ptype_list_skb net/core/dev.c:2533 [inline] ... The root cause is that local delivery hooks in the kernel (e.g., deliver_skb()) may increment the skb's reference count (`users`) before TIPC processes it on ingress. Fix this by calling skb_share_check() to ensure exclusive ownership before passing the skb to tipc_rcv(). As TIPC needs to modify the skb's data, the cloned skb needs to be uncloned when needed. This can be addressed in separate patch. Reported-by: syzbot+0017742620a9d06f06ef@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0017742620a9d06f06ef Closes: https://lore.kernel.org/all/20261018145928.58317-1-ngocthang2710.1999@gmail.com/T/ Fixes: b97bf3fd8f6a ("[TIPC] Initial merge") Co-developed-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com> Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com> Signed-off-by: Tung Nguyen <tung.quang.nguyen@est.tech> Link: https://patch.msgid.link/20261023052921.54220-1-tung.quang.nguyen@est.tech Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daysipmr: drop packets with unknown ingress VIFZhiling Zou
A packet can race with VIF publication and make ipmr_find_vif() return -1 even though the VIF device pointer is already visible. The parent VIF device check can then pass with an invalid ingress VIF. For (*,G) entries, this can also let the packet be forwarded back out its ingress VIF. Drop packets whose ingress VIF lookup fails in both IPv4 and IPv6 forwarding, before checking the MFC parent device. This prevents forwarding with an unknown ingress VIF and avoids the (*,G) hairpin. Without the early check, the negative index can reach the IPv4 offload lookup only for an skb marked for L3 forwarding offload, currently done by mlxsw. The race is rare; the supplied PoC reports only the UBSAN negative-index diagnostic. Fixes: 4eadb88244d1 ("ipmr: do not acquire mrt_lock while calling ip_mr_forward()") Fixes: 9b1c21d898fd ("ip6mr: do not acquire mrt_lock while calling ip6_mr_forward()") Cc: stable@vger.kernel.org Reported-by: Vega <vega@nebusec.ai> Link: https://lore.kernel.org/netdev/b966eb102e98f299e45be59ada033a8766e4c6df.1791899747.git.zhilinz@nebusec.ai/ Suggested-by: Ido Schimmel <idosch@nvidia.com> Suggested-by: Naman Gulati <namangulati@google.com> Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai> Reviewed-by: Naman Gulati <namangulati@google.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/5271fcb94a4d9e697ed64a348e92ea9e74faab1c.1792608753.git.zhilinz@nebusec.ai Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daysipmr, ip6mr: validate packets injected into the register vif on xmitIdo Schimmel
reg_vif_xmit() passes the packet to ipmr_cache_report() which copies its IP header into the IGMPMSG_WHOLEPKT report that is queued to the mroute socket. Nothing guarantees that the packet contains a full IP header, so when a short packet is injected on the register device (e.g., using AF_PACKET), the copy reads past the end of the packet and a recvmsg() on the mroute socket leaks the uninitialized bytes to user space [1]. IPv6 has the same problem [2]. Its reg_vif_xmit() does call pskb_inet_may_pull(), but the helper keys off skb->protocol and does not pull anything when the protocol is neither IPv4 nor IPv6. Fix by dropping packets whose protocol does not match the address family of the register device or that do not contain a full network header. [1] BUG: KMSAN: kernel-infoleak in _copy_to_iter raw_recvmsg Uninit was stored to memory at: ipmr_cache_report reg_vif_xmit packet_sendmsg Uninit was created at: __alloc_skb sock_alloc_send_pskb packet_sendmsg Bytes 1-3 of 21 are uninitialized [2] BUG: KMSAN: kernel-infoleak in _copy_to_iter rawv6_recvmsg Uninit was stored to memory at: ip6mr_cache_report reg_vif_xmit packet_sendmsg Uninit was created at: __alloc_skb sock_alloc_send_pskb packet_sendmsg Bytes 8-23 of 41 are uninitialized Fixes: 14fb64e1f449 ("[IPV6] MROUTE: Support PIM-SM (SSM).") Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Reported-by: Sashiko <netdev-bot+sashiko@kernel.org> Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/0545f0c83f5ee2f6696210f87268e811ef655715.1792476357.git.zhilinz%40nebusec.ai Signed-off-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Link: https://patch.msgid.link/20261025071729.34967-3-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daysipmr: fully initialize the synthetic IP header in ipmr_get_route()Ido Schimmel
For an unresolved multicast route query, ipmr_get_route() builds a synthetic IP header in the headroom obtained from skb_realloc_headroom(), which does not zero the memory it allocates. Only a few fields are initialized, leaving others as stale heap contents. ipmr_cache_report() copies this header into the IGMPMSG_NOCACHE report that is queued to the mroute socket, so a recvmsg() on that socket leaks the uninitialized bytes to user space: the 'tos' field [1] and the 'id' and 'frag_off' fields [2]. Fix by zeroing the IP header before filling in the few fields that are used, so that the entire header is initialized, as in ip6mr_get_route(). [1] BUG: KMSAN: kernel-infoleak in _copy_to_iter raw_recvmsg Uninit was stored to memory at: ipmr_cache_report ipmr_cache_unresolved ipmr_get_route Uninit was created at: pskb_expand_head skb_realloc_headroom ipmr_get_route Byte 1 of 28 is uninitialized [2] BUG: KMSAN: kernel-infoleak in _copy_to_iter raw_recvmsg Uninit was stored to memory at: ipmr_cache_report ipmr_cache_unresolved ipmr_get_route Uninit was created at: pskb_expand_head skb_realloc_headroom ipmr_get_route Bytes 4-7 of 28 are uninitialized Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Reported-by: Sashiko <netdev-bot+sashiko@kernel.org> Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/0545f0c83f5ee2f6696210f87268e811ef655715.1792476357.git.zhilinz%40nebusec.ai Signed-off-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Link: https://patch.msgid.link/20261025071729.34967-2-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daysipmr: clear skb->cb[] in reg_vif_xmit()Eric Dumazet
reg_vif_xmit() hands the skb to ipmr_cache_report() as an IGMPMSG_WHOLEPKT report. When the mroute socket has IP_PKTINFO enabled, ipmr_cache_report() calls ipv4_pktinfo_prepare() on the original skb, which reads skb->cb[] as IPCB. By the time the pimreg device transmits the packet, skb->cb[] is not IPCB anymore: qdisc_pkt_len_init() overwrites IPCB(skb)->iif with qdisc_skb_cb(skb)->pkt_len, and any qdisc installed on the device or a tc BPF program writing skb->cb[] fills the area holding the IP options and IPCB(skb)->flags. For locally generated packets routed out pimreg (they carry an rtable dst), the mroute socket can therefore receive a bogus ipi_ifindex (the packet length), and the l3mdev slave test in ipv4_pktinfo_prepare() is driven by stale qdisc data. Clear IPCB before building the report, as done for IPv6 in commit 238164201431 ("ip6mr: clear skb->cb[] in reg_vif_xmit()"). The skb is freed right after, so nothing else depends on its control block. Fixes: bb7403655b3c ("ipmr: support IP_PKTINFO on cache report IGMP msg") Signed-off-by: Eric Dumazet <edumazet@kernel.org> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn> Link: https://patch.msgid.link/20261025111337.142787-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daysnet: harden qdisc_pkt_len_segs_init() against malicious GSO packetsEric Dumazet
An SKB_GSO_DODGY packet can carry untrusted gso_size and headers. For instance, gso_size=1 and hdr_len=65532 for a 524275-byte frame makes qdisc_pkt_len_segs_init() compute an accounted length of about 4,294,574,091 bytes (after gso_segs silently wrapped in a u16). With DRR quantum 256, the dequeue path then needs ~16.8 million deficit refills before it can dequeue the skb, keeping the CPU in the qdisc path long enough to trigger the soft-lockup watchdog. Commit 8f735d64382d ("net/sched: bound qdisc_pkt_len to prevent qdisc soft lockup") added QDISC_PKT_LEN_MAX to bound size table amplification. Use the same bound for DODGY packets: - Make gso_segs a u32 and drop packets whose segment count does not fit GSO_MAX_SEGS, instead of silently truncating it. - Drop packets whose estimated qdisc_pkt_len() would exceed QDISC_PKT_LEN_MAX. Fixes: 15e5a0307164 ("net_sched: better precise estimation on packet length for untrusted packets") Reported-by: shaos <shawnq1@163.com> Closes: https://lore.kernel.org/netdev/20261022144755.65025-1-shawnq1@163.com/ Signed-off-by: Eric Dumazet <edumazet@kernel.org> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: "Michael S. Tsirkin" <mst@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20261022155436.117507-1-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daysnet/sched: taprio: unwind the netdevice notifier if register_qdisc() failsDudu Lu
taprio_module_init() registers taprio_device_notifier and then returns register_qdisc()'s error directly. When register_qdisc() fails the notifier stays registered, but the loader's failure path frees the module image without ever calling the __exit function, so netdev_chain is left pointing at taprio_device_notifier.notifier_call -- a function pointer that lives in text that has just been freed. register_qdisc() has two failure returns: -EEXIST (duplicate .id) and -EINVAL (malformed cl_ops). taprio_class_ops satisfies every checked implication, so -EINVAL is unreachable and -EEXIST is the only reachable failure; it needs a pre-existing "taprio" entry in qdisc_base. In-tree that is reachable only through bpf_qdisc_reg() (CONFIG_NET_SCH_BPF); a module calling the exported register_qdisc() reaches it as well. Once the notifier is left dangling, the next netdevice event that walks netdev_chain calls through the stale pointer: BUG: KASAN: vmalloc-out-of-bounds in notifier_call_chain+0x650/0xb5c Read of size 8 at addr ffff80001fc5ab08 by task ip/110 notifier_call_chain+0x650/0xb5c raw_notifier_call_chain+0x34/0x64 call_netdevice_notifiers_info+0xa8/0x198 __dev_close_many+0xe0/0x800 ... >ffff80001fc5ab00: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 The shadow row is all f8 (KASAN_VMALLOC_INVALID): the read lands in vmalloc memory that was poisoned when the module image was freed, and the indirect call is unguarded because the only check, func_ptr_is_kernel_text(), is compiled out unless CONFIG_DEBUG_NOTIFIERS. Mirror the sibling sch_cbs.c and act_mirred.c, which unwind the notifier on this failure path. Fixes: 7b9eba7ba0c1 ("net/sched: taprio: fix picos_per_byte miscalculation") Signed-off-by: Dudu Lu <phx0fer@gmail.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20261021155417.66254-1-phx0fer@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daysnet/sched: act_api: inherit filter offload flags only on new actionsAlexandre Cassen
tcf_action_init() gives the skip_sw and skip_hw flags of a filter to the actions it binds. An action that another filter created gets them too, they then apply to every filter that uses this action. When a skip_sw filter reuses the action of a software filter, the software filter silently stops running it. This happens even when the filter add fails on a later action. A skip_hw filter likewise prevents a later filter without flags from reusing the action. Give the flags only to the actions that the filter creates. The mismatch check still rejects a filter that reuses an action with a flag that the filter does not have. Discovered by manual code inspection after the Sashiko AI review [1] of a tunnel_key patch questioned how actions get the filter flags. Reproduced on netdevsim without kernel changes. The egress filter below runs in software only, since netdevsim offloads only ingress filters. Once the skip_sw filter reuses its drop action, the last command shows skip_sw on this action and the egress filter stops dropping packets: ethtool -K eth0 hw-tc-offload on tc qdisc add dev eth0 clsact tc filter add dev eth0 egress protocol ip flower dst_ip 192.0.2.1 \ action gact drop index 1 tc filter add dev eth0 ingress protocol ip flower skip_sw \ dst_ip 192.0.2.2 action gact drop index 1 tc actions get action gact index 1 Tested with the reproducer and the tc-testing action, matchall and flower tests. Fixes: 34d35b4edbbe ("net/sched: act_api: deny mismatched skip_sw/skip_hw flags for actions created by classifiers") Link: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261009051930.3619697-1-acassen%40corp.free.fr [1] Signed-off-by: Alexandre Cassen <acassen@corp.free.fr> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20261021193222.1318333-2-acassen@corp.free.fr Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 daysnet/sched: gred: keep the qdisc lock while updating the tableDudu Lu
gred_change_table_def() publishes table->DPs/def/red_flags under sch_tree_lock(), drops the lock, and then keeps writing state the datapath reads without it: - gred_enable_rio_mode()/gred_disable_rio_mode()/gred_disable_wred_mode() set/clear table->flags; - the red_flags_changed loop writes table->tab[i]->red_flags; - the shadowed-VQ loop frees table->tab[i] and clears the slot. gred_enqueue() and gred_dequeue() read those same fields (test_bit on table->flags, q->red_flags, t->tab[]/t->DPs) under the same root lock on another CPU, so the post-unlock writes race with the enqueue path: BUG: KCSAN: data-race in gred_change_table_def [sch_gred] / gred_enqueue [sch_gred] read (marked) to 0xffff000007ad3b00 of 8 bytes by task 110 on cpu 0: gred_enqueue+0x88/0xc60 [sch_gred] dev_qdisc_enqueue+0x4c/0x19c __dev_queue_xmit+0x10a4/0x1ea4 The comment justifying the early unlock only covers the DP-vs-DPs check, which the shadowed-VQ free loop relies on; it does not cover the scalar mode bits and per-VQ red_flags written afterwards. Move the unlock below those updates so everything the datapath reads is published under the lock that protects it. Fixes: 6639607ed9de ("[PKT_SCHED]: GRED: Use a central table definition change procedure") Signed-off-by: Dudu Lu <phx0fer@gmail.com> Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Daniel Machon <daniel.machon@microchip.com> Link: https://patch.msgid.link/20261021155434.66572-1-phx0fer@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
6 dayslibceph: initialize CRUSH choose argument weightsDarong Lu
Initialize the CRUSH choose argument weight-set array before decoding so entries start in a defined state while the decoder fills them. Cc: stable@vger.kernel.org Fixes: 5cf9c4a9959b ("libceph, crush: per-pool crush_choose_arg_map for crush_do_rule()") Reported-by: Vega <vega@nebusec.ai> Assisted-by: LLM Signed-off-by: Darong Lu <zzyy19904204639@163.com> Signed-off-by: Ren Wei <weir@nebusec.ai> Reviewed-by: Alex Markuze <amarkuze@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>