6.12.92-rc1 review
Subsystems (4)
Greg Kroah-Hartman
maintainercover 6.12.92-rc1 review
This is the start of the stable review cycle for the 6.12.92 release. There are 272 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sat, 30 May 2026 19:45:52 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.92-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.12.92-rc1
Matthieu Buffet <[email protected]>
landlock: Fix TCP handling of short AF_UNSPEC addresses
Tiezhu Yang <[email protected]>
LoongArch: kprobes: Fix handling of fatal unrecoverable recursions
Sabrina Dubroca <[email protected]>
net: gro: don't merge zcopy skbs
Nikhil P. Rao <[email protected]>
pds_core: ensure null-termination for firmware version strings
Aditya Garg <[email protected]>
net: mana: validate rx_req_idx to prevent out-of-bounds array access
Ratheesh Kannoth <[email protected]>
octeontx2-af: npc: Fix allmulticast skip logic for LBK and SDP VFs
Shuicheng Lin <[email protected]>
drm/xe/oa: Fix exec_queue leak on width check in stream open
Richard Fitzgerald <[email protected]>
ASoC: cs35l56: Fix flushing of IRQ work in cs35l56_sdw_remove()
Bartosz Golaszewski <[email protected]>
gpio: cdev: check if uAPI v2 config attributes are correctly zeroed
Andy Shevchenko <[email protected]>
gpiolib: cdev: use !mem_is_zero() instead of memchr_inv(s, 0, n)
Xingwang Xiang <[email protected]>
bpf, skmsg: fix verdict sk_data_ready racing with ktls rx
Rosen Penev <[email protected]>
net: ag71xx: check error for platform_get_irq
Jiajia Liu <[email protected]>
Bluetooth: btmtk: fix urb->setup_packet leak in error paths
David Carlier <[email protected]>
tracing: Avoid NULL return from hist_field_name() on truncation
Zhang Cen <[email protected]>
ALSA: seq: Serialize UMP output teardown with event_input
Johannes Berg <[email protected]>
wifi: mac80211: fix MLE defragmentation
Nikhil P. Rao <[email protected]>
pds_core: fix debugfs_lookup dentry leak and error handling
Nikhil P. Rao <[email protected]>
pds_core: fix error handling in pdsc_devcmd_wait
Ido Schimmel <[email protected]>
bridge: mcast: Fix a possible use-after-free when removing a bridge port
Petr Machata <[email protected]>
net: bridge: Flush multicast groups when snooping is disabled
Guangshuo Li <[email protected]>
RDMA/rtrs: Fix use-after-free in path file creation cleanup
Rafael J. Wysocki <[email protected]>
platform/x86: intel-vbtn: Check ACPI_HANDLE() against NULL
Rafael J. Wysocki <[email protected]>
platform/x86: intel-hid: Check ACPI_HANDLE() against NULL
Rafael J. Wysocki <[email protected]>
platform/x86: hp_accel: Check ACPI_COMPANION() against NULL
Rafael J. Wysocki <[email protected]>
platform/x86: adv_swbutton: Check ACPI_HANDLE() against NULL
Oliver White <[email protected]>
platform/surface: aggregator_registry: omit battery & AC nodes on Surface Laptop 7
Erni Sri Satya Vennela <[email protected]>
net: mana: Fix TOCTOU double-fetch of hwc_msg_id from DMA buffer
Daniel Golle <[email protected]>
net: dsa: mt7530: preserve VLAN tags on trapped link-local frames
Daniel Golle <[email protected]>
net: dsa: mt7530: fix FDB entries not aging out with short timeout
Viktor Jägersküpper <[email protected]>
kbuild: pacman-pkg: make "rc" releases adhere to pacman versioning scheme
Ankit Nautiyal <[email protected]>
drm/i915/dp: Fix readback for target_rr in Adaptive Sync SDP
Grzegorz Nitka <[email protected]>
ice: ptp: serialize E825 PHY timer start with PTP lock
Matthew Leach <[email protected]>
wifi: ath11k: fix peer resolution on rx path when peer_id=0
Mohanram Meenakshisundaram <[email protected]>
drm/xe/pf: Fix CFI failure in debugfs access
Michal Wajdeczko <[email protected]>
drm/xe/vf: Fix signature of print functions
Shuicheng Lin <[email protected]>
drm/xe/gsc: Fix double-free of managed BO in error path
Dmitry Baryshkov <[email protected]>
drm/msm/snapshot: fix dumping of the unaligned regions
Felix Gu <[email protected]>
spi: mtk-snfi: Fix resource leak in mtk_snand_read_page_cache()
Boris Burkov <[email protected]>
btrfs: fix squota accounting during enable generation
Jens Axboe <[email protected]>
io_uring/net: punt IORING_OP_BIND async if it needs file create
Robertus Diawan Chris <[email protected]>
ALSA: scarlett2: Add missing error check when initialise Autogain Status
Mike Christie <[email protected]>
scsi: sd: Fix return code handling in sd_spinup_disk()
Jeroen Massar <[email protected]>
net/mlx5: Do not restore destination-less TC rules
Chuck Lever <[email protected]>
tls: Preserve sk_err across recvmsg() when data has been copied
Juergen Gross <[email protected]>
x86/xen: Fix xen_e820_swap_entry_with_ram()
Sven Schuchmann <[email protected]>
net: phy: DP83TC811: add reading of abilities
Jakub Kicinski <[email protected]>
net: tls: prevent chain-after-chain in plain text SG
Jakub Kicinski <[email protected]>
net: tls: fix off-by-one in sg_chain entry count for wrapped sk_msg ring
Xiang Mei <[email protected]>
net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot
Sayali Patil <[email protected]>
powerpc/time: Remove redundant preempt_disable|enable() calls from arch_irq_work_raise()
Mikko Perttunen <[email protected]>
drm/msm: Fix iommu_map_sgtable() return value check and avoid WARN
Dmitry Baryshkov <[email protected]>
drm/msm/dsi: don't dump registers past the mapped region
Chenguang Zhao <[email protected]>
ethtool: fix ethnl_bitmap32_not_zero() bit interval semantics
Xiang Mei <[email protected]>
net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint
Zack McKevitt <[email protected]>
accel/qaic: Add overflow check to remap_pfn_range during mmap
Sungwoo Kim <[email protected]>
block: bio-integrity: Fix null-ptr-deref in bio_integrity_map_user()
Keith Busch <[email protected]>
blk-integrity: enable p2p source and destination
Keith Busch <[email protected]>
blk-integrity: use simpler alignment check
Caleb Sander Mateos <[email protected]>
block: drop direction param from bio_integrity_copy_user()
Anuj Gupta <[email protected]>
block: modify bio_integrity_map_user to accept iov_iter as argument
Lukas Bulwahn <[email protected]>
HID: quirks: really enable the intended work around for appledisplay
Casey Chen <[email protected]>
block: recompute nr_integrity_segments in blk_insert_cloned_request
David Carlier <[email protected]>
block: don't overwrite bip_vcnt in bio_integrity_copy_user()
Keith Busch <[email protected]>
blk-integrity: remove seed for user mapped buffers
Kang Yang <[email protected]>
wifi: ath10k: skip WMI and beacon transmission when device is wedged
Nicolas Escande <[email protected]>
wifi: ath11k: fix error path leak in ath11k_tm_cmd_wmi_ftm()
Nicolas Escande <[email protected]>
wifi: ath11k: fix error path leaks in some WMI WOW calls
Ethan Nelson-Moore <[email protected]>
net: ethernet: cs89x0: remove stale CONFIG_MACH_MX31ADS reference
Linus Walleij <[email protected]>
net: ethernet: cortina: Carry over frag counter
Andreas Haarmann-Thiemann <[email protected]>
net: ethernet: cortina: Drop half-assembled SKB
Linus Walleij <[email protected]>
net: ethernet: cortina: Make RX SKB per-port
David Howells <[email protected]>
netfs: Fix folio->private handling in netfs_perform_write()
Matthew Wilcox (Oracle) <[email protected]>
netfs: Remove unnecessary references to pages
Matthew Wilcox (Oracle) <[email protected]>
netfs: Fix a few minor bugs in netfs_page_mkwrite()
David Howells <[email protected]>
netfs: Fix partial invalidation of streaming-write folio
David Howells <[email protected]>
netfs: Fix early put of sink folio in netfs_read_gaps()
David Howells <[email protected]>
netfs: Fix write streaming disablement if fd open O_RDWR
David Howells <[email protected]>
netfs: Fix potential deadlock in write-through mode
David Howells <[email protected]>
netfs: Fix streaming write being overwritten
David Howells <[email protected]>
netfs: Defer the emission of trace_netfs_folio()
David Howells <[email protected]>
netfs: Fix netfs_invalidate_folio() to clear dirty bit if all changes gone
David Howells <[email protected]>
netfs: Fix overrun check in netfs_extract_user_iter()
Viacheslav Dubeyko <[email protected]>
netfs: fix VM_BUG_ON_FOLIO() issue in netfs_write_begin() call
Julian Braha <[email protected]>
powerpc: fix dead default for GUEST_STATE_BUFFER_TEST
Kuniyuki Iwashima <[email protected]>
tcp: Fix out-of-bounds access for twsk in tcp_ao_established_key().
Johannes Thumshirn <[email protected]>
zonefs: handle integer overflow in zonefs_fname_to_fno
Jiayuan Chen <[email protected]>
irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT
Zhihao Cheng <[email protected]>
nsfs: fix wrong error code returned for pidns ioctls
Ming Lei <[email protected]>
ublk: reject max_sectors smaller than PAGE_SECTORS in parameter validation
Rosen Penev <[email protected]>
irqchip/ath79-cpu: Remove unused function
Chuck Lever <[email protected]>
NFSD: Fix infinite loop in layout state revocation
Gabor Juhos <[email protected]>
phy: marvell: mvebu-a3700-utmi: fix incorrect USB2_PHY_CTRL register access
Myeonghun Pak <[email protected]>
net: lan966x: avoid unregistering netdev on register failure
Bart Van Assche <[email protected]>
ice: fix locking in ice_dcb_rebuild()
Marcin Szycik <[email protected]>
ice: fix setting RSS VSI hash for E830
Kuniyuki Iwashima <[email protected]>
tcp: Fix imbalanced icsk_accept_queue count.
Martin Kaiser <[email protected]>
test_kprobes: clear kprobes between test runs
Jianpeng Chang <[email protected]>
kprobes: skip non-symbol addresses in kprobe_add_ksym_blacklist()
Florian Westphal <[email protected]>
netfilter: bridge: eb_tables: close module init race
Florian Westphal <[email protected]>
netfilter: x_tables: close dangling table module init race
Florian Westphal <[email protected]>
netfilter: ebtables: close dangling table module init race
Florian Westphal <[email protected]>
netfilter: ebtables: move to two-stage removal scheme
Florian Westphal <[email protected]>
netfilter: x_tables: add and use xtables_unregister_table_exit
Florian Westphal <[email protected]>
netfilter: x_tables: add and use xt_unregister_table_pre_exit
Pablo Neira Ayuso <[email protected]>
netfilter: Exclude LEGACY TABLES on PREEMPT_RT.
Breno Leitao <[email protected]>
netfilter: Make legacy configs user selectable
Florian Westphal <[email protected]>
netfilter: x_tables: unregister the templates first
Filipe Manana <[email protected]>
btrfs: tracepoints: fix sleep while in atomic context in btrfs_sync_file()
Shuhao Fu <[email protected]>
ALSA: hda: cs35l41: Put ACPI device on missing physical node
Shuhao Fu <[email protected]>
ALSA: hda: cs35l56: Put ACPI device after setting companion
Guenter Roeck <[email protected]>
ARM: integrator: Fix early initialization
Sudeep Holla <[email protected]>
firmware: arm_ffa: Fix sched-recv callback partition lookup
Sudeep Holla <[email protected]>
firmware: arm_ffa: Align RxTx buffer size before mapping
Sudeep Holla <[email protected]>
firmware: arm_ffa: Bound PARTITION_INFO_GET_REGS copies
Sudeep Holla <[email protected]>
firmware: arm_ffa: Fix big-endian support in __ffa_partition_info_regs_get()
Maulik Shah <[email protected]>
pinctrl: qcom: Fix wakeirq map by removing disconnected irqs for sm8150
David Gow <[email protected]>
kunit: config: KUNIT_DEBUGFS should depend on DEBUG_FS
David Gow <[email protected]>
kunit: config: Enable KUNIT_DEBUGFS by default
Guo Ren (Alibaba DAMO Academy) <[email protected]>
riscv: mm: Fixup no5lvl failure when vaddr is invalid
Sudeep Holla <[email protected]>
firmware: arm_ffa: Unregister bus notifier on teardown for FF-A v1.0
Sudeep Holla <[email protected]>
firmware: arm_ffa: Allow multiple UUIDs per partition to register SRI callback
Sudeep Holla <[email protected]>
firmware: arm_ffa: Remove unnecessary declaration of ffa_partitions_cleanup()
Sudeep Holla <[email protected]>
firmware: arm_ffa: Unregister the FF-A devices when cleaning up the partitions
Viresh Kumar <[email protected]>
firmware: arm_ffa: Refactor addition of partition information into XArray
Sudeep Holla <[email protected]>
firmware: arm_ffa: Fix per-vcpu self notifications handling in workqueue
Sudeep Holla <[email protected]>
firmware: arm_ffa: Skip free_pages on RX buffer alloc failure
Sudeep Holla <[email protected]>
firmware: arm_ffa: Check for NULL FF-A ID table while driver registration
Takashi Iwai <[email protected]>
HID: uclogic: Fix regression of input name assignment
Biju Das <[email protected]>
pinctrl: renesas: rzg2l: Fix incorrect PUPD register offset for high pins during suspend/resume
Marek Vasut <[email protected]>
ARM: dts: renesas: rskrza1: Drop superfluous cells
Marek Vasut <[email protected]>
ARM: dts: renesas: genmai: Drop superfluous cells
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) reject short block-read responses in the GPIO accessors
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) register the nvmem device after pmbus_do_probe()
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) register the gpio_chip after pmbus_do_probe()
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) don't clobber GPIO bits before PDIO read in get_multiple
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) cap PDIO scan in get_multiple at ADM1266_PDIO_NR
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) bounce blackbox records through a protocol-sized buffer
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) include PEC byte in pmbus_block_xfer read buffer
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) reject implausible blackbox record_count
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) seed timestamp from the real-time clock
Sven Eckelmann <[email protected]>
batman-adv: tt: fix negative tt_buff_len
Sven Eckelmann <[email protected]>
batman-adv: tt: fix negative last_changeset_len
Sven Eckelmann <[email protected]>
batman-adv: tp_meter: fix race condition in send error reporting
Sven Eckelmann <[email protected]>
batman-adv: tp_meter: fix tp_vars reference leak in receiver shutdown
Sven Eckelmann <[email protected]>
batman-adv: tp_meter: avoid use of uninit sender vars
Sven Eckelmann <[email protected]>
batman-adv: bla: fix report_work leak on backbone_gw purge
Sven Eckelmann <[email protected]>
batman-adv: frag: disallow unicast fragment in fragment
Luxiao Xu <[email protected]>
batman-adv: fix tp_meter counter underflow during shutdown
Ruide Cao <[email protected]>
batman-adv: fix fragment reassembly length accounting
Sven Eckelmann <[email protected]>
batman-adv: dat: handle forward allocation error
Ruijie Li <[email protected]>
batman-adv: clear current gateway during teardown
Sven Eckelmann <[email protected]>
batman-adv: mcast: fix use-after-free in orig_node RCU release
Harry Wentland <[email protected]>
drm/amd/display: Validate payload length and link_index in dc_process_dmub_aux_transfer_async
Harry Wentland <[email protected]>
drm/amd/display: Validate GPIO pin LUT table size before iterating
Harry Wentland <[email protected]>
drm/amd/display: Fix integer overflow in bios_get_image()
Osama Abdelkader <[email protected]>
drm/bridge: megachips: remove bridge when irq request fails
Julien Chauveau <[email protected]>
drm/bridge: it66121: acquire reset GPIO in probe
Alan Liu <[email protected]>
drm/amdgpu/vpe: Force collaborate sync after TRAP
Deepanshu Kartikey <[email protected]>
drm/virtio: use uninterruptible resv lock for plane updates
Bartosz Golaszewski <[email protected]>
device property: set fwnode->secondary to NULL in fwnode_init()
Huacai Chen <[email protected]>
LoongArch: Remove unused code to avoid build warning
Michael Bommarito <[email protected]>
RDMA/siw: Reject MPA FPDU length underflow before signed receive math
Johan Hovold <[email protected]>
spi: ti-qspi: fix use-after-free after DMA setup failure
Johan Hovold <[email protected]>
spi: sprd: fix error pointer deref after DMA setup failure
Johan Hovold <[email protected]>
spi: ep93xx: fix error pointer deref after DMA setup failure
Michael Bommarito <[email protected]>
scsi: isci: Fix use-after-free in device removal path
Wayne Chang <[email protected]>
phy: tegra: xusb: Fix per-pad high-speed termination calibration
Johan Hovold <[email protected]>
spi: qup: fix error pointer deref after DMA setup failure
Osama Abdelkader <[email protected]>
drm/bridge: chipone-icn6211: use devm_drm_bridge_add in i2c probe
Osama Abdelkader <[email protected]>
riscv: kvm: return SBI_ERR_FAILURE for pmu_snapshot_set_shmem() when OOM
Michael Bommarito <[email protected]>
KVM: arm64: vgic: Free private_irqs when init fails after allocation
Michael Bommarito <[email protected]>
KVM: arm64: vgic-its: Reject restored DTE with out-of-range num_eventid_bits
Vladimir Murzin <[email protected]>
arm64: probes: Handle probes on hinted conditional branch instructions
Masami Hiramatsu (Google) <[email protected]>
tracing: Do not call map->ops->elt_free() if elt_alloc() fails
Zhihao Cheng <[email protected]>
cifs: Fix busy dentry used after unmounting
Michael Bommarito <[email protected]>
wifi: mac80211: consume only present negotiated TTLM maps
Jann Horn <[email protected]>
af_unix: Fix UAF read of tail->len in unix_stream_data_wait()
John Walker <[email protected]>
wifi: cfg80211: advance loop vars in cfg80211_merge_profile()
Grzegorz Nitka <[email protected]>
ice: restore PTP Rx timestamp config after ethtool set-channels
Marcin Szycik <[email protected]>
ice: fix setting promisc mode while adding VID filter
Sam Daly <[email protected]>
octeontx2-af: CGX: add bounds check to cgx_speed_mbps index
Stephen Smalley <[email protected]>
lsm: hold cred_guard_mutex for lsm_set_self_attr()
Ilya Dryomov <[email protected]>
rbd: eliminate a race in lock_dwork draining on unmap
Michael Bommarito <[email protected]>
ixgbevf: fix use-after-free in VEPA multicast source pruning
Michael Bommarito <[email protected]>
ipv4: raw: reject IP_HDRINCL packets with ihl < 5
Kyle Farnung <[email protected]>
wifi: ath11k: clear shared SRNG pointer state on restart
Stefano Garzarella <[email protected]>
vsock/virtio: reset connection on receiving queue overflow
Minh Nguyen <[email protected]>
vsock/vmci: fix UAF when peer resets connection during handshake
Justin Iurman <[email protected]>
ipv6: ioam: add NULL check for idev in ipv6_hop_ioam()
Steven Rostedt <[email protected]>
ring-buffer: Fix reporting of missed events in iterator
Dawei Feng <[email protected]>
qed: fix double free in qed_cxt_tables_alloc()
Michael Bommarito <[email protected]>
l2tp: use list_del_rcu in l2tp_session_unhash
Konstantin Komarov <[email protected]>
fs/ntfs3: handle attr_set_size() errors when truncating files
Guopeng Zhang <[email protected]>
cgroup/cpuset: Reset DL migration state on can_attach() failure
Tejun Heo <[email protected]>
sched_ext: Avoid UAF in scx_root_enable_workfn() init failure path
Samuele Mariotti <[email protected]>
sched_ext: Fix missing warning in scx_set_task_state() default case
Yizhou Zhao <[email protected]>
netfilter: nft_inner: Fix IPv6 inner_thoff desync
Nan Li <[email protected]>
netfilter: ipset: stop hash:* range iteration at end
Haoze Xie <[email protected]>
netfilter: nf_queue: hold bridge skb->dev while queued
Zhengchuan Liang <[email protected]>
netfilter: ip6t_hbh: reject oversized option lists
Jonas Jelonek <[email protected]>
net: pse-pd: fix sign on -ENOENT check in of_load_pse_pis()
Michael Bommarito <[email protected]>
net: ifb: report ethtool stats over num_tx_queues
Nicolai Buchwitz <[email protected]>
net: bcmgenet: keep RBUF EEE/PM disabled
Zijing Yin <[email protected]>
phonet/pep: disable BH around forwarded sk_receive_skb()
Jiexun Wang <[email protected]>
Bluetooth: serialize accept_q access
Michael Bommarito <[email protected]>
Bluetooth: MGMT: validate Add Extended Advertising Data length
Michael Bommarito <[email protected]>
Bluetooth: L2CAP: ecred_reconfigure: send packed pdu, not stack pointer
Mingyu Wang <[email protected]>
Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths
Jann Horn <[email protected]>
Bluetooth: bnep: Fix UAF read of dev->name
David Carlier <[email protected]>
Bluetooth: ISO: drop ISO_END frames received without prior ISO_START
Safa Karakuş <[email protected]>
Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del()
Abdun Nihaal <[email protected]>
net: wwan: iosm: fix potential memory leaks in ipc_imem_init()
Luiz Capitulino <[email protected]>
selftests/mm: run_vmtests.sh: fix destructive tests invocation
Muchun Song <[email protected]>
mm/memory_hotplug: fix memory block reference leak on remove
Justin Iurman <[email protected]>
ipv6: ioam: refresh hdr pointer before ioam6_event()
Muchun Song <[email protected]>
drivers/base/memory: fix memory block reference leak in poison accounting
Heechan Kang <[email protected]>
io_uring/waitid: clear waitid info before copying it to userspace
Ard Biesheuvel <[email protected]>
efi: Allocate runtime workqueue before ACPI init
Takashi Iwai <[email protected]>
ALSA: asihpi: Fix potential OOB array access at reading cache
Takashi Iwai <[email protected]>
ALSA: pcm: Don't setup bogus iov_iter for silencing
Cássio Gabriel <[email protected]>
ALSA: ua101: Reject too-short USB descriptors
Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) widen blackbox-info buffer to I2C_SMBUS_BLOCK_MAX
ChenXiaoSong <[email protected]>
smb/server: promote S_DEL_ON_CLS to S_DEL_PENDING when close
Jeremy Erazo <[email protected]>
smb: client: use data_len for SMB2 READ encrypted folioq copy
Henrique Carvalho <[email protected]>
smb: client: protect tc_count increment in smb2_find_smb_sess_tcon_unlocked()
Michael Bommarito <[email protected]>
smb: client: require net admin for CIFS SWN netlink
Junyi Liu <[email protected]>
ksmbd: validate SID in parent security descriptor during ACL inheritance
Ferry Meng <[email protected]>
ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow
Jeremy Laratro <[email protected]>
ksmbd: fix null pointer dereference in compare_guid_key()
SeongJae Park <[email protected]>
mm/damon/sysfs-schemes: call missing mem_cgroup_iter_break()
Greg Kroah-Hartman <[email protected]>
sysfs: don't remove existing directory on update failure
Adrian Hunter <[email protected]>
i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
Lukas Bulwahn <[email protected]>
arm64: Kconfig: Remove selecting replaced HAVE_FUNCTION_GRAPH_RETVAL
Guenter Roeck <[email protected]>
hwmon: (pmbus/core) Protect regulator operations with mutex
Pu Lehui <[email protected]>
riscv: fgraph: Fix stack layout to match __arch_ftrace_regs argument of ftrace_return_to_handler
Pu Lehui <[email protected]>
riscv: fgraph: Select HAVE_FUNCTION_GRAPH_TRACER depends on HAVE_DYNAMIC_FTRACE_WITH_ARGS
Lu Baolu <[email protected]>
iommu/vt-d: Draining PRQ in sva unbind path when FPD bit set
Jiri Olsa <[email protected]>
x86/fgraph: Fix return_to_handler regs.rsp value
Jianbo Liu <[email protected]>
net/mlx5e: Use ip6_dst_lookup instead of ipv6_dst_lookup_flow for MAC init
Jianbo Liu <[email protected]>
net/mlx5e: Trigger neighbor resolution for unresolved destinations
Feng Yang <[email protected]>
tracing: Fix the bug where bpf_get_stackid returns -EFAULT on the ARM64
Sasha Levin <[email protected]>
Revert "ice: Remove jumbo_remove step from TX path"
Sasha Levin <[email protected]>
Revert "ice: fix double-free of tx_buf skb"
Ian Rogers <[email protected]>
perf parse-events: Expose/rename config_term_name
Niklas Cassel <[email protected]>
ata: libata-scsi: do not needlessly defer commands when using PMP with FBS
Niklas Cassel <[email protected]>
ata: libata-scsi: do not use the deferred QC feature on PMPs with CBS
Niklas Cassel <[email protected]>
ata: libata-scsi: do not use the deferred QC feature for ATA_DEFER_PORT
Niklas Cassel <[email protected]>
ata: libata-scsi: improve readability of ata_scsi_qc_issue()
Asim Viladi Oglu Manizada <[email protected]>
smb: client: reject userspace cifs.spnego descriptions
Alessio Belle <[email protected]>
drm/imagination: Synchronize interrupts before suspending the GPU
Kuniyuki Iwashima <[email protected]>
af_unix: Give up GC if MSG_PEEK intervened.
DaeMyung Kang <[email protected]>
ksmbd: close durable scavenger races against m_fp_list lookups
Peter Zijlstra (Intel) <[email protected]>
sched/deadline: Stop dl_server before CPU goes offline
Peter Zijlstra <[email protected]>
sched/deadline: Fix dl_server behaviour
Peter Zijlstra <[email protected]>
sched/deadline: Fix dl_server getting stuck
Juri Lelli <[email protected]>
sched/deadline: Always stop dl-server before changing parameters
Huacai Chen <[email protected]>
sched/deadline: Fix dl_server_stopped()
Peter Zijlstra <[email protected]>
sched/deadline: Less agressive dl_server handling
Sasha Levin <[email protected]>
Revert "x86/vdso: Fix output operand size of RDPID"
Vladimir Yakovlev <[email protected]>
spi: spi-dw-dma: fix print error log when wait finish transaction
Xiang Mei <[email protected]>
bridge: mrp: reject zero test interval to avoid OOM panic
Sasha Levin <[email protected]>
Revert "perf tool_pmu: Factor tool events into their own PMU"
Sasha Levin <[email protected]>
Revert "perf python: Add parse_events function"
Sasha Levin <[email protected]>
Revert "perf tool_pmu: Fix aggregation on duration_time"
Sasha Levin <[email protected]>
Revert "perf cgroup: Update metric leader in evlist__expand_cgroup"
Pengpeng Hou <[email protected]>
s390/debug: Reject zero-length input before trimming a newline
Gustavo Sousa <[email protected]>
drm/xe/hdcp: Add NULL check for media_gt in intel_hdcp_gsc_check_status()
Namjae Jeon <[email protected]>
ksmbd: validate owner of durable handle on reconnect
Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: ADD_ADDR rtx: free sk if last
Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: ADD_ADDR rtx: always decrease sk refcount
Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: ADD_ADDR rtx: allow ID 0
Gang Yan <[email protected]>
mptcp: sync the msk->sndbuf at accept() time
-------------
Diffstat:
Makefile | 4 +- arch/arm/boot/dts/renesas/r7s72100-genmai.dts | 3 - arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts | 2 - arch/arm/mach-versatile/integrator_cp.c | 13 +- arch/arm64/Kconfig | 1 - arch/arm64/include/asm/ftrace.h | 1 + arch/arm64/include/asm/insn.h | 2 +- arch/arm64/kvm/arm.c | 4 +- arch/arm64/kvm/vgic/vgic-its.c | 4 + arch/loongarch/kernel/kprobes.c | 4 +- arch/loongarch/mm/init.c | 4 - arch/powerpc/Kconfig.debug | 3 +- arch/powerpc/kernel/time.c | 6 +- arch/riscv/Kconfig | 2 +- arch/riscv/kernel/mcount.S | 24 +- arch/riscv/kvm/vcpu_pmu.c | 6 +- arch/riscv/mm/init.c | 25 ++ arch/s390/kernel/debug.c | 3 + arch/x86/include/asm/segment.h | 8 +- arch/x86/kernel/ftrace_64.S | 5 +- arch/x86/xen/setup.c | 2 +- block/bio-integrity.c | 76 ++-- block/blk-integrity.c | 12 +- block/blk-mq.c | 19 + drivers/accel/qaic/qaic_data.c | 23 +- drivers/ata/libata-core.c | 9 +- drivers/ata/libata-eh.c | 8 +- drivers/ata/libata-pmp.c | 18 +- drivers/ata/libata-scsi.c | 102 ++--- drivers/ata/sata_sil24.c | 6 +- drivers/base/memory.c | 8 +- drivers/block/rbd.c | 20 +- drivers/block/ublk_drv.c | 3 + drivers/bluetooth/btmtk.c | 2 + drivers/bluetooth/hci_ldisc.c | 48 ++- drivers/firmware/arm_ffa/bus.c | 7 +- drivers/firmware/arm_ffa/driver.c | 292 +++++++++++---- drivers/firmware/efi/efi.c | 28 +- drivers/gpio/gpiolib-cdev.c | 21 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c | 7 +- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 9 + .../drm/amd/display/dc/bios/bios_parser_helper.c | 9 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +- drivers/gpu/drm/bridge/chipone-icn6211.c | 4 +- drivers/gpu/drm/bridge/ite-it66121.c | 5 + .../drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 16 +- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/imagination/pvr_power.c | 11 +- drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c | 24 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 1 + drivers/gpu/drm/msm/msm_iommu.c | 5 +- drivers/gpu/drm/virtio/virtgpu_drv.h | 1 + drivers/gpu/drm/virtio/virtgpu_gem.c | 17 + drivers/gpu/drm/virtio/virtgpu_plane.c | 10 +- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 12 +- drivers/gpu/drm/xe/xe_gsc.c | 5 +- drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.c | 6 +- drivers/gpu/drm/xe/xe_gt_sriov_pf_monitor.h | 2 +- drivers/gpu/drm/xe/xe_gt_sriov_vf.c | 24 +- drivers/gpu/drm/xe/xe_gt_sriov_vf.h | 6 +- drivers/gpu/drm/xe/xe_oa.c | 6 +- drivers/hid/hid-quirks.c | 2 +- drivers/hid/hid-uclogic-core.c | 4 +- drivers/hwmon/pmbus/adm1266.c | 32 +- drivers/hwmon/pmbus/pmbus_core.c | 117 ++++-- drivers/i3c/master/mipi-i3c-hci/dma.c | 25 +- drivers/infiniband/sw/siw/siw_qp_rx.c | 15 + drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c | 2 +- drivers/iommu/intel/pasid.c | 22 +- drivers/iommu/intel/pasid.h | 6 + drivers/irqchip/irq-ath79-cpu.c | 7 - drivers/net/dsa/mt7530.c | 47 ++- drivers/net/ethernet/amd/pds_core/debugfs.c | 7 +- drivers/net/ethernet/amd/pds_core/dev.c | 11 +- drivers/net/ethernet/amd/pds_core/devlink.c | 6 +- drivers/net/ethernet/atheros/ag71xx.c | 3 + drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 +- drivers/net/ethernet/cirrus/cs89x0.c | 2 - drivers/net/ethernet/cortina/gemini.c | 21 +- drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 4 +- drivers/net/ethernet/intel/ice/ice_main.c | 10 +- drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 15 +- drivers/net/ethernet/intel/ice/ice_txrx.c | 7 +- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 1 + drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 7 +- .../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 2 +- .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 8 +- .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c | 3 +- .../net/ethernet/microchip/lan966x/lan966x_main.c | 8 +- drivers/net/ethernet/microsoft/mana/hw_channel.c | 35 +- drivers/net/ethernet/qlogic/qed/qed_cxt.c | 2 + drivers/net/ifb.c | 11 +- drivers/net/phy/dp83tc811.c | 1 + drivers/net/pse-pd/pse_core.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.c | 17 +- drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +- drivers/net/wireless/ath/ath11k/hal.c | 14 +- drivers/net/wireless/ath/ath11k/hal_rx.c | 5 +- drivers/net/wireless/ath/ath11k/testmode.c | 1 + drivers/net/wireless/ath/ath11k/wmi.c | 19 +- drivers/net/wwan/iosm/iosm_ipc_imem.c | 2 + drivers/nvme/host/ioctl.c | 17 +- drivers/phy/marvell/phy-mvebu-a3700-utmi.c | 5 +- drivers/phy/tegra/xusb-tegra186.c | 33 +- drivers/phy/tegra/xusb.h | 1 + drivers/pinctrl/qcom/pinctrl-sm8150.c | 8 +- drivers/pinctrl/renesas/pinctrl-rzg2l.c | 2 +- .../platform/surface/surface_aggregator_registry.c | 2 - drivers/platform/x86/adv_swbutton.c | 6 +- drivers/platform/x86/hp/hp_accel.c | 3 + drivers/platform/x86/intel/hid.c | 6 +- drivers/platform/x86/intel/vbtn.c | 6 +- drivers/scsi/isci/host.c | 3 + drivers/scsi/sd.c | 3 +- drivers/spi/spi-dw-dma.c | 2 +- drivers/spi/spi-ep93xx.c | 2 + drivers/spi/spi-mtk-snfi.c | 2 +- drivers/spi/spi-qup.c | 3 + drivers/spi/spi-sprd.c | 3 +- drivers/spi/spi-ti-qspi.c | 1 + fs/btrfs/fs.h | 1 + fs/btrfs/qgroup.c | 31 +- fs/netfs/buffered_read.c | 14 +- fs/netfs/buffered_write.c | 213 +++++++---- fs/netfs/iterator.c | 26 +- fs/netfs/misc.c | 8 +- fs/netfs/read_retry.c | 11 +- fs/netfs/write_issue.c | 41 +- fs/nfsd/nfs4state.c | 7 + fs/nsfs.c | 2 +- fs/ntfs3/file.c | 12 +- fs/smb/client/cifs_spnego.c | 16 + fs/smb/client/cifsfs.c | 2 + fs/smb/client/netlink.c | 6 +- fs/smb/client/smb2ops.c | 4 +- fs/smb/client/smb2transport.c | 2 + fs/smb/server/mgmt/user_session.c | 7 +- fs/smb/server/oplock.c | 13 +- fs/smb/server/oplock.h | 1 + fs/smb/server/smb2pdu.c | 3 +- fs/smb/server/smbacl.c | 78 +++- fs/smb/server/vfs_cache.c | 205 ++++++++-- fs/smb/server/vfs_cache.h | 12 +- fs/sysfs/group.c | 2 +- fs/zonefs/super.c | 6 +- include/asm-generic/kprobes.h | 2 +- include/linux/arm_ffa.h | 3 + include/linux/bio-integrity.h | 5 +- include/linux/blk-integrity.h | 5 +- include/linux/fwnode.h | 1 + include/linux/libata.h | 7 +- include/linux/netfilter/x_tables.h | 3 +- include/linux/netfilter_arp/arp_tables.h | 1 - include/linux/netfilter_ipv4/ip_tables.h | 1 - include/linux/netfilter_ipv6/ip6_tables.h | 1 - include/linux/sched.h | 1 - include/net/af_unix.h | 1 + include/net/bluetooth/bluetooth.h | 1 + include/net/netfilter/nf_queue.h | 1 + include/trace/events/btrfs.h | 4 +- include/trace/events/netfs.h | 8 + io_uring/net.c | 26 +- io_uring/waitid.c | 1 + kernel/cgroup/cpuset.c | 8 +- kernel/irq_work.c | 7 + kernel/sched/core.c | 2 + kernel/sched/deadline.c | 19 +- kernel/sched/debug.c | 6 +- kernel/sched/ext.c | 5 +- kernel/sched/fair.c | 16 +- kernel/sched/sched.h | 37 +- kernel/trace/ring_buffer.c | 8 +- kernel/trace/trace_events_hist.c | 6 +- kernel/trace/tracing_map.c | 17 +- lib/kunit/Kconfig | 5 +- lib/test_kprobes.c | 29 +- mm/damon/sysfs-schemes.c | 1 + mm/memory_hotplug.c | 2 + net/batman-adv/bridge_loop_avoidance.c | 54 ++- net/batman-adv/distributed-arp-table.c | 3 + net/batman-adv/fragmentation.c | 58 ++- net/batman-adv/gateway_client.c | 4 + net/batman-adv/originator.c | 4 +- net/batman-adv/tp_meter.c | 64 +++- net/batman-adv/types.h | 17 +- net/bluetooth/af_bluetooth.c | 99 +++-- net/bluetooth/bnep/core.c | 2 +- net/bluetooth/iso.c | 14 +- net/bluetooth/l2cap_core.c | 2 +- net/bluetooth/l2cap_sock.c | 51 ++- net/bluetooth/mgmt.c | 6 + net/bluetooth/rfcomm/sock.c | 9 +- net/bluetooth/sco.c | 9 +- net/bridge/br_mrp_netlink.c | 4 +- net/bridge/br_multicast.c | 27 +- net/bridge/netfilter/Kconfig | 14 +- net/bridge/netfilter/ebtable_broute.c | 14 +- net/bridge/netfilter/ebtable_filter.c | 14 +- net/bridge/netfilter/ebtable_nat.c | 12 +- net/bridge/netfilter/ebtables.c | 71 ++-- net/core/gro.c | 3 + net/core/skmsg.c | 9 +- net/ethtool/bitset.c | 8 +- net/ipv4/inet_connection_sock.c | 2 +- net/ipv4/netfilter/Kconfig | 32 +- net/ipv4/netfilter/arp_tables.c | 18 +- net/ipv4/netfilter/arptable_filter.c | 27 +- net/ipv4/netfilter/ip_tables.c | 18 +- net/ipv4/netfilter/iptable_filter.c | 27 +- net/ipv4/netfilter/iptable_mangle.c | 29 +- net/ipv4/netfilter/iptable_nat.c | 6 +- net/ipv4/netfilter/iptable_raw.c | 26 +- net/ipv4/netfilter/iptable_security.c | 27 +- net/ipv4/raw.c | 2 +- net/ipv4/tcp_ao.c | 3 +- net/ipv6/exthdrs.c | 21 +- net/ipv6/netfilter/Kconfig | 22 +- net/ipv6/netfilter/ip6_tables.c | 18 +- net/ipv6/netfilter/ip6t_hbh.c | 4 + net/ipv6/netfilter/ip6table_filter.c | 26 +- net/ipv6/netfilter/ip6table_mangle.c | 27 +- net/ipv6/netfilter/ip6table_nat.c | 6 +- net/ipv6/netfilter/ip6table_raw.c | 24 +- net/ipv6/netfilter/ip6table_security.c | 27 +- net/l2tp/l2tp_core.c | 2 +- net/mac80211/mlme.c | 2 +- net/mac80211/parse.c | 71 ++-- net/mptcp/pm_netlink.c | 35 +- net/mptcp/protocol.c | 3 +- net/netfilter/Kconfig | 10 + net/netfilter/ipset/ip_set_hash_ipmark.c | 6 +- net/netfilter/ipset/ip_set_hash_ipport.c | 5 +- net/netfilter/ipset/ip_set_hash_ipportip.c | 5 +- net/netfilter/ipset/ip_set_hash_ipportnet.c | 5 +- net/netfilter/nf_queue.c | 4 +- net/netfilter/nfnetlink_queue.c | 2 + net/netfilter/nft_inner.c | 1 - net/netfilter/x_tables.c | 116 +++++- net/phonet/pep.c | 19 +- net/smc/af_smc.c | 3 +- net/smc/smc_tracepoint.h | 2 +- net/tls/tls_sw.c | 46 ++- net/unix/af_unix.c | 13 +- net/unix/garbage.c | 79 ++-- net/vmw_vsock/virtio_transport_common.c | 20 +- net/vmw_vsock/vmci_transport.c | 2 +- net/wireless/scan.c | 3 + scripts/package/PKGBUILD | 2 +- security/landlock/net.c | 118 +++--- security/lsm_syscalls.c | 9 +- sound/core/pcm_lib.c | 3 + sound/core/seq/seq_ump_client.c | 22 +- sound/pci/asihpi/hpicmn.c | 6 + sound/pci/hda/cs35l41_hda.c | 4 +- sound/pci/hda/cs35l56_hda.c | 1 + sound/soc/codecs/cs35l56-sdw.c | 3 +- sound/usb/misc/ua101.c | 5 +- sound/usb/mixer_scarlett2.c | 2 + tools/perf/builtin-list.c | 13 +- tools/perf/builtin-stat.c | 1 - tools/perf/util/Build | 1 - tools/perf/util/cgroup.c | 30 +- tools/perf/util/evsel.c | 291 ++++++++++++-- tools/perf/util/evsel.h | 30 +- tools/perf/util/metricgroup.c | 1 - tools/perf/util/parse-events.c | 59 ++- tools/perf/util/parse-events.h | 5 + tools/perf/util/parse-events.l | 11 + tools/perf/util/parse-events.y | 16 + tools/perf/util/pmu.c | 20 +- tools/perf/util/pmu.h | 2 - tools/perf/util/pmus.c | 9 - tools/perf/util/print-events.c | 36 +- tools/perf/util/print-events.h | 1 + tools/perf/util/python.c | 61 --- tools/perf/util/stat-display.c | 6 +- tools/perf/util/stat-shadow.c | 1 - tools/perf/util/tool_pmu.c | 417 --------------------- tools/perf/util/tool_pmu.h | 51 --- tools/testing/selftests/mm/run_vmtests.sh | 2 +- 280 files changed, 3293 insertions(+), 1966 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/272 mptcp: sync the msk->sndbuf at accept() time
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gang Yan <[email protected]>
commit fcf04b14334641f4b0b8647824480935e9416d52 upstream.
On passive MPTCP connections, the msk sndbuf is not updated correctly.
The root cause is an order issue in the accept path:
- tcp_check_req() -> subflow_syn_recv_sock() -> mptcp_sk_clone_init() calls __mptcp_propagate_sndbuf() to copy the ssk sndbuf into msk
- Later, tcp_child_process() -> tcp_init_transfer() -> tcp_sndbuf_expand() grows the ssk sndbuf.
So __mptcp_propagate_sndbuf() runs before the ssk sndbuf has been expanded and the msk ends up with a much smaller sndbuf than the subflow:
MPTCP: msk->sndbuf:20480, msk->first->sndbuf:2626560
Fix this by moving the __mptcp_propagate_sndbuf() call from mptcp_sk_clone_init() -- the ssk sndbuf is not yet finalized there -- to __mptcp_propagate_sndbuf() at accept() time, when the ssk sndbuf has been fully expanded by tcp_sndbuf_expand().
[ No conflicts, but move __mptcp_propagate_sndbuf() above the for-loop
(mptcp_for_each_subflow()) present in this version, which will modify 'subflow' used by __mptcp_propagate_sndbuf() in this new patch. ]
--- net/mptcp/protocol.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/mptcp/protocol.c +2 -1
@@ -3493,7 +3493,6 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk,* uses the correct data */ mptcp_copy_inaddrs (nsk, ssk); -__mptcp_propagate_sndbuf (nsk, ssk);mptcp_rcv_space_init (msk, ssk); msk->rcvq_space.time =mptcp_stamp ();
@@ -4101,6 +4100,8 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock, msk =mptcp_sk (newsk); msk->in_accept_queue =0 ; +__mptcp_propagate_sndbuf (newsk,mptcp_subflow_tcp_sock (subflow)); +/* set ssk->sk_socket of accept()ed flows to mptcp socket. * This is needed so NOSPACE flag can be set from tcp stack. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 2/272 mptcp: pm: ADD_ADDR rtx: allow ID 0
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 03f324f3f1f7619a47b9c91282cb12775ab0a2f1 upstream.
ADD_ADDR can be sent for the ID 0, which corresponds to the local address and port linked to the initial subflow.
Indeed, this address could be removed, and re-added later on, e.g. what is done in the "delete re-add signal" MPTCP Join selftests. So no reason to ignore it.
--- net/mptcp/pm_netlink.c | 3 --- 1 file changed, 3 deletions(-)
net/mptcp/pm_netlink.c +0 -3
@@ -304,9 +304,6 @@ static void mptcp_pm_add_timer(struct timer_list *timer)if (inet_sk_state_load (sk) ==TCP_CLOSE )return ; -if (!entry->addr.id) -return ; -bh_lock_sock (sk);if (sock_owned_by_user (sk)) {/* Try again later. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/272 mptcp: pm: ADD_ADDR rtx: always decrease sk refcount
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit 9634cb35af17019baec21ca648516ce376fa10e6 upstream.
When an ADD_ADDR is retransmitted, the sk is held in sk_reset_timer(). It should then be released in all cases at the end.
Some (unlikely) checks were returning directly instead of calling sock_put() to decrease the refcount. Jump to a new 'exit' label to call __sock_put() (which will become sock_put() in the next commit) to fix this potential leak.
While at it, drop the '!msk' check which cannot happen because it is never reset, and explicitly mark the remaining one as "unlikely".
--- net/mptcp/pm_netlink.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
net/mptcp/pm_netlink.c +3 -5
@@ -298,11 +298,8 @@ static void mptcp_pm_add_timer(struct timer_list *timer)pr_debug ("msk=%p\n" , msk); -if (!msk) -return ; - -if (inet_sk_state_load (sk) ==TCP_CLOSE ) -return ; +if (unlikely (inet_sk_state_load (sk) ==TCP_CLOSE )) + goto exit;bh_lock_sock (sk);if (sock_owned_by_user (sk)) {
@@ -340,6 +337,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer) out:bh_unlock_sock (sk); +exit:__sock_put (sk); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/272 mptcp: pm: ADD_ADDR rtx: free sk if last
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
commit b7b9a461569734d33d3259d58d2507adfac107ed upstream.
When an ADD_ADDR is retransmitted, the sk is held in sk_reset_timer(), and released at the end.
If at that moment, it was the last reference being held, the sk would not be freed. sock_put() should then be called instead of __sock_put().
But that's not enough: if it is the last reference, sock_put() will call sk_free(), which will end up calling sk_stop_timer_sync() on the same timer, and waiting indefinitely to finish. So it is needed to mark that the timer is done at the end of the timer handler when it has not been rescheduled, not to call sk_stop_timer_sync() on "itself".
[ Applied to net/mptcp/pm_netlink.c instead of upstream's pm_kernel.c.
Also, there were conflicts, because commit 30549eebc4d8 ("mptcp: make ADD_ADDR retransmission timeout adaptive") is not in this version and changed the context. Also, other conflicts were due to newer patches being backported with resolved conflicts before this one. ]
--- net/mptcp/pm_netlink.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-)
net/mptcp/pm_netlink.c +17 -11
@@ -22,6 +22,7 @@ struct mptcp_pm_add_entry {struct list_head list;struct mptcp_addr_info addr;u8 retrans_times; +bool timer_done;struct timer_list add_timer;struct mptcp_sock *sock;struct rcu_head rcu;
@@ -294,22 +295,22 @@ static void mptcp_pm_add_timer(struct timer_list *timer)struct mptcp_pm_add_entry *entry =from_timer (entry, timer, add_timer);struct mptcp_sock *msk = entry->sock;struct sock *sk = (struct sock *)msk; -unsigned int timeout; +unsigned int timeout =0 ;pr_debug ("msk=%p\n" , msk); +bh_lock_sock (sk);if (unlikely (inet_sk_state_load (sk) ==TCP_CLOSE )) - goto exit; + goto out; -bh_lock_sock (sk);if (sock_owned_by_user (sk)) {/* Try again later. */ -sk_reset_timer (sk, timer, jiffies +HZ /20 ); + timeout =HZ /20 ; goto out; }if (mptcp_pm_should_add_signal_addr (msk)) { -sk_reset_timer (sk, timer, jiffies +HZ ); + timeout =HZ ; goto out; }
@@ -326,9 +327,8 @@ static void mptcp_pm_add_timer(struct timer_list *timer) entry->retrans_times++; } -if (entry->retrans_times <ADD_ADDR_RETRANS_MAX ) -sk_reset_timer (sk, timer, - jiffies + timeout); +if (entry->retrans_times >=ADD_ADDR_RETRANS_MAX ) + timeout =0 ;spin_unlock_bh (&msk->pm.lock);
@@ -336,9 +336,13 @@ static void mptcp_pm_add_timer(struct timer_list *timer)mptcp_pm_subflow_established (msk); out: +if (timeout) +sk_reset_timer (sk, timer, jiffies + timeout); +else +/* if sock_put calls sk_free: avoid waiting for this timer */ + entry->timer_done = true;bh_unlock_sock (sk); -exit: -__sock_put (sk); +sock_put (sk); } struct mptcp_pm_add_entry *
@@ -402,6 +406,7 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,timer_setup (&add_entry->add_timer, mptcp_pm_add_timer,0 ); reset_timer: + add_entry->timer_done = false; timeout =mptcp_get_add_addr_timeout (net);if (timeout)sk_reset_timer (sk, &add_entry->add_timer, jiffies + timeout);
@@ -422,7 +427,8 @@ void mptcp_pm_free_anno_list(struct mptcp_sock *msk)spin_unlock_bh (&msk->pm.lock);list_for_each_entry_safe (entry, tmp, &free_list, list) { -sk_stop_timer_sync (sk, &entry->add_timer); +if (!entry->timer_done) +sk_stop_timer_sync (sk, &entry->add_timer);kfree_rcu (entry, rcu); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 5/272 ksmbd: validate owner of durable handle on reconnect
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 49110a8ce654bbe56bef7c5e44cce31f4b102b8a ]
Currently, ksmbd does not verify if the user attempting to reconnect to a durable handle is the same user who originally opened the file. This allows any authenticated user to hijack an orphaned durable handle by predicting or brute-forcing the persistent ID.
According to MS-SMB2, the server MUST verify that the SecurityContext of the reconnect request matches the SecurityContext associated with the existing open.
Add a durable_owner structure to ksmbd_file to store the original opener's UID, GID, and account name. and catpure the owner information when a file handle becomes orphaned. and implementing ksmbd_vfs_compare_durable_owner() to validate the identity of the requester during SMB2_CREATE (DHnC).
--- fs/smb/server/mgmt/user_session.c | 7 ++- fs/smb/server/oplock.c | 7 +++ fs/smb/server/oplock.h | 1 + fs/smb/server/smb2pdu.c | 3 +- fs/smb/server/vfs_cache.c | 87 +++++++++++++++++++++++++++---- fs/smb/server/vfs_cache.h | 12 ++++- 6 files changed, 102 insertions(+), 15 deletions(-)
fs/smb/server/mgmt/user_session.c +3 -4
@@ -161,11 +161,10 @@ void ksmbd_session_destroy(struct ksmbd_session *sess)if (!sess)return ; +ksmbd_tree_conn_session_logoff (sess); +ksmbd_destroy_file_table (sess);if (sess->user)ksmbd_free_user (sess->user); - -ksmbd_tree_conn_session_logoff (sess); -ksmbd_destroy_file_table (&sess->file_table);ksmbd_launch_ksmbd_durable_scavenger ();ksmbd_session_rpc_clear_list (sess);free_channel_list (sess);
@@ -402,7 +401,7 @@ void destroy_previous_session(struct ksmbd_conn *conn, goto out; } -ksmbd_destroy_file_table (&prev_sess->file_table); +ksmbd_destroy_file_table (prev_sess); prev_sess->state =SMB2_SESSION_EXPIRED ;ksmbd_all_conn_set_status (id,KSMBD_SESS_NEED_SETUP );ksmbd_launch_ksmbd_durable_scavenger ();
fs/smb/server/oplock.c +7 -0
@@ -1841,6 +1841,7 @@ int smb2_check_durable_oplock(struct ksmbd_conn *conn,struct ksmbd_share_config *share, struct ksmbd_file *fp, struct lease_ctx_info *lctx, + struct ksmbd_user *user, char *name) { struct oplock_info *opinfo = opinfo_get(fp);
@@ -1849,6 +1850,12 @@ int smb2_check_durable_oplock(struct ksmbd_conn *conn,if (!opinfo)return 0 ; +if (ksmbd_vfs_compare_durable_owner (fp, user) == false) { +ksmbd_debug (SMB ,"Durable handle reconnect failed: owner mismatch\n" ); + ret = -EBADF ; + goto out; + } +if (opinfo->is_lease == false) {if (lctx) {pr_err ("create context include lease\n" );
fs/smb/server/oplock.h +1 -0
@@ -126,5 +126,6 @@ int smb2_check_durable_oplock(struct ksmbd_conn *conn,struct ksmbd_share_config *share, struct ksmbd_file *fp, struct lease_ctx_info *lctx, + struct ksmbd_user *user, char *name);#endif /* __KSMBD_OPLOCK_H */
fs/smb/server/smb2pdu.c +2 -1
@@ -3016,7 +3016,8 @@ int smb2_open(struct ksmbd_work *work) }if (dh_info.reconnected == true) { - rc =smb2_check_durable_oplock (conn, share, dh_info.fp, lc, name); + rc =smb2_check_durable_oplock (conn, share, dh_info.fp, + lc, sess->user, name);if (rc) {ksmbd_put_durable_fd (dh_info.fp); goto err_out2;
fs/smb/server/vfs_cache.c +78 -9
161 lines not on this page · raw message
fs/smb/server/vfs_cache.h +11 -1
@@ -67,6 +67,13 @@ enum {FP_CLOSED }; +/* Owner information for durable handle reconnect */ +struct durable_owner { +unsigned int uid; +unsigned int gid; +char *name; +}; +struct ksmbd_file {struct file *filp;u64 persistent_id;
@@ -111,6 +118,7 @@ struct ksmbd_file {bool is_durable;bool is_persistent;bool is_resilient; +struct durable_owner owner; }; static inline void set_ctx_actor(struct dir_context *ctx,
@@ -137,7 +145,7 @@ static inline bool ksmbd_stream_fd(struct ksmbd_file *fp) }int ksmbd_init_file_table (struct ksmbd_file_table *ft); -void ksmbd_destroy_file_table (struct ksmbd_file_table *ft); +void ksmbd_destroy_file_table (struct ksmbd_session *sess);int ksmbd_close_fd (struct ksmbd_work *work,u64 id);struct ksmbd_file *ksmbd_lookup_fd_fast (struct ksmbd_work *work,u64 id);struct ksmbd_file *ksmbd_lookup_foreign_fd (struct ksmbd_work *work,u64 id);
@@ -163,6 +171,8 @@ void ksmbd_free_global_file_table(void);void ksmbd_set_fd_limit (unsigned long limit);void ksmbd_update_fstate (struct ksmbd_file_table *ft,struct ksmbd_file *fp,unsigned int state); +bool ksmbd_vfs_compare_durable_owner (struct ksmbd_file *fp, +struct ksmbd_user *user);/* * INODE hash
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 6/272 drm/xe/hdcp: Add NULL check for media_gt in intel_hdcp_gsc_check_status()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gustavo Sousa <[email protected]>
commit 60a1e131a811b68703da58fd805ab359b704ab03 upstream.
When media GT is disabled via configfs, there is no allocation for media_gt, which is kept as NULL. In such scenario, intel_hdcp_gsc_check_status() results in a kernel pagefault error due to >->uc.gsc being evaluated as an invalid memory address.
Fix that by introducing a NULL check on media_gt and bailing out early if so.
While at it, also drop the NULL check for gsc, since it can't be NULL if media_gt is not NULL.
v2:
- Get address for gsc only after checking that gt is not NULL. (Shuicheng)
- Drop the NULL check for gsc. (Shuicheng)
v3:
- Add "Fixes" and "Cc: <stable...>" tags. (Matt)
--- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +10 -2
@@ -39,10 +39,18 @@ bool intel_hdcp_gsc_check_status(struct xe_device *xe) {struct xe_tile *tile =xe_device_get_root_tile (xe);struct xe_gt *gt = tile->media_gt; -struct xe_gsc *gsc = >->uc.gsc; +struct xe_gsc *gsc;bool ret = true; -if (!gsc || !xe_uc_fw_is_enabled (&gsc->fw)) { +if (!gt) { +drm_dbg_kms (&xe->drm, +"not checking GSC status for HDCP2.x: media GT not present or disabled\n" ); +return false; + } + + gsc = >->uc.gsc; + +if (!xe_uc_fw_is_enabled (&gsc->fw)) {drm_dbg_kms (&xe->drm,"GSC Components not ready for HDCP2.x\n" );return false;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/272 s390/debug: Reject zero-length input before trimming a newline
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit c366a7b5ed7564e41345c380285bd3f6cb98971b ]
debug_get_user_string() copies the userspace buffer into a newly allocated NUL-terminated buffer and then unconditionally looks at buffer[user_len - 1] to strip a trailing newline.
A zero-length write reaches this helper unchanged, so the newline trim reads before the start of the allocated buffer.
Reject empty writes before accessing the last input byte.
--- arch/s390/kernel/debug.c | 3 +++ 1 file changed, 3 insertions(+)
arch/s390/kernel/debug.c +3 -0
@@ -1256,6 +1256,9 @@ static inline char *debug_get_user_string(const char __user *user_buf, {char *buffer; +if (!user_len) +return ERR_PTR (-EINVAL ); + buffer =kmalloc (user_len +1 ,GFP_KERNEL );if (!buffer)return ERR_PTR (-ENOMEM );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/272 Revert "perf cgroup: Update metric leader in evlist__expand_cgroup"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit d26e31446c0fa96feca0b7701243b42447225d33.
--- tools/perf/util/cgroup.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-)
tools/perf/util/cgroup.c +7 -23
@@ -417,6 +417,7 @@ int evlist__expand_cgroup(struct evlist *evlist, const char *str, struct rblist *metric_events, bool open_cgroup) {struct evlist *orig_list, *tmp_list; +struct evsel *pos, *evsel, *leader;struct rblist orig_metric_events;struct cgroup *cgrp =NULL ;struct cgroup_name *cn;
@@ -455,7 +456,6 @@ int evlist__expand_cgroup(struct evlist *evlist, const char *str, goto out_err;list_for_each_entry (cn, &cgroup_list, list) { -struct evsel *pos;char *name;if (!cn->used)
@@ -471,37 +471,21 @@ int evlist__expand_cgroup(struct evlist *evlist, const char *str,if (cgrp ==NULL )continue ; -/* copy the list and set to the new cgroup. */ + leader =NULL ;evlist__for_each_entry (orig_list, pos) { -struct evsel *evsel =evsel__clone (/*dest=*/ NULL , pos); - + evsel =evsel__clone (/*dest=*/ NULL , pos);if (evsel ==NULL ) goto out_err; -/* stash the copy during the copying. */ - pos->priv = evsel;cgroup__put (evsel->cgrp); evsel->cgrp =cgroup__get (cgrp); -evlist__add (tmp_list, evsel); - } -/* update leader information using stashed pointer to copy. */ -evlist__for_each_entry (orig_list, pos) { -struct evsel *evsel = pos->priv; - -if (evsel__leader (pos)) -evsel__set_leader (evsel,evsel__leader (pos)->priv); - -if (pos->metric_leader) - evsel->metric_leader = pos->metric_leader->priv; +if (evsel__is_group_leader (pos)) + leader = evsel; +evsel__set_leader (evsel, leader); -if (pos->first_wildcard_match) - evsel->first_wildcard_match = pos->first_wildcard_match->priv; +evlist__add (tmp_list, evsel); } -/* the stashed copy is no longer used. */ -evlist__for_each_entry (orig_list, pos) - pos->priv =NULL ; -/* cgroup__new() has a refcount, release it here */ cgroup__put (cgrp); nr_cgroups++;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 9/272 Revert "perf tool_pmu: Fix aggregation on duration_time"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 310be445ab1028315627b326516f193511cb1c97.
--- tools/perf/util/tool_pmu.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
tools/perf/util/tool_pmu.c +1 -7
@@ -392,14 +392,8 @@ int evsel__read_tool(struct evsel *evsel, int cpu_map_idx, int thread) delta_start *=1000000000 / ticks_per_sec; } count->val = delta_start; + count->ena = count->run = delta_start; count->lost =0 ; -/* -* The values of enabled and running must make a ratio of 100%. The -* exact values don't matter as long as they are non-zero to avoid -* issues with evsel__count_has_error. -*/ - count->ena++; - count->run++;return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 10/272 Revert "perf python: Add parse_events function"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 9cd264079fab9867dbc9fbc8a1e521996e3d7212.
--- tools/perf/util/cgroup.c | 2 +- tools/perf/util/evsel.c | 19 +++++-------- tools/perf/util/evsel.h | 2 +- tools/perf/util/python.c | 61 ---------------------------------------- 4 files changed, 9 insertions(+), 75 deletions(-)
tools/perf/util/cgroup.c +1 -1
@@ -473,7 +473,7 @@ int evlist__expand_cgroup(struct evlist *evlist, const char *str, leader =NULL ;evlist__for_each_entry (orig_list, pos) { - evsel =evsel__clone (/*dest=*/ NULL , pos); + evsel =evsel__clone (pos);if (evsel ==NULL ) goto out_err;
tools/perf/util/evsel.c +7 -12
@@ -332,7 +332,7 @@ static int evsel__copy_config_terms(struct evsel *dst, struct evsel *src)* The assumption is that @orig is not configured nor opened yet. * So we only care about the attributes that can be set while it's parsed. */ -struct evsel *evsel__clone (struct evsel *dest,struct evsel *orig) +struct evsel *evsel__clone (struct evsel *orig) {struct evsel *evsel;
@@ -345,11 +345,7 @@ struct evsel *evsel__clone(struct evsel *dest, struct evsel *orig)if (orig->bpf_obj)return NULL ; -if (dest) - evsel = dest; -else - evsel =evsel__new (&orig->core.attr); - + evsel =evsel__new (&orig->core.attr);if (evsel ==NULL )return NULL ;
@@ -399,12 +395,11 @@ struct evsel *evsel__clone(struct evsel *dest, struct evsel *orig) evsel->core.leader = orig->core.leader; evsel->max_events = orig->max_events; -zfree (&evsel->unit); -if (orig->unit) { - evsel->unit =strdup (orig->unit); -if (evsel->unit ==NULL ) - goto out_err; - } +free ((char *)evsel->unit); + evsel->unit =strdup (orig->unit); +if (evsel->unit ==NULL ) + goto out_err; + evsel->scale = orig->scale; evsel->snapshot = orig->snapshot; evsel->per_pkg = orig->per_pkg;
tools/perf/util/evsel.h +1 -1
@@ -241,7 +241,7 @@ static inline struct evsel *evsel__new(struct perf_event_attr *attr)return evsel__new_idx (attr,0 ); } -struct evsel *evsel__clone (struct evsel *dest,struct evsel *orig); +struct evsel *evsel__clone (struct evsel *orig);int copy_config_terms (struct list_head *dst,struct list_head *src);void free_config_terms (struct list_head *config_terms);
tools/perf/util/python.c +0 -61
79 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 11/272 Revert "perf tool_pmu: Factor tool events into their own PMU"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 7cfcd01f33fc3400c60f923d2896a8cdc60cecc4.
--- tools/perf/builtin-list.c | 13 +- tools/perf/builtin-stat.c | 1 - tools/perf/util/Build | 1 - tools/perf/util/evsel.c | 272 ++++++++++++++++++++-- tools/perf/util/evsel.h | 28 ++- tools/perf/util/metricgroup.c | 1 - tools/perf/util/parse-events.c | 39 ++++ tools/perf/util/parse-events.h | 3 + tools/perf/util/parse-events.l | 11 + tools/perf/util/parse-events.y | 16 ++ tools/perf/util/pmu.c | 20 +- tools/perf/util/pmu.h | 2 - tools/perf/util/pmus.c | 9 - tools/perf/util/print-events.c | 36 ++- tools/perf/util/print-events.h | 1 + tools/perf/util/stat-display.c | 6 +- tools/perf/util/stat-shadow.c | 1 - tools/perf/util/tool_pmu.c | 411 --------------------------------- tools/perf/util/tool_pmu.h | 51 ---- 19 files changed, 392 insertions(+), 530 deletions(-) delete mode 100644 tools/perf/util/tool_pmu.c delete mode 100644 tools/perf/util/tool_pmu.h
tools/perf/builtin-list.c +2 -11
@@ -19,7 +19,6 @@#include "util/string2.h" #include "util/strlist.h" #include "util/strbuf.h" -#include "util/tool_pmu.h" #include <subcmd/pager.h> #include <subcmd/parse-options.h> #include <linux/zalloc.h>
@@ -615,18 +614,9 @@ int cmd_list(int argc, const char **argv) event_symbols_hw, PERF_COUNT_HW_MAX); else if (strcmp(argv[i], "sw") == 0 || strcmp(argv[i], "software") == 0) { - char *old_pmu_glob = default_ps.pmu_glob; - print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE, event_symbols_sw, PERF_COUNT_SW_MAX); - default_ps.pmu_glob = strdup("tool"); - if (!default_ps.pmu_glob) { - ret = -1; - goto out; - } - perf_pmus__print_pmu_events(&print_cb, ps); - zfree(&default_ps.pmu_glob); - default_ps.pmu_glob = old_pmu_glob; + print_tool_events(&print_cb, ps); } else if (strcmp(argv[i], "cache") == 0 || strcmp(argv[i], "hwcache") == 0) print_hwcache_events(&print_cb, ps);
@@ -674,6 +664,7 @@ int cmd_list(int argc, const char **argv) event_symbols_hw, PERF_COUNT_HW_MAX);print_symbol_events (&print_cb, ps,PERF_TYPE_SOFTWARE , event_symbols_sw,PERF_COUNT_SW_MAX ); +print_tool_events (&print_cb, ps);print_hwcache_events (&print_cb, ps);perf_pmus__print_pmu_events (&print_cb, ps);print_tracepoint_events (&print_cb, ps);
tools/perf/builtin-stat.c +0 -1
@@ -46,7 +46,6 @@#include "util/parse-events.h" #include "util/pmus.h" #include "util/pmu.h" -#include "util/tool_pmu.h" #include "util/event.h" #include "util/evlist.h" #include "util/evsel.h"
tools/perf/util/Build +0 -1
@@ -83,7 +83,6 @@ perf-util-y += pmu.o perf-util-y += pmus.o perf-util-y += pmu-flex.o perf-util-y += pmu-bison.o -perf-util-y += tool_pmu.o perf-util-y += svghelper.o perf-util-$(CONFIG_LIBTRACEEVENT) += trace-event-info.o perf-util-y += trace-event-scripting.o
tools/perf/util/evsel.c +255 -17
361 lines not on this page · raw message
tools/perf/util/evsel.h +27 -1
@@ -11,7 +11,6 @@#include <perf/evsel.h> #include "symbol_conf.h" #include "pmus.h" -#include "pmu.h" struct bpf_object ;struct cgroup ;
@@ -23,9 +22,25 @@ struct target;struct hashmap ;struct bperf_leader_bpf ;struct bperf_follower_bpf ; +struct perf_pmu ;typedef int (evsel__sb_cb_t )(union perf_event *event,void *data); +enum perf_tool_event { +PERF_TOOL_NONE =0 , +PERF_TOOL_DURATION_TIME =1 , +PERF_TOOL_USER_TIME =2 , +PERF_TOOL_SYSTEM_TIME =3 , + +PERF_TOOL_MAX , +}; + +const char *perf_tool_event__to_str (enum perf_tool_event ev); +enum perf_tool_event perf_tool_event__from_str (const char *str); + +#define perf_tool_event__for_each_event (ev) \ + for ((ev) = PERF_TOOL_DURATION_TIME; (ev) < PERF_TOOL_MAX; ev++) +/** struct evsel - event selector * * @evlist - evlist this evsel is in, if it is in one.
@@ -68,6 +83,7 @@ struct evsel {const char *unit;struct cgroup *cgrp;const char *metric_id; +enum perf_tool_event tool_event;/* parse modifier helper */ int exclude_GH;int sample_read;
@@ -307,11 +323,21 @@ const char *evsel__name(struct evsel *evsel);bool evsel__name_is (struct evsel *evsel,const char *name);const char *evsel__metric_id (const struct evsel *evsel); +static inline bool evsel__is_tool (const struct evsel *evsel) +{ +return evsel->tool_event !=PERF_TOOL_NONE ; +} +static inline bool evsel__is_retire_lat (const struct evsel *evsel) {return evsel->retire_lat; } +static inline enum perf_tool_event evsel__tool_event (const struct evsel *evsel) +{ +return evsel->tool_event; +} +const char *evsel__group_name (struct evsel *evsel);int evsel__group_desc (struct evsel *evsel,char *buf,size_t size);
tools/perf/util/metricgroup.c +0 -1
@@ -14,7 +14,6 @@#include "pmus.h" #include "print-events.h" #include "smt.h" -#include "tool_pmu.h" #include "expr.h" #include "rblist.h" #include <string.h>
tools/perf/util/parse-events.c +39 -0
@@ -302,6 +302,38 @@ static int add_event(struct list_head *list, int *idx, alternate_hw_config) ? 0 : -ENOMEM; } +static int add_event_tool (struct list_head *list,int *idx, +enum perf_tool_event tool_event) +{ +struct evsel *evsel; +struct perf_event_attr attr = { + .type =PERF_TYPE_SOFTWARE , + .config =PERF_COUNT_SW_DUMMY , + }; +struct perf_cpu_map *cpu_list =NULL ; + +if (tool_event ==PERF_TOOL_DURATION_TIME ) { +/* Duration time is gathered globally, pretend it is only on CPU0. */ + cpu_list =perf_cpu_map__new ("0" ); + } + evsel =__add_event (list, idx, &attr,/*init_attr=*/ true,/*name=*/ NULL , +/*metric_id=*/ NULL ,/*pmu=*/ NULL , +/*config_terms=*/ NULL ,/*auto_merge_stats=*/ false, + cpu_list, +/*alternate_hw_config=*/ PERF_COUNT_HW_MAX ); +perf_cpu_map__put (cpu_list); +if (!evsel) +return -ENOMEM ; + evsel->tool_event = tool_event; +if (tool_event ==PERF_TOOL_DURATION_TIME + || tool_event ==PERF_TOOL_USER_TIME + || tool_event ==PERF_TOOL_SYSTEM_TIME ) { +free ((char *)evsel->unit); + evsel->unit =strdup ("ns" ); + } +return 0 ; +} +/** * parse_aliases - search names for entries beginning or equalling str ignoring * case. If mutliple entries in names match str then the longest
@@ -1398,6 +1430,13 @@ int parse_events_add_numeric(struct parse_events_state *parse_state, type, /*extended_type=*/0, config, head_config); } +int parse_events_add_tool (struct parse_events_state *parse_state, +struct list_head *list, +int tool_event) +{ +return add_event_tool (list, &parse_state->idx, tool_event); +} +static bool config_term_percore (struct list_head *config_terms) {struct evsel_config_term *term;
tools/perf/util/parse-events.h +3 -0
@@ -227,6 +227,9 @@ int parse_events_add_numeric(struct parse_events_state *parse_state, u32 type, u64 config, const struct parse_events_terms *head_config, bool wildcard); +int parse_events_add_tool (struct parse_events_state *parse_state, +struct list_head *list, +int tool_event);int parse_events_add_cache (struct list_head *list,int *idx,const char *name,struct parse_events_state *parse_state,struct parse_events_terms *parsed_terms);
tools/perf/util/parse-events.l +11 -0
@@ -121,6 +121,14 @@ static int sym(yyscan_t scanner, int type, int config) return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW; } +static int tool(yyscan_t scanner, enum perf_tool_event event) +{ + YYSTYPE *yylval = parse_events_get_lval(scanner); + + yylval->num = event; + return PE_VALUE_SYM_TOOL; +} + static int term(yyscan_t scanner, enum parse_events__term_type type) { YYSTYPE *yylval = parse_events_get_lval(scanner);
@@ -396,6 +404,9 @@ cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COU alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } +duration_time { return tool(yyscanner, PERF_TOOL_DURATION_TIME); } +user_time { return tool(yyscanner, PERF_TOOL_USER_TIME); } +system_time { return tool(yyscanner, PERF_TOOL_SYSTEM_TIME); } bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); } cgroup-switches { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); }
tools/perf/util/parse-events.y +16 -0
@@ -56,6 +56,7 @@ static void free_list_evsel(struct list_head* list_evsel) %token PE_START_EVENTS PE_START_TERMS %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM +%token PE_VALUE_SYM_TOOL %token PE_EVENT_NAME %token PE_RAW PE_NAME %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
@@ -67,6 +68,7 @@ static void free_list_evsel(struct list_head* list_evsel) %type <num> PE_VALUE %type <num> PE_VALUE_SYM_HW %type <num> PE_VALUE_SYM_SW +%type <num> PE_VALUE_SYM_TOOL %type <mod> PE_MODIFIER_EVENT %type <term_type> PE_TERM %type <num> value_sym
@@ -348,6 +350,20 @@ value_sym sep_slash_slash_dc PE_ABORT(err); $$ = list; } +| +PE_VALUE_SYM_TOOL sep_slash_slash_dc +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYNOMEM; + err = parse_events_add_tool(_parse_state, list, $1); + if (err) + YYNOMEM; + $$ = list; +} event_legacy_cache: PE_LEGACY_CACHE opt_event_config
tools/perf/util/pmu.c +2 -18
@@ -19,7 +19,6 @@#include "evsel.h" #include "pmu.h" #include "pmus.h" -#include "tool_pmu.h" #include <util/pmu-bison.h> #include <util/pmu-flex.h> #include "parse-events.h"
@@ -1512,9 +1511,6 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, {bool zero = !!pmu->perf_event_attr_init_default; -if (perf_pmu__is_tool (pmu)) -return tool_pmu__config_terms (attr, head_terms, err); -/* Fake PMU doesn't have proper terms so nothing to configure in attr. */ if (perf_pmu__is_fake (pmu))return 0 ;
@@ -1627,8 +1623,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_ info->scale =0.0 ; info->snapshot = false; -/* Tool/fake PMU doesn't rewrite terms. */ -if (perf_pmu__is_tool (pmu) ||perf_pmu__is_fake (pmu)) +/* Fake PMU doesn't rewrite terms. */ +if (perf_pmu__is_fake (pmu)) goto out;list_for_each_entry_safe (term, h, &head_terms->terms, list) {
@@ -1798,8 +1794,6 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) {if (!name)return false; -if (perf_pmu__is_tool (pmu)) -return perf_tool_event__from_str (name) !=PERF_TOOL_NONE ;if (perf_pmu__find_alias (pmu, name,/*load=*/ true) !=NULL )return true;if (pmu->cpu_aliases_added || !pmu->events_table)
@@ -1811,9 +1805,6 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu) {size_t nr; -if (perf_pmu__is_tool (pmu)) -return tool_pmu__num_events (); -pmu_aliases_parse (pmu); nr = pmu->sysfs_aliases + pmu->sys_json_aliases;
@@ -1875,9 +1866,6 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,int ret =0 ;struct strbuf sb; -if (perf_pmu__is_tool (pmu)) -return tool_pmu__for_each_event_cb (pmu, state, cb); -strbuf_init (&sb,/*hint=*/ 0 );pmu_aliases_parse (pmu);pmu_add_cpu_aliases (pmu);
@@ -1966,7 +1954,6 @@ bool perf_pmu__is_software(const struct perf_pmu *pmu)case PERF_TYPE_HW_CACHE :return false;case PERF_TYPE_RAW :return false;case PERF_TYPE_BREAKPOINT :return true; -case PERF_PMU_TYPE_TOOL :return true;default :break ; }for (size_t i =0 ; i <ARRAY_SIZE (known_sw_pmus); i++) {
@@ -2294,9 +2281,6 @@ const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config)if (!pmu)return NULL ; -if (perf_pmu__is_tool (pmu)) -return perf_tool_event__to_str (config); -pmu_aliases_parse (pmu);pmu_add_cpu_aliases (pmu);list_for_each_entry (event, &pmu->aliases, list) {
tools/perf/util/pmu.h +0 -2
@@ -37,7 +37,6 @@ struct perf_pmu_caps { };enum { -PERF_PMU_TYPE_TOOL =0xFFFFFFFE ,PERF_PMU_TYPE_FAKE =0xFFFFFFFF , };
@@ -286,7 +285,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const charstruct perf_pmu *perf_pmu__create_placeholder_core_pmu (struct list_head *core_pmus);void perf_pmu__delete (struct perf_pmu *pmu);struct perf_pmu *perf_pmus__find_core_pmu (void ); -const char *perf_pmu__name_from_config (struct perf_pmu *pmu,u64 config);#endif /* __PMU_H */
tools/perf/util/pmus.c +0 -9
@@ -15,7 +15,6 @@#include "evsel.h" #include "pmus.h" #include "pmu.h" -#include "tool_pmu.h" #include "print-events.h" #include "strbuf.h"
@@ -201,7 +200,6 @@ static void pmu_read_sysfs(bool core_only)int fd;DIR *dir;struct dirent *dent; -struct perf_pmu *tool_pmu;if (read_sysfs_all_pmus || (core_only && read_sysfs_core_pmus))return ;
@@ -231,10 +229,6 @@ static void pmu_read_sysfs(bool core_only)pr_err ("Failure to set up any core PMUs\n" ); }list_sort (NULL , &core_pmus, pmus_cmp); -if (!core_only) { - tool_pmu =perf_pmus__tool_pmu (); -list_add_tail (&tool_pmu->list, &other_pmus); - }list_sort (NULL , &other_pmus, pmus_cmp);if (!list_empty (&core_pmus)) { read_sysfs_core_pmus = true;
@@ -590,9 +584,6 @@ void perf_pmus__print_raw_pmu_events(const struct print_callbacks *print_cb, voiint len =pmu_name_len_no_suffix (pmu->name);const char *desc ="(see 'man perf-list' or 'man perf-record' on how to encode it)" ; -if (perf_pmu__is_tool (pmu)) -continue ; -if (!pmu->is_core) desc =NULL ;
tools/perf/util/print-events.c +35 -1
@@ -29,7 +29,6 @@#include "tracepoint.h" #include "pfm.h" #include "thread_map.h" -#include "tool_pmu.h" #include "util.h" #define MAX_NAME_LEN 100
@@ -44,6 +43,21 @@ static const char * const event_type_descriptors[] = { "Hardware breakpoint", }; +static const struct event_symbol event_symbols_tool[PERF_TOOL_MAX ] = { + [PERF_TOOL_DURATION_TIME ] = { + .symbol ="duration_time" , + .alias ="" , + }, + [PERF_TOOL_USER_TIME ] = { + .symbol ="user_time" , + .alias ="" , + }, + [PERF_TOOL_SYSTEM_TIME ] = { + .symbol ="system_time" , + .alias ="" , + }, +}; +/* * Print the events from <debugfs_mount_point>/tracing/events */
@@ -328,6 +342,24 @@ int print_hwcache_events(const struct print_callbacks *print_cb, void *print_stareturn 0 ; } +void print_tool_events (const struct print_callbacks *print_cb,void *print_state) +{ +// Start at 1 because the first enum entry means no tool event. +for (int i =1 ; i <PERF_TOOL_MAX ; ++i) { + print_cb->print_event (print_state, +"tool" , +/*pmu_name=*/ NULL , + event_symbols_tool[i].symbol, + event_symbols_tool[i].alias, +/*scale_unit=*/ NULL , +/*deprecated=*/ false, +"Tool event" , +/*desc=*/ NULL , +/*long_desc=*/ NULL , +/*encoding_desc=*/ NULL ); + } +} +void print_symbol_events (const struct print_callbacks *print_cb,void *print_state,unsigned int type,const struct event_symbol *syms,unsigned int max)
@@ -391,6 +423,8 @@ void print_events(const struct print_callbacks *print_cb, void *print_state)print_symbol_events (print_cb, print_state,PERF_TYPE_SOFTWARE , event_symbols_sw,PERF_COUNT_SW_MAX ); +print_tool_events (print_cb, print_state); +print_hwcache_events (print_cb, print_state);perf_pmus__print_pmu_events (print_cb, print_state);
tools/perf/util/print-events.h +1 -0
@@ -36,6 +36,7 @@ void print_sdt_events(const struct print_callbacks *print_cb, void *print_state)void print_symbol_events (const struct print_callbacks *print_cb,void *print_state,unsigned int type,const struct event_symbol *syms,unsigned int max); +void print_tool_events (const struct print_callbacks *print_cb,void *print_state);void print_tracepoint_events (const struct print_callbacks *print_cb,void *print_state);bool is_event_supported (u8 type,u64 config);
tools/perf/util/stat-display.c +1 -5
@@ -21,7 +21,6 @@#include "iostat.h" #include "pmu.h" #include "pmus.h" -#include "tool_pmu.h" #define CNTR_NOT_SUPPORTED "<not supported>"#define CNTR_NOT_COUNTED "<not counted>"
@@ -947,10 +946,7 @@ static bool should_skip_zero_counter(struct perf_stat_config *config,if (config->aggr_mode ==AGGR_THREAD && config->system_wide)return true; -/* -* Many tool events are only gathered on the first index, skip other -* zero values. -*/ +/* Tool events have the software PMU but are only gathered on 1. */ if (evsel__is_tool (counter))return true;
tools/perf/util/stat-shadow.c +0 -1
@@ -15,7 +15,6 @@#include <linux/zalloc.h> #include "iostat.h" #include "util/hashmap.h" -#include "tool_pmu.h" struct stats walltime_nsecs_stats;struct rusage_stats ru_stats;
tools/perf/util/tool_pmu.c deleted +0 -411
411 lines not on this page · raw message
tools/perf/util/tool_pmu.h deleted +0 -51
51 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/272 bridge: mrp: reject zero test interval to avoid OOM panic
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit fa6e24963342de4370e3a3c9af41e38277b74cf3 ]
br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied interval value from netlink without validation. When interval is 0, usecs_to_jiffies(0) yields 0, causing the delayed work (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule itself with zero delay. This creates a tight loop on system_percpu_wq that allocates and transmits MRP test frames at maximum rate, exhausting all system memory and causing a kernel panic via OOM deadlock.
The same zero-interval issue applies to br_mrp_start_in_test_parse() for interconnect test frames.
Use NLA_POLICY_MIN(NLA_U32, 1) in the nla_policy tables for both IFLA_BRIDGE_MRP_START_TEST_INTERVAL and IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, so zero is rejected at the netlink attribute parsing layer before the value ever reaches the workqueue scheduling code. This is consistent with how other bridge subsystems (br_fdb, br_mst) enforce range constraints on netlink attributes.
--- net/bridge/br_mrp_netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/bridge/br_mrp_netlink.c +2 -2
@@ -196,7 +196,7 @@ static const struct nla_policy br_mrp_start_test_policy[IFLA_BRIDGE_MRP_START_TEST_MAX + 1] = { [IFLA_BRIDGE_MRP_START_TEST_UNSPEC] = { .type = NLA_REJECT }, [IFLA_BRIDGE_MRP_START_TEST_RING_ID] = { .type = NLA_U32 }, - [IFLA_BRIDGE_MRP_START_TEST_INTERVAL] = { .type = NLA_U32 }, + [IFLA_BRIDGE_MRP_START_TEST_INTERVAL] = NLA_POLICY_MIN(NLA_U32, 1), [IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] = { .type = NLA_U32 }, [IFLA_BRIDGE_MRP_START_TEST_PERIOD] = { .type = NLA_U32 }, [IFLA_BRIDGE_MRP_START_TEST_MONITOR] = { .type = NLA_U32 },
@@ -316,7 +316,7 @@ static const struct nla_policy br_mrp_start_in_test_policy[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1] = { [IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC] = { .type = NLA_REJECT }, [IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] = { .type = NLA_U32 }, - [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = { .type = NLA_U32 }, + [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = NLA_POLICY_MIN(NLA_U32, 1), [IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] = { .type = NLA_U32 }, [IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD] = { .type = NLA_U32 }, };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/272 spi: spi-dw-dma: fix print error log when wait finish transaction
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Yakovlev <[email protected]>
[ Upstream commit 3b46d61890632c8f8b117147b6923bff4b42ccb7 ]
If an error occurs, the device may not have a current message. In this case, the system will crash.
In this case, it's better to use dev from the struct ctlr (struct spi_controller*).
--- drivers/spi/spi-dw-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-dw-dma.c +1 -1
@@ -271,7 +271,7 @@ static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed) msecs_to_jiffies(ms));if (ms ==0 ) { -dev_err (&dws->host->cur_msg->spi->dev, +dev_err (&dws->host->dev,"DMA transaction timed out\n" );return -ETIMEDOUT ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 14/272 Revert "x86/vdso: Fix output operand size of RDPID"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit d607e6b349b014df1d2d0399f6667322626450e0.
--- arch/x86/include/asm/segment.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/include/asm/segment.h +4 -4
@@ -244,7 +244,7 @@ static inline unsigned long vdso_encode_cpunode(int cpu, unsigned long node)static inline void vdso_read_cpunode (unsigned *cpu,unsigned *node) { -unsigned long p; +unsigned int p;/* * Load CPU and node number from the GDT. LSL is faster than RDTSCP
@@ -254,10 +254,10 @@ static inline void vdso_read_cpunode(unsigned *cpu, unsigned *node)* * If RDPID is available, use it. */ -alternative_io ("lsl %[seg],%k[p]" , -"rdpid %[p]" , +alternative_io ("lsl %[seg],%[p]" , +".byte 0xf3,0x0f,0xc7,0xf8" ,/* RDPID %eax/rax */ X86_FEATURE_RDPID, - [p] "=r" (p), [seg] "r" (__CPUNODE_SEG)); + [p] "=a" (p), [seg] "r" (__CPUNODE_SEG)); if (cpu) *cpu = (p & VDSO_CPUNODE_MASK);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 15/272 sched/deadline: Less agressive dl_server handling
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
commit cccb45d7c4295bbfeba616582d0249f2d21e6df5 upstream.
Chris reported that commit 5f6bd380c7bd ("sched/rt: Remove default bandwidth control") caused a significant dip in his favourite benchmark of the day. Simply disabling dl_server cured things.
His workload hammers the 0->1, 1->0 transitions, and the dl_server_{start,stop}() overhead kills it -- fairly obviously a bad idea in hind sight and all that.
Change things around to only disable the dl_server when there has not been a fair task around for a whole period. Since the default period is 1 second, this ensures the benchmark never trips this, overhead gone.
--- include/linux/sched.h | 1 + kernel/sched/deadline.c | 25 ++++++++++++++++++++++--- kernel/sched/fair.c | 9 --------- 3 files changed, 23 insertions(+), 12 deletions(-)
include/linux/sched.h +1 -0
@@ -674,6 +674,7 @@ struct sched_dl_entity { unsigned int dl_defer : 1; unsigned int dl_defer_armed : 1; unsigned int dl_defer_running : 1; + unsigned int dl_server_idle : 1;/* * Bandwidth enforcement timer. Each -deadline task has its
kernel/sched/deadline.c +22 -3
@@ -1201,6 +1201,8 @@ static void __push_dl_task(struct rq *rq, struct rq_flags *rf)/* a defer timer will not be reset if the runtime consumed was < dl_server_min_res */ static const u64 dl_server_min_res =1 *NSEC_PER_MSEC ; +static bool dl_server_stopped (struct sched_dl_entity *dl_se); +static enum hrtimer_restart dl_server_timer (struct hrtimer *timer,struct sched_dl_entity *dl_se) {struct rq *rq =rq_of_dl_se (dl_se);
@@ -1220,6 +1222,7 @@ static enum hrtimer_restart dl_server_timer(struct hrtimer *timer, struct sched_if (!dl_se->server_has_tasks (dl_se)) {replenish_dl_entity (dl_se); +dl_server_stopped (dl_se);return HRTIMER_NORESTART ; }
@@ -1626,8 +1629,10 @@ void dl_server_update_idle_time(struct rq *rq, struct task_struct *p)void dl_server_update (struct sched_dl_entity *dl_se,s64 delta_exec) {/* 0 runtime = fair server disabled */ -if (dl_se->dl_runtime) +if (dl_se->dl_runtime) { + dl_se->dl_server_idle =0 ;update_curr_dl_se (dl_se->rq, dl_se, delta_exec); + } }/*
@@ -1850,7 +1855,7 @@ void dl_server_start(struct sched_dl_entity *dl_se)setup_new_dl_entity (dl_se); } -if (!dl_se->dl_runtime) +if (!dl_se->dl_runtime || dl_se->dl_server_active)return ; dl_se->dl_server_active =1 ;
@@ -1871,6 +1876,20 @@ void dl_server_stop(struct sched_dl_entity *dl_se) dl_se->dl_server_active =0 ; } +static bool dl_server_stopped (struct sched_dl_entity *dl_se) +{ +if (!dl_se->dl_server_active) +return false; + +if (dl_se->dl_server_idle) { +dl_server_stop (dl_se); +return true; + } + + dl_se->dl_server_idle =1 ; +return false; +} +void dl_server_init (struct sched_dl_entity *dl_se,struct rq *rq,dl_server_has_tasks_f has_tasks,dl_server_pick_f pick_task)
@@ -2628,7 +2647,7 @@ static struct task_struct *__pick_task_dl(struct rq *rq)if (dl_server (dl_se)) { p = dl_se->server_pick_task (dl_se);if (!p) { -if (dl_server_active (dl_se)) { +if (!dl_server_stopped (dl_se)) { dl_se->dl_yielded =1 ;update_curr_dl_se (rq, dl_se,0 ); }
kernel/sched/fair.c +0 -9
@@ -5972,7 +5972,6 @@ static bool throttle_cfs_rq(struct cfs_rq *cfs_rq)struct cfs_bandwidth *cfs_b =tg_cfs_bandwidth (cfs_rq->tg);struct sched_entity *se;long queued_delta, runnable_delta, idle_task_delta, delayed_delta, dequeue =1 ; -long rq_h_nr_queued = rq->cfs.h_nr_queued;raw_spin_lock (&cfs_b->lock);/* This will start the period timer if necessary */
@@ -6059,10 +6058,6 @@ static bool throttle_cfs_rq(struct cfs_rq *cfs_rq)/* At this point se is NULL and we are at root level*/ sub_nr_running (rq, queued_delta); - -/* Stop the fair server if throttling resulted in no runnable tasks */ -if (rq_h_nr_queued && !rq->cfs.h_nr_queued) -dl_server_stop (&rq->fair_server); done:/* * Note: distribution will already see us throttled via the
@@ -7162,7 +7157,6 @@ static void set_next_buddy(struct sched_entity *se);static int dequeue_entities (struct rq *rq,struct sched_entity *se,int flags) {bool was_sched_idle =sched_idle_rq (rq); -int rq_h_nr_queued = rq->cfs.h_nr_queued;bool task_sleep = flags &DEQUEUE_SLEEP ;bool task_delayed = flags &DEQUEUE_DELAYED ;struct task_struct *p =NULL ;
@@ -7251,9 +7245,6 @@ static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags)sub_nr_running (rq, h_nr_queued); -if (rq_h_nr_queued && !rq->cfs.h_nr_queued) -dl_server_stop (&rq->fair_server); -/* balance early to pull high priority tasks */ if (unlikely (!was_sched_idle &&sched_idle_rq (rq))) rq->next_balance = jiffies;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 16/272 sched/deadline: Fix dl_server_stopped()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen <[email protected]>
commit 4717432dfd99bbd015b6782adca216c6f9340038 upstream.
Commit cccb45d7c429 ("sched/deadline: Less agressive dl_server handling") introduces dl_server_stopped(). But it is obvious that dl_server_stopped() should return true if dl_se->dl_server_active is 0.
--- kernel/sched/deadline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/deadline.c +1 -1
@@ -1879,7 +1879,7 @@ void dl_server_stop(struct sched_dl_entity *dl_se)static bool dl_server_stopped (struct sched_dl_entity *dl_se) {if (!dl_se->dl_server_active) -return false; +return true;if (dl_se->dl_server_idle) {dl_server_stop (dl_se);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 17/272 sched/deadline: Always stop dl-server before changing parameters
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juri Lelli <[email protected]>
commit bb4700adc3abec34c0a38b64f66258e4e233fc16 upstream.
Commit cccb45d7c4295 ("sched/deadline: Less agressive dl_server handling") reduced dl-server overhead by delaying disabling servers only after there are no fair task around for a whole period, which means that deadline entities are not dequeued right away on a server stop event. However, the delay opens up a window in which a request for changing server parameters can break per-runqueue running_bw tracking, as reported by Yuri.
Close the problematic window by unconditionally calling dl_server_stop() before applying the new parameters (ensuring deadline entities go through an actual dequeue).
--- kernel/sched/debug.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
kernel/sched/debug.c +2 -4
@@ -378,10 +378,8 @@ static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubureturn -EINVAL ; } -if (rq->cfs.h_nr_queued) { -update_rq_clock (rq); -dl_server_stop (&rq->fair_server); - } +update_rq_clock (rq); +dl_server_stop (&rq->fair_server); retval =dl_server_apply_params (&rq->fair_server, runtime, period,0 );
Signature · 1 line
2.53.0
Re: [PATCH 6.12 017/272] sched/deadline: Always stop dl-server before changing parameters
Hi Greg/Sasha,
Quoted 37 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juri Lelli <[email protected]>
commit
bb4700adc3abec34c0a38b64f66258e4e233fc16upstream.Commit
cccb45d7c4295("sched/deadline: Less agressivedl_serverhandling") reduced dl-server overhead by delaying disabling servers only after there are no fair task around for a whole period, which means that deadline entities are not dequeued right away on a server stop event. However, the delay opens up a window in which a request for changing server parameters can break per-runqueuerunning_bwtracking, as reported by Yuri.Close the problematic window by unconditionally calling
dl_server_stop()before applying the new parameters (ensuring deadline entities go through an actual dequeue).Fixes cccb45d7c4295 ("sched/deadline: Less agressive dl_server handling")Reported-by Yuri Andriaccio <[email protected]>Signed-off-by Juri Lelli <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Valentin Schneider <[email protected]>Link https://lore.kernel.org/r/20250721-upstream-fix-dlserver-lessaggressive-b4-v1-1-4ebc10c87e40@redhat.com open hereSigned-off-by Lukas Beckmann <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- kernel/sched/debug.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)kernel/sched/debug.c +0
-0
kernel/sched/debug.c static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubu · line 383
Quoted 10 lines
kernel/sched/debug.c +2
-4@@ -378,10 +378,8 @@ static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubureturn -EINVAL ; } -if (rq->cfs.h_nr_queued) { -update_rq_clock (rq); -dl_server_stop (&rq->fair_server); - } +update_rq_clock (rq); +dl_server_stop (&rq->fair_server);
I have run an AI assisted backport review and took a look at this one.
I think 6.12.y is missing what upstream has:
The backport makes sched_fair_server_write() always do:
update_rq_clock(rq);dl_server_stop(&rq->fair_server);
That matches upstream bb4700adc3ab, but upstream also has this in dl_server_stop():
if (!dl_server(dl_se) || !dl_server_active(dl_se))
return;
6.12.y only has:
if (!dl_se->dl_runtime)
return;
so an inactive but configured fair server can still go through the deadline dequeue accounting path.
So it looks like this backport is not very safe. Thoughts ?
thanks,
Harshit
Quoted 2 lines
kernel/sched/debug.c +0
-0retval =dl_server_apply_params (&rq->fair_server, runtime, period,0 );
Greg Kroah-Hartman
maintainerRe: [PATCH 6.12 017/272] sched/deadline: Always stop dl-server before changing parameters
Quoted 67 lines · Harshit Mogalapalli
Hi Greg/Sasha,
Quoted 37 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juri Lelli <[email protected]>
commit
bb4700adc3abec34c0a38b64f66258e4e233fc16upstream.Commit
cccb45d7c4295("sched/deadline: Less agressivedl_serverhandling") reduced dl-server overhead by delaying disabling servers only after there are no fair task around for a whole period, which means that deadline entities are not dequeued right away on a server stop event. However, the delay opens up a window in which a request for changing server parameters can break per-runqueuerunning_bwtracking, as reported by Yuri.Close the problematic window by unconditionally calling
dl_server_stop()before applying the new parameters (ensuring deadline entities go through an actual dequeue).Fixes cccb45d7c4295 ("sched/deadline: Less agressive dl_server handling")Reported-by Yuri Andriaccio <[email protected]>Signed-off-by Juri Lelli <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>Reviewed-by Valentin Schneider <[email protected]>Link https://lore.kernel.org/r/20250721-upstream-fix-dlserver-lessaggressive-b4-v1-1-4ebc10c87e40@redhat.com open hereSigned-off-by Lukas Beckmann <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- kernel/sched/debug.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)kernel/sched/debug.c +0
-0kernel/sched/debug.c static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubu · line 381
Quoted 8 lines
kernel/sched/debug.c +2
-4@@ -378,10 +378,8 @@ static ssize_t sched_fair_server_write(struct file *filp, const char __user *ubureturn -EINVAL ; } -if (rq->cfs.h_nr_queued) { -update_rq_clock (rq); -dl_server_stop (&rq->fair_server); - } +update_rq_clock (rq); +dl_server_stop (&rq->fair_server);I have run an AI assisted backport review and took a look at this one.
I think 6.12.y is missing what upstream has:
The backport makes
sched_fair_server_write()always do:
update_rq_clock(rq);dl_server_stop(&rq->fair_server);That matches upstream
bb4700adc3ab, but upstream also has this indl_server_stop():if (!dl_server(dl_se) || !dl_server_active(dl_se))
return;6.12.y only has:
Quoted 7 lines
if (!dl_se->dl_runtime)
return;so an inactive but configured fair server can still go through the deadline dequeue accounting path.
So it looks like this backport is not very safe. Thoughts ?
Now dropped, thanks.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 18/272 sched/deadline: Fix dl_server getting stuck
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
commit 4ae8d9aa9f9dc7137ea5e564d79c5aa5af1bc45c upstream.
John found it was easy to hit lockup warnings when running locktorture on a 2 CPU VM, which he bisected down to: commit cccb45d7c429 ("sched/deadline: Less agressive dl_server handling").
While debugging it seems there is a chance where we end up with the dl_server dequeued, with dl_se->dl_server_active. This causes dl_server_start() to return without enqueueing the dl_server, thus it fails to run when RT tasks starve the cpu.
When this happens, dl_server_timer() catches the '!dl_se->server_has_tasks(dl_se)' case, which then calls replenish_dl_entity() and dl_server_stopped() and finally return HRTIMER_NO_RESTART.
This ends in no new timer and also no enqueue, leaving the dl_server 'dead', allowing starvation.
What should have happened is for the bandwidth timer to start the zero-laxity timer, which in turn would enqueue the dl_server and cause dl_se->server_pick_task() to be called -- which will stop the dl_server if no fair tasks are observed for a whole period.
IOW, it is totally irrelevant if there are fair tasks at the moment of bandwidth refresh.
This removes all dl_se->server_has_tasks() users, so remove the whole thing.
[ adjust renamed variable in fair_server_has_tasks (which this patch removes) ]
--- include/linux/sched.h | 1 - kernel/sched/deadline.c | 12 +----------- kernel/sched/fair.c | 7 +------ kernel/sched/sched.h | 4 ---- 4 files changed, 2 insertions(+), 22 deletions(-)
include/linux/sched.h +0 -1
@@ -701,7 +701,6 @@ struct sched_dl_entity {* runnable task. */ struct rq *rq; -dl_server_has_tasks_f server_has_tasks;dl_server_pick_f server_pick_task;#ifdef CONFIG_RT_MUTEXES
kernel/sched/deadline.c +1 -11
@@ -916,7 +916,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se)*/ if (dl_se->dl_defer && !dl_se->dl_defer_running &&dl_time_before (rq_clock (dl_se->rq), dl_se->deadline - dl_se->runtime)) { -if (!is_dl_boosted (dl_se) && dl_se->server_has_tasks (dl_se)) { +if (!is_dl_boosted (dl_se)) {/* * Set dl_se->dl_defer_armed and dl_throttled variables to
@@ -1201,8 +1201,6 @@ static void __push_dl_task(struct rq *rq, struct rq_flags *rf)/* a defer timer will not be reset if the runtime consumed was < dl_server_min_res */ static const u64 dl_server_min_res =1 *NSEC_PER_MSEC ; -static bool dl_server_stopped (struct sched_dl_entity *dl_se); -static enum hrtimer_restart dl_server_timer (struct hrtimer *timer,struct sched_dl_entity *dl_se) {struct rq *rq =rq_of_dl_se (dl_se);
@@ -1220,12 +1218,6 @@ static enum hrtimer_restart dl_server_timer(struct hrtimer *timer, struct sched_if (!dl_se->dl_runtime)return HRTIMER_NORESTART ; -if (!dl_se->server_has_tasks (dl_se)) { -replenish_dl_entity (dl_se); -dl_server_stopped (dl_se); -return HRTIMER_NORESTART ; - } -if (dl_se->dl_defer_armed) {/* * First check if the server could consume runtime in background.
@@ -1891,11 +1883,9 @@ static bool dl_server_stopped(struct sched_dl_entity *dl_se) }void dl_server_init (struct sched_dl_entity *dl_se,struct rq *rq, -dl_server_has_tasks_f has_tasks,dl_server_pick_f pick_task) { dl_se->rq = rq; - dl_se->server_has_tasks = has_tasks; dl_se->server_pick_task = pick_task; }
kernel/sched/fair.c +1 -6
@@ -9058,11 +9058,6 @@ static struct task_struct *__pick_next_task_fair(struct rq *rq, struct task_strureturn pick_next_task_fair (rq, prev,NULL ); } -static bool fair_server_has_tasks (struct sched_dl_entity *dl_se) -{ -return !!dl_se->rq->cfs.nr_running; -} -static struct task_struct *fair_server_pick_task (struct sched_dl_entity *dl_se) {return pick_task_fair (dl_se->rq);
@@ -9074,7 +9069,7 @@ void fair_server_init(struct rq *rq)init_dl_entity (dl_se); -dl_server_init (dl_se, rq, fair_server_has_tasks, fair_server_pick_task); +dl_server_init (dl_se, rq, fair_server_pick_task); }/*
kernel/sched/sched.h +0 -4
@@ -371,9 +371,6 @@ extern s64 dl_scaled_delta_exec(struct rq *rq, struct sched_dl_entity *dl_se, s6* * dl_se::rq -- runqueue we belong to. * -* dl_se::server_has_tasks() -- used on bandwidth enforcement; we 'stop' the -* server when it runs out of tasks to run. -* * dl_se::server_pick() -- nested pick_next_task(); we yield the period if this * returns NULL. *
@@ -389,7 +386,6 @@ extern void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec);extern void dl_server_start (struct sched_dl_entity *dl_se);extern void dl_server_stop (struct sched_dl_entity *dl_se);extern void dl_server_init (struct sched_dl_entity *dl_se,struct rq *rq, -dl_server_has_tasks_f has_tasks,dl_server_pick_f pick_task); extern void dl_server_update_idle_time(struct rq *rq,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 19/272 sched/deadline: Fix dl_server behaviour
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
commit a3a70caf7906708bf9bbc80018752a6b36543808 upstream.
John reported undesirable behaviour with the dl_server since commit:cccb45d7c4295 ("sched/deadline: Less agressive dl_server handling").
When starving fair tasks on purpose (starting spinning FIFO tasks), his fair workload, which often goes (briefly) idle, would delay fair invocations for a second, running one invocation per second was both unexpected and terribly slow.
The reason this happens is that when dl_se->server_pick_task() returns NULL, indicating no runnable tasks, it would yield, pushing any later jobs out a whole period (1 second).
Instead simply stop the server. This should restore behaviour in that a later wakeup (which restarts the server) will be able to continue running (subject to the CBS wakeup rules).
Notably, this does not re-introduce the behaviour cccb45d7c4295 set out to solve, any start/stop cycle is naturally throttled by the timer period (no active cancel).
--- include/linux/sched.h | 1 - kernel/sched/deadline.c | 23 ++--------------------- kernel/sched/sched.h | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 24 deletions(-)
include/linux/sched.h +0 -1
@@ -674,7 +674,6 @@ struct sched_dl_entity { unsigned int dl_defer : 1; unsigned int dl_defer_armed : 1; unsigned int dl_defer_running : 1; - unsigned int dl_server_idle : 1;/* * Bandwidth enforcement timer. Each -deadline task has its
kernel/sched/deadline.c +2 -21
@@ -1621,10 +1621,8 @@ void dl_server_update_idle_time(struct rq *rq, struct task_struct *p)void dl_server_update (struct sched_dl_entity *dl_se,s64 delta_exec) {/* 0 runtime = fair server disabled */ -if (dl_se->dl_runtime) { - dl_se->dl_server_idle =0 ; +if (dl_se->dl_runtime)update_curr_dl_se (dl_se->rq, dl_se, delta_exec); - } }/*
@@ -1868,20 +1866,6 @@ void dl_server_stop(struct sched_dl_entity *dl_se) dl_se->dl_server_active =0 ; } -static bool dl_server_stopped (struct sched_dl_entity *dl_se) -{ -if (!dl_se->dl_server_active) -return true; - -if (dl_se->dl_server_idle) { -dl_server_stop (dl_se); -return true; - } - - dl_se->dl_server_idle =1 ; -return false; -} -void dl_server_init (struct sched_dl_entity *dl_se,struct rq *rq,dl_server_pick_f pick_task) {
@@ -2637,10 +2621,7 @@ static struct task_struct *__pick_task_dl(struct rq *rq)if (dl_server (dl_se)) { p = dl_se->server_pick_task (dl_se);if (!p) { -if (!dl_server_stopped (dl_se)) { - dl_se->dl_yielded =1 ; -update_curr_dl_se (rq, dl_se,0 ); - } +dl_server_stop (dl_se); goto again; } rq->dl_server = dl_se;
kernel/sched/sched.h +31 -2
@@ -377,10 +377,39 @@ extern s64 dl_scaled_delta_exec(struct rq *rq, struct sched_dl_entity *dl_se, s6* dl_server_update() -- called from update_curr_common(), propagates runtime * to the server. * -* dl_server_start() -* dl_server_stop() -- start/stop the server when it has (no) tasks. +* dl_server_start() -- start the server when it has tasks; it will stop +* automatically when there are no more tasks, per +* dl_se::server_pick() returning NULL. +* +* dl_server_stop() -- (force) stop the server; use when updating +* parameters. * * dl_server_init() -- initializes the server. +* +* When started the dl_server will (per dl_defer) schedule a timer for its +* zero-laxity point -- that is, unlike regular EDF tasks which run ASAP, a +* server will run at the very end of its period. +* +* This is done such that any runtime from the target class can be accounted +* against the server -- through dl_server_update() above -- such that when it +* becomes time to run, it might already be out of runtime and get deferred +* until the next period. In this case dl_server_timer() will alternate +* between defer and replenish but never actually enqueue the server. +* +* Only when the target class does not manage to exhaust the server's runtime +* (there's actualy starvation in the given period), will the dl_server get on +* the runqueue. Once queued it will pick tasks from the target class and run +* them until either its runtime is exhaused, at which point its back to +* dl_server_timer, or until there are no more tasks to run, at which point +* the dl_server stops itself. +* +* By stopping at this point the dl_server retains bandwidth, which, if a new +* task wakes up imminently (starting the server again), can be used -- +* subject to CBS wakeup rules -- without having to wait for the next period. +* +* Additionally, because of the dl_defer behaviour the start/stop behaviour is +* naturally thottled to once per period, avoiding high context switch +* workloads from spamming the hrtimer program/cancel paths. */ extern void dl_server_update (struct sched_dl_entity *dl_se,s64 delta_exec);extern void dl_server_start (struct sched_dl_entity *dl_se);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 20/272 sched/deadline: Stop dl_server before CPU goes offline
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra (Intel) <[email protected]>
[ Upstream commit ee6e44dfe6e50b4a5df853d933a96bdff5309e6e ]
IBM CI tool reported kernel warning[1] when running a CPU removal operation through drmgr[2]. i.e "drmgr -c cpu -r -q 1"
WARNING: CPU: 0 PID: 0 at kernel/sched/cpudeadline.c:219 cpudl_set+0x58/0x170 NIP [c0000000002b6ed8] cpudl_set+0x58/0x170 LR [c0000000002b7cb8] dl_server_timer+0x168/0x2a0 Call Trace: [c000000002c2f8c0] init_stack+0x78c0/0x8000 (unreliable) [c0000000002b7cb8] dl_server_timer+0x168/0x2a0 [c00000000034df84] __hrtimer_run_queues+0x1a4/0x390 [c00000000034f624] hrtimer_interrupt+0x124/0x300 [c00000000002a230] timer_interrupt+0x140/0x320
Git bisects to: commit 4ae8d9aa9f9d ("sched/deadline: Fix dl_server getting stuck")
This happens since:
- dl_server hrtimer gets enqueued close to cpu offline, when kthread_park enqueues a fair task.
- CPU goes offline and drmgr removes it from cpu_present_mask.
- hrtimer fires and warning is hit.
Fix it by stopping the dl_server before CPU is marked dead.
[1]: https://lore.kernel.org/all/[email protected]/
[2]: https://github.com/ibm-power-utilities/powerpc-utils/tree/next/src/drmgr
--- kernel/sched/core.c | 2 ++ kernel/sched/deadline.c | 3 +++ 2 files changed, 5 insertions(+)
kernel/sched/core.c +2 -0
@@ -8319,10 +8319,12 @@ int sched_cpu_dying(unsigned int cpu)sched_tick_stop (cpu);rq_lock_irqsave (rq, &rf); +update_rq_clock (rq);if (rq->nr_running !=1 ||rq_has_pinned_tasks (rq)) {WARN (true,"Dying CPU not properly vacated!" );dump_rq_tasks (rq,KERN_WARNING ); } +dl_server_stop (&rq->fair_server);rq_unlock_irqrestore (rq, &rf);calc_load_migrate (rq);
kernel/sched/deadline.c +3 -0
@@ -1848,6 +1848,9 @@ void dl_server_start(struct sched_dl_entity *dl_se)if (!dl_se->dl_runtime || dl_se->dl_server_active)return ; +if (WARN_ON_ONCE (!cpu_online (cpu_of (rq)))) +return ; + dl_se->dl_server_active =1 ;enqueue_dl_entity (dl_se,ENQUEUE_WAKEUP );if (!dl_task (dl_se->rq->curr) ||dl_entity_preempt (dl_se, &rq->curr->dl))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 21/272 ksmbd: close durable scavenger races against m_fp_list lookups
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: DaeMyung Kang <[email protected]>
[ Upstream commit bf736184d063da1a552ffeff0481813599a182cc ]
ksmbd_durable_scavenger() has two related races against any walker that iterates f_ci->m_fp_list, including ksmbd_lookup_fd_inode() (used by ksmbd_vfs_rename) and the share-mode checks in fs/smb/server/smb_common.c.
(1) fp->node list-head reuse. Durable-preserved handles can remain linked on f_ci->m_fp_list after session teardown so share-mode checks still see them while the handle is reconnectable. The scavenger collected expired handles by adding fp->node to a local scavenger_list after removing them from the global durable idr. Because fp->node is the same list_head used by m_fp_list, list_add(&fp->node, &scavenger_list) overwrites the m_fp_list links and corrupts both lists. CONFIG_DEBUG_LIST can report this on the share-mode walk path.
(2) Refcount race against m_fp_list walkers. The scavenger qualifies an expired durable handle with atomic_read(&fp->refcount) > 1 and fp->conn under global_ft.lock, removes fp from global_ft, then drops global_ft.lock before unlinking fp from m_fp_list and freeing it. During that gap fp is still linked on m_fp_list with f_state == FP_INITED. ksmbd_lookup_fd_inode() under m_lock read calls ksmbd_fp_get() (atomic_inc_not_zero on refcount that is still 1) and takes a live reference; the scavenger then unlinks and frees fp while the holder owns a reference, leading to UAF on the holder's subsequent ksmbd_fd_put() and on any field reads performed by a concurrent share-mode walker that iterates m_fp_list without taking ksmbd_fp_get() (smb_check_perm_dleases-like paths).
Fix both:
* Stop reusing fp->node as a scavenger-private list node. Remove one expired handle from global_ft under global_ft.lock, take an explicit transient reference, drop the lock, unlink fp->node from m_fp_list under f_ci->m_lock, then drop both the durable lifetime and transient references with atomic_sub_and_test(2, &fp->refcount). If the scavenger is the last putter the close runs there; otherwise an in-flight holder that already raced through the m_fp_list lookup owns the final close via its ksmbd_fd_put() path. The one-at-a-time disposal can rescan the durable idr when multiple handles expire in the same pass, but durable scavenging is a background expiration path and the final full scan recomputes min_timeout before the next wait.
* Clear fp->persistent_id inside __ksmbd_remove_durable_fd() right after idr_remove(), so a delayed final close from a holder that snatched fp does not re-issue idr_remove() on a persistent id that idr_alloc_cyclic() in ksmbd_open_durable_fd() may have already handed out to a brand-new durable handle.
* Bypass the per-conn open_files_count decrement in __put_fd_final() when fp is detached from any session table (fp->conn cleared by session_fd_check() at durable preserve -- paired with the volatile_id clear at unpublish, so checking fp->conn alone is sufficient). The walker that owns the final close runs from an unrelated work->conn whose stats.open_files_count never tracked this durable fp; without this guard the holder would underflow that unrelated counter.
The two races are folded into one patch because patch (1) alone cleans up the corrupted list but leaves a deterministic UAF window for m_fp_list walkers that the transient-reference and persistent_id discipline in (2) close; bisecting onto an intermediate state would land on a UAF that pre-patch chaos merely made less reproducible.
Validation:
* CONFIG_DEBUG_LIST coverage for the list_head reuse path.
* KASAN-enabled direct SMB2 durable-handle coverage that exercised ksmbd_durable_scavenger() and non-NULL ksmbd_lookup_fd_inode() returns while durable handles expired under concurrent rename lookups, with no KASAN, UAF, list-corruption, ODEBUG, or WARNING reports.
* checkpatch --strict
* make -j$(nproc) M=fs/smb/server
--- fs/smb/server/vfs_cache.c | 104 ++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 27 deletions(-)
fs/smb/server/vfs_cache.c +77 -27
@@ -325,6 +325,14 @@ static void __ksmbd_remove_durable_fd(struct ksmbd_file *fp)return ;idr_remove (global_ft.idr, fp->persistent_id); +/* +* Clear persistent_id so a later __ksmbd_close_fd() that runs from a +* delayed putter (e.g. when a concurrent ksmbd_lookup_fd_inode() +* walker held the final reference) does not re-issue idr_remove() on +* an id that idr_alloc_cyclic() may have already handed out to a new +* durable handle. +*/ + fp->persistent_id =KSMBD_NO_FID ; }static void ksmbd_remove_durable_fd (struct ksmbd_file *fp)
@@ -417,6 +425,20 @@ static struct ksmbd_file *__ksmbd_lookup_fd(struct ksmbd_file_table *ft,static void __put_fd_final (struct ksmbd_work *work,struct ksmbd_file *fp) { +/* +* Detached durable fp -- session_fd_check() cleared fp->conn at +* preserve, so this fp is no longer tracked by any conn's +* stats.open_files_count. This happens when +* ksmbd_scavenger_dispose_dh() hands the final close off to an +* m_fp_list walker (e.g. ksmbd_lookup_fd_inode()) whose work->conn +* is unrelated to the conn that originally opened the handle; close +* via the NULL-ft path so we do not underflow that unrelated +* counter. +*/ +if (!fp->conn) { +__ksmbd_close_fd (NULL , fp); +return ; + }__ksmbd_close_fd (&work->sess->file_table, fp);atomic_dec (&work->conn->stats.open_files_count); }
@@ -788,24 +810,37 @@ static bool ksmbd_durable_scavenger_alive(void)return true; } -static void ksmbd_scavenger_dispose_dh (struct list_head *head) +static void ksmbd_scavenger_dispose_dh (struct ksmbd_file *fp) { -while (!list_empty (head)) { -struct ksmbd_file *fp; +/* +* Durable-preserved fp can remain linked on f_ci->m_fp_list for +* share-mode checks. Unlink it before final close; fp->node is not +* available as a scavenger-private list node because re-adding it to +* another list corrupts m_fp_list. +*/ +down_write (&fp->f_ci->m_lock); +list_del_init (&fp->node); +up_write (&fp->f_ci->m_lock); - fp = list_first_entry(head, struct ksmbd_file, node); -list_del_init (&fp->node); +/* +* Drop both the durable lifetime reference and the transient reference +* taken by the scavenger under global_ft.lock. If a concurrent +* ksmbd_lookup_fd_inode() (or any other m_fp_list walker) snatched fp +* before the unlink above, that holder owns the final close via +* ksmbd_fd_put() -> __ksmbd_close_fd(). Otherwise the scavenger is +* the last putter and finalises fp here. +*/ +if (atomic_sub_and_test (2 , &fp->refcount))__ksmbd_close_fd (NULL , fp); - } }static int ksmbd_durable_scavenger (void *dummy) {struct ksmbd_file *fp =NULL ; +struct ksmbd_file *expired_fp;unsigned int id;unsigned int min_timeout =1 ;bool found_fp_timeout; -LIST_HEAD (scavenger_list);unsigned long remaining_jiffies;__module_get (THIS_MODULE );
@@ -815,8 +850,6 @@ static int ksmbd_durable_scavenger(void *dummy)if (try_to_freeze ())continue ; - found_fp_timeout = false; - remaining_jiffies =wait_event_timeout (dh_wq,ksmbd_durable_scavenger_alive () == false,__msecs_to_jiffies (min_timeout));
@@ -825,23 +858,39 @@ static int ksmbd_durable_scavenger(void *dummy)else min_timeout =DURABLE_HANDLE_MAX_TIMEOUT ; -write_lock (&global_ft.lock); -idr_for_each_entry (global_ft.idr, fp, id) { -if (!fp->durable_timeout) -continue ; - -if (atomic_read (&fp->refcount) >1 || - fp->conn) -continue ; - - found_fp_timeout = true; -if (fp->durable_scavenger_timeout <= -jiffies_to_msecs (jiffies)) { -__ksmbd_remove_durable_fd (fp); -list_add (&fp->node, &scavenger_list); - }else { + do { + expired_fp = NULL; + found_fp_timeout = false; + + write_lock(&global_ft.lock); + idr_for_each_entry(global_ft.idr, fp, id) { unsigned long durable_timeout; + if (!fp->durable_timeout) + continue; + + if (atomic_read(&fp->refcount) > 1 || + fp->conn) + continue; + + found_fp_timeout = true; + if (fp->durable_scavenger_timeout <= + jiffies_to_msecs(jiffies)) { + __ksmbd_remove_durable_fd(fp); + /* + * Take a transient reference so fp + * cannot be freed by an in-flight + * ksmbd_lookup_fd_inode() that found + * it through f_ci->m_fp_list while we + * drop global_ft.lock and reach the + * m_fp_list unlink in + * ksmbd_scavenger_dispose_dh(). + */ + atomic_inc(&fp->refcount); + expired_fp = fp; + break; + } + durable_timeout = fp->durable_scavenger_timeout - jiffies_to_msecs(jiffies);
@@ -849,10 +898,11 @@ static int ksmbd_durable_scavenger(void *dummy)if (min_timeout > durable_timeout) min_timeout = durable_timeout; } - } -write_unlock (&global_ft.lock); +write_unlock (&global_ft.lock); -ksmbd_scavenger_dispose_dh (&scavenger_list); +if (expired_fp) +ksmbd_scavenger_dispose_dh (expired_fp); + }while (expired_fp);if (found_fp_timeout == false)break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 22/272 af_unix: Give up GC if MSG_PEEK intervened.
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit e5b31d988a41549037b8d8721a3c3cae893d8670 ]
Igor Ushakov reported that GC purged the receive queue of an alive socket due to a race with MSG_PEEK with a nice repro.
This is the exact same issue previously fixed by commit cbcf01128d0a ("af_unix: fix garbage collect vs MSG_PEEK").
After GC was replaced with the current algorithm, the cited commit removed the locking dance in unix_peek_fds() and reintroduced the same issue.
The problem is that MSG_PEEK bumps a file refcount without interacting with GC.
Consider an SCC containing sk-A and sk-B, where sk-A is close()d but can be recv()ed via sk-B.
The bad thing happens if sk-A is recv()ed with MSG_PEEK from sk-B and sk-B is close()d while GC is checking unix_vertex_dead() for sk-A and sk-B.
GC thread User thread
--------- -----------
unix_vertex_dead(sk-A)
-> true <------.
\
`------ recv(sk-B, MSG_PEEK)
invalidate !! -> sk-A's file refcount : 1 -> 2 close(sk-B)
-> sk-B's file refcount : 2 -> 1 unix_vertex_dead(sk-B)
-> true
Initially, sk-A's file refcount is 1 by the inflight fd in sk-B recvq. GC thinks sk-A is dead because the file refcount is the same as the number of its inflight fds.
However, sk-A's file refcount is bumped silently by MSG_PEEK, which invalidates the previous evaluation.
At this moment, sk-B's file refcount is 2; one by the open fd, and one by the inflight fd in sk-A. The subsequent close() releases one refcount by the former.
Finally, GC incorrectly concludes that both sk-A and sk-B are dead.
One option is to restore the locking dance in unix_peek_fds(), but we can resolve this more elegantly thanks to the new algorithm.
The point is that the issue does not occur without the subsequent close() and we actually do not need to synchronise MSG_PEEK with the dead SCC detection.
When the issue occurs, close() and GC touch the same file refcount. If GC sees the refcount being decremented by close(), it can just give up garbage-collecting the SCC.
Therefore, we only need to signal the race during MSG_PEEK with a proper memory barrier to make it visible to the GC.
Let's use seqcount_t to notify GC when MSG_PEEK occurs and let it defer the SCC to the next run.
This way no locking is needed on the MSG_PEEK side, and we can avoid imposing a penalty on every MSG_PEEK unnecessarily.
Note that we can retry within unix_scc_dead() if MSG_PEEK is detected, but we do not do so to avoid hung task splat from abusive MSG_PEEK calls.
--- include/net/af_unix.h | 1 + net/unix/af_unix.c | 2 ++ net/unix/garbage.c | 79 ++++++++++++++++++++++++++++--------------- 3 files changed, 54 insertions(+), 28 deletions(-)
include/net/af_unix.h +1 -0
@@ -23,6 +23,7 @@ void unix_del_edges(struct scm_fp_list *fpl);void unix_update_edges (struct unix_sock *receiver);int unix_prepare_fpl (struct scm_fp_list *fpl);void unix_destroy_fpl (struct scm_fp_list *fpl); +void unix_peek_fpl (struct scm_fp_list *fpl);void unix_gc (void );void wait_for_unix_gc (struct scm_fp_list *fpl);
net/unix/af_unix.c +2 -0
@@ -1878,6 +1878,8 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)static void unix_peek_fds (struct scm_cookie *scm,struct sk_buff *skb) { scm->fp =scm_fp_dup (UNIXCB (skb).fp); + +unix_peek_fpl (scm->fp); }static void unix_destruct_scm (struct sk_buff *skb)
net/unix/garbage.c +51 -28
126 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 23/272 drm/imagination: Synchronize interrupts before suspending the GPU
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alessio Belle <[email protected]>
commit 2d7f05cddf4c268cc36256a2476946041dbdd36d upstream.
The runtime PM suspend callback doesn't know whether the IRQ handler is in progress on a different CPU core and doesn't wait for it to finish.
Depending on timing, the IRQ handler could be running while the GPU is suspended, leading to it being killed when trying to access GPU registers. See example signature below.
In a power off sequence initiated by the runtime PM suspend callback, wait for any IRQ handlers in progress on other CPU cores to finish, by calling synchronize_irq().
This version of the patch contains only the part of the upstream commit that applies to 6.12; the rest was a revert of code added in 6.16. The second paragraph above is different because on 6.12 this kind of bug doesn't seem to crash the entire kernel, only the IRQ handler, leaving the driver unusable in practice.
The crash signature below is also different, both because of the above, and because there was no support for TI AM68 SK in 6.12.
Example signature on a TI AM62 SK platform:
[ 7827.189088] Internal error: synchronous external abort: 0000000096000010 [#1] PREEMPT SMP [ 7827.197311] Modules linked in: [ 7827.222015] CPU: 0 UID: 0 PID: 461 Comm: irq/405-gpu Tainted: G M 6.12.90 #5 [ 7827.230461] Tainted: [M]=MACHINE_CHECK [ 7827.234203] Hardware name: Texas Instruments AM625 SK (DT) [ 7827.239682] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 7827.246637] pc : pvr_device_irq_thread_handler+0x64/0x180 [powervr] [ 7827.252941] lr : irq_thread_fn+0x2c/0xa8 [ 7827.256872] sp : ffff800082d8bd50 [ 7827.260179] x29: ffff800082d8bd70 x28: ffff8000800ce374 x27: ffff800081829cc0 [ 7827.267328] x26: ffff000004701e80 x25: ffff000005b884ac x24: ffff000005bd5780 [ 7827.274472] x23: ffff00000da40bc0 x22: ffff00000da40ba0 x21: ffff800082d8bd58 [ 7827.281614] x20: ffff00000da40000 x19: ffff000004701e80 x18: 08000000c6af9003 [ 7827.288750] x17: 0000000000000010 x16: 0000000000000068 x15: 0df234008df66400 [ 7827.295886] x14: 0000000000000000 x13: 000005c68f6e7191 x12: 000000000000025e [ 7827.303020] x11: 00000000000000c0 x10: 0000000000000ac0 x9 : ffff800082d8bd00 [ 7827.310157] x8 : ffff000005bd62a0 x7 : ffff000077261380 x6 : 00000000000005c6 [ 7827.317292] x5 : 000000000000425e x4 : 0000000000000000 x3 : 0000000000000000 [ 7827.324428] x2 : 00000000000008a8 x1 : ffff800082d608a8 x0 : ffff000005bd5780 [ 7827.331568] Call trace: [ 7827.334011] pvr_device_irq_thread_handler+0x64/0x180 [powervr] [ 7827.339954] irq_thread_fn+0x2c/0xa8 [ 7827.343530] irq_thread+0x16c/0x2f4 [ 7827.347019] kthread+0x110/0x114 [ 7827.350248] ret_from_fork+0x10/0x20 [ 7827.353834] Code: f9446682 f943c281 b9404442 8b020021 (b9400021) [ 7827.359921] ---[ end trace 0000000000000000 ]--- [ 7827.364820] genirq: exiting task "irq/405-gpu" (461) is an active IRQ thread (irq 405) [ 8011.230278] powervr fd00000.gpu: Job timeout [ 8011.230350] powervr fd00000.gpu: Job timeout [ 8011.230426] powervr fd00000.gpu: Job timeout
--- drivers/gpu/drm/imagination/pvr_power.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/gpu/drm/imagination/pvr_power.c +8 -3
@@ -84,7 +84,7 @@ pvr_power_request_pwr_off(struct pvr_device *pvr_dev) }static int -pvr_power_fw_disable (struct pvr_device *pvr_dev,bool hard_reset) +pvr_power_fw_disable (struct pvr_device *pvr_dev,bool hard_reset,bool rpm_suspend) {if (!hard_reset) {int err;
@@ -100,6 +100,11 @@ pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset)return err; } +if (rpm_suspend) { +/* Wait for late processing of GPU or firmware IRQs in other cores */ +synchronize_irq (pvr_dev->irq); + } +return pvr_fw_stop (pvr_dev); }
@@ -243,7 +248,7 @@ pvr_power_device_suspend(struct device *dev)return -EIO ;if (pvr_dev->fw_dev.booted) { - err =pvr_power_fw_disable (pvr_dev, false); + err =pvr_power_fw_disable (pvr_dev, false, true);if (err) goto err_drm_dev_exit; }
@@ -425,7 +430,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset) queues_disabled = true; } - err =pvr_power_fw_disable (pvr_dev, hard_reset); + err =pvr_power_fw_disable (pvr_dev, hard_reset, false);if (!err) {if (hard_reset) { pvr_dev->fw_dev.booted = false;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 24/272 smb: client: reject userspace cifs.spnego descriptions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Asim Viladi Oglu Manizada <[email protected]>
commit 3da1fdf4efbc490041eb4f836bf596201203f8f2 upstream.
cifs.spnego key descriptions contain authority-bearing fields such as pid, uid, creduid, and upcall_target that cifs.upcall treats as kernel-originating inputs. However, userspace can also create keys of this type through request_key(2) or add_key(2), allowing those fields to be supplied without CIFS origin.
Only accept cifs.spnego descriptions while CIFS is using its private spnego_cred to request the key.
--- fs/smb/client/cifs_spnego.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
fs/smb/client/cifs_spnego.c +16 -0
@@ -8,6 +8,7 @@*/ #include <linux/list.h> +#include <linux/cred.h> #include <linux/slab.h> #include <linux/string.h> #include <keys/user-type.h>
@@ -46,12 +47,27 @@ cifs_spnego_key_destroy(struct key *key)kfree (key->payload.data[0 ]); } +static int +cifs_spnego_key_vet_description (const char *description) +{ +/* +* cifs.spnego descriptions are authority-bearing inputs to cifs.upcall. +* They are only valid when produced by CIFS while using the private +* spnego_cred installed below. Do not let userspace create this type +* of key through request_key(2)/add_key(2), since the helper treats +* pid/uid/creduid/upcall_target as kernel-originating fields. +*/ +if (current_cred () != spnego_cred) +return -EPERM ; +return 0 ; +}/* * keytype for CIFS spnego keys */ struct key_type cifs_spnego_key_type = { .name ="cifs.spnego" , + .vet_description = cifs_spnego_key_vet_description, .instantiate = cifs_spnego_key_instantiate, .destroy = cifs_spnego_key_destroy, .describe = user_describe,
Greg Kroah-Hartman
maintainerPATCH 25/272 ata: libata-scsi: improve readability of ata_scsi_qc_issue()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Cassel <[email protected]>
commit 360190bd965f93794d5f5685a6de22ce6da2b672 upstream.
Improve readability of ata_scsi_qc_issue().
No functional changes.
--- drivers/ata/libata-scsi.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-)
drivers/ata/libata-scsi.c +21 -22
@@ -1779,7 +1779,7 @@ static int ata_scsi_qc_issue(struct ata_int ret;if (!ap->ops->qc_defer) - goto issue; + goto issue_qc;/* * If we already have a deferred qc, then rely on the SCSI layer to
@@ -1798,38 +1798,37 @@ static int ata_scsi_qc_issue(struct ata_break ;case ATA_DEFER_LINK : ret =SCSI_MLQUEUE_DEVICE_BUSY ; -break ; + goto defer_qc;case ATA_DEFER_PORT : ret =SCSI_MLQUEUE_HOST_BUSY ; -break ; + goto defer_qc;default :WARN_ON_ONCE (1 ); ret =SCSI_MLQUEUE_HOST_BUSY ; -break ; + goto defer_qc; } -if (ret) { -/* -* We must defer this qc: if this is not an NCQ command, keep -* this qc as a deferred one and report to the SCSI layer that -* we issued it so that it is not requeued. The deferred qc will -* be issued with the port deferred_qc_work once all on-going -* commands complete. -*/ -if (!ata_is_ncq (qc->tf.protocol)) { - ap->deferred_qc = qc; -return 0 ; - } +issue_qc: +ata_qc_issue (qc); +return 0 ; -/* Force a requeue of the command to defer its execution. */ -ata_qc_free (qc); -return ret; +defer_qc: +/* +* We must defer this qc: if this is not an NCQ command, keep +* this qc as a deferred one and report to the SCSI layer that +* we issued it so that it is not requeued. The deferred qc will +* be issued with the port deferred_qc_work once all on-going +* commands complete. +*/ +if (!ata_is_ncq (qc->tf.protocol)) { + ap->deferred_qc = qc; +return 0 ; } -issue: -ata_qc_issue (qc); +/* Force a requeue of the command to defer its execution. */ +ata_qc_free (qc); -return 0 ; +return ret; }/**
Greg Kroah-Hartman
maintainerPATCH 26/272 ata: libata-scsi: do not use the deferred QC feature for ATA_DEFER_PORT
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Cassel <[email protected]>
commit ce4548807d2e4ae48fd0dbe38865467369877913 upstream.
The deferred QC feature was meant to handle mixed NCQ and non-NCQ commands, i.e. for return value ATA_DEFER_LINK.
ATA_DEFER_PORT is returned by PATA drivers, but also certain SATA drivers like sata_mv and sata_sil24 that uses ap->excl_link to workaround hardware bugs in these HBAs. Regardless of the reason, using the deferred QC feature for ATA_DEFER_PORT is always wrong, and will break the ap->excl_link usage of the SATA drivers that rely on that feature.
Modify ata_scsi_qc_issue() to only use the deferred QC feature when mixing NCQ and non-NCQ commands, i.e. ATA_DEFER_LINK.
--- drivers/ata/libata-scsi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/ata/libata-scsi.c +3 -2
@@ -1801,11 +1801,11 @@ static int ata_scsi_qc_issue(struct ata_ goto defer_qc;case ATA_DEFER_PORT : ret =SCSI_MLQUEUE_HOST_BUSY ; - goto defer_qc; + goto free_qc;default :WARN_ON_ONCE (1 ); ret =SCSI_MLQUEUE_HOST_BUSY ; - goto defer_qc; + goto free_qc; } issue_qc:
@@ -1825,6 +1825,7 @@ defer_qc:return 0 ; } +free_qc:/* Force a requeue of the command to defer its execution. */ ata_qc_free (qc);
Greg Kroah-Hartman
maintainerPATCH 27/272 ata: libata-scsi: do not use the deferred QC feature on PMPs with CBS
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Cassel <[email protected]>
commit f233124fb36cd57ef09f96d517a38ab4b902e15e upstream.
When using Port Multipliers (PMPs) with Command-Based Switching (CBS), you can only issue commands to one link at a time. For PMPs with CBS, there is already code to handle commands being sent to different links in sata_pmp_qc_defer_cmd_switch() using ap->excl_link. sata_sil24 also makes use of ap->excl_link.
A user on the list reported that commit 0ea84089dbf6 ("ata: libata-scsi:
avoid Non-NCQ command starvation") broke PMPs with CBS. The commit introduced code that stores a deferred qc in ap->deferred_qc, to later be issued via a workqueue. It turns out that this change is incompatible with the existing ap->excl_link handling used by PMPs with CBS.
Thus, modify sata_pmp_qc_defer_cmd_switch() and sil24_qc_defer() to return ATA_DEFER_LINK_EXCL, and make sure that the deferred QC handling via workqueue is not used for this return value.
This way, PMPs with CBS will work once again. Note that the starvation referenced in commit 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation") can only happen on libsas ports, and libsas does not support Port Multipliers, thus there is no harm of reverting back to the previous way of deferring commands for PMPs with CBS.
Non-libsas ports connected to anything but a PMP with CBS (e.g. a normal drive or a PMP with FBS) will continue using the deferred workqueue, since it does result in lower completion latencies for non-NCQ commands, even though the workqueue is not strictly needed to avoid starvation for non-libsas ports.
If we want to modify the scope of the workqueue issuing to also handle PMPs with CBS, then we should ensure that we can save both NCQ and non-NCQ commands in ap->deferred_qc, while also removing the existing PMP CBS handling using ap->excl_link, such that we don't duplicate features.
While at it, also add a comment explaining how the ap->excl_link mechanism works.
--- drivers/ata/libata-pmp.c | 13 ++++++++++++- drivers/ata/libata-scsi.c | 8 ++++++++ drivers/ata/sata_sil24.c | 6 +++++- include/linux/libata.h | 1 + 4 files changed, 26 insertions(+), 2 deletions(-)
drivers/ata/libata-pmp.c +12 -1
@@ -110,13 +110,24 @@ int sata_pmp_qc_defer_cmd_switch(struct {struct ata_link *link = qc->dev->link;struct ata_port *ap = link->ap; +int ret;if (ap->excl_link ==NULL || ap->excl_link == link) {if (ap->nr_active_links ==0 ||ata_link_active (link)) { qc->flags |=ATA_QCFLAG_CLEAR_EXCL ; -return ata_std_qc_defer (qc); + ret =ata_std_qc_defer (qc); +if (ret ==ATA_DEFER_LINK ) +return ATA_DEFER_LINK_EXCL ; +return ret; } +/* +* Note: ap->excl_link contains the link that is next in line, +* i.e. implicit round robin. If there is only one link +* dispatching, ap->excl_link will be left unclaimed, allowing +* other links to set ap->excl_link, ensuring that the currently +* active link cannot queue any more. +*/ ap->excl_link = link; }
drivers/ata/libata-scsi.c +8 -0
@@ -1799,6 +1799,14 @@ static int ata_scsi_qc_issue(struct ata_case ATA_DEFER_LINK : ret =SCSI_MLQUEUE_DEVICE_BUSY ; goto defer_qc; +case ATA_DEFER_LINK_EXCL : +/* +* Drivers making use of ap->excl_link cannot store the QC in +* ap->deferred_qc, because the ap->excl_link handling is +* incompatible with the ap->deferred_qc workqueue handling. +*/ + ret =SCSI_MLQUEUE_DEVICE_BUSY ; + goto free_qc;case ATA_DEFER_PORT : ret =SCSI_MLQUEUE_HOST_BUSY ; goto free_qc;
drivers/ata/sata_sil24.c +5 -1
@@ -790,6 +790,7 @@ static int sil24_qc_defer(struct ata_questruct ata_link *link = qc->dev->link;struct ata_port *ap = link->ap;u8 prot = qc->tf.protocol; +int ret;/* * There is a bug in the chip:
@@ -827,7 +828,10 @@ static int sil24_qc_defer(struct ata_que qc->flags |=ATA_QCFLAG_CLEAR_EXCL ; } -return ata_std_qc_defer (qc); + ret =ata_std_qc_defer (qc); +if (ret ==ATA_DEFER_LINK ) +return ATA_DEFER_LINK_EXCL ; +return ret; }static enum ata_completion_errors sil24_qc_prep (struct ata_queued_cmd *qc)
include/linux/libata.h +1 -0
@@ -348,6 +348,7 @@ enum {/* return values for ->qc_defer */ ATA_DEFER_LINK =1 ,ATA_DEFER_PORT =2 , +ATA_DEFER_LINK_EXCL =3 ,/* desc_len for ata_eh_info and context */ ATA_EH_DESC_LEN = 80,
Greg Kroah-Hartman
maintainerPATCH 28/272 ata: libata-scsi: do not needlessly defer commands when using PMP with FBS
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Cassel <[email protected]>
commit 759e8756da00aa115d504a18155b1d1ee1cc12e8 upstream.
The ACS specification does not allow a non-NCQ command to be issued while an NCQ command is outstanding.
Commit 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation") introduced a feature where a deferred non-NCQ command gets issued from a workqueue. The design stores a single non-NCQ command per port.
However, when using Port Multipliers (PMPs), specifically PMPs that support FIS-Based Switching (FBS), non-NCQ and NCQ commands can be mixed on the same port, just not for the same link, see e.g. ata_std_qc_defer() which is, and always has operated on a per-link basis.
Therefore, move the deferred_qc from struct ata_port to struct ata_link. This way, when using a PMP with FBS, we will not needlessly defer commands to all other links, just because one link issued a non-NCQ command while having an NCQ command outstanding. Only commands for that specific link will be deferred. This is in line with how PMPs with FBS worked before commit 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation").
--- drivers/ata/libata-core.c | 9 +++++-- drivers/ata/libata-eh.c | 8 +++--- drivers/ata/libata-pmp.c | 5 +++- drivers/ata/libata-scsi.c | 54 +++++++++++++++++++++++++--------------------- include/linux/libata.h | 6 ++--- 5 files changed, 47 insertions(+), 35 deletions(-)
drivers/ata/libata-core.c +6 -3
@@ -5444,6 +5444,7 @@ void ata_link_init(struct ata_port *ap, link->pmp = pmp; link->active_tag =ATA_TAG_POISON ; link->hw_sata_spd_limit =UINT_MAX ; +INIT_WORK (&link->deferred_qc_work, ata_scsi_deferred_qc_work);/* can't use iterator, ap isn't initialized yet */ for (i =0 ; i <ATA_MAX_DEVICES ; i++) {
@@ -5526,7 +5527,6 @@ struct ata_port *ata_port_alloc(struct amutex_init (&ap->scsi_scan_mutex);INIT_DELAYED_WORK (&ap->hotplug_task, ata_scsi_hotplug);INIT_DELAYED_WORK (&ap->scsi_rescan_task, ata_scsi_dev_rescan); -INIT_WORK (&ap->deferred_qc_work, ata_scsi_deferred_qc_work);INIT_LIST_HEAD (&ap->eh_done_q);init_waitqueue_head (&ap->eh_wait_q);init_completion (&ap->park_req_pending);
@@ -6149,12 +6149,15 @@ static void ata_port_detach(struct ata_p/* It better be dead now and not have any remaining deferred qc. */ WARN_ON (!(ap->pflags &ATA_PFLAG_UNLOADED )); -WARN_ON (ap->deferred_qc); -cancel_work_sync (&ap->deferred_qc_work);cancel_delayed_work_sync (&ap->hotplug_task);cancel_delayed_work_sync (&ap->scsi_rescan_task); +ata_for_each_link (link, ap,PMP_FIRST ) { +WARN_ON (link->deferred_qc); +cancel_work_sync (&link->deferred_qc_work); + } +/* Delete port multiplier link transport devices */ if (ap->pmp_link) {int i;
drivers/ata/libata-eh.c +4 -4
@@ -645,11 +645,11 @@ void ata_scsi_cmd_error_handler(struct Sif (qc->scsicmd != scmd)continue ;if ((qc->flags &ATA_QCFLAG_ACTIVE ) || - qc == ap->deferred_qc) + qc == qc->dev->link->deferred_qc)break ; } -if (i <ATA_MAX_QUEUE && qc == ap->deferred_qc) { +if (i <ATA_MAX_QUEUE && qc == qc->dev->link->deferred_qc) {/* * This is a deferred command that timed out while * waiting for the command queue to drain. Since the qc
@@ -660,8 +660,8 @@ void ata_scsi_cmd_error_handler(struct S* deferred qc work from issuing this qc. */ WARN_ON_ONCE (qc->flags &ATA_QCFLAG_ACTIVE ); - ap->deferred_qc =NULL ; -cancel_work (&ap->deferred_qc_work); + qc->dev->link->deferred_qc =NULL ; +cancel_work (&qc->dev->link->deferred_qc_work);set_host_byte (scmd,DID_TIME_OUT );scsi_eh_finish_cmd (scmd, &ap->eh_done_q); }else if (i <ATA_MAX_QUEUE ) {
drivers/ata/libata-pmp.c +4 -1
@@ -582,8 +582,11 @@ static void sata_pmp_detach(struct ata_dif (ap->ops->pmp_detach) ap->ops->pmp_detach (ap); -ata_for_each_link (tlink, ap,EDGE ) +ata_for_each_link (tlink, ap,EDGE ) { +WARN_ON (tlink->deferred_qc); +cancel_work_sync (&tlink->deferred_qc_work);ata_eh_detach_dev (tlink->device); + }spin_lock_irqsave (ap->lock, flags); ap->nr_pmp_links =0 ;
drivers/ata/libata-scsi.c +30 -24
121 lines not on this page · raw message
include/linux/libata.h +3 -3
@@ -853,6 +853,9 @@ struct ata_link {unsigned int sata_spd;/* current SATA PHY speed */ enum ata_lpm_policy lpm_policy; +struct work_struct deferred_qc_work; +struct ata_queued_cmd *deferred_qc; +/* record runtime error info, protected by host_set lock */ struct ata_eh_info eh_info;/* EH context */
@@ -898,9 +901,6 @@ struct ata_port {u64 qc_active;int nr_active_links;/* #links with active qcs */ -struct work_struct deferred_qc_work; -struct ata_queued_cmd *deferred_qc; -struct ata_link link;/* host default link */ struct ata_link *slave_link;/* see ata_slave_link_init() */
Greg Kroah-Hartman
maintainerPATCH 29/272 perf parse-events: Expose/rename config_term_name
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit d2f3ecb0ca2099d13bf8bf69219214c1425dc453 ]
Expose config_term_name as parse_events__term_type_str so that PMUs not in pmu.c may access it.
--- tools/perf/util/parse-events.c | 20 +++++++++++--------- tools/perf/util/parse-events.h | 2 ++ 2 files changed, 13 insertions(+), 9 deletions(-)
tools/perf/util/parse-events.c +11 -9
@@ -801,7 +801,7 @@ static int check_type_val(struct parse_events_term *term,static bool config_term_shrinked; -static const char *config_term_name (enum parse_events__term_type term_type) +const char *parse_events__term_type_str (enum parse_events__term_type term_type) {/* * Update according to parse-events.l
@@ -887,7 +887,7 @@ config_term_avail(enum parse_events__term_type term_type, struct parse_events_er/* term_type is validated so indexing is safe */ if (asprintf (&err_str,"'%s' is not usable in 'perf stat'" , -config_term_name (term_type)) >=0 ) +parse_events__term_type_str (term_type)) >=0 )parse_events_error__handle (err,-1 , err_str,NULL );return false; }
@@ -1011,7 +1011,7 @@ do { \case PARSE_EVENTS__TERM_TYPE_HARDWARE :default :parse_events_error__handle (err, term->err_term, -strdup (config_term_name (term->type_term)), +strdup (parse_events__term_type_str (term->type_term)),parse_events_formats_error_string (NULL ));return -EINVAL ; }
@@ -1135,8 +1135,9 @@ static int config_term_tracepoint(struct perf_event_attr *attr,default :if (err) {parse_events_error__handle (err, term->err_term, -strdup (config_term_name (term->type_term)), -strdup ("valid terms: call-graph,stack-size\n" )); +strdup (parse_events__term_type_str (term->type_term)), +strdup ("valid terms: call-graph,stack-size\n" ) + ); }return -EINVAL ; }
@@ -2581,7 +2582,7 @@ int parse_events_term__num(struct parse_events_term **term,struct parse_events_term temp = { .type_val =PARSE_EVENTS__TERM_TYPE_NUM , .type_term = type_term, - .config = config ? :strdup (config_term_name (type_term)), + .config = config ? :strdup (parse_events__term_type_str (type_term)), .no_value = no_value, .err_term = loc_term ? loc_term->first_column :0 , .err_val = loc_val ? loc_val->first_column :0 ,
@@ -2615,7 +2616,7 @@ int parse_events_term__term(struct parse_events_term **term, void *loc_term, void *loc_val) { return parse_events_term__str(term, term_lhs, NULL, -strdup (config_term_name (term_rhs )), +strdup (parse_events__term_type_str (term_rhs )),loc_term ,loc_val ); }
@@ -2722,7 +2723,8 @@ int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, structif (ret <0 )return ret; }else if ((unsigned int )term->type_term < __PARSE_EVENTS__TERM_TYPE_NR) { - ret =strbuf_addf (sb,"%s=" ,config_term_name (term->type_term)); + ret =strbuf_addf (sb,"%s=" , +parse_events__term_type_str (term->type_term));if (ret <0 )return ret; }
@@ -2742,7 +2744,7 @@ static void config_terms_list(char *buf, size_t buf_sz) buf[0 ] ='\0' ;for (i =0 ; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) { -const char *name =config_term_name (i); +const char *name =parse_events__term_type_str (i);if (!config_term_avail (i,NULL ))continue ;
tools/perf/util/parse-events.h +2 -0
@@ -168,6 +168,8 @@ struct parse_events_state {bool wild_card_pmus; }; +const char *parse_events__term_type_str (enum parse_events__term_type term_type); +bool parse_events__filter_pmu (const struct parse_events_state *parse_state,const struct perf_pmu *pmu);void parse_events__shrink_config_terms (void );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 30/272 Revert "ice: fix double-free of tx_buf skb"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit fd95ef8d0f6dbe2daa95d6488c9e0f8a95a7e048.
--- drivers/net/ethernet/intel/ice/ice_txrx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/ethernet/intel/ice/ice_txrx.c +2 -4
@@ -2346,9 +2346,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)ice_trace (xmit_frame_ring, tx_ring, skb); -/* record the location of the first descriptor for this packet */ - first = &tx_ring->tx_buf[tx_ring->next_to_use]; - count =ice_xmit_desc_count (skb);if (ice_chk_linearize (skb, count)) {if (__skb_linearize (skb))
@@ -2374,6 +2371,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) offload.tx_ring = tx_ring; +/* record the location of the first descriptor for this packet */ + first = &tx_ring->tx_buf[tx_ring->next_to_use]; first->skb = skb; first->type =ICE_TX_BUF_SKB ; first->bytecount = max_t(unsigned int, skb->len, ETH_ZLEN);
@@ -2437,7 +2436,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) out_drop:ice_trace (xmit_frame_ring_drop, tx_ring, skb);dev_kfree_skb_any (skb); - first->type =ICE_TX_BUF_EMPTY ;return NETDEV_TX_OK ; }
Signature · 1 line
2.53.0
Re: [PATCH 6.12 030/272] Revert "ice: fix double-free of tx_buf skb"
Hi Sasha/Greg,
Quoted 35 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit
fd95ef8d0f6dbe2daa95d6488c9e0f8a95a7e048.Signed-off-by Sasha Levin <[email protected]>--- drivers/net/ethernet/intel/ice/ice_txrx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)drivers/net/ethernet/intel/ice/ice_txrx.c +2
-3@@ -2346,9 +2346,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)ice_trace (xmit_frame_ring, tx_ring, skb); -/* record the location of the first descriptor for this packet */ - first = &tx_ring->tx_buf[tx_ring->next_to_use]; - count =ice_xmit_desc_count (skb);if (ice_chk_linearize (skb, count)) {if (__skb_linearize (skb))@@ -2374,6 +2371,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) offload.tx_ring = tx_ring; +/* record the location of the first descriptor for this packet */ + first = &tx_ring->tx_buf[tx_ring->next_to_use]; first->skb = skb; first->type =ICE_TX_BUF_SKB ; first->bytecount = max_t(unsigned int, skb->len, ETH_ZLEN);
drivers/net/ethernet/intel/ice/ice_txrx.c ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) · line 2440
Quoted 6 lines
drivers/net/ethernet/intel/ice/ice_txrx.c +0
-1@@ -2437,7 +2436,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) out_drop:ice_trace (xmit_frame_ring_drop, tx_ring, skb);dev_kfree_skb_any (skb); - first->type =ICE_TX_BUF_EMPTY ;return NETDEV_TX_OK ; }
I ran an AI-assisted backport review and then checked this one against the 6.12.y tree.
I think this purely opens the issue again back, we need some sort of TODO list for tracking these backports that are reverted for now.
Issue goes back like this
That fix(what we are reverting) made ice_xmit_frame_ring() clear the TX buffer state on the drop path:
dev_kfree_skb_any(skb);first->type = ICE_TX_BUF_EMPTY;
After the revert, first->skb is still recorded and first->type is still set to ICE_TX_BUF_SKB before ice_tso() / ice_tx_csum(), but the error path now only frees the skb and returns.
Later ice_clean_tx_ring() -> ice_unmap_and_free_tx_buf() still treats ICE_TX_BUF_SKB as owning a live skb and frees tx_buf->skb.
So its again the same issue coming back to stable.
I looked up the reason for the revert and the reason for the revert is we took a prerequisite for this which doesn't fit will so to revert the prerequisite we reverted this fix as well, I think we need adapted patch to older stable trees.
https://lore.kernel.org/all/[email protected]/
Nothing to do now but I think we need to add some sort TODO-backports list in stable-queue , thoughts ?
thanks,
Harshit
Quoted 1 line
Greg Kroah-Hartman
maintainerRe: [PATCH 6.12 030/272] Revert "ice: fix double-free of tx_buf skb"
Quoted 70 lines · Harshit Mogalapalli
Hi Sasha/Greg,
Quoted 31 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit
fd95ef8d0f6dbe2daa95d6488c9e0f8a95a7e048.Signed-off-by Sasha Levin <[email protected]>--- drivers/net/ethernet/intel/ice/ice_txrx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)drivers/net/ethernet/intel/ice/ice_txrx.c +2
-3@@ -2346,9 +2346,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)ice_trace (xmit_frame_ring, tx_ring, skb); -/* record the location of the first descriptor for this packet */ - first = &tx_ring->tx_buf[tx_ring->next_to_use]; - count =ice_xmit_desc_count (skb);if (ice_chk_linearize (skb, count)) {if (__skb_linearize (skb))@@ -2374,6 +2371,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) offload.tx_ring = tx_ring; +/* record the location of the first descriptor for this packet */ + first = &tx_ring->tx_buf[tx_ring->next_to_use]; first->skb = skb; first->type =ICE_TX_BUF_SKB ; first->bytecount = max_t(unsigned int, skb->len, ETH_ZLEN);drivers/net/ethernet/intel/ice/ice_txrx.c ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) · line 2440
Quoted 6 lines
drivers/net/ethernet/intel/ice/ice_txrx.c +0
-1@@ -2437,7 +2436,6 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring) out_drop:ice_trace (xmit_frame_ring_drop, tx_ring, skb);dev_kfree_skb_any (skb); - first->type =ICE_TX_BUF_EMPTY ;return NETDEV_TX_OK ; }I ran an AI-assisted backport review and then checked this one against the 6.12.y tree.
I think this purely opens the issue again back, we need some sort of TODO list for tracking these backports that are reverted for now.
Issue goes back like this
That fix(what we are reverting) made
ice_xmit_frame_ring()clear the TX buffer state on the drop path:
dev_kfree_skb_any(skb);first->type=ICE_TX_BUF_EMPTY;After the revert,
first->skbis still recorded andfirst->typeis still set toICE_TX_BUF_SKBbeforeice_tso()/ice_tx_csum(), but the error path now only frees the skb and returns.Later
ice_clean_tx_ring()->ice_unmap_and_free_tx_buf()still treatsICE_TX_BUF_SKBas owning a live skb and freestx_buf->skb.So its again the same issue coming back to stable.
I looked up the reason for the revert and the reason for the revert is we took a prerequisite for this which doesn't fit will so to revert the prerequisite we reverted this fix as well, I think we need adapted patch to older stable trees.
Quoted 4 lines
https://lore.kernel.org/all/[email protected]/
Nothing to do now but I think we need to add some sort TODO-backports list in stable-queue , thoughts ?
Sure, but ideally people would just send the missing backports :)
Greg Kroah-Hartman
maintainerPATCH 31/272 Revert "ice: Remove jumbo_remove step from TX path"
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 7332d208c9d2067546eb7af5339773c966ac5625.
--- drivers/net/ethernet/intel/ice/ice_txrx.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/intel/ice/ice_txrx.c +3 -0
@@ -2346,6 +2346,9 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)ice_trace (xmit_frame_ring, tx_ring, skb); +if (unlikely (ipv6_hopopt_jumbo_remove (skb))) + goto out_drop; + count =ice_xmit_desc_count (skb);if (ice_chk_linearize (skb, count)) {if (__skb_linearize (skb))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 32/272 tracing: Fix the bug where bpf_get_stackid returns -EFAULT on the ARM64
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Feng Yang <[email protected]>
commit fd2f74f8f3d3c1a524637caf5bead9757fae4332 upstream.
When using bpf_program__attach_kprobe_multi_opts on ARM64 to hook a BPF program that contains the bpf_get_stackid function, the BPF program fails to obtain the stack trace and returns -EFAULT.
This is because ftrace_partial_regs omits the configuration of the pstate register, leaving pstate at the default value of 0. When get_perf_callchain executes, it uses user_mode(regs) to determine whether it is in kernel mode. This leads to a misjudgment that the code is in user mode,
so perf_callchain_kernel is not executed and the function returns directly. As a result, trace->nr becomes 0, and finally -EFAULT is returned.
Therefore, the assignment of the pstate register is added here.
--- arch/arm64/include/asm/ftrace.h | 1 + 1 file changed, 1 insertion(+)
arch/arm64/include/asm/ftrace.h +1 -0
@@ -145,6 +145,7 @@ ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs) regs->pc = afregs->pc; regs->regs[29 ] = afregs->fp; regs->regs[30 ] = afregs->lr; + regs->pstate = PSR_MODE_EL1h;return regs; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 33/272 net/mlx5e: Trigger neighbor resolution for unresolved destinations
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jianbo Liu <[email protected]>
commit 9ab89bde13e5251e1d0507e1cc426edcdfe19142 upstream.
When initializing the MAC addresses for an outbound IPsec packet offload rule in mlx5e_ipsec_init_macs, the call to dst_neigh_lookup is used to find the next-hop neighbor (typically the gateway in tunnel mode). This call might create a new neighbor entry if one doesn't already exist. This newly created entry starts in the INCOMPLETE state, as the kernel hasn't yet sent an ARP or NDISC probe to resolve the MAC address. In this case, neigh_ha_snapshot will correctly return an all-zero MAC address.
IPsec packet offload requires the actual next-hop MAC address to program the rule correctly. If the neighbor state is INCOMPLETE when the rule is created, the hardware rule is programmed with an all-zero destination MAC address. Packets sent using this rule will be subsequently dropped by the receiving network infrastructure or host.
This patch adds a check specifically for the outbound offload path. If neigh_ha_snapshot returns an all-zero MAC address, it proactively calls neigh_event_send(n, NULL). This ensures the kernel immediately sends the initial ARP or NDISC probe if one isn't already pending, accelerating the resolution process. This helps prevent the hardware rule from being programmed with an invalid MAC address and avoids packet drops due to unresolved neighbors.
--- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +3 -0
@@ -365,6 +365,9 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,neigh_ha_snapshot (addr, n, netdev);ether_addr_copy (dst, addr); +if (attrs->dir ==XFRM_DEV_OFFLOAD_OUT && +is_zero_ether_addr (addr)) +neigh_event_send (n,NULL );dst_release (rt_dst_entry);neigh_release (n);return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 34/272 net/mlx5e: Use ip6_dst_lookup instead of ipv6_dst_lookup_flow for MAC init
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jianbo Liu <[email protected]>
commit e35d7da8dd9e55b37c3e8ab548f6793af0c2ab49 upstream.
Replace ipv6_stub->ipv6_dst_lookup_flow() with ip6_dst_lookup() in mlx5e_ipsec_init_macs() since IPsec transformations are not needed during Security Association setup - only basic routing information is required for nexthop MAC address resolution.
This resolves an issue where XfrmOutNoStates error counter would be incremented when xfrm policy is configured before xfrm state, as the IPsec-aware routing function would attempt policy checks during SA initialization.
--- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +2 -3
@@ -348,9 +348,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry, rt_dst_entry = &rt->dst;break ;case AF_INET6 : - rt_dst_entry = ipv6_stub->ipv6_dst_lookup_flow ( -dev_net (netdev),NULL , &fl6,NULL ); -if (IS_ERR (rt_dst_entry)) +if (!IS_ENABLED (CONFIG_IPV6 ) || +ip6_dst_lookup (dev_net (netdev),NULL , &rt_dst_entry, &fl6)) goto neigh;break ;default :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 35/272 x86/fgraph: Fix return_to_handler regs.rsp value
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Olsa <[email protected]>
commit 8bc11700e0d23d4fdb7d8d5a73b2e95de427cabc upstream.
The previous change (Fixes commit) messed up the rsp register value, which is wrong because it's already adjusted with FRAME_SIZE, we need the original rsp value.
This change does not affect fprobe current kernel unwind, the !perf_hw_regs path perf_callchain_kernel:
if (perf_hw_regs(regs)) {
if (perf_callchain_store(entry, regs->ip))
return;
unwind_start(&state, current, regs, NULL);
} else {
unwind_start(&state, current, NULL, (void *)regs->sp);
}which uses pt_regs.sp as first_frame boundary (FRAME_SIZE shift makes no difference, unwind stil stops at the right frame).
This change fixes the other path when we want to unwind directly from pt_regs sp/fp/ip state, which is coming in following change.
--- arch/x86/kernel/ftrace_64.S | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/x86/kernel/ftrace_64.S +4 -1
@@ -349,6 +349,9 @@ SYM_CODE_START(return_to_handler) UNWIND_HINT_UNDEFINED ANNOTATE_NOENDBR + /* Store original rsp for pt_regs.sp value. */ + movq %rsp, %rdi + /* Restore return_to_handler value that got eaten by previous ret instruction. */ subq $8, %rsp UNWIND_HINT_FUNC
@@ -359,7 +362,7 @@ SYM_CODE_START(return_to_handler) movq %rax, RAX(%rsp) movq %rdx, RDX(%rsp) movq %rbp, RBP(%rsp) - movq %rsp, RSP(%rsp) + movq %rdi, RSP(%rsp) movq %rsp, %rdi call ftrace_return_to_handler
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 36/272 iommu/vt-d: Draining PRQ in sva unbind path when FPD bit set
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lu Baolu <[email protected]>
commit cf08ca81d08a04b3b304e8fb4e052f323a09783d upstream.
When a device uses a PASID for SVA (Shared Virtual Address), it's possible that the PASID entry is marked as non-present and FPD bit set before the device flushes all ongoing DMA requests and removes the SVA domain. This can occur when an exception happens and the process terminates before the device driver stops DMA and calls the iommu driver to unbind the PASID.
There's no need to drain the PRQ in the mm release path. Instead, the PRQ will be drained in the SVA unbind path. But in such case, intel_pasid_tear_down_entry() only checks the presence of the pasid entry and returns directly.
Add the code to clear the FPD bit and drain the PRQ.
--- drivers/iommu/intel/pasid.c | 22 +++++++++++++++++++++- drivers/iommu/intel/pasid.h | 6 ++++++ 2 files changed, 27 insertions(+), 1 deletion(-)
drivers/iommu/intel/pasid.c +21 -1
@@ -245,11 +245,31 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,spin_lock (&iommu->lock); pte =intel_pasid_get_entry (dev, pasid); -if (WARN_ON (!pte) || !pasid_pte_is_present (pte)) { +if (WARN_ON (!pte)) {spin_unlock (&iommu->lock);return ; } +if (!pasid_pte_is_present (pte)) { +if (!pasid_pte_is_fault_disabled (pte)) { +WARN_ON (READ_ONCE (pte->val[0 ]) !=0 ); +spin_unlock (&iommu->lock); +return ; + } + +/* +* When a PASID is used for SVA by a device, it's possible +* that the pasid entry is non-present with the Fault +* Processing Disabled bit set. Clear the pasid entry and +* drain the PRQ for the PASID before return. +*/ +pasid_clear_entry (pte); +spin_unlock (&iommu->lock); +intel_iommu_drain_pasid_prq (dev, pasid); + +return ; + } + did =pasid_get_domain_id (pte); pgtt =pasid_pte_get_pgtt (pte);pasid_clear_present (pte);
drivers/iommu/intel/pasid.h +6 -0
@@ -80,6 +80,12 @@ static inline bool pasid_pte_is_present(struct pasid_entry *pte)return READ_ONCE (pte->val[0 ]) &PASID_PTE_PRESENT ; } +/* Get FPD(Fault Processing Disable) bit of a PASID table entry */ +static inline bool pasid_pte_is_fault_disabled (struct pasid_entry *pte) +{ +return READ_ONCE (pte->val[0 ]) &PASID_PTE_FPD ; +} +/* Get PGTT field of a PASID table entry */ static inline u16 pasid_pte_get_pgtt (struct pasid_entry *pte) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 37/272 riscv: fgraph: Select HAVE_FUNCTION_GRAPH_TRACER depends on HAVE_DYNAMIC_FTRACE_WITH_ARGS
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pu Lehui <[email protected]>
commit e8eb8e1bdae94b9e003f5909519fd311d0936890 upstream.
Currently, fgraph on riscv relies on the infrastructure of DYNAMIC_FTRACE_WITH_ARGS. However, DYNAMIC_FTRACE_WITH_ARGS may be turned off on riscv, which will cause the enabled fgraph to be abnormal. Therefore, let's select HAVE_FUNCTION_GRAPH_TRACER depends on HAVE_DYNAMIC_FTRACE_WITH_ARGS.
--- arch/riscv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/riscv/Kconfig +1 -1
@@ -143,7 +143,7 @@ config RISCV select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL - select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FUNCTION_GRAPH_TRACER if HAVE_DYNAMIC_FTRACE_WITH_ARGS select HAVE_FUNCTION_GRAPH_FREGS select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION select HAVE_EBPF_JIT if MMU
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 38/272 riscv: fgraph: Fix stack layout to match __arch_ftrace_regs argument of ftrace_return_to_handler
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pu Lehui <[email protected]>
commit 67a5ba8f742f247bc83e46dd2313c142b1383276 upstream.
Naresh Kamboju reported a "Bad frame pointer" kernel warning while running LTP trace ftrace_stress_test.sh in riscv. We can reproduce the same issue with the following command:
``` $ cd /sys/kernel/debug/tracing $ echo 'f:myprobe do_nanosleep%return args1=$retval' > dynamic_events $ echo 1 > events/fprobes/enable $ echo 1 > tracing_on $ sleep 1 ```
And we can get the following kernel warning:
[ 127.692888] ------------[ cut here ]------------ [ 127.693755] Bad frame pointer: expected ff2000000065be50, received ba34c141e9594000 [ 127.693755] from func do_nanosleep return to ffffffff800ccb16 [ 127.698699] WARNING: CPU: 1 PID: 129 at kernel/trace/fgraph.c:755 ftrace_return_to_handler+0x1b2/0x1be [ 127.699894] Modules linked in: [ 127.700908] CPU: 1 UID: 0 PID: 129 Comm: sleep Not tainted 6.14.0-rc3-g0ab191c74642 #32 [ 127.701453] Hardware name: riscv-virtio,qemu (DT) [ 127.701859] epc : ftrace_return_to_handler+0x1b2/0x1be [ 127.702032] ra : ftrace_return_to_handler+0x1b2/0x1be [ 127.702151] epc : ffffffff8013b5e0 ra : ffffffff8013b5e0 sp : ff2000000065bd10 [ 127.702221] gp : ffffffff819c12f8 tp : ff60000080853100 t0 : 6e00000000000000 [ 127.702284] t1 : 0000000000000020 t2 : 6e7566206d6f7266 s0 : ff2000000065bd80 [ 127.702346] s1 : ff60000081262000 a0 : 000000000000007b a1 : ffffffff81894f20 [ 127.702408] a2 : 0000000000000010 a3 : fffffffffffffffe a4 : 0000000000000000 [ 127.702470] a5 : 0000000000000000 a6 : 0000000000000008 a7 : 0000000000000038 [ 127.702530] s2 : ba34c141e9594000 s3 : 0000000000000000 s4 : ff2000000065bdd0 [ 127.702591] s5 : 00007fff8adcf400 s6 : 000055556dc1d8c0 s7 : 0000000000000068 [ 127.702651] s8 : 00007fff8adf5d10 s9 : 000000000000006d s10: 0000000000000001 [ 127.702710] s11: 00005555737377c8 t3 : ffffffff819d899e t4 : ffffffff819d899e [ 127.702769] t5 : ffffffff819d89a0 t6 : ff2000000065bb18 [ 127.702826] status: 0000000200000120 badaddr: 0000000000000000 cause: 0000000000000003 [ 127.703292] [<ffffffff8013b5e0>] ftrace_return_to_handler+0x1b2/0x1be [ 127.703760] [<ffffffff80017bce>] return_to_handler+0x16/0x26 [ 127.704009] [<ffffffff80017bb8>] return_to_handler+0x0/0x26 [ 127.704057] [<ffffffff800d3352>] common_nsleep+0x42/0x54 [ 127.704117] [<ffffffff800d44a2>] __riscv_sys_clock_nanosleep+0xba/0x10a [ 127.704176] [<ffffffff80901c56>] do_trap_ecall_u+0x188/0x218 [ 127.704295] [<ffffffff8090cc3e>] handle_exception+0x14a/0x156 [ 127.705436] ---[ end trace 0000000000000000 ]---
The reason is that the stack layout for constructing argument for the ftrace_return_to_handler in the return_to_handler does not match the __arch_ftrace_regs structure of riscv, leading to unexpected results.
--- arch/riscv/kernel/mcount.S | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-)
arch/riscv/kernel/mcount.S +11 -13
@@ -12,8 +12,6 @@ #include <asm/asm-offsets.h> #include <asm/ftrace.h> -#define ABI_SIZE_ON_STACK 80 - .text .macro SAVE_ABI_STATE
@@ -28,12 +26,12 @@ * register if a0 was not saved. */ .macro SAVE_RET_ABI_STATE - addi sp, sp, -ABI_SIZE_ON_STACK - REG_S ra, 1*SZREG(sp) - REG_S s0, 8*SZREG(sp) - REG_S a0, 10*SZREG(sp) - REG_S a1, 11*SZREG(sp) - addi s0, sp, ABI_SIZE_ON_STACK + addi sp, sp, -FREGS_SIZE_ON_STACK + REG_S ra, FREGS_RA(sp) + REG_S s0, FREGS_S0(sp) + REG_S a0, FREGS_A0(sp) + REG_S a1, FREGS_A1(sp) + addi s0, sp, FREGS_SIZE_ON_STACK .endm .macro RESTORE_ABI_STATE
@@ -43,11 +41,11 @@ .endm .macro RESTORE_RET_ABI_STATE - REG_L ra, 1*SZREG(sp) - REG_L s0, 8*SZREG(sp) - REG_L a0, 10*SZREG(sp) - REG_L a1, 11*SZREG(sp) - addi sp, sp, ABI_SIZE_ON_STACK + REG_L ra, FREGS_RA(sp) + REG_L s0, FREGS_S0(sp) + REG_L a0, FREGS_A0(sp) + REG_L a1, FREGS_A1(sp) + addi sp, sp, FREGS_SIZE_ON_STACK .endm SYM_TYPED_FUNC_START(ftrace_stub)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 39/272 hwmon: (pmbus/core) Protect regulator operations with mutex
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit 754bd2b4a084b90b5e7b630e1f423061a9b9b761 ]
The regulator operations pmbus_regulator_get_voltage(), pmbus_regulator_set_voltage(), and pmbus_regulator_list_voltage() access PMBus registers and shared data but were not protected by the update_lock mutex. This could lead to race conditions.
However, adding mutex protection directly to these functions causes a deadlock because pmbus_regulator_notify() (which calls regulator_notifier_call_chain()) is often called with the mutex already held (e.g., from pmbus_fault_handler()). If a regulator callback then calls one of the now-protected voltage functions, it will attempt to acquire the same mutex.
Rework pmbus_regulator_notify() to utilize a worker function to send notifications outside of the mutex protection. Events are stored as atomics in a per-page bitmask and processed by the worker.
Initialize the worker and its associated data during regulator registration, and ensure it is cancelled on device removal using devm_add_action_or_reset().
While at it, remove the unnecessary include of linux/of.h.
--- drivers/hwmon/pmbus/pmbus_core.c | 117 ++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 26 deletions(-)
drivers/hwmon/pmbus/pmbus_core.c +91 -26
@@ -6,6 +6,7 @@* Copyright (c) 2012 Guenter Roeck */ +#include <linux/atomic.h> #include <linux/debugfs.h> #include <linux/delay.h> #include <linux/kernel.h>
@@ -20,8 +21,8 @@#include <linux/pmbus.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> -#include <linux/of.h> #include <linux/thermal.h> +#include <linux/workqueue.h> #include "pmbus.h" /*
@@ -102,6 +103,11 @@ struct pmbus_data {struct mutex update_lock; +#if IS_ENABLED (CONFIG_REGULATOR ) +atomic_t regulator_events[PMBUS_PAGES ]; +struct work_struct regulator_notify_work; +#endif +bool has_status_word;/* device uses STATUS_WORD register */ int (*read_status)(struct i2c_client *client,int page);
@@ -3181,12 +3187,19 @@ static int pmbus_regulator_get_voltage(struct regulator_dev *rdev) .class = PSC_VOLTAGE_OUT, .convert = true, }; +int ret; +mutex_lock (&data->update_lock); s.data =_pmbus_read_word_data (client, s.page,0xff ,PMBUS_READ_VOUT ); -if (s.data <0 ) -return s.data; +if (s.data <0 ) { + ret = s.data; + goto unlock; + } -return (int )pmbus_reg2data (data, &s) *1000 ;/* unit is uV */ + ret = (int )pmbus_reg2data (data, &s) *1000 ;/* unit is uV */ +unlock: +mutex_unlock (&data->update_lock); +return ret; } static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
@@ -3203,16 +3216,22 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv, };int val =DIV_ROUND_CLOSEST (min_uv,1000 );/* convert to mV */ int low, high; +int ret; *selector =0 ; +mutex_lock (&data->update_lock); low =pmbus_regulator_get_low_margin (client, s.page); -if (low <0 ) -return low; +if (low <0 ) { + ret = low; + goto unlock; + } high =pmbus_regulator_get_high_margin (client, s.page); -if (high <0 ) -return high; +if (high <0 ) { + ret = high; + goto unlock; + }/* Make sure we are within margins */ if (low > val)
@@ -3222,7 +3241,10 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv, val =pmbus_data2reg (data, &s, val); -return _pmbus_write_word_data (client, s.page,PMBUS_VOUT_COMMAND , (u16 )val); + ret =_pmbus_write_word_data (client, s.page,PMBUS_VOUT_COMMAND , (u16 )val); +unlock: +mutex_unlock (&data->update_lock); +return ret; } static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
@@ -3230,7 +3252,9 @@ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev, {struct device *dev =rdev_get_dev (rdev);struct i2c_client *client =to_i2c_client (dev->parent); +struct pmbus_data *data =i2c_get_clientdata (client);int val, low, high; +int ret;if (selector >= rdev->desc->n_voltages || selector < rdev->desc->linear_min_sel)
@@ -3240,18 +3264,29 @@ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev, val =DIV_ROUND_CLOSEST (rdev->desc->min_uV + (rdev->desc->uV_step * selector),1000 );/* convert to mV */ +mutex_lock (&data->update_lock); + low =pmbus_regulator_get_low_margin (client,rdev_get_id (rdev)); -if (low <0 ) -return low; +if (low <0 ) { + ret = low; + goto unlock; + } high =pmbus_regulator_get_high_margin (client,rdev_get_id (rdev)); -if (high <0 ) -return high; +if (high <0 ) { + ret = high; + goto unlock; + } -if (val >= low && val <= high) -return val *1000 ;/* unit is uV */ +if (val >= low && val <= high) { + ret = val *1000 ;/* unit is uV */ + goto unlock; + } -return 0 ; + ret =0 ; +unlock: +mutex_unlock (&data->update_lock); +return ret; }const struct regulator_ops pmbus_regulator_ops = {
@@ -3266,12 +3301,42 @@ const struct regulator_ops pmbus_regulator_ops = { };EXPORT_SYMBOL_NS_GPL (pmbus_regulator_ops,PMBUS ); +static void pmbus_regulator_notify_work_cancel (void *data) +{ +struct pmbus_data *pdata = data; + +cancel_work_sync (&pdata->regulator_notify_work); +} + +static void pmbus_regulator_notify_worker (struct work_struct *work) +{ +struct pmbus_data *data = + container_of(work, struct pmbus_data, regulator_notify_work); +int i, j; + +for (i =0 ; i < data->info->pages; i++) { +int event; + + event =atomic_xchg (&data->regulator_events[i],0 ); +if (!event) +continue ; + +for (j =0 ; j < data->info->num_regulators; j++) { +if (i ==rdev_get_id (data->rdevs[j])) { +regulator_notifier_call_chain (data->rdevs[j], + event,NULL ); +break ; + } + } + } +} +static int pmbus_regulator_register (struct pmbus_data *data) {struct device *dev = data->dev;const struct pmbus_driver_info *info = data->info;const struct pmbus_platform_data *pdata =dev_get_platdata (dev); -int i; +int i, ret; data->rdevs =devm_kzalloc (dev,sizeof (struct regulator_dev *) * info->num_regulators,GFP_KERNEL );
@@ -3295,20 +3360,20 @@ static int pmbus_regulator_register(struct pmbus_data *data) info->reg_desc[i].name); } +INIT_WORK (&data->regulator_notify_work, pmbus_regulator_notify_worker); + + ret =devm_add_action_or_reset (dev, pmbus_regulator_notify_work_cancel, data); +if (ret) +return ret; +return 0 ; }static int pmbus_regulator_notify (struct pmbus_data *data,int page,int event) { -int j; - -for (j =0 ; j < data->info->num_regulators; j++) { -if (page ==rdev_get_id (data->rdevs[j])) { -regulator_notifier_call_chain (data->rdevs[j], event,NULL ); -break ; - } - } -return 0 ; +atomic_or (event, &data->regulator_events[page]); +schedule_work (&data->regulator_notify_work); +return 0 ; }#else static int pmbus_regulator_register (struct pmbus_data *data)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 40/272 arm64: Kconfig: Remove selecting replaced HAVE_FUNCTION_GRAPH_RETVAL
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukas Bulwahn <[email protected]>
commit f458b2165d7ac0f2401fff48f19c8f864e7e1e38 upstream.
Commit a3ed4157b7d8 ("fgraph: Replace fgraph_ret_regs with ftrace_regs") replaces the config HAVE_FUNCTION_GRAPH_RETVAL with the config HAVE_FUNCTION_GRAPH_FREGS, and it replaces all the select commands in the various architecture Kconfig files. In the arm64 architecture, the commit adds the 'select HAVE_FUNCTION_GRAPH_FREGS', but misses to remove the 'select HAVE_FUNCTION_GRAPH_RETVAL', i.e., the select on the replaced config.
Remove selecting the replaced config. No functional change, just cleanup.
--- arch/arm64/Kconfig | 1 - 1 file changed, 1 deletion(-)
arch/arm64/Kconfig +0 -1
@@ -219,7 +219,6 @@ config ARM64 select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_GRAPH_FREGS select HAVE_FUNCTION_GRAPH_TRACER - select HAVE_FUNCTION_GRAPH_RETVAL select HAVE_GCC_PLUGINS select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \ HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 41/272 i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
[ Upstream commit b795e68bf3073d67bebbb5a44d93f49efc5b8cc7 ]
The logic used to abort the DMA ring contains several flaws:
1. The driver unconditionally issues a ring abort even when the ring has already stopped.
2. The completion used to wait for abort completion is never re-initialized, resulting in incorrect wait behavior.
3. The abort sequence unintentionally clears RING_CTRL_ENABLE, which resets hardware ring pointers and disrupts the controller state.
4. If the ring is already stopped, the abort operation should be considered successful without attempting further action.
Fix the abort handling by checking whether the ring is running before issuing an abort, re-initializing the completion when needed, ensuring that RING_CTRL_ENABLE remains asserted during abort, and treating an already stopped ring as a successful condition.
--- drivers/i3c/master/mipi-i3c-hci/dma.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-)
drivers/i3c/master/mipi-i3c-hci/dma.c +17 -10
@@ -457,16 +457,23 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,struct hci_rh_data *rh = &rings->headers[xfer_list[0 ].ring_number];unsigned int i;bool did_unqueue = false; - -/* stop the ring */ -rh_reg_write (RING_CONTROL ,RING_CTRL_ABORT ); -if (wait_for_completion_timeout (&rh->op_done,HZ ) ==0 ) { -/* -* We're deep in it if ever this condition is ever met. -* Hardware might still be writing to memory, etc. -*/ -dev_crit (&hci->master.dev,"unable to abort the ring\n" ); -WARN_ON (1 ); +u32 ring_status; + + ring_status =rh_reg_read (RING_STATUS ); +if (ring_status &RING_STATUS_RUNNING ) { +/* stop the ring */ +reinit_completion (&rh->op_done); +rh_reg_write (RING_CONTROL ,RING_CTRL_ENABLE |RING_CTRL_ABORT ); +wait_for_completion_timeout (&rh->op_done,HZ ); + ring_status =rh_reg_read (RING_STATUS ); +if (ring_status &RING_STATUS_RUNNING ) { +/* +* We're deep in it if ever this condition is ever met. +* Hardware might still be writing to memory, etc. +*/ +dev_crit (&hci->master.dev,"unable to abort the ring\n" ); +WARN_ON (1 ); + } }for (i =0 ; i < n; i++) {
Signature · 1 line
2.53.0
Re: [PATCH 6.12 041/272] i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
Hi Greg/Sasha,
Quoted 61 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
[ Upstream commit
b795e68bf3073d67bebbb5a44d93f49efc5b8cc7]The logic used to abort the DMA ring contains several flaws:
1. The driver unconditionally issues a ring abort even when the ring has already stopped.
2. The completion used to wait for abort completion is never re-initialized, resulting in incorrect wait behavior.
3. The abort sequence unintentionally clearsRING_CTRL_ENABLE, which resets hardware ring pointers and disrupts the controller state.
4. If the ring is already stopped, the abort operation should be considered successful without attempting further action.Fix the abort handling by checking whether the ring is running before issuing an abort, re-initializing the completion when needed, ensuring that
RING_CTRL_ENABLEremains asserted during abort, and treating an already stopped ring as a successful condition.Fixes 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")Signed-off-by Adrian Hunter <[email protected]>Reviewed-by Frank Li <[email protected]>Signed-off-by Alexandre Belloni <[email protected]>Signed-off-by Jianqiang kang <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- drivers/i3c/master/mipi-i3c-hci/dma.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-)drivers/i3c/master/mipi-i3c-hci/dma.c +7
-10@@ -457,16 +457,23 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,struct hci_rh_data *rh = &rings->headers[xfer_list[0 ].ring_number];unsigned int i;bool did_unqueue = false; - -/* stop the ring */ -rh_reg_write (RING_CONTROL ,RING_CTRL_ABORT ); -if (wait_for_completion_timeout (&rh->op_done,HZ ) ==0 ) { -/* -* We're deep in it if ever this condition is ever met. -* Hardware might still be writing to memory, etc. -*/ -dev_crit (&hci->master.dev,"unable to abort the ring\n" ); -WARN_ON (1 ); +u32 ring_status; + + ring_status =rh_reg_read (RING_STATUS ); +if (ring_status &RING_STATUS_RUNNING ) { +/* stop the ring */ +reinit_completion (&rh->op_done); +rh_reg_write (RING_CONTROL ,RING_CTRL_ENABLE |RING_CTRL_ABORT );
drivers/i3c/master/mipi-i3c-hci/dma.c static bool hci_dma_dequeue_xfer(struct i3c_hci *hci, · line 476
Quoted 10 lines
drivers/i3c/master/mipi-i3c-hci/dma.c +10
-0+wait_for_completion_timeout (&rh->op_done,HZ ); + ring_status =rh_reg_read (RING_STATUS ); +if (ring_status &RING_STATUS_RUNNING ) { +/* +* We're deep in it if ever this condition is ever met. +* Hardware might still be writing to memory, etc. +*/ +dev_crit (&hci->master.dev,"unable to abort the ring\n" ); +WARN_ON (1 ); + }
I ran an AI-assisted backport review and checked the 6.12.y tree.
The posted backport adds the RING_CTRL_ABORT completion handling, including:
reinit_completion(&rh->op_done);
rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);
wait_for_completion_timeout(&rh->op_done, HZ);In upstream b795e68bf307, that path runs under hci->control_mutex, and the ring bookkeeping is also serialized with hci->lock.
@@ -546,18 +546,25 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number];
unsigned int i;
bool did_unqueue = false;+ u32 ring_status;
guard(mutex)(&hci->control_mutex);
- /* stop the ring */
- rh_reg_write(RING_CONTROL, RING_CTRL_ABORT);
- if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) {
- /*
- * We're deep in it if ever this condition is ever met.
- * Hardware might still be writing to memory, etc.
- */- dev_crit(&hci->master.dev, "unable to abort the ring\n");
- WARN_ON(1);
+ ring_status = rh_reg_read(RING_STATUS);
+ if (ring_status & RING_STATUS_RUNNING) {
+ /* stop the ring */
+ reinit_completion(&rh->op_done);
+ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);
+ wait_for_completion_timeout(&rh->op_done, HZ);
+ ring_status = rh_reg_read(RING_STATUS);
+ if (ring_status & RING_STATUS_RUNNING) {
+ /*
+ * We're deep in it if ever this condition is ever met.
+ * Hardware might still be writing to memory, etc.
+ */
+ dev_crit(&hci->master.dev, "unable to abort the ring\n");
+ WARN_ON(1);
+ }
}
spin_lock_irq(&hci->lock);Downstream 6.12.y has the new reinit_completion() path, but it still lacks the MIPI I3C HCI control_mutex and the IRQ/dequeue ring-state locking.
So the backport can reinitialize and wait on the shared ring completion while another timeout/dequeue or IRQ completion path is still touching the same transfer state. Thoughts ?
Maybe we should drop this for now and queue it up with its prerequisites together ?
thanks,
Harshit
Quoted 3 lines
drivers/i3c/master/mipi-i3c-hci/dma.c +0
-0}for (i =0 ; i < n; i++) {
Re: [PATCH 6.12 041/272] i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
Quoted 130 lines · Harshit Mogalapalli
Hi Greg/Sasha,
Quoted 62 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
[ Upstream commit
b795e68bf3073d67bebbb5a44d93f49efc5b8cc7]The logic used to abort the DMA ring contains several flaws:
1. The driver unconditionally issues a ring abort even when the ring has already stopped.
2. The completion used to wait for abort completion is never re-initialized, resulting in incorrect wait behavior.
3. The abort sequence unintentionally clearsRING_CTRL_ENABLE, which resets hardware ring pointers and disrupts the controller state.
4. If the ring is already stopped, the abort operation should be considered successful without attempting further action.Fix the abort handling by checking whether the ring is running before issuing an abort, re-initializing the completion when needed, ensuring that
RING_CTRL_ENABLEremains asserted during abort, and treating an already stopped ring as a successful condition.Fixes 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")Signed-off-by Adrian Hunter <[email protected]>Reviewed-by Frank Li <[email protected]>Signed-off-by Alexandre Belloni <[email protected]>Signed-off-by Jianqiang kang <[email protected]>Signed-off-by Sasha Levin <[email protected]>---
drivers/i3c/master/mipi-i3c-hci/dma.c| 27 +++++++++++++++++----------1 file changed, 17 insertions(+), 10 deletions(-)drivers/i3c/master/mipi-i3c-hci/dma.c +7
-10@@ -457,16 +457,23 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci, struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number]; unsigned int i; bool did_unqueue = false; - - /* stop the ring */ - rh_reg_write(RING_CONTROL, RING_CTRL_ABORT); - if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) { - /* - * We're deep in it if ever this condition is ever met. - * Hardware might still be writing to memory, etc. - */ - dev_crit(&hci->master.dev, "unable to abort the ring\n"); - WARN_ON(1); + u32 ring_status; + + ring_status = rh_reg_read(RING_STATUS); + if (ring_status & RING_STATUS_RUNNING) { + /* stop the ring */ + reinit_completion(&rh->op_done); + rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);drivers/i3c/master/mipi-i3c-hci/dma.c static bool hci_dma_dequeue_xfer(struct i3c_hci · line 477
Quoted 10 lines
drivers/i3c/master/mipi-i3c-hci/dma.c +10
-0+ wait_for_completion_timeout(&rh->op_done, HZ); + ring_status = rh_reg_read(RING_STATUS); + if (ring_status & RING_STATUS_RUNNING) { + /* + * We're deep in it if ever this condition is ever met. + * Hardware might still be writing to memory, etc. + */ + dev_crit(&hci->master.dev, "unable to abort the ring\n"); + WARN_ON(1); + }I ran an AI-assisted backport review and checked the 6.12.y tree.
The posted backport adds the
RING_CTRL_ABORTcompletion handling, including:
reinit_completion(&rh->op_done);rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);wait_for_completion_timeout(&rh->op_done, HZ);In upstream
b795e68bf307, that path runs underhci->control_mutex, and the ring bookkeeping is also serialized withhci->lock.drivers/i3c/master/mipi-i3c-hci/dma.c +11
-9@@ -546,18 +546,25 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci, struct hci_rh_data *rh = &rings- >headers[xfer_list[0].ring_number]; unsigned int i; bool did_unqueue = false; + u32 ring_status; guard(mutex)(&hci->control_mutex); - /* stop the ring */ - rh_reg_write(RING_CONTROL, RING_CTRL_ABORT); - if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) { - /* - * We're deep in it if ever this condition is ever met. - * Hardware might still be writing to memory, etc. - */ - dev_crit(&hci->master.dev, "unable to abort the ring\n"); - WARN_ON(1); + ring_status = rh_reg_read(RING_STATUS); + if (ring_status & RING_STATUS_RUNNING) { + /* stop the ring */ + reinit_completion(&rh->op_done); + rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE |RING_CTRL_ABORT ); + wait_for_completion_timeout(&rh->op_done, HZ); + ring_status = rh_reg_read(RING_STATUS); + if (ring_status & RING_STATUS_RUNNING) { + /* +* We're deep in it if ever this condition is ever met.
+ * Hardware might still be writing to memory, etc. + */
+dev_crit(&hci->master.dev, "unable to abort the ring\n");
+WARN_ON(1);
+ }
}
spin_lock_irq(&hci->lock);
Quoted 5 lines
Downstream 6.12.y has the new
reinit_completion()path, but it still lacks the MIPI I3C HCIcontrol_mutexand the IRQ/dequeue ring-state locking.So the backport can reinitialize and wait on the shared ring completion while another timeout/dequeue or IRQ completion path is still touching the same transfer state. Thoughts ?
Maybe we should drop this for now and queue it up with its prerequisites together ?
Forgot to metnion, the prerequisites are 1dca8aee80ee ("i3c: mipi-i3c-hci: Fix race in DMA ring dequeue") and f0b5159637ca ("i3c: mipi-i3c-hci: Fix race between DMA ring dequeue and interrupt handler")
thanks,
Harshit
Quoted 11 lines
thanks,
HarshitQuoted 2 lines
drivers/i3c/master/mipi-i3c-hci/dma.c +0
-0} for (i = 0; i < n; i++) {
Greg Kroah-Hartman
maintainerRe: [PATCH 6.12 041/272] i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue
Quoted 146 lines · Harshit Mogalapalli
Quoted 145 lines · Harshit Mogalapalli
Hi Greg/Sasha,
Quoted 67 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
[ Upstream commit
b795e68bf3073d67bebbb5a44d93f49efc5b8cc7]The logic used to abort the DMA ring contains several flaws:
1. The driver unconditionally issues a ring abort even when the ring has
already stopped.
2. The completion used to wait for abort completion is never re-initialized, resulting in incorrect wait behavior.
3. The abort sequence unintentionally clearsRING_CTRL_ENABLE, which resets hardware ring pointers and disrupts the controller state.
4. If the ring is already stopped, the abort operation should be considered successful without attempting further action.Fix the abort handling by checking whether the ring is running before issuing an abort, re-initializing the completion when needed, ensuring that
RING_CTRL_ENABLEremains asserted during abort, and treating an already stopped ring as a successful condition.Fixes 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")Signed-off-by Adrian Hunter <[email protected]>Reviewed-by Frank Li <[email protected]>Signed-off-by Alexandre Belloni <[email protected]>Signed-off-by Jianqiang kang <[email protected]>Signed-off-by Sasha Levin <[email protected]>---
drivers/i3c/master/mipi-i3c-hci/dma.c| 27 +++++++++++++++++----------1 file changed, 17 insertions(+), 10 deletions(-)drivers/i3c/ renamed from drivers/i3c/master/mipi-i3c-hci/dma.c +0
-0
master/mipi-i3c-hci/dma.c
indexb9496e8c4784d..44461f13b54cd100644drivers/i3c/master/mipi-i3c-hci/dma.c +7
-10@@ -457,16 +457,23 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci, struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number]; unsigned int i; bool did_unqueue = false; - - /* stop the ring */ - rh_reg_write(RING_CONTROL, RING_CTRL_ABORT); - if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) { - /* - * We're deep in it if ever this condition is ever met. - * Hardware might still be writing to memory, etc. - */ - dev_crit(&hci->master.dev, "unable to abort the ring\n"); - WARN_ON(1); + u32 ring_status; + + ring_status = rh_reg_read(RING_STATUS); + if (ring_status & RING_STATUS_RUNNING) { + /* stop the ring */ + reinit_completion(&rh->op_done); + rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);drivers/i3c/master/mipi-i3c-hci/dma.c static bool hci_dma_dequeue_xfer(struct · line 477
Quoted 10 lines
drivers/i3c/master/mipi-i3c-hci/dma.c +10
-0+ wait_for_completion_timeout(&rh->op_done, HZ); + ring_status = rh_reg_read(RING_STATUS); + if (ring_status & RING_STATUS_RUNNING) { + /* + * We're deep in it if ever this condition is ever met. + * Hardware might still be writing to memory, etc. + */ + dev_crit(&hci->master.dev, "unable to abort the ring\n"); + WARN_ON(1); + }I ran an AI-assisted backport review and checked the 6.12.y tree.
The posted backport adds the
RING_CTRL_ABORTcompletion handling, including:
reinit_completion(&rh->op_done);rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT);wait_for_completion_timeout(&rh->op_done, HZ);In upstream
b795e68bf307, that path runs underhci->control_mutex, and the ring bookkeeping is also serialized withhci->lock.drivers/i3c/master/mipi-i3c-hci/dma.c +11
-9@@ -546,18 +546,25 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci, struct hci_rh_data *rh = &rings- >headers[xfer_list[0].ring_number]; unsigned int i; bool did_unqueue = false; + u32 ring_status; guard(mutex)(&hci->control_mutex); - /* stop the ring */ - rh_reg_write(RING_CONTROL, RING_CTRL_ABORT); - if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) { - /* - * We're deep in it if ever this condition is ever met. - * Hardware might still be writing to memory, etc. - */ - dev_crit(&hci->master.dev, "unable to abort the ring\n"); - WARN_ON(1); + ring_status = rh_reg_read(RING_STATUS); + if (ring_status & RING_STATUS_RUNNING) { + /* stop the ring */ + reinit_completion(&rh->op_done); + rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE |RING_CTRL_ABORT ); + wait_for_completion_timeout(&rh->op_done, HZ); + ring_status = rh_reg_read(RING_STATUS); + if (ring_status & RING_STATUS_RUNNING) { + /* +* We're deep in it if ever this condition is ever met.
+ * Hardware might still be writing to memory, etc. + */
+dev_crit(&hci->master.dev, "unable to abort the ring\n");
+WARN_ON(1);
+ }
}
spin_lock_irq(&hci->lock);Downstream 6.12.y has the new
reinit_completion()path, but it still lacks the MIPI I3C HCIcontrol_mutexand the IRQ/dequeue ring-state locking.So the backport can reinitialize and wait on the shared ring completion while another timeout/dequeue or IRQ completion path is still touching the same transfer state. Thoughts ?
Quoted 6 lines
Quoted 2 lines
Maybe we should drop this for now and queue it up with its prerequisites together ?
Forgot to metnion, the prerequisites are
1dca8aee80ee("i3c: mipi-i3c-hci:
Fix race in DMA ring dequeue") andf0b5159637ca("i3c: mipi-i3c-hci: Fix race between DMA ring dequeue and interrupt handler")
I'll just drop it for now for all branches as I doubt anyone has i3c hardware on those old branches just yet (or if they do, they can send the needed backports...)
thanks,
greg k-h
Greg Kroah-Hartman
maintainerPATCH 42/272 sysfs: dont remove existing directory on update failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit 237557b8a81ab948e8332f7c0058e758f081c0a3 upstream.
When sysfs_update_group() is called for a named group and create_files() fails (e.g. -ENOMEM), internal_create_group() calls kernfs_remove(kn) on the group directory. In the update path, kn was obtained via kernfs_find_and_get() and refers to a directory that already existed before this call. Removing it silently destroys a sysfs group that the caller did not create.
Only remove the directory if we created it ourselves. On update failure the directory remains as it is left empty by remove_files() inside create_files(), but can be repopulated by a retry.
--- fs/sysfs/group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/sysfs/group.c +1 -1
@@ -179,7 +179,7 @@ static int internal_create_group(structkernfs_get (kn); error =create_files (kn, kobj, uid, gid, grp, update);if (error) { -if (grp->name) +if (grp->name && !update)kernfs_remove (kn); }kernfs_put (kn);
Greg Kroah-Hartman
maintainerPATCH 43/272 mm/damon/sysfs-schemes: call missing mem_cgroup_iter_break()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: SeongJae Park <[email protected]>
commit d4e7b5c4cc353f154d5ab8bb2e1ce7714d77a6e9 upstream.
damon_sysfs_memcg_path_to_id() breaks mem_cgroup_iter() loop without calling mem_cgroup_iter_break(). This leaks the cgroup reference. Fix the issue by calling mem_cgroup_iter_break() before the break.
The issue was discovered [1] by Sashiko.
--- mm/damon/sysfs-schemes.c | 1 + 1 file changed, 1 insertion(+)
mm/damon/sysfs-schemes.c +1 -0
@@ -1913,6 +1913,7 @@ static int damon_sysfs_memcg_path_to_id(if (damon_sysfs_memcg_path_eq (memcg, path, memcg_path)) { *id =mem_cgroup_id (memcg); found = true; +mem_cgroup_iter_break (NULL , memcg);break ; } }
Greg Kroah-Hartman
maintainerPATCH 44/272 ksmbd: fix null pointer dereference in compare_guid_key()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeremy Laratro <[email protected]>
commit 4b83cbc4c15f09b000cc06f033f64b0824b6dc87 upstream.
session_fd_check() walks the per-inode m_op_list during durable-handle session teardown and sets op->conn = NULL for every opinfo whose conn matched the closing session's connection. The matching opinfo, however, stays linked in its per-ClientGuid lease_table_list entry's lb->lease_list because destroy_lease_table() only runs on full TCP-connection teardown, not on SESSION_LOGOFF.
If the same TCP connection then negotiates a fresh session with the same ClientGuid (ClientGuid is bound to NEGOTIATE, not the session, and is unchanged across LOGOFF + SETUP) and issues a SMB2 CREATE with a lease context on a different inode, find_same_lease_key() walks lb->lease_list, reaches the stale opinfo, and calls compare_guid_key(), which unconditionally dereferences opinfo->conn->ClientGUID. The conn pointer is NULL and the kernel panics.
Reproducer requires only a successful SMB2 SESSION_SETUP and a share configured with 'durable handles = yes'. KASAN report on mainline 70390501d194:
general protection fault, probably for non-canonical address 0xdffffc0000000069: 0000 [#1] SMP KASAN PTI KASAN: null-ptr-deref in range [0x0000000000000348-0x000000000000034f] Workqueue: ksmbd-io handle_ksmbd_work RIP: 0010:bcmp+0x5b/0x230 Call Trace: compare_guid_key+0x4b/0xd0 find_same_lease_key+0x324/0x690 smb2_open+0x6aea/0x8e60 handle_ksmbd_work+0x796/0xee0 ...
Faulting address 0x348 is the offset of ClientGUID within struct ksmbd_conn, confirming opinfo->conn was NULL.
Read opinfo->conn once and bail out if it has been cleared by a concurrent session_fd_check(). A half-detached opinfo cannot be the owner of an active lease, so returning 0 is the correct match result.
--- fs/smb/server/oplock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
fs/smb/server/oplock.c +5 -1
@@ -484,8 +484,12 @@ static inline int compare_guid_key(struc const char *guid1, const char *key1) { const char *guid2, *key2; +struct ksmbd_conn *conn; - guid2 = opinfo->conn->ClientGUID; + conn =READ_ONCE (opinfo->conn); +if (!conn) +return 0 ; + guid2 = conn->ClientGUID; key2 = opinfo->o_lease->lease_key;if (!memcmp (guid1, guid2,SMB2_CLIENT_GUID_SIZE ) && !memcmp (key1, key2,SMB2_LEASE_KEY_SIZE ))
Greg Kroah-Hartman
maintainerPATCH 45/272 ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ferry Meng <[email protected]>
commit af92ee994cc7f7e83a41c2025f32257a2f82a7ef upstream.
Commit 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16 DACL size overflow") added check_add_overflow() guards that break out of the ACE-building loops in set_posix_acl_entries_dacl() when the accumulated DACL size would wrap past 65535.
However, each iteration allocates a struct smb_sid via kmalloc_obj() at the top of the loop and relies on the kfree(sid) call at the end of the loop body (the 'pass_same_sid' label in the first loop, and the explicit kfree at the tail of the second loop) to release it. The newly introduced 'break' statements bypass those kfree() calls, leaking the sid buffer every time an overflow is detected.
A malicious or malformed file with enough POSIX ACL entries to trip the overflow check will leak one or more struct smb_sid allocations on every request that touches the file's DACL, providing a trivial kernel memory exhaustion vector.
Free sid before breaking out of the loops to plug the leak.
--- fs/smb/server/smbacl.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
fs/smb/server/smbacl.c +9 -3
@@ -643,8 +643,10 @@ static void set_posix_acl_entries_dacl(s ntace = (struct smb_ace *)((char *)pndace + *size); ace_sz =fill_ace_for_sid (ntace, sid,ACCESS_ALLOWED , flags, pace->e_perm,0777 ); -if (check_add_overflow (*size, ace_sz, size)) +if (check_add_overflow (*size, ace_sz, size)) { +kfree (sid);break ; + } (*num_aces)++;if (pace->e_tag ==ACL_USER ) ntace->access_req |=
@@ -655,8 +657,10 @@ static void set_posix_acl_entries_dacl(s ntace = (struct smb_ace *)((char *)pndace + *size); ace_sz =fill_ace_for_sid (ntace, sid,ACCESS_ALLOWED ,0x03 , pace->e_perm,0777 ); -if (check_add_overflow (*size, ace_sz, size)) +if (check_add_overflow (*size, ace_sz, size)) { +kfree (sid);break ; + } (*num_aces)++;if (pace->e_tag ==ACL_USER ) ntace->access_req |=
@@ -698,8 +702,10 @@ posix_default_acl: ntace = (struct smb_ace *)((char *)pndace + *size); ace_sz =fill_ace_for_sid (ntace, sid,ACCESS_ALLOWED ,0x0b , pace->e_perm,0777 ); -if (check_add_overflow (*size, ace_sz, size)) +if (check_add_overflow (*size, ace_sz, size)) { +kfree (sid);break ; + } (*num_aces)++;if (pace->e_tag ==ACL_USER ) ntace->access_req |=
Greg Kroah-Hartman
maintainerPATCH 46/272 ksmbd: validate SID in parent security descriptor during ACL inheritance
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junyi Liu <[email protected]>
commit 69f030cf95488ae1186c72ac8c66fd279664ea7f upstream.
Introduce smb_validate_ntsd_sid() helper to safely validate Owner SID and Group SID inside the NT Security Descriptor (smb_ntsd) retrieved from the parent directory.
--- fs/smb/server/smbacl.c | 66 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 16 deletions(-)
fs/smb/server/smbacl.c +50 -16
@@ -1096,6 +1096,40 @@ static int smb_append_inherited_ace(strureturn 0 ; } +static int smb_validate_ntsd_sid (struct smb_ntsd *pntsd,size_t pntsd_size, +unsigned int sid_offset,struct smb_sid **sid, +size_t *sid_size) +{ +size_t sid_end; + + *sid =NULL ; + *sid_size =0 ; + +if (!sid_offset) +return 0 ; + +if (sid_offset <sizeof (struct smb_ntsd ) || +check_add_overflow (sid_offset, (size_t )CIFS_SID_BASE_SIZE , + &sid_end) || + sid_end > pntsd_size) +return -EINVAL ; + + *sid = (struct smb_sid *)((char *)pntsd + sid_offset); +if ((*sid)->num_subauth >SID_MAX_SUB_AUTHORITIES ) +return -EINVAL ; + +if (check_add_overflow ((size_t )CIFS_SID_BASE_SIZE , +sizeof (__le32) * (size_t )(*sid)->num_subauth, + &sid_end)) +return -EINVAL ; + +if (sid_offset > pntsd_size || sid_end > pntsd_size - sid_offset) +return -EINVAL ; + + *sid_size = sid_end; +return 0 ; +} +int smb_inherit_dacl (struct ksmbd_conn *conn,const struct path *path,unsigned int uid,unsigned int gid)
@@ -1108,28 +1142,28 @@ int smb_inherit_dacl(struct ksmbd_conn *struct dentry *parent = path->dentry->d_parent;struct mnt_idmap *idmap =mnt_idmap (path->mnt);int inherited_flags =0 , flags =0 , i, nt_size =0 , pdacl_size; -int rc =0 , pntsd_type, pntsd_size, acl_len, aces_size; +int rc =0 , pntsd_type, ppntsd_size, acl_len, aces_size;unsigned int dacloffset;size_t dacl_struct_end;u16 num_aces, ace_cnt =0 ;char *aces_base;bool is_dir =S_ISDIR (d_inode (path->dentry)->i_mode); - pntsd_size =ksmbd_vfs_get_sd_xattr (conn, idmap, + ppntsd_size =ksmbd_vfs_get_sd_xattr (conn, idmap, parent, &parent_pntsd); -if (pntsd_size <=0 ) +if (ppntsd_size <=0 )return -ENOENT ; dacloffset =le32_to_cpu (parent_pntsd->dacloffset);if (!dacloffset ||check_add_overflow (dacloffset,sizeof (struct smb_acl ), &dacl_struct_end) || - dacl_struct_end > (size_t )pntsd_size) { + dacl_struct_end > (size_t )ppntsd_size) { rc = -EINVAL ; goto free_parent_pntsd; } parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset); - acl_len = pntsd_size - dacloffset; + acl_len = ppntsd_size - dacloffset; num_aces =le16_to_cpu (parent_pdacl->num_aces); pntsd_type =le16_to_cpu (parent_pntsd->type); pdacl_size =le16_to_cpu (parent_pdacl->size);
@@ -1243,19 +1277,19 @@ pass:struct smb_ntsd *pntsd;struct smb_acl *pdacl;struct smb_sid *powner_sid =NULL , *pgroup_sid =NULL ; -int powner_sid_size =0 , pgroup_sid_size =0 , pntsd_size; +size_t powner_sid_size =0 , pgroup_sid_size =0 , pntsd_size;size_t pntsd_alloc_size; -if (parent_pntsd->osidoffset) { - powner_sid = (struct smb_sid *)((char *)parent_pntsd + -le32_to_cpu (parent_pntsd->osidoffset)); - powner_sid_size =1 +1 +6 + (powner_sid->num_subauth *4 ); - } -if (parent_pntsd->gsidoffset) { - pgroup_sid = (struct smb_sid *)((char *)parent_pntsd + -le32_to_cpu (parent_pntsd->gsidoffset)); - pgroup_sid_size =1 +1 +6 + (pgroup_sid->num_subauth *4 ); - } + rc =smb_validate_ntsd_sid (parent_pntsd, ppntsd_size, +le32_to_cpu (parent_pntsd->osidoffset), + &powner_sid, &powner_sid_size); +if (rc) + goto free_aces_base; + rc =smb_validate_ntsd_sid (parent_pntsd, ppntsd_size, +le32_to_cpu (parent_pntsd->gsidoffset), + &pgroup_sid, &pgroup_sid_size); +if (rc) + goto free_aces_base; if (check_add_overflow(sizeof(struct smb_ntsd), (size_t)powner_sid_size,
Greg Kroah-Hartman
maintainerPATCH 47/272 smb: client: require net admin for CIFS SWN netlink
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit d1ebfce2c1d161186a82e77590bf7da2ea1bce91 upstream.
CIFS_GENL_CMD_SWN_NOTIFY is the userspace witness-notify command. The intended sender is the cifs.witness helper, but the generic-netlink operation currently has no capability flag, so any local process can send RESOURCE_CHANGE or CLIENT_MOVE notifications to the in-kernel witness handler.
The same family exposes CIFS_GENL_MCGRP_SWN without multicast-group capability flags. Register messages sent to that group include the witness registration id and, for NTLM-authenticated mounts, the username, domain, and password attributes copied from the CIFS session. An unprivileged local process should not be able to join that group and receive those messages.
Require CAP_NET_ADMIN for incoming SWN_NOTIFY commands with GENL_ADMIN_PERM, and require CAP_NET_ADMIN over the network namespace for joining the SWN multicast group with GENL_MCAST_CAP_NET_ADMIN. The cifs.witness service runs with the privileges needed for both operations.
--- fs/smb/client/netlink.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
fs/smb/client/netlink.c +5 -1
@@ -33,13 +33,17 @@ static const struct nla_policy cifs_genlstatic const struct genl_ops cifs_genl_ops[] = { { .cmd =CIFS_GENL_CMD_SWN_NOTIFY , + .flags =GENL_ADMIN_PERM , .validate =GENL_DONT_VALIDATE_STRICT |GENL_DONT_VALIDATE_DUMP , .doit = cifs_swn_notify, }, };static const struct genl_multicast_group cifs_genl_mcgrps[] = { - [CIFS_GENL_MCGRP_SWN ] = { .name =CIFS_GENL_MCGRP_SWN_NAME }, + [CIFS_GENL_MCGRP_SWN ] = { + .name =CIFS_GENL_MCGRP_SWN_NAME , + .flags =GENL_MCAST_CAP_NET_ADMIN , + }, };struct genl_family cifs_genl_family = {
Greg Kroah-Hartman
maintainerPATCH 48/272 smb: client: protect tc_count increment in smb2_find_smb_sess_tcon_unlocked()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henrique Carvalho <[email protected]>
commit 4d8690dace005a38e6dbde9ecce2da3ad85c7c41 upstream.
Commit 96c4af418586 ("cifs: Fix locking usage for tcon fields") refactored cifs code to change cifs_tcp_ses_lock for tc_lock around tc_count changes.
There was missing lock around tc_count increment inside smb2_find_smb_sess_tcon_unlocked().
--- fs/smb/client/smb2transport.c | 2 ++ 1 file changed, 2 insertions(+)
fs/smb/client/smb2transport.c +2 -0
@@ -214,7 +214,9 @@ smb2_find_smb_sess_tcon_unlocked(structlist_for_each_entry (tcon, &ses->tcon_list, tcon_list) {if (tcon->tid != tid)continue ; +spin_lock (&tcon->tc_lock); ++tcon->tc_count; +spin_unlock (&tcon->tc_lock);trace_smb3_tcon_ref (tcon->debug_id, tcon->tc_count, netfs_trace_tcon_ref_get_find_sess_tcon);return tcon;
Greg Kroah-Hartman
maintainerPATCH 49/272 smb: client: use data_len for SMB2 READ encrypted folioq copy
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeremy Erazo <[email protected]>
commit d4d76c9ee1997cc8c977a63f6c43551c253c1066 upstream.
In handle_read_data() the encrypted/folioq branch (buf_len <= data_offset, reached via receive_encrypted_read for transform PDUs > CIFSMaxBufSize + MAX_HEADER_SIZE) copies the READ payload using buffer_len rather than data_len:
rdata->result = cifs_copy_folioq_to_iter(buffer, buffer_len, cur_off, &rdata->subreq.io_iter); ... rdata->got_bytes = buffer_len;
buffer_len comes from the SMB3 transform header OriginalMessageSize field (OriginalMessageSize - read_rsp_size); it represents the size of the decrypted message after the SMB2 header. data_len comes from the SMB2 READ response DataLength field; it represents the actual READ payload size and may be smaller than buffer_len when the decrypted message contains padding or other trailing bytes after the READ payload. The existing check data_len > buffer_len - pad_len only enforces an upper bound, so a server that emits OriginalMessageSize larger than read_rsp_size + pad_len + data_len passes the check and the kernel copies buffer_len bytes per response, ignoring the server-asserted DataLength.
Two observable failures with a crafted server (DataLength=4, buffer_len=20000):
- the kernel returns 20000 bytes per sub-request to userspace and sets got_bytes = buffer_len, even though the response claimed only 4 bytes of payload;
- on a partial netfs sub-request whose iterator is sized to data_len, the over-large copy_folio_to_iter() short-reads, cifs_copy_folioq_to_iter() returns -EIO via the n != len path, and the entire netfs read collapses to -EIO even though the leading sub-requests succeeded.
Use data_len for the copy length and for got_bytes so the kernel honours the server-asserted READ payload size. For well-formed servers (where buffer_len == pad_len + data_len) the change is behaviour-equivalent.
--- fs/smb/client/smb2ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/client/smb2ops.c +2 -2
@@ -4781,7 +4781,7 @@ handle_read_data(struct TCP_Server_Info }/* Copy the data to the output I/O iterator. */ - rdata->result =cifs_copy_folioq_to_iter (buffer, buffer_len, + rdata->result =cifs_copy_folioq_to_iter (buffer, data_len, cur_off, &rdata->subreq.io_iter);if (rdata->result !=0 ) {if (is_offloaded)
@@ -4790,7 +4790,7 @@ handle_read_data(struct TCP_Server_Infodequeue_mid (mid, rdata->result);return 0 ; } - rdata->got_bytes = buffer_len; + rdata->got_bytes = data_len; }else if (buf_len >= data_offset + data_len) {/* read response payload is in buf */
Greg Kroah-Hartman
maintainerPATCH 50/272 smb/server: promote S_DEL_ON_CLS to S_DEL_PENDING when close
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: ChenXiaoSong <[email protected]>
commit 4ec9c8e023c79f613fe4d5ad8cc737112efb2e44 upstream.
Reproducer:
1. server: systemctl start ksmbd
2. client: mount -t cifs //${server_ip}/export /mnt
3. client: C program: openat(AT_FDCWD, "/mnt", O_RDWR | O_TMPFILE, 0600)
Do not treat FILE_DELETE_ON_CLOSE_LE as delete pending while files remain open.
This patch fixes xfstests generic/004.
--- fs/smb/server/vfs_cache.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
fs/smb/server/vfs_cache.c +12 -4
@@ -118,7 +118,7 @@ int ksmbd_query_inode_status(struct dentreturn ret;down_read (&ci->m_lock); -if (ci->m_flags & (S_DEL_PENDING |S_DEL_ON_CLS )) +if (ci->m_flags &S_DEL_PENDING ) ret =KSMBD_INODE_STATUS_PENDING_DELETE ;else ret =KSMBD_INODE_STATUS_OK ;
@@ -134,7 +134,7 @@ bool ksmbd_inode_pending_delete(struct kint ret;down_read (&ci->m_lock); - ret = (ci->m_flags & (S_DEL_PENDING |S_DEL_ON_CLS )); + ret = (ci->m_flags &S_DEL_PENDING );up_read (&ci->m_lock);return ret;
@@ -302,12 +302,20 @@ static void __ksmbd_inode_close(struct k } } +down_write (&ci->m_lock); +/* Promote S_DEL_ON_CLS to S_DEL_PENDING when close */ +if (ci->m_flags &S_DEL_ON_CLS ) { + ci->m_flags &= ~S_DEL_ON_CLS ; + ci->m_flags |=S_DEL_PENDING ; + } +up_write (&ci->m_lock); +if (atomic_dec_and_test (&ci->m_count)) {bool do_unlink = false;down_write (&ci->m_lock); -if (ci->m_flags & (S_DEL_ON_CLS |S_DEL_PENDING )) { - ci->m_flags &= ~(S_DEL_ON_CLS |S_DEL_PENDING ); +if (ci->m_flags &S_DEL_PENDING ) { + ci->m_flags &= ~S_DEL_PENDING ; do_unlink = true; }up_write (&ci->m_lock);
Greg Kroah-Hartman
maintainerPATCH 51/272 hwmon: (pmbus/adm1266) widen blackbox-info buffer to I2C_SMBUS_BLOCK_MAX
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdurrahman Hussain <[email protected]>
commit eee213daa1e1b402eb631bcd1b8c5aa340a6b081 upstream.
adm1266_nvmem_read_blackbox() declares a 5-byte stack buffer and passes it to i2c_smbus_read_block_data() to retrieve the 4-byte BLACKBOX_INFO response. i2c_smbus_read_block_data() does not honour caller buffer sizes -- it memcpy()s data.block[0] bytes from the SMBus transaction (where data.block[0] is the length byte returned by the slave device, up to I2C_SMBUS_BLOCK_MAX = 32):
memcpy(values, &data.block[1], data.block[0]);
If the device returns any block length above 5, the call overflows the caller's 5-byte stack buffer before the post-call
if (ret != 4) return -EIO;
check has a chance to reject the response.
Widen the local buffer to I2C_SMBUS_BLOCK_MAX so the helper has room for any well-formed SMBus block response, matching the convention used by the other i2c_smbus_read_block_data() callers in this driver.
--- drivers/hwmon/pmbus/adm1266.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/pmbus/adm1266.c +1 -1
@@ -349,7 +349,7 @@ static int adm1266_nvmem_read_blackbox(s {int record_count;char index; -u8 buf[5 ]; +u8 buf[I2C_SMBUS_BLOCK_MAX ];int ret; ret =i2c_smbus_read_block_data (data->client,ADM1266_BLACKBOX_INFO , buf);
Greg Kroah-Hartman
maintainerPATCH 52/272 ALSA: ua101: Reject too-short USB descriptors
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cássio Gabriel <[email protected]>
commit b59d5c51bb328a60749b4dd5fe7e649bfb4089b4 upstream.
find_format_descriptor() walks the class-specific interface extras by advancing with bLength. It rejects descriptors that extend past the remaining buffer, but it does not reject descriptor lengths smaller than a USB descriptor header.
Reject too-short descriptors before using bLength to advance the local scan. This keeps the UA-101 parser robust against malformed descriptor data and matches the usual USB descriptor walking rules.
--- sound/usb/misc/ua101.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
sound/usb/misc/ua101.c +3 -2
@@ -914,8 +914,9 @@ find_format_descriptor(struct usb_interfstruct uac_format_type_i_discrete_descriptor *desc; desc = (struct uac_format_type_i_discrete_descriptor *)extra; -if (desc->bLength > extralen) { -dev_err (&interface->dev,"descriptor overflow\n" ); +if (desc->bLength <sizeof (struct usb_descriptor_header ) || + desc->bLength > extralen) { +dev_err (&interface->dev,"invalid descriptor length\n" );return NULL ; } if (desc->bLength == UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1) &&
Greg Kroah-Hartman
maintainerPATCH 53/272 ALSA: pcm: Dont setup bogus iov_iter for silencing
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit e4d3386b74fba8e01280484b67ee481ece00201e upstream.
At transition to the iov_iter for PCM data transfer, we blindly applied the iov_iter setup also for silencing (i.e. data = NULL), and it leads to a calculation of bogus iov_iter. Fortunately this didn't cause troubles on most of architectures but it goes wrong on RISC-V now, causing a NULL dereference.
Handle the NULL data case to treat the silencing in interleaved_copy() for addressing the bug above. noninterleaved_copy() has already the NULL data handling, so it doesn't need changes.
--- sound/core/pcm_lib.c | 3 +++ 1 file changed, 3 insertions(+)
sound/core/pcm_lib.c +3 -0
@@ -2138,6 +2138,9 @@ static int interleaved_copy(struct snd_p off =frames_to_bytes (runtime, off); frames =frames_to_bytes (runtime, frames); +if (!data) +return fill_silence (substream,0 , hwoff,NULL , frames); +return do_transfer (substream,0 , hwoff, data + off, frames, transfer, in_kernel); }
Greg Kroah-Hartman
maintainerPATCH 54/272 ALSA: asihpi: Fix potential OOB array access at reading cache
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit 7b7d6572145c1dab2dd9bfb550b188e5f0ff3c3f upstream.
find_control() to retrieve a cached info accesses the array with the given index blindly, which may lead to an OOB array access. Add a sanity check for avoiding it.
--- sound/pci/asihpi/hpicmn.c | 6 ++++++ 1 file changed, 6 insertions(+)
sound/pci/asihpi/hpicmn.c +6 -0
@@ -276,6 +276,12 @@ static short find_control(u16 control_inreturn 0 ; } +if (control_index >= p_cache->control_count) { +HPI_DEBUG_LOG (VERBOSE ,"control_index out of bounce %d\n" , + control_index); +return 0 ; + } + *pI = p_cache->p_info[control_index];if (!*pI) { HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
Greg Kroah-Hartman
maintainerPATCH 55/272 efi: Allocate runtime workqueue before ACPI init
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ard Biesheuvel <[email protected]>
commit 13c6da02e767152c9ac4330962247a5e47011035 upstream.
Since commit
5894cf571e14 ("acpi/prmt: Use EFI runtime sandbox to invoke PRM handlers")
ACPI PRM calls are delegated to a workqueue which runs in a kernel thread, making it easier to detect and mitigate faulting memory accesses performed by the firmware.
Rafael reports that such PRM accesses may occur before efisubsys_init() executes, which is where the workqueue is allocated, leading to NULL pointer dereferences. Since acpi_init() [which triggers the early PRM accesses] executes as a subsys_initcall() as well, and has its own dependencies that may be sensitive to initcall ordering, deferring acpi_init() is not an option.
So instead, split off the workqueue allocation into its own postcore initcall, as this is the only missing piece to allow EFI runtime calls to be made. This ensures that EFI runtime call (including PRM calls) are accessible to all code running at subsys_initcall() level.
--- drivers/firmware/efi/efi.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-)
drivers/firmware/efi/efi.c +16 -12
@@ -387,21 +387,11 @@ static void __init efi_debugfs_init(voidstatic inline void efi_debugfs_init (void ) {}#endif -/* -* We register the efi subsystem with the firmware subsystem and the -* efivars subsystem with the efi subsystem, if the system was booted with -* EFI. -*/ -static int __init efisubsys_init (void ) +static int __init efipostcore_init (void ) { -int error; -if (!efi_enabled (EFI_RUNTIME_SERVICES )) efi.runtime_supported_mask =0 ; -if (!efi_enabled (EFI_BOOT )) -return 0 ; -if (efi.runtime_supported_mask) {/* * Since we process only one efi_runtime_service() at a time, an
@@ -413,9 +403,23 @@ static int __init efisubsys_init(void)pr_err ("Creating efi_rts_wq failed, EFI runtime services disabled.\n" );clear_bit (EFI_RUNTIME_SERVICES , &efi.flags); efi.runtime_supported_mask =0 ; -return 0 ; } } +return 0 ; +} +postcore_initcall (efipostcore_init); + +/* +* We register the efi subsystem with the firmware subsystem and the +* efivars subsystem with the efi subsystem, if the system was booted with +* EFI. +*/ +static int __init efisubsys_init (void ) +{ +int error; + +if (!efi_enabled (EFI_BOOT )) +return 0 ;if (efi_rt_services_supported (EFI_RT_SUPPORTED_TIME_SERVICES ))platform_device_register_simple ("rtc-efi" ,0 ,NULL ,0 );
Greg Kroah-Hartman
maintainerPATCH 56/272 io_uring/waitid: clear waitid info before copying it to userspace
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heechan Kang <[email protected]>
commit 93d93f5f8da791e98159795c6ef683f45bd95d13 upstream.
IORING_OP_WAITID stores its result fields in struct io_waitid::info and later copies them to userspace siginfo. The prep path initializes the request arguments, but it does not initialize info itself.
If the wait operation completes without reporting a child event, the common wait code can return without writing wo_info. In that case io_waitid_finish() still copies iw->info to userspace, exposing stale bytes from the reused io_kiocb command storage.
Clear the result storage during prep so the io_uring path matches the regular waitid syscall, which uses a zero-initialized struct waitid_info.
--- io_uring/waitid.c | 1 + 1 file changed, 1 insertion(+)
io_uring/waitid.c +1 -0
@@ -294,6 +294,7 @@ int io_waitid_prep(struct io_kiocb *req, iw->upid =READ_ONCE (sqe->fd); iw->options =READ_ONCE (sqe->file_index); iw->infop =u64_to_user_ptr (READ_ONCE (sqe->addr2)); +memset (&iw->info,0 ,sizeof (iw->info));return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 57/272 drivers/base/memory: fix memory block reference leak in poison accounting
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muchun Song <[email protected]>
commit 03a2cc1756a0570f887d624cd6c535ea0cbd4951 upstream.
memblk_nr_poison_inc() and memblk_nr_poison_sub() look up a memory block via find_memory_block_by_id(), which acquires a reference to the memory block device.
Both helpers use the returned memory block without dropping that reference, leaking the device reference on each successful lookup. Drop the reference after updating nr_hwpoison.
--- drivers/base/memory.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/base/memory.c +6 -2
@@ -1232,8 +1232,10 @@ void memblk_nr_poison_inc(unsigned longconst unsigned long block_id =pfn_to_block_id (pfn);struct memory_block *mem =find_memory_block_by_id (block_id); -if (mem) +if (mem) {atomic_long_inc (&mem->nr_hwpoison); +put_device (&mem->dev); + } }void memblk_nr_poison_sub (unsigned long pfn,long i)
@@ -1241,8 +1243,10 @@ void memblk_nr_poison_sub(unsigned longconst unsigned long block_id =pfn_to_block_id (pfn);struct memory_block *mem =find_memory_block_by_id (block_id); -if (mem) +if (mem) {atomic_long_sub (i, &mem->nr_hwpoison); +put_device (&mem->dev); + } }static unsigned long memblk_nr_poison (struct memory_block *mem)
Greg Kroah-Hartman
maintainerPATCH 58/272 ipv6: ioam: refresh hdr pointer before ioam6_event()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Iurman <[email protected]>
commit e46e6bc97fb1f339730ff1ba74267fbf48e7a422 upstream.
Reported by Sashiko:
In ipv6_hop_ioam(), the hdr pointer is initialized to point into the skb's linear data buffer. Later, the code calls skb_ensure_writable(), which might reallocate the buffer:
if (skb_ensure_writable(skb, optoff + 2 + hdr->opt_len)) goto drop; /* Trace pointer may have changed */ trace = (struct ioam6_trace_hdr *)(skb_network_header(skb) + optoff + sizeof(*hdr)); ioam6_fill_trace_data(skb, ns, trace, true); ioam6_event(IOAM6_EVENT_TRACE, dev_net(skb->dev), GFP_ATOMIC, (void *)trace, hdr->opt_len - 2);
If the skb is cloned or lacks sufficient linear headroom, skb_ensure_writable() will invoke pskb_expand_head(), which reallocates the skb's data buffer and frees the old one, invalidating pointers to it. While the code recalculates the trace pointer immediately after the call to skb_ensure_writable(), it fails to recalculate the hdr pointer.
This patch fixes the above by recalculating the hdr pointer before passing hdr->opt_len to ioam6_event(), so that we avoid any UaF.
--- net/ipv6/exthdrs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/ipv6/exthdrs.c +3 -3
@@ -957,9 +957,9 @@ static bool ipv6_hop_ioam(struct sk_buffif (skb_ensure_writable (skb, optoff +2 + hdr->opt_len)) goto drop; -/* Trace pointer may have changed */ - trace = (struct ioam6_trace_hdr *)(skb_network_header (skb) - + optoff +sizeof (*hdr)); +/* Trace and hdr pointers may have changed */ + hdr = (struct ioam6_hdr *)(skb_network_header (skb) + optoff); + trace = (struct ioam6_trace_hdr *)((u8 *)hdr +sizeof (*hdr));ioam6_fill_trace_data (skb, ns, trace, true);
Greg Kroah-Hartman
maintainerPATCH 59/272 mm/memory_hotplug: fix memory block reference leak on remove
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muchun Song <[email protected]>
commit 93866f55f7e292fe3d47d36c9efe5ee10213a06b upstream.
Patch series "mm: Fix memory block leaks and locking", v2.
This series fixes two memory block device reference leaks and one locking issue around the per-memory_block hwpoison counter.
This patch (of 2):
remove_memory_blocks_and_altmaps() looks up each memory block with find_memory_block(), which acquires a reference to the memory block device.
That reference is never dropped on this path, resulting in a leaked device reference when removing memory blocks and their altmaps. Drop the reference after retrieving mem->altmap and clearing mem->altmap, before removing the memory block device.
--- mm/memory_hotplug.c | 2 ++ 1 file changed, 2 insertions(+)
mm/memory_hotplug.c +2 -0
@@ -1406,6 +1406,8 @@ static void remove_memory_blocks_and_alt altmap = mem->altmap; mem->altmap =NULL ; +/* drop the ref. we got via find_memory_block() */ +put_device (&mem->dev);remove_memory_block_devices (cur_start, memblock_size);
Greg Kroah-Hartman
maintainerPATCH 60/272 selftests/mm: run_vmtests.sh: fix destructive tests invocation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Capitulino <[email protected]>
commit 3432cbb291aabf85f8af4b9d1ec37179168ff999 upstream.
Destructive tests should be invoked with -d command-line option, but this won't work today since 'd' is missing in getopts command-line. This commit fixes it.
--- tools/testing/selftests/mm/run_vmtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/mm/run_vmtests.sh +1 -1
@@ -85,7 +85,7 @@ RUN_ALL=false RUN_DESTRUCTIVE=false TAP_PREFIX="# " -while getopts "aht:n" OPT; do +while getopts "aht:nd" OPT; do case ${OPT} in "a") RUN_ALL=true ;; "h") usage ;;
Greg Kroah-Hartman
maintainerPATCH 61/272 net: wwan: iosm: fix potential memory leaks in ipc_imem_init()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit c5d93b2c40355e999715262a824965aac025a427 upstream.
The memory allocated in ipc_protocol_init() is not freed on the error paths that follow in ipc_imem_init(). Fix that by calling the corresponding release function ipc_protocol_deinit() in the error path.
--- drivers/net/wwan/iosm/iosm_ipc_imem.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wwan/iosm/iosm_ipc_imem.c +2 -0
@@ -1430,6 +1430,8 @@ imem_config_fail: protocol_init_fail:cancel_work_sync (&ipc_imem->run_state_worker);ipc_task_deinit (ipc_imem->ipc_task); +if (ipc_imem->ipc_protocol) +ipc_protocol_deinit (ipc_imem->ipc_protocol); ipc_task_init_fail:kfree (ipc_imem->ipc_task); ipc_task_fail:
Greg Kroah-Hartman
maintainerPATCH 62/272 Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Safa Karakuş <[email protected]>
commit ab1513597c6cf17cd1ad2a21e3b045421b48e022 upstream.
bt_accept_dequeue() unlinks a not-yet-accepted child from the parent accept queue and release_sock()s it before returning, so the returned sk has no caller reference and is unlocked.
l2cap_sock_cleanup_listen() walks these children on listening-socket close. A concurrent HCI disconnect drives hci_rx_work -> l2cap_conn_del() which runs l2cap_chan_del() + l2cap_sock_kill() and frees the child sk and its l2cap_chan; cleanup_listen() then uses both:
BUG: KASAN: slab-use-after-free in l2cap_sock_kill
l2cap_sock_kill / l2cap_sock_cleanup_listen / __x64_sys_close
Freed by: l2cap_conn_del -> l2cap_sock_close_cb -> l2cap_sock_killThis is distinct from the two fixes already in this area: commit e83f5e24da741 ("Bluetooth: serialize accept_q access") serialises the accept_q list/poll and takes temporary refs inside bt_accept_dequeue(), and CVE-2025-39860 serialises the userspace close()/accept() race by calling cleanup_listen() under lock_sock() in l2cap_sock_release(). Neither covers l2cap_conn_del() running from hci_rx_work, so this UAF still reproduces on current bluetooth/master.
Take the reference at the source: bt_accept_dequeue() does sock_hold() while sk is still locked, before release_sock(); callers sock_put(). cleanup_listen() pins the chan with l2cap_chan_hold_unless_zero() under a brief child sk lock (serialising vs l2cap_sock_teardown_cb()), drops it before l2cap_chan_lock(), and skips a duplicate l2cap_sock_kill() on SOCK_DEAD. conn->lock is not taken here: cleanup_listen() runs under the parent sk lock and that would invertconn->lock -> chan->lock -> sk_lock (lockdep).
KASAN/SMP: an unprivileged listen/close vs HCI-disconnect race produced 12 use-after-free reports per run before this change; 0, and no lockdep report, over 1600+ raced iterations after it on bluetooth/master.
--- net/bluetooth/af_bluetooth.c | 10 ++++++++ net/bluetooth/iso.c | 9 ++++++- net/bluetooth/l2cap_sock.c | 51 +++++++++++++++++++++++++++++++++++++------ net/bluetooth/rfcomm/sock.c | 9 ++++++- net/bluetooth/sco.c | 9 ++++++- 5 files changed, 78 insertions(+), 10 deletions(-)
net/bluetooth/af_bluetooth.c +10 -0
@@ -306,6 +306,16 @@ restart:if (newsock)sock_graft (sk, newsock); +/* Hand the caller a reference taken while sk is +* still locked. bt_accept_unlink() just dropped +* the accept-queue reference; without this hold a +* concurrent teardown (e.g. l2cap_conn_del() -> +* l2cap_sock_kill()) could free sk between +* release_sock() and the caller using it. Every +* caller drops this with sock_put() when done. +*/ +sock_hold (sk); +release_sock (sk);return sk; }
net/bluetooth/iso.c +8 -1
@@ -722,6 +722,8 @@ static void iso_sock_cleanup_listen(struwhile ((sk =bt_accept_dequeue (parent,NULL ))) {iso_sock_close (sk);iso_sock_kill (sk); +/* Drop the reference handed back by bt_accept_dequeue(). */ +sock_put (sk); }/* If listening socket has a hcon, properly disconnect it */
@@ -1263,8 +1265,13 @@ static int iso_sock_accept(struct socket } ch =bt_accept_dequeue (sk, newsock); -if (ch) +if (ch) { +/* Drop the bridging ref from bt_accept_dequeue(); +* the grafted socket keeps ch alive from here. +*/ +sock_put (ch);break ; + }if (!timeo) { err = -EAGAIN ;
net/bluetooth/l2cap_sock.c +44 -7
74 lines not on this page · raw message
net/bluetooth/rfcomm/sock.c +8 -1
@@ -180,6 +180,8 @@ static void rfcomm_sock_cleanup_listen(swhile ((sk =bt_accept_dequeue (parent,NULL ))) {rfcomm_sock_close (sk);rfcomm_sock_kill (sk); +/* Drop the reference handed back by bt_accept_dequeue(). */ +sock_put (sk); } parent->sk_state =BT_CLOSED ;
@@ -496,8 +498,13 @@ static int rfcomm_sock_accept(struct soc } nsk =bt_accept_dequeue (sk, newsock); -if (nsk) +if (nsk) { +/* Drop the bridging ref from bt_accept_dequeue(); +* the grafted socket keeps nsk alive from here. +*/ +sock_put (nsk);break ; + }if (!timeo) { err = -EAGAIN ;
net/bluetooth/sco.c +8 -1
@@ -433,6 +433,8 @@ static void sco_sock_cleanup_listen(struwhile ((sk =bt_accept_dequeue (parent,NULL ))) {sco_sock_close (sk);sco_sock_kill (sk); +/* Drop the reference handed back by bt_accept_dequeue(). */ +sock_put (sk); } parent->sk_state =BT_CLOSED ;
@@ -705,8 +707,13 @@ static int sco_sock_accept(struct socket } ch =bt_accept_dequeue (sk, newsock); -if (ch) +if (ch) { +/* Drop the bridging ref from bt_accept_dequeue(); +* the grafted socket keeps ch alive from here. +*/ +sock_put (ch);break ; + }if (!timeo) { err = -EAGAIN ;
Greg Kroah-Hartman
maintainerPATCH 63/272 Bluetooth: ISO: drop ISO_END frames received without prior ISO_START
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
commit 84c24fb151fc1179355296d7ff29129ac7c42129 upstream.
ISO data PDUs carry a packet-boundary flag indicating START, CONT, END or SINGLE. The ISO_CONT branch of iso_recv() guards against a missing ISO_START by checking conn->rx_len before touching conn->rx_skb, but ISO_END does not.
If a peer sends an ISO_END as the first packet on a fresh ISO connection, conn->rx_skb is still NULL and conn->rx_len is zero, so skb_put(conn->rx_skb, ...) dereferences NULL and oopses. For BIS, where receivers sync to a broadcaster without pairing, any broadcaster on the air can trigger this.
Mirror the ISO_CONT check at the top of ISO_END so a stray end fragment is logged and dropped instead of crashing the host.
--- net/bluetooth/iso.c | 5 +++++ 1 file changed, 5 insertions(+)
net/bluetooth/iso.c +5 -0
@@ -2319,6 +2319,11 @@ void iso_recv(struct hci_conn *hcon, strbreak ;case ISO_END : +if (!conn->rx_len) { +BT_ERR ("Unexpected end frame (len %d)" , skb->len); + goto drop; + } +skb_copy_from_linear_data (skb,skb_put (conn->rx_skb, skb->len), skb->len); conn->rx_len -= skb->len;
Greg Kroah-Hartman
maintainerPATCH 64/272 Bluetooth: bnep: Fix UAF read of dev->name
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn <[email protected]>
commit 59e932ded949fa6f0340bf7c6d7818f962fa4fd2 upstream.
bnep_add_connection() needs to keep holding the bnep_session_sem while reading dev->name (just like bnep_get_connlist() does); otherwise the bnep_session() thread can concurrently free the net_device, which can for example be triggered by a concurrent bnep_del_connection().
(This UAF is fairly uninteresting from a security perspective; calling bnep_add_connection() requires passing a capable(CAP_NET_ADMIN) check. It also requires completely tearing down a netdev during a fairly tight race window.)
--- net/bluetooth/bnep/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/bnep/core.c +1 -1
@@ -638,8 +638,8 @@ int bnep_add_connection(struct bnep_conn goto failed; } -up_write (&bnep_session_sem);strcpy (req->device, dev->name); +up_write (&bnep_session_sem);return 0 ; failed:
Greg Kroah-Hartman
maintainerPATCH 65/272 Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mingyu Wang <[email protected]>
commit c1bb9336ae6b54a5f6a353c4bd4ed9a4307e429b upstream.
Vulnerabilities leading to Use-After-Free (UAF) and Null Pointer Dereference (NPD) conditions were observed in the lifecycle management of hci_uart.
The primary issue arises because the workqueues (init_ready and write_work) are only flushed/cancelled if the HCI_UART_PROTO_READY flag is set during TTY close. If a hangup occurs before setup completes, hci_uart_tty_close() skips the teardown of these workqueues and proceeds to free the hu struct. When the scheduled work executes later, it blindly dereferences the freed hu struct.
Furthermore, several data races and UAFs were identified in the teardown sequence:
1. Calling hci_uart_flush() from hci_uart_close() without effectively disabling write_work causes a race condition where both can concurrently double-free hu->tx_skb. This happens because protocol timers can concurrently invoke hci_uart_tx_wakeup() and requeue write_work.
2. Calling hci_free_dev(hdev) before hu->proto->close(hu) causes a UAF when vendor specific protocol close callbacks dereference hu->hdev.
3. In the initialization error paths, failing to take the proto_lock write lock before clearing PROTO_READY leads to races with active readers. Additionally, hci_uart_tty_receive() accesses hu->hdev outside the read lock, leading to UAFs if the initialization error path frees hdev concurrently.
Fix these synchronization and lifecycle issues by:
1. Re-ordering hci_uart_tty_close() to clear HCI_UART_PROTO_READY first, followed immediately by a cancel_work_sync(&hu->write_work). Clearing the flag locks out concurrent protocol timers from successfully invoking hci_uart_tx_wakeup(), effectively rendering the cancellation permanent and preventing the tx_skb double-free.
2. Note: Clearing PROTO_READY early causes hci_uart_close() to skip hu->proto->flush(). This is perfectly safe in the tty_close path because hu->proto->close() executes shortly after, which intrinsically purges all protocol SKB queues and tears down the state.
3. Relocating hu->proto->close(hu) strictly prior to hci_free_dev(hdev) across all close and error paths to prevent vendor-level UAFs.
4. Moving the hdev->stat.byte_rx increment in hci_uart_tty_receive() inside the proto_lock read-side critical section to safely synchronize with device unregistration.
5. Adding cancel_work_sync(&hu->write_work) to hci_uart_close() to safely flush the workqueue before hci_uart_flush() is invoked via the HCI core.
6. Utilizing cancel_work_sync() instead of disable_work_sync() across all paths to prevent permanently breaking user-space retry capabilities.
--- drivers/bluetooth/hci_ldisc.c | 48 +++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-)
drivers/bluetooth/hci_ldisc.c +40 -8
@@ -194,7 +194,15 @@ void hci_uart_init_work(struct work_stru err =hci_register_dev (hu->hdev);if (err <0 ) {BT_ERR ("Can't register HCI device" ); + +percpu_down_write (&hu->proto_lock);clear_bit (HCI_UART_PROTO_READY , &hu->flags); +percpu_up_write (&hu->proto_lock); + +/* Safely cancel work after clearing flags */ +cancel_work_sync (&hu->write_work); + +/* Close protocol before freeing hdev */ hu->proto->close (hu); hdev = hu->hdev; hu->hdev =NULL ;
@@ -263,8 +271,12 @@ static int hci_uart_open(struct hci_dev/* Close device */ static int hci_uart_close (struct hci_dev *hdev) { +struct hci_uart *hu =hci_get_drvdata (hdev); +BT_DBG ("hdev %p" , hdev); +cancel_work_sync (&hu->write_work); +hci_uart_flush (hdev); hdev->flush =NULL ;return 0 ;
@@ -531,6 +543,7 @@ static void hci_uart_tty_close(struct tt {struct hci_uart *hu = tty->disc_data;struct hci_dev *hdev; +bool proto_ready;BT_DBG ("tty %p" , tty);
@@ -540,24 +553,38 @@ static void hci_uart_tty_close(struct ttif (!hu)return ; - hdev = hu->hdev; -if (hdev) -hci_uart_close (hdev); +/* Wait for init_ready to finish to prevent registration races */ +cancel_work_sync (&hu->init_ready); -if (test_bit (HCI_UART_PROTO_READY , &hu->flags)) { + proto_ready =test_bit (HCI_UART_PROTO_READY , &hu->flags); +if (proto_ready) {percpu_down_write (&hu->proto_lock);clear_bit (HCI_UART_PROTO_READY , &hu->flags);percpu_up_write (&hu->proto_lock); + } -cancel_work_sync (&hu->init_ready); -cancel_work_sync (&hu->write_work); +/* +* Unconditionally cancel write_work AFTER clearing PROTO_READY. +* This ensures that concurrent protocol timers cannot requeue +* write_work via hci_uart_tx_wakeup(), permanently preventing +* double-free races and UAFs. +*/ +cancel_work_sync (&hu->write_work); + + hdev = hu->hdev; +if (hdev) +hci_uart_close (hdev);/* proto->flush is safely skipped */ +if (proto_ready) {if (hdev) {if (test_bit (HCI_UART_REGISTERED , &hu->flags))hci_unregister_dev (hdev); -hci_free_dev (hdev); } +/* Close protocol before freeing hdev (intrinsically purges queues) */ hu->proto->close (hu); + +if (hdev) +hci_free_dev (hdev); }clear_bit (HCI_UART_PROTO_SET , &hu->flags);
@@ -625,11 +652,12 @@ static void hci_uart_tty_receive(struct* tty caller */ hu->proto->recv (hu, data, count); -percpu_up_read (&hu->proto_lock);if (hu->hdev) hu->hdev->stat.byte_rx += count; +percpu_up_read (&hu->proto_lock); +tty_unthrottle (tty); }
@@ -695,6 +723,10 @@ static int hci_uart_register_dev(structpercpu_down_write (&hu->proto_lock);clear_bit (HCI_UART_PROTO_INIT , &hu->flags);percpu_up_write (&hu->proto_lock); +/* Cancel work after clearing flags */ +cancel_work_sync (&hu->write_work); + +/* Close protocol before freeing hdev */ hu->proto->close (hu); hu->hdev =NULL ;hci_free_dev (hdev);
Greg Kroah-Hartman
maintainerPATCH 66/272 Bluetooth: L2CAP: ecred_reconfigure: send packed pdu, not stack pointer
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 3374ef8cf99368a40f7efd51a2a375a4c5dc6f0d upstream.
Commit 1c08108f3014 ("Bluetooth: L2CAP: Avoid -Wflex-array-member-not-at-end warnings") converted the on-stack request PDU in l2cap_ecred_reconfigure() from an explicit packed struct to DEFINE_RAW_FLEX(), but did not adjust the size and source-pointer arguments to l2cap_send_cmd():
- struct {
- struct l2cap_ecred_reconf_req req;
- __le16 scid;
- } pdu;
+ DEFINE_RAW_FLEX(struct l2cap_ecred_reconf_req, pdu, scid, 1);
...
l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
sizeof(pdu), &pdu);After the conversion, DEFINE_RAW_FLEX() expands to declare an anonymous union pdu_u plus a local pointer "pdu" pointing at it. Therefore:
- sizeof(pdu) is now sizeof(struct l2cap_ecred_reconf_req *) = 8 on
64-bit (4 on 32-bit), not the 6 bytes of (mtu, mps, scid[1]).
- &pdu is the address of the local pointer's stack storage, not the address of the request payload.
l2cap_send_cmd() forwards (data, count) to l2cap_build_cmd(), which calls skb_put_data(skb, data, count). The L2CAP_ECRED_RECONFIGURE_REQ packet body therefore contains 8 bytes copied from the kernel stack starting at &pdu -- the 8 bytes overlap the pdu pointer's value, leaking a kernel stack address to the paired Bluetooth peer. The intended (mtu, mps, scid) fields are not transmitted at all, so the peer rejects the request as malformed and the L2CAP_ECRED_RECONFIGURE feature itself has been broken for the local-side initiator since the introducing commit landed.
The sibling site l2cap_ecred_conn_req() in the same commit was converted correctly (sizeof(*pdu) + len, pdu); only this site was missed.
Restore the original semantics: pass the full flex-struct size via struct_size(pdu, scid, 1) and the pdu pointer (the struct address) as the source.
Validated on a stock 7.0-based host kernel via the real call path:setsockopt(SOL_BLUETOOTH, BT_RCVMTU, ...) on a BT_CONNECTED L2CAP_MODE_EXT_FLOWCTL socket emits an L2CAP_ECRED_RECONFIGURE_REQ whose body is 8 bytes (the on-stack pdu local's value) rather than the expected 6. Three captures from fresh socket / fresh hciemu peer on the same host -- low bytes vary per call, high 0xffff confirms a kernel virtual address (KASLR-randomised stack slot, not a fixed string):
RECONF_REQ body (ident=0x02 len=8): 42 fb 54 af 0e ca ff ff RECONF_REQ body (ident=0x02 len=8): 52 3d 2e af 0e ca ff ff RECONF_REQ body (ident=0x02 len=8): b2 fc 5b af 0e ca ff ff
After this patch the body is 6 bytes carrying the expected little-endian (mtu, mps, scid).
--- net/bluetooth/l2cap_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +1 -1
@@ -7199,7 +7199,7 @@ static void l2cap_ecred_reconfigure(stru chan->ident =l2cap_get_ident (conn);l2cap_send_cmd (conn, chan->ident,L2CAP_ECRED_RECONF_REQ , -sizeof (pdu), &pdu); +struct_size (pdu, scid,1 ), pdu); }int l2cap_chan_reconfigure (struct l2cap_chan *chan,__u16 mtu)
Greg Kroah-Hartman
maintainerPATCH 67/272 Bluetooth: MGMT: validate Add Extended Advertising Data length
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit d3f7d17960ed50df3a6709c5158caff989c8c905 upstream.
MGMT_OP_ADD_EXT_ADV_DATA is registered as a variable-length command, with MGMT_ADD_EXT_ADV_DATA_SIZE as the fixed header size. The handler then uses cp->adv_data_len and cp->scan_rsp_len to validate and copy cp->data, but it never checks that those bytes are part of the mgmt command payload.
A short command can therefore make add_ext_adv_data() pass an out-of-bounds pointer into tlv_data_is_valid(). If the bytes beyond the command buffer are addressable, they can also be copied into the advertising instance as scan response data, where the caller can read them back via MGMT_OP_GET_ADV_INSTANCE. The trigger requires CAP_NET_ADMIN in the initial user namespace; KASAN reports an 8-byte slab-out-of-bounds read.
Reject commands whose length does not match the fixed header plus both advertising data lengths before parsing cp->data.
--- net/bluetooth/mgmt.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/bluetooth/mgmt.c +6 -0
@@ -9193,9 +9193,15 @@ static int add_ext_adv_data(struct sockstruct adv_info *adv_instance;int err =0 ;struct mgmt_pending_cmd *cmd; +u16 expected_len;BT_DBG ("%s" , hdev->name); + expected_len =struct_size (cp, data, cp->adv_data_len + cp->scan_rsp_len); +if (expected_len != data_len) +return mgmt_cmd_status (sk, hdev->id,MGMT_OP_ADD_EXT_ADV_DATA , +MGMT_STATUS_INVALID_PARAMS ); +hci_dev_lock (hdev); adv_instance =hci_find_adv_instance (hdev, cp->instance);
Greg Kroah-Hartman
maintainerPATCH 68/272 Bluetooth: serialize accept_q access
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiexun Wang <[email protected]>
commit e83f5e24da741fa9405aeeff00b08c5ee7c37b88 upstream.
bt_sock_poll() walks the accept queue without synchronization, while child teardown can unlink the same socket and drop its last reference. The unsynchronized accept queue walk has existed since the initial Bluetooth import.
Protect accept_q with a dedicated lock for queue updates and polling. Also rework bt_accept_dequeue() to take temporary child references under the queue lock before dropping it and locking the child socket.
--- include/net/bluetooth/bluetooth.h | 1 net/bluetooth/af_bluetooth.c | 87 ++++++++++++++++++++++++++++---------- 2 files changed, 66 insertions(+), 22 deletions(-)
include/net/bluetooth/bluetooth.h +1 -0
@@ -380,6 +380,7 @@ void baswap(bdaddr_t *dst, const bdaddr_struct bt_sock {struct sock sk;struct list_head accept_q; +spinlock_t accept_q_lock;/* protects accept_q */ struct sock *parent;unsigned long flags;void (*skb_msg_name)(struct sk_buff *,void *,int *);
net/bluetooth/af_bluetooth.c +65 -22
163 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 69/272 phonet/pep: disable BH around forwarded sk_receive_skb()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zijing Yin <[email protected]>
commit dbc81608e3a653dea6cf403f20cae35468b8ab9c upstream.
The networking receive path is usually run from softirq context, but protocols that take the socket lock may have packets stored in the backlog and processed later from process context. In that case release_sock() -> __release_sock() drops the slock with spin_unlock_bh() and then calls sk->sk_backlog_rcv() with bottom halves enabled.
Typical sk_backlog_rcv handlers process the socket whose backlog is being drained, so the BH state at entry is irrelevant for the slocks they touch. pep_do_rcv() is different: when the inbound skb targets an existing PEP pipe, it forwards the skb to a different *child* socket via sk_receive_skb(). That helper takes the child slock with bh_lock_sock_nested(), which is just spin_lock_nested() and assumes BH is already off. The same child slock therefore ends up acquired with BH on (process path) and with BH off (softirq path):
process context softirq context
--------------- ---------------
release_sock(listener) __netif_receive_skb()
__release_sock() phonet_rcv()
spin_unlock_bh() __sk_receive_skb(listener)
[BH now ENABLED] [BH already disabled]
sk_backlog_rcv: sk_backlog_rcv: pep_do_rcv() pep_do_rcv()
sk_receive_skb(child) sk_receive_skb(child)
bh_lock_sock_nested(child) bh_lock_sock_nested(child)
=> SOFTIRQ-ON-W => IN-SOFTIRQ-W
Lockdep flags this as inconsistent lock state, and it can become a real self-deadlock if a softirq on the same CPU tries to receive to the same child socket while its slock is held in the BH-enabled path:
WARNING: inconsistent lock state
inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
(slock-AF_PHONET/1){+.?.}-{3:3}, at: __sk_receive_skb+0x1cf/0x900
__sk_receive_skb net/core/sock.c:563
sk_receive_skb include/net/sock.h:2022 [inline]
pep_do_rcv net/phonet/pep.c:675
sk_backlog_rcv include/net/sock.h:1190
__release_sock net/core/sock.c:3216
release_sock net/core/sock.c:3815
pep_sock_accept net/phonet/pep.c:879Wrap the forwarded sk_receive_skb() in local_bh_disable() / local_bh_enable() so the child slock is always acquired with BH off. local_bh_disable() nests safely on the softirq path.
Discovered via in-house syzkaller fuzzing; the same root cause also on the linux-6.1.y syzbot dashboard as extid 44f0626dd6284f02663c. Reproduced under KASAN + LOCKDEP + PROVE_LOCKING, reproducer:
https://pastebin.com/A3t8xzCR
--- net/phonet/pep.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
net/phonet/pep.c +17 -2
@@ -671,8 +671,23 @@ static int pep_do_rcv(struct sock *sk, s/* Look for an existing pipe handle */ sknode =pep_find_pipe (&pn->hlist, &dst, pipe_handle); -if (sknode) -return sk_receive_skb (sknode, skb,1 ); +if (sknode) { +int rc; + +/* pep_do_rcv() runs from two contexts: from softirq via +* phonet_rcv() -> __sk_receive_skb() with BH disabled, +* and from process context via +* release_sock() -> __release_sock(), which drops +* the listener slock with spin_unlock_bh() before draining +* the backlog. The child pipe slock is taken below via +* bh_lock_sock_nested(), which does not itself disable BH, so +* disable BH here to keep both acquire contexts consistent. +*/ +local_bh_disable (); + rc =sk_receive_skb (sknode, skb,1 ); +local_bh_enable (); +return rc; + }switch (hdr->message_id) {case PNS_PEP_CONNECT_REQ :
Greg Kroah-Hartman
maintainerPATCH 70/272 net: bcmgenet: keep RBUF EEE/PM disabled
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Buchwitz <[email protected]>
commit 9a1730245e416d11ad5c0f2c100061d61cc43f60 upstream.
Setting RBUF_EEE_EN | RBUF_PM_EN in RBUF_ENERGY_CTRL breaks the RX path on GENET hardware once MAC EEE becomes active. RX traffic stops flowing while the link stays up and the usual descriptor/RX error counters remain quiet. In that state the MAC still accepts frames (rbuf_ovflow_cnt keeps climbing) but RBUF no longer forwards them to DMA, so rx_packets is no longer incremented at the netdev level. On some boards the corruption ends up as a paging fault in skb_release_data via bcmgenet_rx_poll on an LPI exit.
Reproduced on Pi 4B (BCM2711 + BCM54213PE) and confirmed by Florian Fainelli on an internal Broadcom 4908-family board with the same crash signature. RBUF_PM_EN is not publicly documented.
This shows up more often now that phy_support_eee() enables EEE by default, but it also affects older kernels as soon as TX LPI is turned on via ethtool, so it is not specific to recent changes.
Always clear RBUF_EEE_EN | RBUF_PM_EN in bcmgenet_eee_enable_set so the bits stay off across resets. UMAC and TBUF setup is left alone so TX-side EEE keeps working.
--- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +4 -5
@@ -1325,13 +1325,12 @@ void bcmgenet_eee_enable_set(struct net_ reg &= ~(TBUF_EEE_EN |TBUF_PM_EN );bcmgenet_writel (reg, priv->base + off); -/* Do the same for thing for RBUF */ +/* RBUF EEE/PM can break the RX path on GENET. Keep it disabled. */ reg =bcmgenet_rbuf_readl (priv,RBUF_ENERGY_CTRL ); -if (enable) - reg |=RBUF_EEE_EN |RBUF_PM_EN ; -else +if (reg & (RBUF_EEE_EN |RBUF_PM_EN )) { reg &= ~(RBUF_EEE_EN |RBUF_PM_EN ); -bcmgenet_rbuf_writel (priv, reg,RBUF_ENERGY_CTRL ); +bcmgenet_rbuf_writel (priv, reg,RBUF_ENERGY_CTRL ); + }if (!enable && priv->clk_eee_enabled) {clk_disable_unprepare (priv->clk_eee);
Greg Kroah-Hartman
maintainerPATCH 71/272 net: ifb: report ethtool stats over num_tx_queues
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 5db89c99566fc4728cc92e941d8e1975711e24b5 upstream.
ifb_dev_init() allocates dp->tx_private to dev->num_tx_queues entries via kzalloc_objs(*txp, dev->num_tx_queues). Both IFB per-queue RX and TX stats live in those entries: ifb_xmit() updates txp->rx_stats using the skb queue mapping, ifb_ri_tasklet() updates txp->tx_stats, and ifb_stats64() aggregates both over dev->num_tx_queues.
The ethtool stats callbacks instead size and walk the per-queue stats with dev->real_num_rx_queues and dev->real_num_tx_queues. With an asymmetric device where the RX queue count exceeds the TX queue count, for example:
ip link add name ifb10 numtxqueues 1 numrxqueues 8 type ifb ethtool -S ifb10
ifb_get_ethtool_stats() indexes past the tx_private allocation and copies adjacent slab data through ETHTOOL_GSTATS.
Use dev->num_tx_queues consistently for the stats strings, the stats count, and the stats data walks. This reports one RX stats group and one TX stats group for each backing ifb_q_private entry, which is the queue set IFB can actually populate.
Reproduced under UML+KASAN at v7.1-rc2:
BUG: KASAN: slab-out-of-bounds in ifb_fill_stats_data+0x3c/0xae Read of size 8 at addr 0000000062dbd228 by task ethtool/36 ifb_fill_stats_data+0x3c/0xae ifb_get_ethtool_stats+0xc0/0x129 __dev_ethtool+0x1ca5/0x363c dev_ethtool+0x123/0x1b3 dev_ioctl+0x56c/0x744 sock_do_ioctl+0x15f/0x1b2 sock_ioctl+0x4d5/0x50a sys_ioctl+0xd8b/0xde9
With the patch applied, the same UML+KASAN repro is silent and ethtool -S ifb10 reports only the stats backed by the single allocated tx_private entry.
--- drivers/net/ifb.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/net/ifb.c +5 -6
@@ -211,12 +211,12 @@ static void ifb_get_strings(struct net_dswitch (stringset) {case ETH_SS_STATS : -for (i =0 ; i < dev->real_num_rx_queues; i++) +for (i =0 ; i < dev->num_tx_queues; i++)for (j =0 ; j <IFB_Q_STATS_LEN ; j++)ethtool_sprintf (&p,"rx_queue_%u_%.18s" , i, ifb_q_stats_desc[j].desc); -for (i =0 ; i < dev->real_num_tx_queues; i++) +for (i =0 ; i < dev->num_tx_queues; i++)for (j =0 ; j <IFB_Q_STATS_LEN ; j++)ethtool_sprintf (&p,"tx_queue_%u_%.18s" , i, ifb_q_stats_desc[j].desc);
@@ -229,8 +229,7 @@ static int ifb_get_sset_count(struct net {switch (sset) {case ETH_SS_STATS : -return IFB_Q_STATS_LEN * (dev->real_num_rx_queues + - dev->real_num_tx_queues); +return IFB_Q_STATS_LEN * dev->num_tx_queues *2 ;default :return -EOPNOTSUPP ; }
@@ -262,12 +261,12 @@ static void ifb_get_ethtool_stats(structstruct ifb_q_private *txp;int i; -for (i =0 ; i < dev->real_num_rx_queues; i++) { +for (i =0 ; i < dev->num_tx_queues; i++) { txp = dp->tx_private + i;ifb_fill_stats_data (&data, &txp->rx_stats); } -for (i =0 ; i < dev->real_num_tx_queues; i++) { +for (i =0 ; i < dev->num_tx_queues; i++) { txp = dp->tx_private + i;ifb_fill_stats_data (&data, &txp->tx_stats); }
Greg Kroah-Hartman
maintainerPATCH 72/272 net: pse-pd: fix sign on -ENOENT check in of_load_pse_pis()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Jelonek <[email protected]>
commit 33d35975cbead3fa6b738ee57e5e45e14fbe0886 upstream.
of_count_phandle_with_args() returns the count on success and a negative errno on failure, including -ENOENT when the "pairsets" property is absent. The existing comparison in of_load_pse_pis() checks against ENOENT (positive 2) instead of -ENOENT, so the branch is taken for any error return: legitimate DTs that omit "pairsets" trigger a spurious "wrong number of pairsets" error and probe fails with -EINVAL.
Compare against -ENOENT so a missing "pairsets" property is correctly treated as "this PI has no pairsets, continue".
--- drivers/net/pse-pd/pse_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/pse-pd/pse_core.c +1 -1
@@ -184,7 +184,7 @@ static int of_load_pse_pis(struct pse_co ret =of_load_pse_pi_pairsets (node, &pi, ret);if (ret) goto out; - }else if (ret !=ENOENT ) { + }else if (ret != -ENOENT ) {dev_err (pcdev->dev,"error: wrong number of pairsets. Should be 1 or 2, got %d (%pOF)\n" , ret, node);
Greg Kroah-Hartman
maintainerPATCH 73/272 netfilter: ip6t_hbh: reject oversized option lists
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhengchuan Liang <[email protected]>
commit 4322dcde6b4173c2d8e8e6118ed290794263bcc8 upstream.
struct ip6t_opts stores at most IP6T_OPTS_OPTSNR option descriptors, but hbh_mt6_check() does not reject larger optsnr values supplied from userspace.
Validate optsnr in the rule setup path so only match data that fits the fixed-size opts array can be installed. This follows the existing xtables pattern of rejecting invalid user-provided counts in checkentry() and keeps the packet matching path unchanged.
struct ip6t_opts has a fixed opts[IP6T_OPTS_OPTSNR] array, where IP6T_OPTS_OPTSNR is 16, then off-by-one array access is possible:
[ 137.924693][ T8692] UBSAN: array-index-out-of-bounds in ../net/ipv6/netfilter/ip6t_hbh.c:110:29 [ 137.926167][ T8692] index 16 is out of range for type '__u16 [16]'
--- net/ipv6/netfilter/ip6t_hbh.c | 4 ++++ 1 file changed, 4 insertions(+)
net/ipv6/netfilter/ip6t_hbh.c +4 -0
@@ -168,6 +168,10 @@ static int hbh_mt6_check(const struct xtpr_debug ("unknown flags %X\n" , optsinfo->invflags);return -EINVAL ; } +if (optsinfo->optsnr >IP6T_OPTS_OPTSNR ) { +pr_debug ("too many supported opts specified\n" ); +return -EINVAL ; + }if (optsinfo->flags &IP6T_OPTS_NSTRICT ) {pr_debug ("Not strict - not implemented" );
Greg Kroah-Hartman
maintainerPATCH 74/272 netfilter: nf_queue: hold bridge skb->dev while queued
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoze Xie <[email protected]>
commit e196115ec330a18de415bdb9f5071aa9f08e53ce upstream.
br_pass_frame_up() rewrites skb->dev from the ingress port to the bridge master before queueing bridge LOCAL_IN packets. NFQUEUE only holds references on state.in/out and bridge physdevs, so a queued bridge packet can retain a freed bridge master in skb->dev until reinjection.
When the verdict is reinjected later, br_netif_receive_skb() re-enters the receive path with skb->dev still pointing at the freed bridge master, triggering a use-after-free.
Store skb->dev in the queue entry, hold a reference on it for the queue lifetime, and use the saved device when dropping queued packets during NETDEV_DOWN handling.
--- include/net/netfilter/nf_queue.h | 1 + net/netfilter/nf_queue.c | 4 +++- net/netfilter/nfnetlink_queue.c | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-)
include/net/netfilter/nf_queue.h +1 -0
@@ -14,6 +14,7 @@ struct nf_queue_entry {struct list_head list;struct rhash_head hash_node;struct sk_buff *skb; +struct net_device *skb_dev;unsigned int id;unsigned int hook_index;/* index in hook_entries->hook[] */ #if IS_ENABLED (CONFIG_BRIDGE_NETFILTER )
net/netfilter/nf_queue.c +3 -1
@@ -60,6 +60,7 @@ static void nf_queue_entry_release_refs(struct nf_hook_state *state = &entry->state;/* Release those devices we held, or Alexey will kill me. */ +dev_put (entry->skb_dev);dev_put (state->in);dev_put (state->out);if (state->sk)
@@ -101,6 +102,7 @@ bool nf_queue_entry_get_refs(struct nf_qif (state->sk && !refcount_inc_not_zero (&state->sk->sk_refcnt))return false; +dev_hold (entry->skb_dev);dev_hold (state->in);dev_hold (state->out);
@@ -201,11 +203,11 @@ static int __nf_queue(struct sk_buff *sk *entry = (struct nf_queue_entry ) { .skb = skb, + .skb_dev = skb->dev, .state = *state, .hook_index = index, .size =sizeof (*entry) + route_key_size, }; -__nf_queue_entry_init_physdevs (entry);if (!nf_queue_entry_get_refs (entry)) {
net/netfilter/nfnetlink_queue.c +2 -0
@@ -1196,6 +1196,8 @@ dev_cmp(struct nf_queue_entry *entry, unif (physinif == ifindex || physoutif == ifindex)return 1 ;#endif +if (entry->skb_dev && entry->skb_dev->ifindex == ifindex) +return 1 ;if (entry->state.in)if (entry->state.in->ifindex == ifindex)return 1 ;
Greg Kroah-Hartman
maintainerPATCH 75/272 netfilter: ipset: stop hash:* range iteration at end
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nan Li <[email protected]>
commit 0d3a282ab5f165fc207ff49ea5b6ad8f54616bd6 upstream.
The following hash set variants:
hash:ip,mark
hash:ip,port
hash:ip,port,ip
hash:ip,port,net
iterate IPv4 ranges with a 32-bit iterator.
The iterator must stop once the last address in the requested range has been processed. Advancing it once more can move the traversal state past the end of the request, so a later retry may continue from an unintended position.
Handle the iterator increment explicitly at the end of the loop and stop once the upper bound has been processed. This keeps the existing retry behaviour intact for valid ranges while preventing traversal from continuing past the original boundary.
--- net/netfilter/ipset/ip_set_hash_ipmark.c | 6 +++++- net/netfilter/ipset/ip_set_hash_ipport.c | 5 ++++- net/netfilter/ipset/ip_set_hash_ipportip.c | 5 ++++- net/netfilter/ipset/ip_set_hash_ipportnet.c | 5 ++++- 4 files changed, 17 insertions(+), 4 deletions(-)
net/netfilter/ipset/ip_set_hash_ipmark.c +5 -1
@@ -150,7 +150,7 @@ hash_ipmark4_uadt(struct ip_set *set, stif (retried) ip =ntohl (h->next.ip); -for (; ip <= ip_to; ip++, i++) { +for (; ip <= ip_to; i++) { e.ip =htonl (ip);if (i >IPSET_MAX_RANGE ) {hash_ipmark4_data_next (&h->next, &e);
@@ -162,6 +162,10 @@ hash_ipmark4_uadt(struct ip_set *set, streturn ret; ret =0 ; + +if (ip == ip_to) +break ; + ip++; }return ret; }
net/netfilter/ipset/ip_set_hash_ipport.c +4 -1
@@ -186,7 +186,7 @@ hash_ipport4_uadt(struct ip_set *set, stif (retried) ip =ntohl (h->next.ip); -for (; ip <= ip_to; ip++) { +for (; ip <= ip_to;) { p = retried && ip ==ntohl (h->next.ip) ?ntohs (h->next.port) : port;for (; p <= port_to; p++, i++) {
@@ -203,6 +203,9 @@ hash_ipport4_uadt(struct ip_set *set, st ret =0 ; } +if (ip == ip_to) +break ; + ip++; }return ret; }
net/netfilter/ipset/ip_set_hash_ipportip.c +4 -1
@@ -182,7 +182,7 @@ hash_ipportip4_uadt(struct ip_set *set,if (retried) ip =ntohl (h->next.ip); -for (; ip <= ip_to; ip++) { +for (; ip <= ip_to;) { p = retried && ip ==ntohl (h->next.ip) ?ntohs (h->next.port) : port;for (; p <= port_to; p++, i++) {
@@ -199,6 +199,9 @@ hash_ipportip4_uadt(struct ip_set *set, ret =0 ; } +if (ip == ip_to) +break ; + ip++; }return ret; }
net/netfilter/ipset/ip_set_hash_ipportnet.c +4 -1
@@ -274,7 +274,7 @@ hash_ipportnet4_uadt(struct ip_set *set, p = port; ip2 = ip2_from; } -for (; ip <= ip_to; ip++) { +for (; ip <= ip_to;) { e.ip =htonl (ip);for (; p <= port_to; p++) { e.port =htons (p);
@@ -298,6 +298,9 @@ hash_ipportnet4_uadt(struct ip_set *set, ip2 = ip2_from; } p = port; +if (ip == ip_to) +break ; + ip++; }return ret; }
Greg Kroah-Hartman
maintainerPATCH 76/272 netfilter: nft_inner: Fix IPv6 inner_thoff desync
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
commit b6a91f68ebfed9c38e0e9150f58a9b85da07181c upstream.
In nft_inner_parse_l2l3(), when processing inner IPv6 packets, ipv6_find_hdr() correctly computes the transport header offset traversing all extension headers, but the result is immediately overwritten with nhoff + sizeof(_ip6h) (40 bytes), which only accounts for the IPv6 base header. This creates a desync between inner_thoff (wrong — points to extension header start) and l4proto (correct — e.g., IPPROTO_TCP), enabling transport header forgery and potential firewall bypass. This issue affects stable versions from Linux 6.2.
For comparison, the normal (non-inner) IPv6 path correctly preserves ipv6_find_hdr()'s result. Removing the incorrect overwrite ensures that ipv6_find_hdr()'s calculated transport header offset is preserved, thereby fixing the desynchronization.
--- net/netfilter/nft_inner.c | 1 - 1 file changed, 1 deletion(-)
net/netfilter/nft_inner.c +0 -1
@@ -156,7 +156,6 @@ static int nft_inner_parse_l2l3(const streturn -1 ;if (fragoff ==0 ) { - thoff = nhoff +sizeof (_ip6h); ctx->flags |=NFT_PAYLOAD_CTX_INNER_TH ; ctx->inner_thoff = thoff; ctx->l4proto = l4proto;
Greg Kroah-Hartman
maintainerPATCH 77/272 sched_ext: Fix missing warning in scx_set_task_state() default case
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuele Mariotti <[email protected]>
[ Upstream commit b905ee77d5f557a83a485b4146210f54f13365fc ]
In scx_set_task_state(), the default case was setting the warn flag, but then returning immediately. This is problematic because the only purpose of the warn flag is to trigger WARN_ONCE, but the early return prevented it from ever firing, leaving invalid task states undetected and untraced.
To fix this, a WARN_ONCE call is now added directly in the default case.
The fix addresses two aspects:
- Guarantees the invalid task states are properly logged and traced.
- Provides a distinct warning message ("sched_ext: Invalid task state") specifically for states outside the defined scx_task_state enum values, making it easier to distinguish from other transition warnings.
This ensures proper detection and reporting of invalid states.
Stable-dep-of: 9a415cc53711 ("sched_ext: Avoid UAF in scx_root_enable_workfn() init failure path")
--- kernel/sched/ext.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/sched/ext.c +2 -1
@@ -3637,7 +3637,8 @@ static void scx_set_task_state(struct ta warn = prev_state !=SCX_TASK_READY ;break ;default : - warn = true; +WARN_ONCE (1 ,"sched_ext: Invalid task state %d -> %d for %s[%d]" , + prev_state, state, p->comm, p->pid);return ; }
Greg Kroah-Hartman
maintainerPATCH 78/272 sched_ext: Avoid UAF in scx_root_enable_workfn() init failure path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 9a415cc53711f2238e0f0ca8a6bcc796c003b127 ]
In scx_root_enable_workfn(), put_task_struct(p) is called before scx_error() dereferences p->comm and p->pid. If the iterator's reference is the last drop, the task is freed synchronously and the deref becomes a UAF.
Move put_task_struct() past scx_error().
--- kernel/sched/ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/ext.c +1 -1
@@ -5406,11 +5406,11 @@ static void scx_ops_enable_workfn(struct ret =scx_ops_init_task (p,task_group (p), false);if (ret) { -put_task_struct (p);scx_task_iter_relock (&sti);scx_task_iter_stop (&sti);scx_ops_error ("ops.init_task() failed (%d) for %s[%d]" , ret, p->comm, p->pid); +put_task_struct (p); goto err_disable_unlock_all; }
Greg Kroah-Hartman
maintainerPATCH 79/272 cgroup/cpuset: Reset DL migration state on can_attach() failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guopeng Zhang <[email protected]>
[ Upstream commit 4a39eda5fdd867fc39f3c039714dd432cee00268 ]
cpuset_can_attach() accumulates temporary SCHED_DEADLINE migration state in the destination cpuset while walking the taskset.
If a later task_can_attach() or security_task_setscheduler() check fails, cgroup_migrate_execute() treats cpuset as the failing subsystem and does not call cpuset_cancel_attach() for it. The partially accumulated state is then left behind and can be consumed by a later attach, corrupting cpuset DL task accounting and pending DL bandwidth accounting.
Reset the pending DL migration state from the common error exit when ret is non-zero. Successful can_attach() keeps the state for cpuset_attach() or cpuset_cancel_attach().
--- kernel/cgroup/cpuset.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/cgroup/cpuset.c +4 -4
@@ -2996,16 +2996,13 @@ static int cpuset_can_attach(struct cgroint cpu =cpumask_any_and (cpu_active_mask, cs->effective_cpus);if (unlikely (cpu >= nr_cpu_ids)) { -reset_migrate_dl_data (cs); ret = -EINVAL ; goto out_unlock; } ret =dl_bw_alloc (cpu, cs->sum_migrate_dl_bw); -if (ret) { -reset_migrate_dl_data (cs); +if (ret) goto out_unlock; - } } out_success:
@@ -3014,7 +3011,10 @@ out_success:* changes which zero cpus/mems_allowed. */ cs->attach_in_progress++; + out_unlock: +if (ret) +reset_migrate_dl_data (cs);mutex_unlock (&cpuset_mutex);return ret; }
Greg Kroah-Hartman
maintainerPATCH 80/272 fs/ntfs3: handle attr_set_size() errors when truncating files
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Komarov <[email protected]>
[ Upstream commit 576248a34b927e93b2fd3fff7df735ba73ad7d01 ]
If attr_set_size() fails while truncating down, the error is silently ignored and the inode may be left in an inconsistent state.
--- fs/ntfs3/file.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
fs/ntfs3/file.c +4 -8
@@ -500,8 +500,8 @@ static int ntfs_truncate(struct inode *i {struct super_block *sb = inode->i_sb;struct ntfs_inode *ni =ntfs_i (inode); -int err, dirty =0 ;u64 new_valid; +int err;if (!S_ISREG (inode->i_mode))return 0 ;
@@ -517,7 +517,6 @@ static int ntfs_truncate(struct inode *i } new_valid =ntfs_up_block (sb,min_t (u64, ni->i_valid, new_size)); -truncate_setsize (inode, new_size);ni_lock (ni);
@@ -531,22 +530,19 @@ static int ntfs_truncate(struct inode *i ni->i_valid = new_valid;ni_unlock (ni); +if (unlikely (err)) +return err; ni->std_fa |=FILE_ATTRIBUTE_ARCHIVE ;inode_set_mtime_to_ts (inode,inode_set_ctime_current (inode));if (!IS_DIRSYNC (inode)) { - dirty =1 ; +mark_inode_dirty (inode); }else { err =ntfs_sync_inode (inode);if (err)return err; } -if (dirty) -mark_inode_dirty (inode); - -/*ntfs_flush_inodes(inode->i_sb, inode, NULL);*/ -return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 81/272 l2tp: use list_del_rcu in l2tp_session_unhash
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 979c017803c40829b03acd9e5236e354b7622360 upstream.
An unprivileged local user can pin a host CPU indefinitely in l2tp_session_get_by_ifname() by issuing L2TP_CMD_SESSION_GET on L2TP_ATTR_IFNAME concurrently with L2TP_CMD_SESSION_CREATE and L2TP_CMD_SESSION_DELETE on the same tunnel. All three commands take GENL_UNS_ADMIN_PERM, so CAP_NET_ADMIN in the netns user namespace suffices; on any host that has l2tp_core loaded the trigger is reachable from a standard unshare -Urn sandbox.
l2tp_session_unhash() removes a session from tunnel->session_list with list_del_init(), but that list is walked by l2tp_session_get_by_ifname() with list_for_each_entry_rcu() under rcu_read_lock_bh(). list_del_init() leaves the deleted entry's next/prev self-pointing; a reader that has loaded the entry and then advances pos->list.next reads &session->list, container_of()s back to the same session, and list_for_each_entry_rcu() never reaches the list head. The CPU stays in strcmp() inside the walker, with BH and preemption disabled, so RCU grace periods on the host stall behind it and the wedged thread cannot be killed (SIGKILL is delivered on syscall return).
Use list_del_rcu() to match the existing list_add_rcu() in l2tp_session_register(); the deleted session remains visible to in-flight walkers with consistent next/prev pointers until kfree_rcu() in l2tp_session_free() releases it. tunnel->session_list has exactly one list_del_init() call site; the list_del_init (&session->clist) at l2tp_core.c:533 operates on the per-collision list, which is not walked under RCU. list_empty(&session->list) is not used anywhere in net/l2tp/ after the unhash point, so dropping the post-delete self-init is safe; the fix has no userspace-visible behavior change.
--- net/l2tp/l2tp_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/l2tp/l2tp_core.c +1 -1
@@ -1360,7 +1360,7 @@ static void l2tp_session_unhash(struct lspin_lock_bh (&pn->l2tp_session_idr_lock);/* Remove from the per-tunnel list */ -list_del_init (&session->list); +list_del_rcu (&session->list);/* Remove from per-net IDR */ if (tunnel->version ==L2TP_HDR_VER_3 ) {
Greg Kroah-Hartman
maintainerPATCH 82/272 qed: fix double free in qed_cxt_tables_alloc()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <[email protected]>
commit 2bccfb8476ca5f3548afbd623dc7a6980d4e77de upstream.
If one of the later PF or VF CID bitmap allocations fails, qed_cid_map_alloc() jumps to cid_map_fail and frees the previously allocated CID bitmaps before returning an error. qed_cxt_tables_alloc() then calls qed_cxt_mngr_free(), which invokes qed_cid_map_free() again.
Fix this by setting each CID bitmap pointer to NULL after bitmap_free() to avoid double free.
The bug was first flagged by an experimental analysis tool we are developing for kernel memory-management bugs while analyzing v6.13-rc1. The tool is still under development and is not yet publicly available. Manual inspection confirms that the bug is still present in v7.1-rc3.
Runtime reproduction was not attempted because exercising the failing allocation path requires device-specific setup.
--- drivers/net/ethernet/qlogic/qed/qed_cxt.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/qlogic/qed/qed_cxt.c +2 -0
@@ -1038,11 +1038,13 @@ static void qed_cid_map_free(struct qed_for (type =0 ; type <MAX_CONN_TYPES ; type++) {bitmap_free (p_mngr->acquired[type].cid_map); + p_mngr->acquired[type].cid_map =NULL ; p_mngr->acquired[type].max_count =0 ; p_mngr->acquired[type].start_cid =0 ;for (vf =0 ; vf <MAX_NUM_VFS ; vf++) {bitmap_free (p_mngr->acquired_vf[type][vf].cid_map); + p_mngr->acquired_vf[type][vf].cid_map =NULL ; p_mngr->acquired_vf[type][vf].max_count =0 ; p_mngr->acquired_vf[type][vf].start_cid =0 ; }
Greg Kroah-Hartman
maintainerPATCH 83/272 ring-buffer: Fix reporting of missed events in iterator
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt <[email protected]>
commit a254b6d13b0edd6272926674d2afc46d46e496b7 upstream.
When tracing is active while reading the trace file, if the iterator reading the buffer detects that the writer has passed the iterator head, it will reset and set a "missed events" flag. This flag is passed to the output processing to show the user that events were missed:
CPU:4 [LOST EVENTS]
The problem is that the flag is reset after it is checked in ring_buffer_iter_dropped(). But the "trace" file iterates over all the CPU ring buffers and it will check if they are dropped when figuring out which buffer to print next. This prematurely clears the missed_events flag if the CPU buffer with the missed events is not the one that is printed next.
On the iteration where the CPU buffer with the missed events is printed, the check if it had missed events would return false and the output does not show that events were missed.
Do not reset the missed_events flag when checking if there were missed events, but instead clear it when moving the iterator head to the next event.
--- kernel/trace/ring_buffer.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
kernel/trace/ring_buffer.c +3 -5
@@ -5120,6 +5120,7 @@ static void rb_iter_reset(struct ring_bu iter->head_page = cpu_buffer->reader_page; iter->head = cpu_buffer->reader_page->read; iter->next_event = iter->head; + iter->missed_events =0 ; iter->cache_reader_page = iter->head_page; iter->cache_read = cpu_buffer->read;
@@ -5735,10 +5736,7 @@ ring_buffer_peek(struct trace_buffer *bu*/ bool ring_buffer_iter_dropped (struct ring_buffer_iter *iter) { -bool ret = iter->missed_events !=0 ; - - iter->missed_events =0 ; -return ret; +return iter->missed_events !=0 ; }EXPORT_SYMBOL_GPL (ring_buffer_iter_dropped);
@@ -5900,7 +5898,7 @@ void ring_buffer_iter_advance(struct rinunsigned long flags;raw_spin_lock_irqsave (&cpu_buffer->reader_lock, flags); - + iter->missed_events =0 ;rb_advance_iter (iter);raw_spin_unlock_irqrestore (&cpu_buffer->reader_lock, flags);
Greg Kroah-Hartman
maintainerPATCH 84/272 ipv6: ioam: add NULL check for idev in ipv6_hop_ioam()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Iurman <[email protected]>
commit d4ea0dfd75011b78cebf3808f98ac4c4f51a6fb9 upstream.
Reported by Sashiko:
The function ipv6_hop_ioam() accesses __in6_dev_get(skb->dev)->cnf.ioam6_enabled without validating the returned idev pointer. Because addrconf_ifdown() can concurrently clear dev->ip6_ptr via RCU, __in6_dev_get() can return NULL during interface teardown, which could cause a NULL pointer dereference when processing an IOAM Hop-by-Hop option.
Let's add a check and use SKB_DROP_REASON_IPV6DISABLED accordingly.
--- net/ipv6/exthdrs.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
net/ipv6/exthdrs.c +13 -2
@@ -912,16 +912,27 @@ static bool ipv6_hop_ra(struct sk_buff *static bool ipv6_hop_ioam (struct sk_buff *skb,int optoff) { +enum skb_drop_reason drop_reason;struct ioam6_trace_hdr *trace;struct ioam6_namespace *ns; +struct inet6_dev *idev;struct ioam6_hdr *hdr; + drop_reason =SKB_DROP_REASON_IP_INHDR ; +/* Bad alignment (must be 4n-aligned) */ if (optoff &3 ) goto drop; +/* Does the device still have IPv6 configuration? */ + idev =__in6_dev_get (skb->dev); +if (!idev) { + drop_reason =SKB_DROP_REASON_IPV6DISABLED ; + goto drop; + } +/* Ignore if IOAM is not enabled on ingress */ -if (!READ_ONCE (__in6_dev_get (skb->dev)->cnf.ioam6_enabled)) +if (!READ_ONCE (idev->cnf.ioam6_enabled)) goto ignore;/* Truncated Option header */
@@ -974,7 +985,7 @@ ignore:return true; drop: -kfree_skb_reason (skb,SKB_DROP_REASON_IP_INHDR ); +kfree_skb_reason (skb, drop_reason);return false; }
Greg Kroah-Hartman
maintainerPATCH 85/272 vsock/vmci: fix UAF when peer resets connection during handshake
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Minh Nguyen <[email protected]>
commit 99e22ddf4edb63dc8382bc028af928056d3450cf upstream.
vmci_transport_recv_connecting_server() returned err = 0 for a peer RST in its default switch arm:
err = pkt->type == VMCI_TRANSPORT_PACKET_TYPE_RST ? 0 : -EINVAL;
That made vmci_transport_recv_listen() skip vsock_remove_pending(), leaving the pending socket on the listener's pending_links with sk_state = TCP_CLOSE while destroy: still dropped the explicit reference taken before schedule_delayed_work().
One second later vsock_pending_work() observed is_pending=true and performed full cleanup: vsock_remove_pending() then the two trailing sock_put(sk) calls -- the first reached refcount 0 and __sk_freed the socket, and the second wrote into the freed object:
BUG: KASAN: slab-use-after-free in refcount_warn_saturate Write of size 4 at addr ffff88800b1cac80 by task kworker Workqueue: events vsock_pending_work
Treat peer RST like any other unexpected packet type (err = -EINVAL). All destroy: arms now return err < 0, so vmci_transport_recv_listen() removes pending from pending_links synchronously and vsock_pending_work() takes the is_pending=false / !rejected branch, dropping only its own work reference. This also closes the multi-packet race Sashiko reported on v2: pending is removed from the list before any subsequent packet can find it.
The pre-existing sk_acceptq_removed() gap on the err < 0 path of vmci_transport_recv_listen() that Sashiko also noted is not introduced or changed by this patch.
Tested on lts-6.12.79 with KASAN: 52/100 unpatched -> 0/100 patched.
--- net/vmw_vsock/vmci_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/vmw_vsock/vmci_transport.c +1 -1
@@ -1156,7 +1156,7 @@ vmci_transport_recv_connecting_server(st/* Close and cleanup the connection. */ vmci_transport_send_reset (pending, pkt); skerr =EPROTO ; - err = pkt->type ==VMCI_TRANSPORT_PACKET_TYPE_RST ?0 : -EINVAL ; + err = -EINVAL ; goto destroy; }
Greg Kroah-Hartman
maintainerPATCH 86/272 vsock/virtio: reset connection on receiving queue overflow
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefano Garzarella <[email protected]>
commit a4f0b001782b21663d10df983b4b208195bec66c upstream.
When there is no more space to queue an incoming packet, the packet is silently dropped. This causes data loss without any notification to either peer, since there is no retransmission.
Under normal circumstances, this should never happen. However, it could happen if the other peer doesn't respect the credit, or if the skb overhead, which we recently began to take into account with commit 059b7dbd20a6 ("vsock/virtio: fix potential unbounded skb queue"), is too high.
Fix this by resetting the connection and setting the local socket error to ENOBUFS when virtio_transport_recv_enqueue() can no longer queue a packet, so both peers are explicitly notified of the failure rather than silently losing data.
--- net/vmw_vsock/virtio_transport_common.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
net/vmw_vsock/virtio_transport_common.c +15 -5
@@ -1348,7 +1348,7 @@ destroy:return err; } -static void +static bool virtio_transport_recv_enqueue (struct vsock_sock *vsk,struct sk_buff *skb) {
@@ -1363,10 +1363,8 @@ virtio_transport_recv_enqueue(struct vsospin_lock_bh (&vvs->rx_lock); can_enqueue =virtio_transport_inc_rx_pkt (vvs, len); -if (!can_enqueue) { - free_pkt = true; +if (!can_enqueue) goto out; - }if (le32_to_cpu (hdr->flags) &VIRTIO_VSOCK_SEQ_EOM ) vvs->msg_count++;
@@ -1406,6 +1404,8 @@ out:spin_unlock_bh (&vvs->rx_lock);if (free_pkt)kfree_skb (skb); + +return can_enqueue; } static int
@@ -1418,7 +1418,17 @@ virtio_transport_recv_connected(struct sswitch (le16_to_cpu (hdr->op)) {case VIRTIO_VSOCK_OP_RW : -virtio_transport_recv_enqueue (vsk, skb); +if (!virtio_transport_recv_enqueue (vsk, skb)) { +/* There is no more space to queue the packet, so let's +* close the connection; otherwise, we'll lose data. +*/ + (void )virtio_transport_reset (vsk, skb); +virtio_transport_do_close (vsk, true); + sk->sk_err =ENOBUFS ; +sk_error_report (sk); +vsock_remove_sock (vsk); +break ; + }vsock_data_ready (sk);return err;case VIRTIO_VSOCK_OP_CREDIT_REQUEST :
Greg Kroah-Hartman
maintainerPATCH 87/272 wifi: ath11k: clear shared SRNG pointer state on restart
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Farnung <[email protected]>
commit f51e4b3b5574ad8cb5b16b11f8a1452147ece87a upstream.
LMAC rings reuse the shared rdp/wrp pointer buffers without going through the normal SRNG hw-init path that zeros non-LMAC ring pointers. After restart, ath11k_hal_srng_clear() can therefore hand stale hp/tp state from the previous firmware instance back to the new one.
Clear the shared pointer buffers while keeping the allocations in place so restart still avoids reallocating SRNG DMA memory, but starts with fresh ring-pointer state.
--- drivers/net/wireless/ath/ath11k/hal.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath11k/hal.c +11 -3
@@ -1385,14 +1385,22 @@ EXPORT_SYMBOL(ath11k_hal_srng_deinit);void ath11k_hal_srng_clear (struct ath11k_base *ab) { -/* No need to memset rdp and wrp memory since each individual -* segment would get cleared in ath11k_hal_srng_src_hw_init() -* and ath11k_hal_srng_dst_hw_init(). +/* +* Preserve the shared pointer buffers, but clear the previous +* firmware instance's hp/tp state before handing them back to FW. +* LMAC rings reuse this shared memory without going through the +* normal SRNG hw-init path that zeros non-LMAC ring pointers. */ memset (ab->hal.srng_list,0 ,sizeof (ab->hal.srng_list));memset (ab->hal.shadow_reg_addr,0 ,sizeof (ab->hal.shadow_reg_addr)); +if (ab->hal.rdp.vaddr) +memset (ab->hal.rdp.vaddr,0 , +sizeof (*ab->hal.rdp.vaddr) *HAL_SRNG_RING_ID_MAX ); +if (ab->hal.wrp.vaddr) +memset (ab->hal.wrp.vaddr,0 , +sizeof (*ab->hal.wrp.vaddr) *HAL_SRNG_NUM_LMAC_RINGS ); ab->hal.avail_blk_resource =0 ; ab->hal.current_blk_index =0 ; ab->hal.num_shadow_reg_configured =0 ;
Greg Kroah-Hartman
maintainerPATCH 88/272 ipv4: raw: reject IP_HDRINCL packets with ihl < 5
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 915fab69823a14c170dbaa3b41978768e0fe62fc upstream.
raw_send_hdrinc() validates that the caller-supplied IPv4 header fits within the message length:
iphlen = iph->ihl * 4;
err = -EINVAL;
if (iphlen > length)
goto error_free;
if (iphlen >= sizeof(*iph)) {
/* fix up saddr, tot_len, id, csum, transport_header */
}It does not, however, reject ihl < 5. For such a packet the "if (iphlen >= sizeof(*iph))" branch is skipped, leaving the crafted iphdr untouched, but the packet is still handed to __ip_local_out() and onward. Downstream consumers that read iph->ihl assume a sane value: net/ipv4/ah4.c:ah_output() in particular subtracts sizeof(struct iphdr) from top_iph->ihl * 4 and passes the (signed-int-negative, then cast to size_t) result to memcpy(), producing an OOB access of length close to SIZE_MAX and a host kernel panic.
An IPv4 header with ihl < 5 is malformed by definition (RFC 791:
"Internet Header Length is the length of the internet header in 32 bit words ... Note that the minimum value for a correct header is 5."). The kernel should not be willing to inject such a packet into its own output path.
Reject "iphlen < sizeof(*iph)" alongside the existing "iphlen > length" check. This matches the principle that locally constructed packets that re-enter the IP stack must pass the same basic sanity tests that a foreign packet would be subjected to.
Once this lands, the "if (iphlen >= sizeof(*iph))" wrapper around the fixup branch becomes redundant; left in place to keep the patch minimal and backport-friendly. A follow-up can unwrap it.
Note that commit 86f4c90a1c5c ("ipv4, ipv6: ensure raw socket message is big enough to hold an IP header") ensures the message buffer is large enough to hold an iphdr, but does not constrain the self-reported iph->ihl.
Reachability: the malformed packet source is any caller with CAP_NET_RAW, including an unprivileged process in a user+net namespace on a kernel with CONFIG_USER_NS=y. The reproduced AH crash also requires a matching xfrm AH policy on the outgoing route; a container granted CAP_NET_ADMIN can install that state and policy in its netns. Loopback bypasses xfrm_output, so the trigger uses a real netdev.
Reproduced on UML + KASAN: kernel-mode fault at addr 0x0 with memcpy_orig at the crash site. Same shape reproduces inside a rootless Docker container with --cap-add NET_ADMIN on a stock distro kernel.
--- net/ipv4/raw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/raw.c +1 -1
@@ -390,7 +390,7 @@ static int raw_send_hdrinc(struct sock ** in, reject the frame as invalid */ err = -EINVAL ; -if (iphlen > length) +if (iphlen > length || iphlen <sizeof (*iph)) goto error_free;if (iphlen >=sizeof (*iph)) {
Greg Kroah-Hartman
maintainerPATCH 89/272 ixgbevf: fix use-after-free in VEPA multicast source pruning
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 5d49b568c188dc77199d8d2b959c91da8cc27cf1 upstream.
ixgbevf_clean_rx_irq() prunes frames whose source MAC matches the VF's own address (VEPA multicast workaround) by freeing the skb and continuing to the next descriptor:
dev_kfree_skb_irq(skb);
continue;The skb pointer is declared outside the while loop and persists across iterations. Because the continue skips the "skb = NULL" reset at the bottom of the loop, the next iteration enters the "else if (skb)" path and calls ixgbevf_add_rx_frag() on the freed skb, dereferencing skb_shinfo(skb)->nr_frags - a use-after-free in NAPI softirq context.
The sibling driver iavf already handles this correctly by nulling the pointer before continuing. Apply the same pattern here.
I do not have ixgbevf hardware; the bug was found by static analysis (scan_drop_continue_loops.py + semgrep drop_continue_in_loop, multi-tool corroboration with the highest score in the scan). The UAF was confirmed under KASAN by loading a test module that reproduces the exact code pattern (alloc skb, kfree_skb, then read skb_shinfo(skb)->nr_frags):
BUG: KASAN: slab-use-after-free in ixgbevf_uaf_test_init+0x100/0x1000 Read of size 8 at addr 000000006163ae78 by task insmod/30 freed 208-byte region [000000006163adc0, 000000006163ae90)
QEMU emulates igb (82576) but not ixgbe (82599), and the igbvf VF driver does not include the VEPA source pruning path, so a full end-to-end reproduction with emulated hardware was not possible.
--- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +1 -0
@@ -1224,6 +1224,7 @@ static int ixgbevf_clean_rx_irq(struct i ether_addr_equal(rx_ring->netdev->dev_addr, eth_hdr(skb)->h_source)) {dev_kfree_skb_irq (skb); + skb =NULL ;continue ; }
Greg Kroah-Hartman
maintainerPATCH 90/272 rbd: eliminate a race in lock_dwork draining on unmap
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilya Dryomov <[email protected]>
commit 9fc75b71fdd38465c76c6f6a884cdd4ae3c72d90 upstream.
Given how rbd_lock_add_request() and rbd_img_exclusive_lock() are written, lock_dwork may be (re)queued more than it's actually needed:
for example in case a new I/O request comes in while we are in the middle of rbd_acquire_lock() on behalf of another I/O request. This is expected and with rbd_release_lock() preemptively canceling lock_dwork is benign under normal operation.
A more problematic example is maybe_kick_acquire():
if (have_requests || delayed_work_pending(&rbd_dev->lock_dwork)) {
dout("%s rbd_dev %p kicking lock_dwork\n", __func__, rbd_dev);
mod_delayed_work(rbd_dev->task_wq, &rbd_dev->lock_dwork, 0);
}It's not unrealistic for lock_dwork to get canceled right after delayed_work_pending() returns true and for mod_delayed_work() to requeue it right there anyway. This is a classic TOCTOU race.
When it comes to unmapping the image, there is an implicit assumption of no self-initiated exclusive lock activity past the point of return from rbd_dev_image_unlock() which unlocks the lock if it happens to be held. This unlock is assumed to be final and lock_dwork (as well as all other exclusive lock tasks, really) isn't expected to get queued again. However, lock_dwork is canceled only in cancel_tasks_sync() (i.e. later in the unmap sequence) and on top of that the cancellation can get in effect nullified by maybe_kick_acquire(). This may result in rbd_acquire_lock() executing after rbd_dev_device_release() and rbd_dev_image_release() run and free and/or reset a bunch of things. One of the possible failure modes then is a violated
rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
in rbd_dev_header_info() which is called via rbd_dev_refresh() from rbd_post_acquire_action().
Redo exclusive lock task draining to provide saner semantics and try to meet the assumptions around rbd_dev_image_unlock().
--- drivers/block/rbd.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-)
drivers/block/rbd.c +8 -12
@@ -4565,24 +4565,12 @@ out:return ret; } -static void cancel_tasks_sync (struct rbd_device *rbd_dev) -{ -dout ("%s rbd_dev %p\n" , __func__, rbd_dev); - -cancel_work_sync (&rbd_dev->acquired_lock_work); -cancel_work_sync (&rbd_dev->released_lock_work); -cancel_delayed_work_sync (&rbd_dev->lock_dwork); -cancel_work_sync (&rbd_dev->unlock_work); -} -/* * header_rwsem must not be held to avoid a deadlock with * rbd_dev_refresh() when flushing notifies. */ static void rbd_unregister_watch (struct rbd_device *rbd_dev) { -cancel_tasks_sync (rbd_dev); -mutex_lock (&rbd_dev->watch_mutex);if (rbd_dev->watch_state ==RBD_WATCH_STATE_REGISTERED )__rbd_unregister_watch (rbd_dev);
@@ -6549,10 +6537,18 @@ out_err:static void rbd_dev_image_unlock (struct rbd_device *rbd_dev) { +dout ("%s rbd_dev %p\n" , __func__, rbd_dev); + +disable_delayed_work_sync (&rbd_dev->lock_dwork); +disable_work_sync (&rbd_dev->unlock_work); +down_write (&rbd_dev->lock_rwsem);if (__rbd_is_lock_owner (rbd_dev))__rbd_release_lock (rbd_dev);up_write (&rbd_dev->lock_rwsem); + +flush_work (&rbd_dev->acquired_lock_work); +flush_work (&rbd_dev->released_lock_work); }/*
Greg Kroah-Hartman
maintainerPATCH 91/272 lsm: hold cred_guard_mutex for lsm_set_self_attr()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Smalley <[email protected]>
commit 4a9b16541ad3faf8bccb398532bf3f8b6bbf1188 upstream.
Just as proc_pid_attr_write() already does before calling the LSM hook. This only matters for SELinux and AppArmor which check whether the process is being ptraced and if so, whether to allow the transition.
--- security/lsm_syscalls.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
security/lsm_syscalls.c +8 -1
@@ -55,7 +55,14 @@ u64 lsm_name_to_attr(const char *name) SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *, ctx, u32, size, u32, flags) { -return security_setselfattr (attr, ctx, size, flags); +int rc; + + rc =mutex_lock_interruptible (¤t->signal->cred_guard_mutex); +if (rc <0 ) +return rc; + rc =security_setselfattr (attr, ctx, size, flags); +mutex_unlock (¤t->signal->cred_guard_mutex); +return rc; }/**
Greg Kroah-Hartman
maintainerPATCH 92/272 octeontx2-af: CGX: add bounds check to cgx_speed_mbps index
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sam Daly <[email protected]>
commit c0bf0a4f3f1f5f57aa83e1400ba4f56f0abfd542 upstream.
cgx_speed_mbps has 13 elements but RESP_LINKSTAT_SPEED can yield values 0-15. If it returns a value >= 13, this causes an out-of-bounds array access. Add a bounds check and default to speed 0 if the index is out of range.
--- drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/ethernet/marvell/octeontx2/af/cgx.c +6 -1
@@ -1286,13 +1286,18 @@ static inline void link_status_user_formstruct cgx_link_user_info *linfo, struct cgx *cgx, u8 lmac_id) { + unsigned int speed; + linfo->link_up =FIELD_GET (RESP_LINKSTAT_UP , lstat); linfo->full_duplex =FIELD_GET (RESP_LINKSTAT_FDUPLEX , lstat); - linfo->speed = cgx_speed_mbps[FIELD_GET (RESP_LINKSTAT_SPEED , lstat)]; linfo->an =FIELD_GET (RESP_LINKSTAT_AN , lstat); linfo->fec =FIELD_GET (RESP_LINKSTAT_FEC , lstat); linfo->lmac_type_id =FIELD_GET (RESP_LINKSTAT_LMAC_TYPE , lstat); + speed =FIELD_GET (RESP_LINKSTAT_SPEED , lstat); + linfo->speed = speed <ARRAY_SIZE (cgx_speed_mbps) ? + cgx_speed_mbps[speed] :0 ; +if (linfo->lmac_type_id >=LMAC_MODE_MAX ) {dev_err (&cgx->pdev->dev,"Unknown lmac_type_id %d reported by firmware on cgx port%d:%d" , linfo->lmac_type_id, cgx->cgx_id, lmac_id);
Greg Kroah-Hartman
maintainerPATCH 93/272 ice: fix setting promisc mode while adding VID filter
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marcin Szycik <[email protected]>
commit ebc8de716c9ec2be384abdc2dd866da26c6580d1 upstream.
There are at least two paths through which VSI promiscuous mode can be independently configured via ice_fltr_set_vsi_promisc():
- ice_vlan_rx_add_vid() (netdev op)
- ice_service_task() -> ... -> ice_set_promisc()
Both paths may try to program promiscuous mode concurrently. One such scenario is:
1. Add ice netdev to bond
2. Add the bond netdev to bridge
3. ice netdev enters allmulticast mode (IFF_ALLMULTI)
4. Service task programs promisc mode filter
5. Bridge -> bond calls ice_vlan_rx_add_vid()
Crucially, ice_vlan_rx_add_vid() fails if ice_fltr_set_vsi_promisc() returns any error, including -EEXIST. This causes VLAN filtering setup to fail on the bond interface. ice_set_promisc() already handles -EEXIST correctly.
Fix by adding the same -EEXIST check to ice_vlan_rx_add_vid(): if the promisc filter is already programmed, continue without returning error.
--- drivers/net/ethernet/intel/ice/ice_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/ice/ice_main.c +1 -1
@@ -3808,7 +3808,7 @@ int ice_vlan_rx_add_vid(struct net_devic ret =ice_fltr_set_vsi_promisc (&vsi->back->hw, vsi->idx,ICE_MCAST_VLAN_PROMISC_BITS , vid); -if (ret) +if (ret && ret != -EEXIST ) goto finish; }
Greg Kroah-Hartman
maintainerPATCH 94/272 ice: restore PTP Rx timestamp config after ethtool set-channels
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Grzegorz Nitka <[email protected]>
commit 975b564d195b13ca6ee1ef5e6a9561734898eb17 upstream.
When ethtool -L changes queue counts, ice_vsi_recfg_qs() closes and rebuilds the VSI, reallocating Rx rings. The newly allocated rings have ptp_rx cleared, so RX hardware timestamps are no longer attached to skb until hwtstamp configuration is applied again.
Restore timestamp mode after ice_vsi_open() in the queue reconfiguration path, matching reset/rebuild behavior and ensuring newly rebuilt Rx rings have PTP RX timestamping re-enabled.
Testing hints:
- run ptp4l application in client synchronization mode:
ptp4l -i ethX -m -s
- run PTP traffic
- change queue number on ethX netdev interface:
ethtool -L ethX combined new_queue_size
- observe ptp4l output
- expected result: no "received DELAY_REQ without timestamp" messages
--- drivers/net/ethernet/intel/ice/ice_main.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/ethernet/intel/ice/ice_main.c +6 -0
@@ -4197,6 +4197,12 @@ int ice_vsi_recfg_qs(struct ice_vsi *vsi }ice_pf_dcb_recfg (pf, locked);ice_vsi_open (vsi); +/* Rx rings are reallocated during VSI rebuild and lose their ptp_rx +* flag. Restore timestamp mode so newly allocated rings are set up +* for hardware Rx timestamping. +*/ +if (test_bit (ICE_FLAG_PTP_SUPPORTED , pf->flags)) +ice_ptp_restore_timestamp_mode (pf); goto done; rebuild_err:
Greg Kroah-Hartman
maintainerPATCH 95/272 wifi: cfg80211: advance loop vars in cfg80211_merge_profile()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Walker <[email protected]>
commit 7666dbb1bacc4ba522b96740cba7283d243d16e1 upstream.
cfg80211_merge_profile() reassembles a Multi-BSSID non-transmitted BSS profile that has been split across multiple consecutive MBSSID elements. Its while-loop calls
cfg80211_get_profile_continuation(ie, ielen, mbssid_elem, sub_elem)
but never advances mbssid_elem or sub_elem inside the body. Each iteration therefore searches for a continuation that follows the same fixed pair; the helper returns the same next_mbssid; and the same next_sub bytes are memcpy()'d into merged_ie at a growing offset until the buffer fills.
Advance both mbssid_elem and sub_elem to the just-consumed continuation so the next call to cfg80211_get_profile_continuation() searches for a further continuation beyond it (or returns NULL when none exists).
A specially-crafted malicious beacon can take advantage of this bug to cause the kernel to spend an excessive amount of time in cfg80211_merge_profile (up to as much as 2ms per beacon received), which could theoretically be abused in some way.
--- net/wireless/scan.c | 3 +++ 1 file changed, 3 insertions(+)
net/wireless/scan.c +3 -0
@@ -2421,6 +2421,9 @@ size_t cfg80211_merge_profile(const u8 *memcpy (merged_ie + copied_len, next_sub->data, next_sub->datalen); copied_len += next_sub->datalen; + + mbssid_elem = next_mbssid; + sub_elem = next_sub; }return copied_len;
Greg Kroah-Hartman
maintainerPATCH 96/272 af_unix: Fix UAF read of tail->len in unix_stream_data_wait()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn <[email protected]>
commit be309f8eae8b474a4a617eaae01324da996fc719 upstream.
unix_stream_data_wait() does skb_peek_tail(&sk->sk_receive_queue) without holding any lock that prevents SKBs on that queue from being dequeued and freed.
This has been the case since commit 79f632c71bea ("unix/stream: fix peeking with an offset larger than data in queue").
The first consequence of this is that the pointer comparison tail != last can be false even if last semantically refers to an already-freed SKB while tail is a new SKB allocated at the same address; which can cause unix_stream_data_wait() to wrongly keep blocking after new data has arrived, but only in a weird scenario where a peeking recv() and a normal recv() on the same socket are racing, which is probably not a real problem.
But since commit 2b514574f7e8 ("net: af_unix: implement splice for stream af_unix sockets"), tail is actually dereferenced, which can cause UAF in the following race scenario (where test_setup() runs single-threaded, and afterwards, test_thread1() and test_thread2() run concurrently in two threads:
```
static int socks[2];
void test_setup(void) {
socketpair(AF_UNIX, SOCK_STREAM, 0, socks);
send(socks[1], "A", 1, 0);
int peekoff = 1;
setsockopt(socks[0], SOL_SOCKET, SO_PEEK_OFF, &peekoff, sizeof(peekoff));
}
void test_thread1(void) {
char dummy;
recv(socks[0], &dummy, 1, MSG_PEEK);
}
void test_thread2(void) {
char dummy;
recv(socks[0], &dummy, 1, 0);
shutdown(socks[1], SHUT_WR);
}
```when racing like this:
```
thread1 thread2
unix_stream_read_generic
mutex_lock(&u->iolock)
skb_peek(&sk->sk_receive_queue)
skb_peek_next(skb, &sk->sk_receive_queue)
mutex_unlock(&u->iolock)
unix_stream_read_generic
unix_state_lock(sk)
skb_peek(&sk->sk_receive_queue)
unix_state_unlock(sk)
unix_stream_data_wait
unix_state_lock(sk)
tail = skb_peek_tail(&sk->sk_receive_queue)
spin_lock(&sk->sk_receive_queue.lock)
__skb_unlink(skb, &sk->sk_receive_queue)
spin_unlock(&sk->sk_receive_queue.lock)
consume_skb(skb) [frees the SKB]
`tail != last`: false
`tail`: true
`tail->len != last_len` ***UAF***
```Fix the UAF by removing the read of tail->len; checking tail->len would only make sense if SKBs in the receive queue of a UNIX socket could grow, which can no longer happen.
Kuniyuki explained:
Quoted 11 lines
When commit
869e7c62486e("net:af_unix: implement stream sendpage support") addedsendpage()support, data could be appended to the last skb in the receiver's queue.That's why we needed to check if the length of the last skb was changed while waiting for new data in
unix_stream_data_wait().However, commit
a0dbf5f818f9("af_unix: SupportMSG_SPLICE_PAGES") and commit57d44a354a43("unix: Convertunix_stream_sendpage()to useMSG_SPLICE_PAGES") refactoredsendmsg(), and now data is always added to a new skb.
That means this fix is not suitable for kernels before 6.5.
--- net/unix/af_unix.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
net/unix/af_unix.c +2 -9
@@ -2570,8 +2570,7 @@ static int unix_read_skb(struct sock *sk* Sleep until more data has arrived. But check for races.. */ static long unix_stream_data_wait (struct sock *sk,long timeo, -struct sk_buff *last,unsigned int last_len, -bool freezable) +struct sk_buff *last,bool freezable) {unsigned int state =TASK_INTERRUPTIBLE | freezable *TASK_FREEZABLE ;struct sk_buff *tail;
@@ -2584,7 +2583,6 @@ static long unix_stream_data_wait(struct tail =skb_peek_tail (&sk->sk_receive_queue); if (tail != last || - (tail && tail->len != last_len) || sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN) || signal_pending(current) ||
@@ -2779,7 +2777,6 @@ static int unix_stream_read_generic(struint flags = state->flags;bool check_creds = false;struct scm_cookie scm; -unsigned int last_len;struct unix_sock *u;int copied =0 ;int err =0 ;
@@ -2825,7 +2822,6 @@ redo: goto unlock; } last = skb =skb_peek (&sk->sk_receive_queue); - last_len = last ? last->len :0 ; again: #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
@@ -2859,8 +2855,7 @@ again:mutex_unlock (&u->iolock); - timeo =unix_stream_data_wait (sk, timeo, last, - last_len, freezable); + timeo =unix_stream_data_wait (sk, timeo, last, freezable);if (signal_pending (current)) { err =sock_intr_errno (timeo);
@@ -2877,7 +2872,6 @@ unlock:while (skip >=unix_skb_len (skb)) { skip -=unix_skb_len (skb); last = skb; - last_len = skb->len; skb =skb_peek_next (skb, &sk->sk_receive_queue);if (!skb) goto again;
@@ -2950,7 +2944,6 @@ unlock: skip =0 ; last = skb; - last_len = skb->len;unix_state_lock (sk); skb =skb_peek_next (skb, &sk->sk_receive_queue);if (skb)
Greg Kroah-Hartman
maintainerPATCH 97/272 wifi: mac80211: consume only present negotiated TTLM maps
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit a6e6ccd5bd07155c2add6c74ce1a5e68ad3b95ea upstream.
ieee80211_tid_to_link_map_size_ok() validates negotiated TTLM elements against the number of link-map entries indicated by link_map_presence. ieee80211_parse_neg_ttlm() must consume the same layout.
The parser advanced its cursor for every TID, including TIDs whose presence bit is clear and therefore have no map bytes in the element. A sparse map can then make a later present TID read past the validated element.
The bad bytes land in neg_ttlm->{up,down}link[tid] but are gated by valid_links before being applied to driver state, so a peer cannot turn the read into a policy change. Under KUnit + KASAN with an exact-sized element allocation the OOB read is reported as a slab-out-of-bounds; whether the same trigger fires under the production RX path depends on surrounding allocator state.
Advance the cursor only when the current TID has a map present.
--- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/mlme.c +1 -1
@@ -7290,6 +7290,7 @@ ieee80211_parse_neg_ttlm(struct ieee8021 "No active links for TID %d", tid);return -EINVAL ; } + pos += map_size; }else { map =0 ; }
@@ -7308,7 +7309,6 @@ ieee80211_parse_neg_ttlm(struct ieee8021default :return -EINVAL ; } - pos += map_size; }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 98/272 cifs: Fix busy dentry used after unmounting
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
commit c68337442f03953237a94577beb468ab2662a851 upstream.
Since commit 340cea84f691c ("cifs: open files should not hold ref on superblock"), cifs file only holds the dentry ref_cnt, the cifs file close work(cfile->deferred) could be executed after unmounting, which will trigger a warning in generic_shutdown_super:
BUG: Dentry 00000000a14a6845{i=c,n=file} still in use (1) [unmount of
cifs cifs]The detailed processs is:
process A process B kworker
fd = open(PATH)
vfs_open
file->__f_path = *path // dentry->d_lockref.count = 1 cifs_open
cifs_new_fileinfo
cfile->dentry = dget(dentry) // dentry->d_lockref.count = 2
close(fd)
__fput
cifs_close
queue_delayed_work(deferredclose_wq, cfile->deferred)
dput(dentry) // dentry->d_lockref.count = 1
smb2_deferred_work_close
_cifsFileInfo_put
list_del(&cifs_file->flist)
umount
cleanup_mnt
deactivate_super
cifs_kill_sb
cifs_close_all_deferred_files_sb
cifs_close_all_deferred_files
// cannot find cfile, skip _cifsFileInfo_put
kill_anon_super
generic_shutdown_super
shrink_dcache_for_umount
umount_check
WARN ! // dentry->d_lockref.count = 1
cifsFileInfo_put_final
dput(cifs_file->dentry)
// dentry->d_lockref.count = 0Fix it by flushing 'deferredclose_wq' before calling kill_anon_super.
Fetch a reproducer in https://bugzilla.kernel.org/show_bug.cgi?id=221548.
--- fs/smb/client/cifsfs.c | 2 ++ 1 file changed, 2 insertions(+)
fs/smb/client/cifsfs.c +2 -0
@@ -299,6 +299,8 @@ static void cifs_kill_sb(struct super_bl/* Wait for all pending oplock breaks to complete */ flush_workqueue (cifsoplockd_wq); +/* Wait for all opened files to release */ +flush_workqueue (deferredclose_wq);/* finally release root dentry */ dput (cifs_sb->root);
Greg Kroah-Hartman
maintainerPATCH 99/272 tracing: Do not call map->ops->elt_free() if elt_alloc() fails
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
commit 8f0f5c4fb9df0e19a341e0c6ed8dc4fda9124f03 upstream.
In paths where tracing_map_elt_alloc() failed to allocate objects, the map->ops->elt_alloc() call was never successful. In this case, map->ops->elt_free() should not be called.
--- kernel/trace/tracing_map.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
kernel/trace/tracing_map.c +13 -4
@@ -386,13 +386,11 @@ static void tracing_map_elt_init_fields( } } -static void tracing_map_elt_free (struct tracing_map_elt *elt) +static void __tracing_map_elt_free (struct tracing_map_elt *elt) {if (!elt)return ; -if (elt->map->ops && elt->map->ops->elt_free) - elt->map->ops->elt_free (elt);kfree (elt->fields);kfree (elt->vars);kfree (elt->var_set);
@@ -400,6 +398,17 @@ static void tracing_map_elt_free(structkfree (elt); } +static void tracing_map_elt_free (struct tracing_map_elt *elt) +{ +if (!elt) +return ; + +/* Only objects initialized with alloc_elt() should be passed to free_elt().*/ +if (elt->map->ops && elt->map->ops->elt_free) + elt->map->ops->elt_free (elt); +__tracing_map_elt_free (elt); +} +static struct tracing_map_elt *tracing_map_elt_alloc (struct tracing_map *map) {struct tracing_map_elt *elt;
@@ -444,7 +453,7 @@ static struct tracing_map_elt *tracing_m }return elt; free: -tracing_map_elt_free (elt); +__tracing_map_elt_free (elt);return ERR_PTR (err); }
Greg Kroah-Hartman
maintainerPATCH 100/272 arm64: probes: Handle probes on hinted conditional branch instructions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Murzin <[email protected]>
commit 2ccd8ff980b50e842481bae71102fa3883fc4377 upstream.
BC.cond instructions introduced by FEAT_HBC cannot be executed out-of-line, like other branch instructions. However, they can be simulated in the same way as B.cond instructions.
Extend the B.cond decoder mask to match BC.cond instructions as well, and handle them using the existing B.cond simulation path.
--- arch/arm64/include/asm/insn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/insn.h +1 -1
@@ -405,7 +405,7 @@ __AARCH64_INSN_FUNCS(cbz, 0x7F000000, 0x __AARCH64_INSN_FUNCS(cbnz, 0x7F000000, 0x35000000) __AARCH64_INSN_FUNCS(tbz, 0x7F000000, 0x36000000) __AARCH64_INSN_FUNCS(tbnz, 0x7F000000, 0x37000000) -__AARCH64_INSN_FUNCS(bcond, 0xFF000010, 0x54000000) +__AARCH64_INSN_FUNCS(bcond, 0xFF000000, 0x54000000) __AARCH64_INSN_FUNCS(svc, 0xFFE0001F, 0xD4000001) __AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002)__AARCH64_INSN_FUNCS (smc,0xFFE0001F ,0xD4000003 )
Greg Kroah-Hartman
maintainerPATCH 101/272 KVM: arm64: vgic-its: Reject restored DTE with out-of-range num_eventid_bits
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 9ce754ed8e7ab4e3999767ce1505f85c449ccb07 upstream.
Userspace can restore an ITS Device Table Entry whose Size field encodes more EventID bits than the virtual ITS supports. The live MAPD path rejects that state, but vgic_its_restore_dte() accepts it and stores the out-of-range value in dev->num_eventid_bits.
Reject restored DTEs with num_eventid_bits > VITS_TYPER_IDBITS before allocating the device. This mirrors the MAPD check and prevents the restored state from reaching vgic_its_restore_itt(), where the unchecked value can be converted into an oversized scan_its_table() range.
--- arch/arm64/kvm/vgic/vgic-its.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/arm64/kvm/vgic/vgic-its.c +4 -0
@@ -2295,6 +2295,10 @@ static int vgic_its_restore_dte(struct v/* dte entry is valid */ offset = (entry &KVM_ITS_DTE_NEXT_MASK ) >>KVM_ITS_DTE_NEXT_SHIFT ; +/* Mimic the MAPD behaviour and reject invalid EID bits. */ +if (num_eventid_bits >VITS_TYPER_IDBITS ) +return -EINVAL ; +if (!vgic_its_check_id (its, baser, id,NULL ))return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 102/272 KVM: arm64: vgic: Free private_irqs when init fails after allocation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit f19c354dbd457759dfcf1195ab4bdba2bb568323 upstream.
Companion to commit 250f25367b58 ("KVM: arm64: Tear down vGIC on failed vCPU creation"), which added the missing kvm_vgic_vcpu_destroy() call to the kvm_share_hyp() failure path in kvm_arch_vcpu_create(). The kvm_vgic_vcpu_init() failure path immediately above it has the same shape and still needs the same cleanup.
Call kvm_vgic_vcpu_destroy() when kvm_vgic_vcpu_init() fails so private IRQs allocated before a redistributor iodev registration failure are released before the failed vCPU is freed.
--- arch/arm64/kvm/arm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm64/kvm/arm.c +3 -1
@@ -490,8 +490,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpukvm_destroy_mpidr_data (vcpu->kvm); err =kvm_vgic_vcpu_init (vcpu); -if (err) +if (err) { +kvm_vgic_vcpu_destroy (vcpu);return err; + } err =kvm_share_hyp (vcpu, vcpu +1 );if (err)
Greg Kroah-Hartman
maintainerPATCH 103/272 riscv: kvm: return SBI_ERR_FAILURE for pmu_snapshot_set_shmem() when OOM
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Osama Abdelkader <[email protected]>
commit 0835ee26938e15eccd70f7d33da386b6490f9449 upstream.
kvm_riscv_vcpu_pmu_snapshot_set_shmem() returned -ENOMEM from the SBI extension handler, which caused kvm_riscv_vcpu_sbi_ecall() to abort KVM_RUN and surface the error to userspace instead of ompleting the ECALL with a negative SBI error in a0.
Use SBI_ERR_FAILURE and the normal retdata path, matching other PMU handlers and kvm_sbi_ext_pmu_handler comment.
--- arch/riscv/kvm/vcpu_pmu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/riscv/kvm/vcpu_pmu.c +4 -2
@@ -435,8 +435,10 @@ int kvm_riscv_vcpu_pmu_snapshot_set_shme } kvpmu->sdata =kzalloc (snapshot_area_size,GFP_ATOMIC ); -if (!kvpmu->sdata) -return -ENOMEM ; +if (!kvpmu->sdata) { + sbiret =SBI_ERR_FAILURE ; + goto out; + }if (kvm_vcpu_write_guest (vcpu, saddr, kvpmu->sdata, snapshot_area_size)) {kfree (kvpmu->sdata);
Greg Kroah-Hartman
maintainerPATCH 104/272 drm/bridge: chipone-icn6211: use devm_drm_bridge_add in i2c probe
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Osama Abdelkader <[email protected]>
commit 73d01051e8040c0b1de7fd26b3b8d0c2ffa6895c upstream.
Use devm_drm_bridge_add() so the bridge is released if probe fails after registration, and drop drm_bridge_remove() in chipone_i2c_probe.
--- drivers/gpu/drm/bridge/chipone-icn6211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/chipone-icn6211.c +3 -1
@@ -757,7 +757,9 @@ static int chipone_i2c_probe(struct i2c_dev_set_drvdata (dev, icn);i2c_set_clientdata (client, icn); -drm_bridge_add (&icn->bridge); + ret =devm_drm_bridge_add (dev, &icn->bridge); +if (ret) +return ret;return chipone_dsi_host_attach (icn); }
Greg Kroah-Hartman
maintainerPATCH 105/272 spi: qup: fix error pointer deref after DMA setup failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit a7e8f3efd50a165ba0189f6dc57f7e51a7d149db upstream.
The driver falls back to PIO mode if DMA setup fails during probe.
Make sure to the clear the DMA channel pointers on setup failure to avoid dereferencing an error pointer (or attempting to release a channel a second time) on later probe errors or driver unbind.
This issue was flagged by Sashiko when reviewing a devres allocation conversion patch.
--- drivers/spi/spi-qup.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/spi/spi-qup.c +3 -0
@@ -996,8 +996,11 @@ static int spi_qup_init_dma(struct spi_c err:dma_release_channel (host->dma_tx); + host->dma_tx =NULL ; err_tx:dma_release_channel (host->dma_rx); + host->dma_rx =NULL ; +return ret; }
Greg Kroah-Hartman
maintainerPATCH 106/272 phy: tegra: xusb: Fix per-pad high-speed termination calibration
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wayne Chang <[email protected]>
commit da110228b54f2e2143d97ea7151e0dc22e539d67 upstream.
The existing code reads a single hs_term_range_adj value from bit field [10:7] of FUSE_SKU_CALIB_0 and applies it to all USB2 pads uniformly. However, on SoCs that support per-pad termination, each pad has its own hs_term_range_adj field: pad 0 in FUSE_SKU_CALIB_0[10:7], and pads 1-3 in FUSE_USB_CALIB_EXT_0 at bit offsets [8:5], [12:9], and [16:13] respectively.
Fix the calibration by reading per-pad values from the appropriate fuse registers. For SoCs that do not support per-pad termination, replicate pad 0's value to all pads to maintain existing behavior.
Add a has_per_pad_term flag to the SoC data to indicate whether per-pad termination values are available in FUSE_USB_CALIB_EXT_0.
--- drivers/phy/tegra/xusb-tegra186.c | 33 ++++++++++++++++++++++++++------- drivers/phy/tegra/xusb.h | 1 + 2 files changed, 27 insertions(+), 7 deletions(-)
drivers/phy/tegra/xusb-tegra186.c +26 -7
@@ -20,8 +20,8 @@/* FUSE USB_CALIB registers */ #define HS_CURR_LEVEL_PADX_SHIFT (x) ((x) ? (11 + (x - 1) * 6) : 0)#define HS_CURR_LEVEL_PAD_MASK 0x3f -#define HS_TERM_RANGE_ADJ_SHIFT 7 -#define HS_TERM_RANGE_ADJ_MASK 0xf +#define HS_TERM_RANGE_ADJ_PADX_SHIFT (x) ((x) ? (5 + (x - 1) * 4) : 7) +#define HS_TERM_RANGE_ADJ_PAD_MASK 0xf#define HS_SQUELCH_SHIFT 29#define HS_SQUELCH_MASK 0x7
@@ -253,7 +253,7 @@struct tegra_xusb_fuse_calibration {u32 *hs_curr_level;u32 hs_squelch; -u32 hs_term_range_adj; +u32 *hs_term_range_adj;u32 rpd_ctrl; };
@@ -930,7 +930,7 @@ static int tegra186_utmi_phy_power_on(st value =padctl_readl (padctl,XUSB_PADCTL_USB2_OTG_PADX_CTL1 (index)); value &= ~TERM_RANGE_ADJ (~0 ); - value |=TERM_RANGE_ADJ (priv->calib.hs_term_range_adj); + value |=TERM_RANGE_ADJ (priv->calib.hs_term_range_adj[index]); value &= ~RPD_CTRL (~0 ); value |=RPD_CTRL (priv->calib.rpd_ctrl);padctl_writel (padctl, value,XUSB_PADCTL_USB2_OTG_PADX_CTL1 (index));
@@ -1464,17 +1464,23 @@ static const char * const tegra186_usb3_static int tegra186_xusb_read_fuse_calibration (struct tegra186_xusb_padctl *padctl) { +const struct tegra_xusb_padctl_soc *soc = padctl->base.soc;struct device *dev = padctl->base.dev;unsigned int i, count;u32 value, *level; +u32 *hs_term_range_adj;int err; - count = padctl->base.soc->ports.usb2.count; + count = soc->ports.usb2.count; level =devm_kcalloc (dev, count,sizeof (u32),GFP_KERNEL );if (!level)return -ENOMEM ; + hs_term_range_adj =devm_kcalloc (dev, count,sizeof (u32),GFP_KERNEL ); +if (!hs_term_range_adj) +return -ENOMEM ; + err =tegra_fuse_readl (TEGRA_FUSE_SKU_CALIB_0 , &value);if (err) return dev_err_probe(dev, err,
@@ -1490,8 +1496,8 @@ tegra186_xusb_read_fuse_calibration(stru padctl->calib.hs_squelch = (value >>HS_SQUELCH_SHIFT ) &HS_SQUELCH_MASK ; - padctl->calib.hs_term_range_adj = (value >>HS_TERM_RANGE_ADJ_SHIFT ) & -HS_TERM_RANGE_ADJ_MASK ; + hs_term_range_adj[0 ] = (value >>HS_TERM_RANGE_ADJ_PADX_SHIFT (0 )) & +HS_TERM_RANGE_ADJ_PAD_MASK ; err =tegra_fuse_readl (TEGRA_FUSE_USB_CALIB_EXT_0 , &value);if (err) {
@@ -1503,6 +1509,17 @@ tegra186_xusb_read_fuse_calibration(stru padctl->calib.rpd_ctrl = (value >>RPD_CTRL_SHIFT ) &RPD_CTRL_MASK ; +for (i =1 ; i < count; i++) { +if (soc->has_per_pad_term) + hs_term_range_adj[i] = + (value >>HS_TERM_RANGE_ADJ_PADX_SHIFT (i)) & +HS_TERM_RANGE_ADJ_PAD_MASK ; +else + hs_term_range_adj[i] = hs_term_range_adj[0 ]; + } + + padctl->calib.hs_term_range_adj = hs_term_range_adj; +return 0 ; }
@@ -1708,6 +1725,7 @@ const struct tegra_xusb_padctl_soc tegra .num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names), .supports_gen2 = true, .poll_trk_completed = true, + .has_per_pad_term = true, };EXPORT_SYMBOL_GPL (tegra194_xusb_padctl_soc);
@@ -1732,6 +1750,7 @@ const struct tegra_xusb_padctl_soc tegra .trk_hw_mode = false, .trk_update_on_idle = true, .supports_lp_cfg_en = true, + .has_per_pad_term = true, };EXPORT_SYMBOL_GPL (tegra234_xusb_padctl_soc);#endif
drivers/phy/tegra/xusb.h +1 -0
@@ -436,6 +436,7 @@ struct tegra_xusb_padctl_soc {bool trk_hw_mode;bool trk_update_on_idle;bool supports_lp_cfg_en; +bool has_per_pad_term; };struct tegra_xusb_padctl {
Greg Kroah-Hartman
maintainerPATCH 107/272 scsi: isci: Fix use-after-free in device removal path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit b52a8d52c3125ec9a93106ed816582368de34426 upstream.
The ISCI completion tasklet is initialized in isci_host_alloc() (drivers/scsi/isci/init.c:496) and scheduled from both MSI-X and legacy interrupt handlers (drivers/scsi/isci/host.c:223,613).
isci_host_deinit() stops the controller and waits for stop completion, but it never kills completion_tasklet before teardown continues. A top-of-function tasklet_kill() is not sufficient here: interrupts are only disabled when isci_host_stop_complete() runs, so until wait_for_stop() returns the IRQ handlers can still requeue the tasklet. The tasklet callback also re-enables interrupts after draining completions, so killing the tasklet before the source is quiesced leaves the same race open.
Once wait_for_stop() returns, no further IRQ-driven scheduling can occur. Kill completion_tasklet there so teardown cannot race a queued tasklet running on a dead ihost. On remove or unload, the stale callback can otherwise dereference ihost and touch ihost->smu_registers after the host lifetime ends.
A UML + KASAN analogue reproduced the failure class both with no tasklet_kill() and with tasklet_kill() placed before source quiesce, and stayed clean once the kill happened after quiescing the scheduling source.
This mirrors commit f6ab594672d4 ("scsi: aic94xx: fix use-after-free in device removal path"), but ISCI needs the kill after wait_for_stop().
--- drivers/scsi/isci/host.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/scsi/isci/host.c +3 -0
@@ -1252,6 +1252,9 @@ void isci_host_deinit(struct isci_host *wait_for_stop (ihost); +/* No further IRQ-driven scheduling can happen past wait_for_stop(). */ +tasklet_kill (&ihost->completion_tasklet); +/* phy stop is after controller stop to allow port and device to * go idle before shutting down the phys, but the expectation is * that i/o has been shut off well before we reach this
Greg Kroah-Hartman
maintainerPATCH 108/272 spi: ep93xx: fix error pointer deref after DMA setup failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 5e121a81667a83e9a01d62b429e340f5a4a84abc upstream.
The driver falls back to PIO mode if DMA setup fails during probe.
Make sure to the clear the DMA channel pointers on setup failure to avoid dereferencing an error pointer on later probe errors or driver unbind.
This issue was flagged by Sashiko when reviewing a devres allocation conversion patch.
--- drivers/spi/spi-ep93xx.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/spi/spi-ep93xx.c +2 -0
@@ -582,12 +582,14 @@ static int ep93xx_spi_setup_dma(struct device *dev, struct ep93xx_spi *espi) espi->dma_rx =dma_request_chan (dev,"rx" );if (IS_ERR (espi->dma_rx)) { ret =dev_err_probe (dev,PTR_ERR (espi->dma_rx),"rx DMA setup failed" ); + espi->dma_rx =NULL ; goto fail_free_page; } espi->dma_tx =dma_request_chan (dev,"tx" );if (IS_ERR (espi->dma_tx)) { ret =dev_err_probe (dev,PTR_ERR (espi->dma_tx),"tx DMA setup failed" ); + espi->dma_tx =NULL ; goto fail_release_rx; }
Signature · 1 line
2.54.0
Greg Kroah-Hartman
maintainerPATCH 109/272 spi: sprd: fix error pointer deref after DMA setup failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 3d67fffb74267772d461c02c67f1eff893ad547d upstream.
The driver falls back to PIO mode if DMA setup fails during probe.
Make sure to check the dma.enabled flag before trying to release the DMA channels also on late probe errors to avoid dereferencing an error pointer (or attempting to release a channel a second time).
This issue was flagged by Sashiko when reviewing a devres allocation conversion patch.
--- drivers/spi/spi-sprd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/spi-sprd.c +2 -1
@@ -993,7 +993,8 @@ err_rpm_put: disable_clk:clk_disable_unprepare (ss->clk); release_dma: -sprd_spi_dma_release (ss); +if (ss->dma.enable) +sprd_spi_dma_release (ss); free_controller:spi_controller_put (sctlr);
Greg Kroah-Hartman
maintainerPATCH 110/272 spi: ti-qspi: fix use-after-free after DMA setup failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit ea6ec3343e05f7937a53eb6d7617b3abdb4abc19 upstream.
The driver falls back to PIO mode if DMA setup fails during probe.
Make sure to clear the DMA channel pointer also if buffer allocation fails to avoid passing a pointer to the released channel to the DMA engine (or trying to free the channel a second time on late probe errors or driver unbind).
This issue was flagged by Sashiko when reviewing a devres allocation conversion patch.
--- drivers/spi/spi-ti-qspi.c | 1 + 1 file changed, 1 insertion(+)
drivers/spi/spi-ti-qspi.c +1 -0
@@ -874,6 +874,7 @@ static int ti_qspi_probe(struct platformdev_err (qspi->dev,"dma_alloc_coherent failed, using PIO mode\n" );dma_release_channel (qspi->rx_chan); + qspi->rx_chan =NULL ; goto no_dma; } host->dma_rx = qspi->rx_chan;
Greg Kroah-Hartman
maintainerPATCH 111/272 RDMA/siw: Reject MPA FPDU length underflow before signed receive math
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 0ce1bc9e46ecabe84772bb561e373c0d9876d6f2 upstream.
A malicious connected siw peer can send an iWARP FPDU whose MPA length field (c_hdr->mpa_len, 16 bit big-endian, peer-controlled) is smaller than the fixed DDP/RDMAP header for the announced opcode. Soft-iWARP parses the full header in siw_get_hdr() based on iwarp_pktinfo[opcode] .hdr_len, but never compares mpa_len against that header length.
siw_tcp_rx_data() then derives
srx->fpdu_part_rem = be16_to_cpu(mpa_len) - fpdu_part_rcvd
+ MPA_HDR_SIZE;
where fpdu_part_rcvd equals iwarp_pktinfo[opcode].hdr_len at this point. For a tagged WRITE (hdr_len 16, MPA_HDR_SIZE 2) the smallest on-wire mpa_len of 0 yields fpdu_part_rem = -14, and any mpa_len below hdr_len - MPA_HDR_SIZE underflows to a negative int.
The signed value then flows into siw_proc_write()/siw_proc_rresp() as
bytes = min(srx->fpdu_part_rem, srx->skb_new);
is handed to siw_check_mem() as an int len (whose interval check addr + len > mem->va + mem->len is satisfied for a valid base when len is negative), and reaches siw_rx_data() -> siw_rx_kva() / siw_rx_umem() -> skb_copy_bits() as a signed copy length. The header copy branch in skb_copy_bits() promotes that to size_t, producing a multi-gigabyte read.
KASAN under a KUnit harness that drives the real kernel TCP receive path -- a loopback AF_INET socketpair, the malformed FPDU written via kernel_sendmsg, sk_data_ready firing in softirq, tcp_read_sock dispatching to siw_tcp_rx_data -- reports:
BUG: KASAN: use-after-free in skb_copy_bits+0x284/0x480
Read of size 4294967295 at addr ffff888...
Call Trace:
skb_copy_bits
siw_rx_kva
siw_rx_data
siw_check_mem
siw_proc_write
siw_tcp_rx_data
__tcp_read_sock
siw_qp_llp_data_ready
tcp_data_ready
tcp_data_queueAdd the missing invariant at the earliest point where the peer header is fully assembled. iwarp_pktinfo[*].hdr_len - MPA_HDR_SIZE is exactly the value the siw transmitter uses as the minimum mpa_len for each opcode (drivers/infiniband/sw/siw/siw_qp.c:33), so this matches the protocol contract. Out-of-range FPDUs terminate the connection with TERM_ERROR_LAYER_LLP / LLP_ETYPE_MPA / LLP_ECODE_FPDU_START -- which is RFC 5044 Section 8 error code 3 ("Marker and ULPDU Length fields do not agree on the start of an FPDU"), the correct framing-error class for this inconsistency.
--- drivers/infiniband/sw/siw/siw_qp_rx.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/infiniband/sw/siw/siw_qp_rx.c +15 -0
@@ -1082,6 +1082,21 @@ static int siw_get_hdr(struct siw_rx_str }/* +* Peer-controlled mpa_len must not underflow srx->fpdu_part_rem +* in siw_tcp_rx_data(); a negative value flows as a signed copy +* length into siw_check_mem() and skb_copy_bits(). +*/ +if (unlikely (be16_to_cpu (c_hdr->mpa_len) +MPA_HDR_SIZE < + iwarp_pktinfo[opcode].hdr_len)) { +pr_warn_ratelimited ("siw: short mpa_len %u for opcode %u (hdr_len %u)\n" , +be16_to_cpu (c_hdr->mpa_len), opcode, + iwarp_pktinfo[opcode].hdr_len); +siw_init_terminate (rx_qp (srx),TERM_ERROR_LAYER_LLP , +LLP_ETYPE_MPA ,LLP_ECODE_FPDU_START ,0 ); +return -EINVAL ; + } + +/* * DDP/RDMAP header receive completed. Check if the current * DDP segment starts a new RDMAP message or continues a previously * started RDMAP message.
Greg Kroah-Hartman
maintainerPATCH 112/272 LoongArch: Remove unused code to avoid build warning
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen <[email protected]>
commit 0ccc9d47cf020994097ff51827cebd04aa2b0bf4 upstream.
After commit feee6b2989165631b1 ("mm/memory_hotplug: shrink zones when offlining memory"), __remove_pages() doesn't need the "zone" parameter so the "page" variable is also unused. Remove the unused code to avoid such build warning:
arch/loongarch/mm/init.c: In function 'arch_remove_memory':arch/loongarch/mm/init.c:134:22: warning: variable 'page' set but not used [-Wunused-but-set-variable=]
134 | struct page *page = pfn_to_page(start_pfn);
--- arch/loongarch/mm/init.c | 4 ---- 1 file changed, 4 deletions(-)
arch/loongarch/mm/init.c +0 -4
@@ -107,11 +107,7 @@ void arch_remove_memory(u64 start, u64 s {unsigned long start_pfn = start >>PAGE_SHIFT ;unsigned long nr_pages = size >>PAGE_SHIFT ; -struct page *page =pfn_to_page (start_pfn); -/* With altmap the first mapped page is offset from @start */ -if (altmap) - page +=vmem_altmap_offset (altmap);__remove_pages (start_pfn, nr_pages, altmap); }
Greg Kroah-Hartman
maintainerPATCH 113/272 device property: set fwnode->secondary to NULL in fwnode_init()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
commit 215c90ee656114f5e8c32408228d97082f8e0eef upstream.
If a firmware node is allocated on the stack (for instance: temporary software node whose life-time we control) or on the heap - but using a non-zeroing allocation function - and initialized using fwnode_init(), its secondary pointer will contain uninitalized memory which likely will be neither NULL nor IS_ERR() and so may end up being dereferenced (for
example: in dev_to_swnode()). Set fwnode->secondary to NULL on initialization.
--- include/linux/fwnode.h | 1 + 1 file changed, 1 insertion(+)
include/linux/fwnode.h +1 -0
@@ -200,6 +200,7 @@ struct fwnode_operations {static inline void fwnode_init (struct fwnode_handle *fwnode,const struct fwnode_operations *ops) { + fwnode->secondary =NULL ; fwnode->ops = ops;INIT_LIST_HEAD (&fwnode->consumers);INIT_LIST_HEAD (&fwnode->suppliers);
Greg Kroah-Hartman
maintainerPATCH 114/272 drm/virtio: use uninterruptible resv lock for plane updates
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
commit 9af1b6e175c82daf4b423da339a722d8e67a735a upstream.
virtio_gpu_cursor_plane_update() and virtio_gpu_resource_flush() lock the framebuffer BO's dma_resv via virtio_gpu_array_lock_resv() and ignore its return value. The function can fail with -EINTR from dma_resv_lock_interruptible() (signal during lock wait) or with -ENOMEM from dma_resv_reserve_fences() (fence slot allocation), leaving the resv lock not held. The queue path then walks the object array and calls dma_resv_add_fence(), which requires the lock held; with lockdep enabled this trips dma_resv_assert_held():
WARNING: drivers/dma-buf/dma-resv.c:296 at dma_resv_add_fence+0x71e/0x840 Call Trace: virtio_gpu_array_add_fence virtio_gpu_queue_ctrl_sgs virtio_gpu_queue_fenced_ctrl_buffer virtio_gpu_cursor_plane_update drm_atomic_helper_commit_planes drm_atomic_helper_commit_tail commit_tail drm_atomic_helper_commit drm_atomic_commit drm_atomic_helper_update_plane __setplane_atomic drm_mode_cursor_universal drm_mode_cursor_common drm_mode_cursor_ioctl drm_ioctl __x64_sys_ioctl
Beyond the WARN, mutating the dma_resv fence list without the lock races with concurrent readers/writers and can corrupt the list.
Both call sites run inside the .atomic_update plane callback, which DRM atomic helpers do not allow to fail (by the time it runs, the commit has been signed off to userspace and there is no clean rollback path). Moving the lock acquisition to .prepare_fb was rejected because the broader lock scope deadlocks against other BO locking paths in the same atomic commit.
Introduce virtio_gpu_lock_one_resv_uninterruptible() that uses dma_resv_lock() instead of dma_resv_lock_interruptible(). This eliminates the -EINTR failure mode -- the realistic syzbot trigger -- without extending the lock hold across the commit. The helper locks a single BO and rejects nents > 1 with -EINVAL; both fix sites lock exactly one BO.
Use it from virtio_gpu_cursor_plane_update() and virtio_gpu_resource_flush(); check the return value to handle the remaining -ENOMEM case from dma_resv_reserve_fences() by freeing the objs and skipping the plane update for that frame. The framebuffer BOs touched here are not shared with other contexts and lock contention is expected to be brief, so the loss of signal-interruptibility is acceptable.
Other callers of virtio_gpu_array_lock_resv() (the ioctl paths) continue to use the interruptible variant.
The bug was reported by syzbot, triggered via fault injection (fail_nth) on the DRM_IOCTL_MODE_CURSOR path, which forces the -ENOMEM branch in dma_resv_reserve_fences().
--- drivers/gpu/drm/virtio/virtgpu_drv.h | 1 + drivers/gpu/drm/virtio/virtgpu_gem.c | 17 +++++++++++++++++ drivers/gpu/drm/virtio/virtgpu_plane.c | 10 ++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-)
drivers/gpu/drm/virtio/virtgpu_drv.h +1 -0
@@ -318,6 +318,7 @@ virtio_gpu_array_from_handles(struct drmvoid virtio_gpu_array_add_obj (struct virtio_gpu_object_array *objs,struct drm_gem_object *obj);int virtio_gpu_array_lock_resv (struct virtio_gpu_object_array *objs); +int virtio_gpu_lock_one_resv_uninterruptible (struct virtio_gpu_object_array *objs);void virtio_gpu_array_unlock_resv (struct virtio_gpu_object_array *objs);void virtio_gpu_array_add_fence (struct virtio_gpu_object_array *objs,struct dma_fence *fence);
drivers/gpu/drm/virtio/virtgpu_gem.c +17 -0
@@ -236,6 +236,23 @@ int virtio_gpu_array_lock_resv(struct vireturn ret; } +int virtio_gpu_lock_one_resv_uninterruptible (struct virtio_gpu_object_array *objs) +{ +int ret; + +if (objs->nents !=1 ) +return -EINVAL ; + +dma_resv_lock (objs->objs[0 ]->resv,NULL ); + + ret =dma_resv_reserve_fences (objs->objs[0 ]->resv,1 ); +if (ret) { +virtio_gpu_array_unlock_resv (objs); +return ret; + } +return 0 ; +} +void virtio_gpu_array_unlock_resv (struct virtio_gpu_object_array *objs) {if (objs->nents ==1 ) {
drivers/gpu/drm/virtio/virtgpu_plane.c +8 -2
@@ -168,7 +168,10 @@ static void virtio_gpu_resource_flush(stif (!objs)return ;virtio_gpu_array_add_obj (objs, vgfb->base.obj[0 ]); -virtio_gpu_array_lock_resv (objs); +if (virtio_gpu_lock_one_resv_uninterruptible (objs)) { +virtio_gpu_array_put_free (objs); +return ; + }virtio_gpu_cmd_resource_flush (vgdev, bo->hw_res_handle, x, y, width, height, objs, vgplane_st->fence);
@@ -339,7 +342,10 @@ static void virtio_gpu_cursor_plane_updaif (!objs)return ;virtio_gpu_array_add_obj (objs, vgfb->base.obj[0 ]); -virtio_gpu_array_lock_resv (objs); +if (virtio_gpu_lock_one_resv_uninterruptible (objs)) { +virtio_gpu_array_put_free (objs); +return ; + } virtio_gpu_cmd_transfer_to_host_2d (vgdev, 0, plane->state->crtc_w,
Greg Kroah-Hartman
maintainerPATCH 115/272 drm/amdgpu/vpe: Force collaborate sync after TRAP
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Liu <[email protected]>
commit b6074630a461b1322a814988779005cbc43612ea upstream.
VPE1 could possibly hang and fail to power off at the end of commands in collaboration mode. This workaround adds a COLLAB_SYNC after TRAP to force instances synchronized to avoid VPE1 fail to power off.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c +6 -1
@@ -556,6 +556,11 @@ static void vpe_ring_emit_fence(struct aamdgpu_ring_write (ring,0 ); } +/* WA: Force sync after TRAP to avoid VPE1 fail to power off */ +if (ring->adev->vpe.collaborate_mode) { +amdgpu_ring_write (ring,VPE_CMD_HEADER (VPE_CMD_OPCODE_COLLAB_SYNC ,0 )); +amdgpu_ring_write (ring,0xabcd ); + } }static void vpe_ring_emit_pipeline_sync (struct amdgpu_ring *ring)
@@ -904,7 +909,7 @@ static const struct amdgpu_ring_funcs vp .emit_frame_size =5 +/* vpe_ring_init_cond_exec */ 6 +/* vpe_ring_emit_pipeline_sync */ -10 +10 +10 +/* vpe_ring_emit_fence */ +12 +12 +12 +/* vpe_ring_emit_fence */ /* vpe_ring_emit_vm_flush */ SOC15_FLUSH_GPU_TLB_NUM_WREG *3 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6,
Greg Kroah-Hartman
maintainerPATCH 116/272 drm/bridge: it66121: acquire reset GPIO in probe
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julien Chauveau <[email protected]>
commit e02b5262fd288cc235f14e12233ea54e78c04611 upstream.
The it66121_ctx structure has a gpio_reset field, and it66121_hw_reset() calls gpiod_set_value() on it. However, the GPIO descriptor is never acquired via devm_gpiod_get(), leaving gpio_reset as NULL throughout the driver lifetime.
gpiod_set_value() silently returns when passed a NULL descriptor, so the hardware reset sequence in it66121_hw_reset() is a no-op. This leaves the chip in an undefined state at probe time, which can prevent it from responding on the I2C bus.
The DT binding marks reset-gpios as a required property, so all compliant device trees provide this GPIO. Add the missing devm_gpiod_get() call after enabling power supplies and before the hardware reset, so the chip is properly reset with power applied.
--- drivers/gpu/drm/bridge/ite-it66121.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/bridge/ite-it66121.c +5 -0
@@ -1559,6 +1559,11 @@ static int it66121_probe(struct i2c_cliereturn ret; } + ctx->gpio_reset =devm_gpiod_get (dev,"reset" ,GPIOD_OUT_LOW ); +if (IS_ERR (ctx->gpio_reset)) +return dev_err_probe (dev,PTR_ERR (ctx->gpio_reset), +"Failed to get reset GPIO\n" ); +it66121_hw_reset (ctx); ctx->regmap =devm_regmap_init_i2c (client, &it66121_regmap_config);
Greg Kroah-Hartman
maintainerPATCH 117/272 drm/bridge: megachips: remove bridge when irq request fails
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Osama Abdelkader <[email protected]>
commit d45d5c819f2cd0b6b5d76a194a537a5f4aeefecb upstream.
If devm_request_threaded_irq() fails after drm_bridge_add(), remove the bridge before returning.
Keep drm_bridge_add() rather than devm_drm_bridge_add(): registration is tied to the STDP4028 device while ge_b850v3_register() may complete from either I2C probe; devm would not unwind the bridge if the other client's probe fails.
--- drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 16 +++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +10 -6
@@ -258,7 +258,6 @@ static void ge_b850v3_lvds_remove(void) goto out;drm_bridge_remove (&ge_b850v3_lvds_ptr->bridge); - ge_b850v3_lvds_ptr =NULL ; out:mutex_unlock (&ge_b850v3_lvds_dev_mutex);
@@ -268,6 +267,7 @@ static int ge_b850v3_register(void) {struct i2c_client *stdp4028_i2c = ge_b850v3_lvds_ptr->stdp4028_i2c;struct device *dev = &stdp4028_i2c->dev; +int ret;/* drm bridge initialization */ ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs;
@@ -285,11 +285,15 @@ static int ge_b850v3_register(void)if (!stdp4028_i2c->irq)return 0 ; -return devm_request_threaded_irq (&stdp4028_i2c->dev, - stdp4028_i2c->irq,NULL , - ge_b850v3_lvds_irq_handler, -IRQF_TRIGGER_HIGH |IRQF_ONESHOT , -"ge-b850v3-lvds-dp" , ge_b850v3_lvds_ptr); + ret =devm_request_threaded_irq (&stdp4028_i2c->dev, + stdp4028_i2c->irq,NULL , + ge_b850v3_lvds_irq_handler, +IRQF_TRIGGER_HIGH |IRQF_ONESHOT , +"ge-b850v3-lvds-dp" , ge_b850v3_lvds_ptr); +if (ret) +drm_bridge_remove (&ge_b850v3_lvds_ptr->bridge); + +return ret; }static int stdp4028_ge_b850v3_fw_probe (struct i2c_client *stdp4028_i2c)
Greg Kroah-Hartman
maintainerPATCH 118/272 drm/amd/display: Fix integer overflow in bios_get_image()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Wentland <[email protected]>
commit cd86529ec61474a38c3837fb7823790a7c3f8cce upstream.
[Why&How]
The bounds check in bios_get_image() computes 'offset + size' using unsigned 32-bit arithmetic before comparing against bios_size. If a VBIOS image contains a near-UINT32_MAX offset the addition wraps to a small value, the comparison passes, and the function returns a wild pointer past the VBIOS mapping.
Additionally, the comparison uses '<' (strict), which incorrectly rejects the valid exact-fit case where offset + size == bios_size.
Fix both issues by restructuring the check to avoid the addition
entirely: first reject if offset alone exceeds bios_size, then check size against the remaining space (bios_size - offset). This eliminates the overflow and correctly permits exact-fit accesses.
--- drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c +6 -3
@@ -37,10 +37,13 @@ uint8_t *bios_get_image(struct dc_bios * uint32_t offset, uint32_t size) { -if (bp->bios && offset + size < bp->bios_size) -return bp->bios + offset; -else +if (!bp->bios)return NULL ; + +if (offset > bp->bios_size || size > bp->bios_size - offset) +return NULL ; + +return bp->bios + offset; }#include "reg_helper.h"
Greg Kroah-Hartman
maintainerPATCH 119/272 drm/amd/display: Validate GPIO pin LUT table size before iterating
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Wentland <[email protected]>
commit 86d2b20644b11d21fe52c596e6e922b4590a3e3f upstream.
[Why&How]
The GPIO pin table parsers in get_gpio_i2c_info() and bios_parser_get_gpio_pin_info() derive an element count from the VBIOS table_header.structuresize field, then iterate over gpio_pin[] entries. However, GET_IMAGE() only validates that the table header itself fits within the BIOS image. If the VBIOS reports a structuresize larger than the actual mapped data, the loop reads past the end of the BIOS image, causing an out-of-bounds read.
Fix this by calling bios_get_image() to validate that the full claimed structuresize is accessible within the BIOS image before entering the loop in both functions.
--- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +9 -0
@@ -492,6 +492,10 @@ static enum bp_result get_gpio_i2c_info( - sizeof(struct atom_common_table_header)) /sizeof (struct atom_gpio_pin_assignment ); +if (!bios_get_image (&bp->base,DATA_TABLES (gpio_pin_lut), +le16_to_cpu (header->table_header.structuresize))) +return BP_RESULT_BADBIOSTABLE ; + pin = (struct atom_gpio_pin_assignment *) header->gpio_pin;for (table_index =0 ; table_index < count; table_index++) {
@@ -680,6 +684,11 @@ static enum bp_result bios_parser_get_gp count = (le16_to_cpu (header->table_header.structuresize) -sizeof (struct atom_common_table_header )) /sizeof (struct atom_gpio_pin_assignment ); + +if (!bios_get_image (&bp->base,DATA_TABLES (gpio_pin_lut), +le16_to_cpu (header->table_header.structuresize))) +return BP_RESULT_BADBIOSTABLE ; +for (i =0 ; i < count; ++i) {if (header->gpio_pin[i].gpio_id != gpio_id)continue ;
Greg Kroah-Hartman
maintainerPATCH 120/272 drm/amd/display: Validate payload length and link_index in dc_process_dmub_aux_transfer_async
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Wentland <[email protected]>
commit 6c92f6d9600efa3ef0d9e560a2b52776d9803c29 upstream.
[Why&How]dc_process_dmub_aux_transfer_async() copies payload->length bytes into a 16-byte stack buffer (dpaux.data[16]) guarded only by an ASSERT(), which is a no-op in release builds. If a caller ever passes length > 16 this results in a stack buffer overflow via memcpy.
Additionally, link_index is used to dereference dc->links[] without bounds checking against dc->link_count, risking an out-of-bounds access.
Replace the ASSERT with a hard runtime check that returns false when payload->length exceeds the destination buffer size, and add a bounds check for link_index before it is used.
--- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/core/dc.c +5 -1
@@ -5661,7 +5661,11 @@ bool dc_process_dmub_aux_transfer_async(uint8_t action;union dmub_rb_cmd cmd = {0 }; -ASSERT (payload->length <=16 ); +if (link_index >= dc->link_count || !dc->links[link_index]) +return false; + +if (payload->length >sizeof (cmd.dp_aux_access.aux_control.dpaux.data)) +return false; cmd.dp_aux_access.header.type =DMUB_CMD__DP_AUX_ACCESS ; cmd.dp_aux_access.header.payload_bytes =0 ;
Greg Kroah-Hartman
maintainerPATCH 121/272 batman-adv: mcast: fix use-after-free in orig_node RCU release
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 20c2d6a20ca936f5aaa6dd40f73f262ac45c87cc upstream.
batadv_mcast_purge_orig() removes entries from RCU-protected hlists but does not wait for an RCU grace period before returning. Concurrent RCU readers may still accesses references to those entries at the point of removal. RCU-protected readers trying to operate on entries like orig->mcast_want_all_ipv6_node will then access already freed memory.
Fix this by moving batadv_mcast_purge_orig() to batadv_orig_node_release(), just before the call_rcu() invocation. This ensures RCU readers that were active at purge time have drained before the orig_node memory is reclaimed.
--- net/batman-adv/originator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/batman-adv/originator.c +2 -2
@@ -850,8 +850,6 @@ static void batadv_orig_node_free_rcu(st orig_node = container_of(rcu, struct batadv_orig_node, rcu); -batadv_mcast_purge_orig (orig_node); -batadv_frag_purge_orig (orig_node,NULL );kfree (orig_node->tt_buff);
@@ -905,6 +903,8 @@ void batadv_orig_node_release(struct kre/* Free nc_nodes */ batadv_nc_purge_orig (orig_node->bat_priv, orig_node,NULL ); +batadv_mcast_purge_orig (orig_node); +call_rcu (&orig_node->rcu, batadv_orig_node_free_rcu); }
Greg Kroah-Hartman
maintainerPATCH 122/272 batman-adv: clear current gateway during teardown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruijie Li <[email protected]>
commit a340a51ed801eab7bb454150c226323b865263cc upstream.
batadv_gw_node_free() removes the gateway list entries during mesh teardown, but it does not clear the currently selected gateway. This leaves stale gateway state behind across cleanup and can break a later mesh recreation.
Clear bat_priv->gw.curr_gw before walking the gateway list so the selected gateway reference is dropped as part of teardown.
--- net/batman-adv/gateway_client.c | 4 ++++ 1 file changed, 4 insertions(+)
net/batman-adv/gateway_client.c +4 -0
@@ -479,10 +479,14 @@ void batadv_gw_node_delete(struct batadv*/ void batadv_gw_node_free (struct batadv_priv *bat_priv) { +struct batadv_gw_node *curr_gw;struct batadv_gw_node *gw_node;struct hlist_node *node_tmp;spin_lock_bh (&bat_priv->gw.list_lock); + curr_gw =rcu_replace_pointer (bat_priv->gw.curr_gw,NULL , true); +batadv_gw_node_put (curr_gw); +hlist_for_each_entry_safe (gw_node, node_tmp, &bat_priv->gw.gateway_list, list) {hlist_del_init_rcu (&gw_node->list);
Greg Kroah-Hartman
maintainerPATCH 123/272 batman-adv: dat: handle forward allocation error
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 2d8826a2d3657cea66fb0370f9e521575a673871 upstream.
batadv_dat_forward_data() calls pskb_copy_for_clone() to duplicate an skb for each DHT candidate, but does not check the return value before passing it to batadv_send_skb_prepare_unicast_4addr(). That function dereferences the skb unconditionally, so a failed allocation triggers a NULL pointer dereference.
Skip forwarding to the current DHT candidate on allocation failure.
--- net/batman-adv/distributed-arp-table.c | 3 +++ 1 file changed, 3 insertions(+)
net/batman-adv/distributed-arp-table.c +3 -0
@@ -698,6 +698,9 @@ static bool batadv_dat_forward_data(stru goto free_orig; tmp_skb =pskb_copy_for_clone (skb,GFP_ATOMIC ); +if (!tmp_skb) + goto free_neigh; +if (!batadv_send_skb_prepare_unicast_4addr (bat_priv, tmp_skb, cand[i].orig_node, packet_subtype)) {
Greg Kroah-Hartman
maintainerPATCH 124/272 batman-adv: fix fragment reassembly length accounting
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruide Cao <[email protected]>
commit 9cd3f16c320bfdadd4509358122368deb56a5741 upstream.
batman-adv keeps a running payload length for queued fragments and uses it to validate a fragment chain before reassembly.
That accounting currently allows the accumulated fragment length to be truncated during updates. As a result, malformed fragment chains can bypass the intended validation and drive reassembly with inconsistent length state, leading to a local denial of service.
Fix the accounting by storing the accumulated length in a length-typed field and rejecting update overflows before the existing validation logic runs.
The fix was verified against the original reproducer and against valid fragment reassembly paths.
--- net/batman-adv/fragmentation.c | 23 +++++++++++++++++------ net/batman-adv/types.h | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-)
net/batman-adv/fragmentation.c +17 -6
@@ -17,6 +17,7 @@#include <linux/lockdep.h> #include <linux/minmax.h> #include <linux/netdevice.h> +#include <linux/overflow.h> #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/spinlock.h>
@@ -80,9 +81,9 @@ void batadv_frag_purge_orig(struct batad* * Return: the maximum size of payload that can be fragmented. */ -static int batadv_frag_size_limit (void ) +static size_t batadv_frag_size_limit (void ) { -int limit =BATADV_FRAG_MAX_FRAG_SIZE ; +size_t limit =BATADV_FRAG_MAX_FRAG_SIZE ; limit -=sizeof (struct batadv_frag_packet ); limit *=BATADV_FRAG_MAX_FRAGMENTS ;
@@ -143,7 +144,9 @@ static bool batadv_frag_insert_packet(ststruct batadv_frag_packet *frag_packet;u8 bucket;u16 seqno, hdr_size =sizeof (struct batadv_frag_packet ); +bool overflow = false;bool ret = false; +size_t data_len;/* Linearize packet to avoid linearizing 16 packets in a row when doing * the later merge. Non-linear merge should be added to remove this
@@ -153,6 +156,7 @@ static bool batadv_frag_insert_packet(st goto err; frag_packet = (struct batadv_frag_packet *)skb->data; + data_len = skb->len - hdr_size; seqno =ntohs (frag_packet->seqno); bucket = seqno %BATADV_FRAG_BUFFER_COUNT ;
@@ -171,7 +175,7 @@ static bool batadv_frag_insert_packet(stspin_lock_bh (&chain->lock);if (batadv_frag_init_chain (chain, seqno)) {hlist_add_head (&frag_entry_new->list, &chain->fragment_list); - chain->size = skb->len - hdr_size; + chain->size = data_len; chain->timestamp = jiffies; chain->total_size =ntohs (frag_packet->total_size); ret = true;
@@ -188,7 +192,11 @@ static bool batadv_frag_insert_packet(stif (frag_entry_curr->no < frag_entry_new->no) {hlist_add_before (&frag_entry_new->list, &frag_entry_curr->list); - chain->size += skb->len - hdr_size; + +if (check_add_overflow (chain->size, data_len, + &chain->size)) + overflow = true; + chain->timestamp = jiffies; ret = true; goto out;
@@ -201,13 +209,16 @@ static bool batadv_frag_insert_packet(st/* Reached the end of the list, so insert after 'frag_entry_last'. */ if (likely (frag_entry_last)) {hlist_add_behind (&frag_entry_new->list, &frag_entry_last->list); - chain->size += skb->len - hdr_size; + +if (check_add_overflow (chain->size, data_len, &chain->size)) + overflow = true; + chain->timestamp = jiffies; ret = true; } out: -if (chain->size >batadv_frag_size_limit () || +if (overflow || chain->size >batadv_frag_size_limit () || chain->total_size !=ntohs (frag_packet->total_size) || chain->total_size >batadv_frag_size_limit ()) {/* Clear chain if total size of either the list or the packet
net/batman-adv/types.h +1 -1
@@ -295,7 +295,7 @@ struct batadv_frag_table_entry {u16 seqno;/** @size: accumulated size of packets in list */ -u16 size; +size_t size;/** @total_size: expected size of the assembled packet */ u16 total_size;
Greg Kroah-Hartman
maintainerPATCH 125/272 batman-adv: fix tp_meter counter underflow during shutdown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luxiao Xu <[email protected]>
commit 94f3b133168d1c49895e7cc6afbcf1cc0b354602 upstream.
batadv_tp_sender_shutdown() unconditionally decrements the "sending" atomic counter. If multiple paths (e.g. timeout, user cancel, and normal finish) call this function, the counter can underflow to -1.
Since the sender logic treats any non-zero value as "still sending", a negative value causes the sender kthread to loop indefinitely. This leads to a use-after-free when the interface is removed while the zombie thread is still active.
Fix this by using atomic_xchg() to ensure the counter only transitions from 1 to 0 once.
--- net/batman-adv/tp_meter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/batman-adv/tp_meter.c +2 -2
@@ -451,7 +451,7 @@ static void batadv_tp_sender_end(structstatic void batadv_tp_sender_shutdown (struct batadv_tp_vars *tp_vars,enum batadv_tp_meter_reason reason) { -if (!atomic_dec_and_test (&tp_vars->sending)) +if (atomic_xchg (&tp_vars->sending,0 ) !=1 )return ; tp_vars->reason = reason;
@@ -885,7 +885,7 @@ static int batadv_tp_send(void *arg)"Meter: %s() cannot send packets (%d)\n" , __func__, err);/* ensure nobody else tries to stop the thread now */ -if (atomic_dec_and_test (&tp_vars->sending)) +if (atomic_xchg (&tp_vars->sending,0 ) ==1 ) tp_vars->reason = err;break ; }
Greg Kroah-Hartman
maintainerPATCH 126/272 batman-adv: frag: disallow unicast fragment in fragment
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit bc62216dc8e221e3781afa14430f45208bfa9af9 upstream.
batadv_frag_skb_buffer() is called by batadv_batman_skb_recv() when a BATADV_UNICAST_FRAG packet is received. Once all fragments are collected and the packet is reassembled, batadv_recv_frag_packet() calls batadv_batman_skb_recv() again to process the defragmented payload.
A malicious sender can craft a BATADV_UNICAST_FRAG packet whose reassembled payload is itself a BATADV_UNICAST_FRAG packet (matryoshka-style nesting). Each nesting level recurses through batadv_batman_skb_recv() without bound, growing the kernel stack until it is exhausted.
Since refragmentation or fragments in fragments are not actually allowed, discard all packets which are still BATADV_UNICAST_FRAG packets after the defragmentation process.
--- net/batman-adv/fragmentation.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
net/batman-adv/fragmentation.c +35 -0
@@ -305,6 +305,31 @@ free: }/** +* batadv_skb_is_frag() - check if newly merged skb is gain a unicast packet +* @skb: newly merged skb +* +* Return: if newly skb is of type BATADV_UNICAST_FRAG +*/ +static bool batadv_skb_is_frag (struct sk_buff *skb) +{ +struct batadv_ogm_packet *batadv_ogm_packet; + +/* packet should hold at least type and version */ +if (unlikely (!pskb_may_pull (skb,2 ))) +return false; + + batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data; + +if (batadv_ogm_packet->version !=BATADV_COMPAT_VERSION ) +return false; + +if (batadv_ogm_packet->packet_type !=BATADV_UNICAST_FRAG ) +return false; + +return true; +} + +/** * batadv_frag_skb_buffer() - buffer fragment for later merge * @skb: skb to buffer * @orig_node_src: originator that the skb is received from
@@ -337,6 +362,16 @@ bool batadv_frag_skb_buffer(struct sk_buif (!skb_out) goto out_err; +/* fragment in fragment is not allowed. otherwise it is possible +* to exhaust the stack when receiving a matryoshka-style +* "fragments in a fragment packet" +*/ +if (batadv_skb_is_frag (skb_out)) { +kfree_skb (skb_out); + skb_out =NULL ; + goto out_err; + } + out: ret = true; out_err:
Greg Kroah-Hartman
maintainerPATCH 127/272 batman-adv: bla: fix report_work leak on backbone_gw purge
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 0459430add32ea41f3e2ef9351610e6d33627a6b upstream.
batadv_bla_purge_backbone_gw() removes stale backbone gateway entries, but fails to properly handle their associated report_work:
- If report_work is running, the purge must wait for it to finish before freeing the backbone_gw, otherwise the worker may access freed memory (e.g. bat_priv).
- If report_work is pending, the purge must cancel it and release the reference held for that pending work item.
The previous implementation called hlist_for_each_entry_safe() inside a spin_lock_bh() section, but cancel_work_sync() may sleep and therefore cannot be called from within a spinlock-protected region.
Restructure the loop to handle one entry per spinlock critical section:
acquire the lock, find the next entry to purge, remove it from the hash list, then release the lock before calling cancel_work_sync() and dropping the hash_entry reference. Repeat until no more entries require purging.
--- net/batman-adv/bridge_loop_avoidance.c | 60 ++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 22 deletions(-)
net/batman-adv/bridge_loop_avoidance.c +38 -22
@@ -1224,6 +1224,7 @@ static void batadv_bla_purge_backbone_gwstruct hlist_head *head;struct batadv_hashtable *hash;spinlock_t *list_lock;/* protects write access to the hash lists */ +bool purged;int i; hash = bat_priv->bla.backbone_hash;
@@ -1234,30 +1235,45 @@ static void batadv_bla_purge_backbone_gw head = &hash->table[i]; list_lock = &hash->list_locks[i]; -spin_lock_bh (list_lock); -hlist_for_each_entry_safe (backbone_gw, node_tmp, - head, hash_entry) { -if (now) - goto purge_now; -if (!batadv_has_timed_out (backbone_gw->lasttime, -BATADV_BLA_BACKBONE_TIMEOUT )) -continue ; - -batadv_dbg (BATADV_DBG_BLA , backbone_gw->bat_priv, -"%s(): backbone gw %pM timed out\n" , - __func__, backbone_gw->orig); +do { + purged = false; + +spin_lock_bh (list_lock); +hlist_for_each_entry_safe (backbone_gw, node_tmp, + head, hash_entry) { +if (now) + goto purge_now; +if (!batadv_has_timed_out (backbone_gw->lasttime, +BATADV_BLA_BACKBONE_TIMEOUT )) +continue ; + +batadv_dbg (BATADV_DBG_BLA , backbone_gw->bat_priv, +"%s(): backbone gw %pM timed out\n" , + __func__, backbone_gw->orig); purge_now: -/* don't wait for the pending request anymore */ -if (atomic_read (&backbone_gw->request_sent)) -atomic_dec (&bat_priv->bla.num_requests); - -batadv_bla_del_backbone_claims (backbone_gw); - -hlist_del_rcu (&backbone_gw->hash_entry); -batadv_backbone_gw_put (backbone_gw); - } -spin_unlock_bh (list_lock); + purged = true; + +/* don't wait for the pending request anymore */ +if (atomic_read (&backbone_gw->request_sent)) +atomic_dec (&bat_priv->bla.num_requests); + +batadv_bla_del_backbone_claims (backbone_gw); + +hlist_del_rcu (&backbone_gw->hash_entry); +break ; + } +spin_unlock_bh (list_lock); + +if (purged) { +/* reference for pending report_work */ +if (cancel_work_sync (&backbone_gw->report_work)) +batadv_backbone_gw_put (backbone_gw); + +/* reference for hash_entry */ +batadv_backbone_gw_put (backbone_gw); + } + }while (purged); } }
Greg Kroah-Hartman
maintainerPATCH 128/272 batman-adv: tp_meter: avoid use of uninit sender vars
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 6c65cf23d4c6170fcf5714c32aa64689718cb142 upstream.
batadv_tp_recv_ack() and batadv_tp_stop() are only valid for tp_vars in the BATADV_TP_SENDER role. When called with a BATADV_TP_RECEIVER role, it proceeds to read sender-only members that were never initialized, leading to undefined behavior.
This can be triggered when a node that is currently acting as a receiver in an ongoing tp_meter session receives a malicious ACK packet.
Guard against this by checking tp_vars->role immediately after the lookup and bailing out if it is not BATADV_TP_SENDER, before any of those members are accessed.
--- net/batman-adv/tp_meter.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
net/batman-adv/tp_meter.c +9 -2
@@ -663,6 +663,9 @@ static void batadv_tp_recv_ack(struct baif (unlikely (!tp_vars))return ; +if (unlikely (tp_vars->role !=BATADV_TP_SENDER )) + goto out; +if (unlikely (atomic_read (&tp_vars->sending) ==0 )) goto out;
@@ -1100,12 +1103,16 @@ void batadv_tp_stop(struct batadv_priv *if (!tp_vars) {batadv_dbg (BATADV_DBG_TP_METER , bat_priv,"Meter: trying to interrupt an already over connection\n" ); - goto out; + goto out_put_orig_node; } +if (unlikely (tp_vars->role !=BATADV_TP_SENDER )) + goto out_put_tp_vars; +batadv_tp_sender_shutdown (tp_vars, return_value); +out_put_tp_vars:batadv_tp_vars_put (tp_vars); -out: +out_put_orig_node:batadv_orig_node_put (orig_node); }
Greg Kroah-Hartman
maintainerPATCH 129/272 batman-adv: tp_meter: fix tp_vars reference leak in receiver shutdown
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 77098e4bea37af51d3962efa88a5af2ea5e1ac57 upstream.
The receiver shutdown timer handler, batadv_tp_receiver_shutdown(), is responsible for releasing the tp_vars reference it holds. However, the existing logic for coordinating this release with batadv_tp_stop_all() was flawed.
timer_shutdown_sync() guarantees the timer will not fire again after it returns, but it returns non-zero only when the timer was pending at the time of the call. If the timer had already expired (and batadv_tp_stop_all() would unsucessfully try to rearm itself), batadv_tp_stop_all() skips its batadv_tp_vars_put(), and batadv_tp_receiver_shutdown() fails to put its own reference as well.
Fix this by introducing a new atomic variable receiving that is set to 1 when the receiver is initialized and cleared atomically with atomic_xchg() by whichever side claims it first. Only the side that observes the transition from 1 to 0 is responsible for releasing the tp_vars timer reference, eliminating the uncertainty.
--- net/batman-adv/tp_meter.c | 13 +++++++++++-- net/batman-adv/types.h | 3 +++ 2 files changed, 14 insertions(+), 2 deletions(-)
net/batman-adv/tp_meter.c +11 -2
@@ -8,6 +8,7 @@#include "main.h" #include <linux/atomic.h> +#include <linux/bug.h> #include <linux/build_bug.h> #include <linux/byteorder/generic.h> #include <linux/cache.h>
@@ -1163,6 +1164,9 @@ static void batadv_tp_receiver_shutdown(spin_unlock_bh (&tp_vars->unacked_lock);/* drop reference of timer */ +if (WARN_ON (atomic_xchg (&tp_vars->receiving,0 ) !=1 )) +return ; +batadv_tp_vars_put (tp_vars); }
@@ -1381,6 +1385,7 @@ batadv_tp_init_recv(struct batadv_priv *ether_addr_copy (tp_vars->other_end, icmp->orig); tp_vars->role =BATADV_TP_RECEIVER ; +atomic_set (&tp_vars->receiving,1 );memcpy (tp_vars->session, icmp->session,sizeof (tp_vars->session)); tp_vars->last_recv =BATADV_TP_FIRST_SEQ ; tp_vars->bat_priv = bat_priv;
@@ -1553,8 +1558,12 @@ void batadv_tp_stop_all(struct batadv_prbreak ;case BATADV_TP_RECEIVER :batadv_tp_list_detach (tp_var); -if (timer_shutdown_sync (&tp_var->timer)) -batadv_tp_vars_put (tp_var); +timer_shutdown_sync (&tp_var->timer); + +if (atomic_xchg (&tp_var->receiving,0 ) !=1 ) +break ; + +batadv_tp_vars_put (tp_var);break ; }
net/batman-adv/types.h +3 -0
@@ -1461,6 +1461,9 @@ struct batadv_tp_vars {/** @sending: sending binary semaphore: 1 if sending, 0 is not */ atomic_t sending; +/** @receiving: receiving binary semaphore: 1 if receiving, 0 is not */ +atomic_t receiving; +/** @reason: reason for a stopped session */ enum batadv_tp_meter_reason reason;