Skip to contentSkip to conversation

7.0.11-rc1 review

PATCH In review Greg Kroah-Hartman 21 participants 495 messages May 28 – Jul 6 1 message not in the archive Page 1 of 4

Subsystems (6)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 7.0.11-rc1 review

This is the start of the stable review cycle for the 7.0.11 release. There are 461 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:49 +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/v7.x/stable-review/patch-7.0.11-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-7.0.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>

    Linux 7.0.11-rc1

Armin Wolf <[email protected]>
platform/x86: uniwill-laptop: Do not enable the charging limit even when forced

Werner Sembach <[email protected]>
Documentation: laptops: Update documentation for uniwill laptops

Damien Le Moal <[email protected]>
block: avoid use-after-free in disk_free_zone_resources()

Tiezhu Yang <[email protected]>
LoongArch: kprobes: Fix handling of fatal unrecoverable recursions

Junyi Liu <[email protected]>
ksmbd: fix durable reconnect error path file lifetime

Keith Busch <[email protected]>
blk-mq: pop cached request if it is usable

Alexander A. Klimov <[email protected]>
io_uring/nop: pass all errors to userspace

Wei Fang <[email protected]>

    net: enetc: fix missing error code when pf->vf_state allocation fails

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

Lorenzo Bianconi <[email protected]>
net: airoha: Disable GDM2 forwarding before configuring GDM2 loopback

Weiming Shi <[email protected]>
tap: fix stack info leak in tap_ioctl() SIOCGIFHWADDR

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

Keith Busch <[email protected]>
nvme-pci: fix dma mapping leak on data setup error

Keith Busch <[email protected]>
nvme-pci: fix dma_vecs leak on p2p memory

Nimrod Oren <[email protected]>
selftests: net: Fix checksums in xdp_native

Richard Fitzgerald <[email protected]>
ASoC: cs-amp-lib: Fix missing dput() after debugfs_lookup()

Richard Fitzgerald <[email protected]>
ASoC: cs-amp-lib: Fix wrong sizeof() in _cs_amp_set_efi_calibration_data()

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: aggregator: lock device when calling device_is_bound()

Bartosz Golaszewski <[email protected]>
gpio: aggregator: remove the software node when deactivating the aggregator

Bartosz Golaszewski <[email protected]>
gpio: aggregator: stop using dev-sync-probe

Bartosz Golaszewski <[email protected]>
gpio: aggregator: fix a potential use-after-free

Bartosz Golaszewski <[email protected]>
gpio: cdev: check if uAPI v2 config attributes are correctly zeroed

Zhi Li <[email protected]>
net: stmmac: eswin: validate RGMII delay values

Zhi Li <[email protected]>
net: stmmac: eswin: correct RGMII delay granularity to 20 ps

Zhi Li <[email protected]>
net: stmmac: eswin: clear TXD and RXD delay registers during initialization

Zhi Li <[email protected]>
net: stmmac: eswin: fix HSP CSR init ordering after clock enable

Eric Dumazet <[email protected]>
tcp: fix stale per-CPU tcp_tw_isn leak enabling ISN prediction

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

David Howells <[email protected]>
rxrpc: Fix DATA decrypt vs splice() by copying data to buffer in recvmsg

David Howells <[email protected]>
crypto/krb5, rxrpc: Fix lack of pre-decrypt/pre-verify length checks

Jakub Kicinski <[email protected]>
net: shaper: rework the VALID marking (again)

Jakub Kicinski <[email protected]>
net: shaper: annotate the data races

Prathamesh Deshpande <[email protected]>
net/mlx5e: Fix eswitch mode block underflow on IPsec acquire SA

Gal Pressman <[email protected]>
udp: Fix UDP length on last GSO_PARTIAL segment

Alice Mikityanska <[email protected]>
udp: gso: Fix handling checksum in __udp_gso_segment

Jiajia Liu <[email protected]>

    Bluetooth: btmtk: fix urb->setup_packet leak in error paths

Kiran K <[email protected]>
Bluetooth: btintel_pcie: Fix incorrect MAC access programming

Luiz Augusto von Dentz <[email protected]>
Bluetooth: hci_sync: Fix not setting mask for HCI_EVT_LE_ALL_REMOTE_FEATURES_COMPLETE

David Carlier <[email protected]>
tracing: Avoid NULL return from hist_field_name() on truncation

Cunlong Li <[email protected]>
cgroup: rstat: relax NMI guard after switch to try_cmpxchg

Zhang Cen <[email protected]>
ALSA: seq: Serialize UMP output teardown with event_input

Shitalkumar Gandhi <[email protected]>
wifi: wilc1000: fix dma_buffer leak on bus acquire failure

Johannes Berg <[email protected]>
wifi: mac80211: fix multi-link element inheritance

Johannes Berg <[email protected]>
wifi: mac80211: fix MLE defragmentation

Alexandru Hossu <[email protected]>

    wifi: mac80211: bounds-check link_id in ieee80211_ml_epcs

Jia Zhu <[email protected]>
erofs: fix metabuf leak in inode xattr initialization

Utkal Singh <[email protected]>
erofs: harden h_shared_count in erofs_init_inode_xattrs()

Gao Xiang <[email protected]>
erofs: fix managed cache race for unaligned extents

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

Christian Marangi <[email protected]>
net: airoha: Fix NPU RX DMA descriptor bits

Nicolai Buchwitz <[email protected]>
net: phy: honor eee_disabled_modes in phy_advertise_eee_all()

Nicolai Buchwitz <[email protected]>
net: phy: honor eee_disabled_modes in phy_support_eee()

Ido Schimmel <[email protected]>
bridge: mcast: Fix a possible use-after-free when removing a bridge port

Guangshuo Li <[email protected]>
RDMA/rtrs: Fix use-after-free in path file creation cleanup

Shiraz Saleem <[email protected]>
RDMA/mana_ib: Report max_msg_sz in mana_ib_query_port

Timur Kristóf <[email protected]>
drm/amdgpu/vce1: Fix VCE 1 firmware size and offsets

Timur Kristóf <[email protected]>
drm/amdgpu/vce1: Check that the GPU address is < 128 MiB

Timur Kristóf <[email protected]>
drm/amdgpu: Align amdgpu_gtt_mgr entries to TLB size on Tahiti (v2)

Robertus Diawan Chris <[email protected]>
ASoC: soc-utils: Add missing va_end in snd_soc_ret()

Ahmed Yaseen <[email protected]>
platform/x86: asus-armoury: fix mini-LED mode get/set on MODE2 devices

Armin Wolf <[email protected]>
platform/x86: uniwill-laptop: Fix behavior of "force" module param

Armin Wolf <[email protected]>
platform/x86: uniwill-laptop: Accept charging threshold of 0

Armin Wolf <[email protected]>
platform/x86: uniwill-laptop: Properly initialize charging threshold

Rafael J. Wysocki <[email protected]>
platform/x86: intel-vbtn: Check ACPI_HANDLE() against NULL

Rafael J. Wysocki <[email protected]>
platform/x86: intel_sar: 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

Xiangxu Yin <[email protected]>
phy: qcom: qmp-usbc: Fix out-of-bounds array access in dp swing config

Ankit Nautiyal <[email protected]>
drm/i915/dp: Fix readback for target_rr in Adaptive Sync SDP

Kohei Enju <[email protected]>
igc: set tx buffer type for SMD frames

Grzegorz Nitka <[email protected]>
ice: ptp: use primary NAC semaphore on E825

Grzegorz Nitka <[email protected]>
ice: ptp: serialize E825 PHY timer start with PTP lock

David Howells <[email protected]>
cifs: Fix undefined variables

Dragos Tatulea <[email protected]>
net/mlx5e: xsk: Fix unlocked writing to ICOSQ

Qing Ming <[email protected]>
cgroup/rstat: validate cpu before css_rstat_cpu() access

Paul E. McKenney <[email protected]>
srcu: Don't queue workqueue handlers to never-online CPUs

Michael Bommarito <[email protected]>

    io_uring: propagate array_index_nospec opcode into req->opcode

Louis-Alexis Eyraud <[email protected]>
drm/mediatek: mtk_hdmi_ddc: Fix non-static global variable

Louis-Alexis Eyraud <[email protected]>
drm/mediatek: mtk_cec: Fix non-static global variable

Louis-Alexis Eyraud <[email protected]>
drm/mediatek: mtk_hdmi_v2: Fix non-static global variable

Louis-Alexis Eyraud <[email protected]>
drm/mediatek: mtk_hdmi_ddc_v2: Fix non-static global variable

Baochen Qiang <[email protected]>
wifi: ath12k: fix EHT TX MCS limitation due to wrong 20 MHz-only parsing

Matthew Leach <[email protected]>
wifi: ath11k: fix peer resolution on rx path when peer_id=0

Gustavo Sousa <[email protected]>
drm/xe: Define and use MCR version of COMMON_SLICE_CHICKEN4

Matt Roper <[email protected]>
drm/xe/tuning: Apply windower hardware filtering setting on Xe3 and Xe3p

Gustavo Sousa <[email protected]>
drm/xe: Define and use MCR version of COMMON_SLICE_CHICKEN1

Matt Roper <[email protected]>
drm/xe: Consolidate workaround entries for Wa_18033852989

Matt Roper <[email protected]>
drm/xe: Consolidate workaround entries for Wa_14019988906

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

Boris Brezillon <[email protected]>
drm/gem: Make the GEM LRU lock part of drm_device

Jianpeng Chang <[email protected]>
dma-mapping: move dma_map_resource() sanity check into debug code

Miri Korenblit <[email protected]>
wifi: iwlwifi: mld: don't dereference a pointer before NULL checking it

Cole Leavitt <[email protected]>
wifi: iwlwifi: mld: fix TSO segmentation explosion when AMSDU is disabled

Guenter Roeck <[email protected]>
hwmon: (lm90) Add lock protection to lm90_alert

Guenter Roeck <[email protected]>
hwmon: (lm90) Stop work before releasing hwmon device

Dmitry Baryshkov <[email protected]>
drm/msm/snapshot: fix dumping of the unaligned regions

Eric Naim <[email protected]>
ALSA: hda/realtek: Use ALC287_FIXUP_TXNW2781_I2C for ASUS Strix Gxx5

Florian Westphal <[email protected]>
netfilter: nft_inner: release local_lock before re-enabling softirqs

Felix Gu <[email protected]>
spi: mtk-snfi: Fix resource leak in mtk_snand_read_page_cache()

Cássio Gabriel <[email protected]>
ASoC: amd: acp-sdw-legacy: check CPU DAI name before logging

Boris Burkov <[email protected]>
btrfs: fix squota accounting during enable generation

Boris Burkov <[email protected]>
btrfs: check for subvolume before deleting squota qgroup

Stefano Garzarella <[email protected]>
vsock/virtio: fix zerocopy completion for multi-skb sends

Jens Axboe <[email protected]>
io_uring/net: punt IORING_OP_BIND async if it needs file create

Hongling Zeng <[email protected]>
cachefiles: Fix error return when vfs_mkdir() fails

Matt DeVillier <[email protected]>
ALSA: hda/ca0132: Disable auto-detect on manual output select

Robertus Diawan Chris <[email protected]>
ALSA: scarlett2: Add missing error check when initialise Autogain Status

Jason Gunthorpe <[email protected]>
iommupt: Fix the end_index calculation in __map_range_leaf()

Jason Gunthorpe <[email protected]>
iommupt: Check for missing PAGE_SIZE in the pgsize_bitmap

Jason Gunthorpe <[email protected]>
iommu: Handle unmap error when iommu_debug is enabled

Jason Gunthorpe <[email protected]>
iommu: Fix up map/unmap debugging for iommupt domains

Jason Gunthorpe <[email protected]>
iommu: Fix loss of errno on map failure for classic ops

Jason Gunthorpe <[email protected]>
iommupt: Avoid rewalking during map

Jason Gunthorpe <[email protected]>
iommupt: Directly call iommupt's unmap_range()

Alexander A. Klimov <[email protected]>

    ASoC: codecs: fs210x: fix possible buffer overflow

Mike Christie <[email protected]>
scsi: sd: Fix return code handling in sd_spinup_disk()

Or Har-Toov <[email protected]>
net/mlx5: Skip disabled vports when setting max TX speed

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

Ralf Lici <[email protected]>
ovpn: disable BHs when updating device stats

Matt Evans <[email protected]>
vfio/pci: Check BAR resources before exporting a DMABUF

Juergen Gross <[email protected]>

    x86/xen: Fix xen_e820_swap_entry_with_ram()

Kees Cook <[email protected]>
gcc-plugins: Always define CONST_CAST_GIMPLE and CONST_CAST_TREE

David Carlier <[email protected]>
phy: apple: atc: Fix typec switch/mux leak on unbind

DaeMyung Kang <[email protected]>
cifs: client: stage smb3_reconfigure() updates and restore ctx on failure

Antonio Quartulli <[email protected]>
ovpn: fix race between deleting interface and adding new peer

David Carlier <[email protected]>
ovpn: respect peer refcount in CMD_NEW_PEER error path

David Carlier <[email protected]>
ovpn: tcp - use cached peer pointer in ovpn_tcp_close()

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()

Randy Dunlap <[email protected]>
riscv: Docs: fix unmatched quote warning

Cássio Gabriel <[email protected]>
ASoC: sdw_utils: Check speaker component string allocation

Maciej Strozek <[email protected]>
ASoC: sdw_utils: cs42l43: allow spk component names to be combined

Maciej Strozek <[email protected]>
ASoC: intel: sof_sdw: Prepare for configuration without a jack

Chen Ni <[email protected]>
drm/msm/a6xx: Check kzalloc return in a8xx_hfi_send_perf_table

Mikko Perttunen <[email protected]>
drm/msm: Fix iommu_map_sgtable() return value check and avoid WARN

Rob Clark <[email protected]>
drm/msm/a6xx: Restore sysprof_active

Dmitry Baryshkov <[email protected]>
drm/msm/adreno: fix userspace-triggered crash on a2xx-a4xx

Felix Gu <[email protected]>
drm/msm/adreno: Fix a reference leak in a6xx_gpu_init()

Akhil P Oommen <[email protected]>
drm/msm/a6xx: Add soft fuse detection support

Alexander Koskovich <[email protected]>
drm/msm: Fix GMEM_BASE for A650

Ricardo Neri <[email protected]>
Documentation: intel_pstate: Fix description of asymmetric packing with SMT

Borislav Petkov (AMD) <[email protected]>
x86/mce: Restore MCA polling interval halving

Ming Lei <[email protected]>
selftests: ublk: cap nthreads to kernel's actual nr_hw_queues

Damien Le Moal <[email protected]>
block: fix handling of dead zone write plugs

Damien Le Moal <[email protected]>
block: allow submitting all zone writes from a single context

Damien Le Moal <[email protected]>
block: rename struct gendisk zone_wplugs_lock field

Dmitry Baryshkov <[email protected]>
drm/msm/dpu: don't mix devm and drmm functions

Dmitry Baryshkov <[email protected]>
drm/msm/dsi: don't dump registers past the mapped region

Mahadevan P <[email protected]>
drm/msm/dpu: Fix Kaanapali CWB register configuration

Neil Armstrong <[email protected]>
drm/msm/dpu: fix UV scanlines calculation for YUV UBWC formats

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()

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()

Jakub Kicinski <[email protected]>
net: shaper: reject QUEUE scope handle with missing id

Jakub Kicinski <[email protected]>
net: shaper: enforce singleton NETDEV scope with id 0

Jakub Kicinski <[email protected]>
net: shaper: reject handle IDs exceeding internal bit-width

Jakub Kicinski <[email protected]>
net: shaper: fix undersized reply skb allocation in GROUP command

Jakub Kicinski <[email protected]>
net: shaper: set ret to -ENOMEM when genlmsg_new() fails in group_doit

Jakub Kicinski <[email protected]>
net: shaper: reject duplicate leaves in GROUP request

Jakub Kicinski <[email protected]>
net: shaper: fix trivial ordering issue in net_shaper_commit()

Jakub Kicinski <[email protected]>
net: shaper: flip the polarity of the valid flag

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]>
afs: Fix the locking used by afs_get_link()

David Howells <[email protected]>
netfs, afs: Fix write skipping in dir/link writepages

David Howells <[email protected]>
netfs: Fix netfs_read_folio() to wait on writeback

David Howells <[email protected]>

    netfs: Fix folio->private handling in netfs_perform_write()

David Howells <[email protected]>
netfs: Fix partial invalidation of streaming-write folio

David Howells <[email protected]>
netfs: Fix potential UAF in netfs_unlock_abandoned_read_pages()

David Howells <[email protected]>
netfs: Fix leak of request in netfs_write_begin() error handling

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 read-gaps to remove netfs_folio from filled folio

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

David Howells <[email protected]>
netfs: Fix zeropoint update where i_size > remote_i_size

David Howells <[email protected]>

    netfs: Fix potential for tearing in ->remote_i_size and ->zero_point

David Howells <[email protected]>
netfs: Fix netfs_read_to_pagecache() to pause on subreq failure

David Howells <[email protected]>

    netfs: Fix missing barriers when accessing stream->subrequests locklessly

David Howells <[email protected]>
netfs: Fix missing locking around retry adding new subreqs

David Howells <[email protected]>
netfs: Fix cancellation of a DIO and single read subrequests

Aboorva Devarajan <[email protected]>
powerpc/hv-gpci: fix preempt count leak in sysfs show paths

Julian Braha <[email protected]>
powerpc: fix dead default for GUEST_STATE_BUFFER_TEST

Ally Heev <[email protected]>
powerpc: 82xx: fix uninitialized pointers with free attribute

Mario Limonciello <[email protected]>
ASoC: SOF: amd: Fix error code handling in psp_send_cmd()

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

Chia-Lin Kao (AceLan) <[email protected]>
nvme-pci: fix use-after-free in nvme_free_host_mem()

Keith Busch <[email protected]>
nvme: fix bio leak on mapping failure

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

Pankaj Raghav <[email protected]>
fs: fix forced iversion increment on lazytime timestamp updates

Rosen Penev <[email protected]>
irqchip/ath79-cpu: Remove unused function

Hongling Zeng <[email protected]>
fs: Fix return in jfs_mkdir and orangefs_mkdir

Junyoung Jang <[email protected]>
fs/statmount: fix slab out-of-bounds write in statmount_mnt_idmap

Masami Hiramatsu (Google) <[email protected]>
fprobe: Fix unregister_fprobe() to wait for RCU grace period

Mac Chiang <[email protected]>
ASoC: sdw_utils: Add quirk to ignore RT721 CODEC_MIC

Mac Chiang <[email protected]>
ASoC: sdw_utils: Add quirk to ignore RT712 CODEC_MIC

Chuck Lever <[email protected]>
NFSD: Fix infinite loop in layout state revocation

Felix Gu <[email protected]>
phy: spacemit: Remove incorrect clk_disable() in spacemit_usb2phy_init()

Gabor Juhos <[email protected]>
phy: marvell: mvebu-a3700-utmi: fix incorrect USB2_PHY_CTRL register access

Shitalkumar Gandhi <[email protected]>
net: ti: icssm-prueth: fix eth_ports_node leak in probe

Myeonghun Pak <[email protected]>
net: lan966x: avoid unregistering netdev on register failure

Ivan Vecera <[email protected]>
ice: dpll: fix misplaced header macros

Ivan Vecera <[email protected]>
ice: dpll: fix rclk pin state get for E810

Bart Van Assche <[email protected]>
ice: fix locking in ice_dcb_rebuild()

Marcin Szycik <[email protected]>
ice: fix setting RSS VSI hash for E830

Emil Tantilov <[email protected]>
idpf: fix read_dev_clk_lock spinlock init in idpf_ptp_init()

Mohsin Bashir <[email protected]>
net: shaper: Reject reparenting of existing nodes

Dragos Tatulea <[email protected]>
net: napi: Avoid gro timer misfiring at end of busypoll

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()

Pablo Neira Ayuso <[email protected]>
netfilter: nf_conntrack_expect: restore helper propagation via expectation

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

Florian Westphal <[email protected]>
netfilter: x_tables: unregister the templates first

Florian Westphal <[email protected]>
netfilter: x_tables: allocate hook ops while under mutex

Florian Westphal <[email protected]>
netfilter: x_tables: allow initial table replace without emitting audit log message

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: Snapshot notifier callbacks under lock

Sudeep Holla <[email protected]>
firmware: arm_ffa: Align RxTx buffer size before mapping

Sudeep Holla <[email protected]>
firmware: arm_ffa: Validate framework notification message layout

Sudeep Holla <[email protected]>
firmware: arm_ffa: Keep framework RX release under lock

Sudeep Holla <[email protected]>
firmware: arm_ffa: Bound PARTITION_INFO_GET_REGS copies

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

Michael Neuling <[email protected]>
riscv: Fix register corruption from uninitialized cregs on error

Michael Neuling <[email protected]>
riscv: errata: Fix bitwise vs logical AND in MIPS errata patching

Sudeep Holla <[email protected]>
firmware: arm_ffa: Unregister bus notifier on teardown for FF-A v1.0

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

Dan Carpenter <[email protected]>
HID: intel-thc-hid: Intel-quickspi: Fix some error codes

David Carlier <[email protected]>
mm/memfd_luo: report error when restoring a folio fails mid-loop

Evangelos Petrongonas <[email protected]>
kho: skip KHO for crash kernel

Maulik Shah <[email protected]>
pinctrl: qcom: Fix GPIO to PDC wake irq map for qcs615

Xianwei Zhao <[email protected]>
pinctrl: meson: amlogic-a4: fix deadlock issue

Lad Prabhakar <[email protected]>
pinctrl: renesas: rzg2l: Fix SMT register cache handling

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

Geert Uytterhoeven <[email protected]>
arm64: dts: renesas: r8a78000: Fix SCIF brg_int clocks

Til Kaiser <[email protected]>
pinctrl: qcom: ipq4019: mark gpio as a GPIO pin function

Bartosz Golaszewski <[email protected]>
pinctrl: mediatek: moore: implement gpio_chip::get_direction()

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: prevent TVLV entry number overflow

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: tt: avoid empty VLAN responses

Sven Eckelmann <[email protected]>
batman-adv: tt: reject oversized local TVLV buffers

Sven Eckelmann <[email protected]>
batman-adv: tt: fix TOCTOU race for reported vlans

Sven Eckelmann <[email protected]>
batman-adv: tp_meter: avoid role confusion in tp_list

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: directly shut down timer on cleanup

Sven Eckelmann <[email protected]>
batman-adv: tp_meter: avoid use of uninit sender vars

Sven Eckelmann <[email protected]>
batman-adv: bla: avoid NULL-ptr deref for claim via dropped interface

Sven Eckelmann <[email protected]>
batman-adv: bla: avoid double decrement of bla.num_requests

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

Sven Eckelmann <[email protected]>
batman-adv: iv: recover OGM scheduling after forward packet error

Sven Eckelmann <[email protected]>
batman-adv: tvlv: reject oversized TVLV packets

Sven Eckelmann <[email protected]>
batman-adv: tvlv: abort OGM send on tvlv append failure

Sven Eckelmann <[email protected]>
batman-adv: v: stop OGMv2 on disabled interface

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

Niranjana Vishwanathapura <[email protected]>
drm/xe/multi_queue: Fix secondary queue error case

Deepanshu Kartikey <[email protected]>
drm/virtio: use uninterruptible resv lock for plane updates

Maíra Canal <[email protected]>
drm/v3d: Release indirect CSD GEM reference on CPU job free

Maíra Canal <[email protected]>
drm/v3d: Fix use-after-free of CPU job query arrays on error path

Daniel J Blueman <[email protected]>
drm/msm: Fix shrinker deadlock

Chaitanya Kumar Borah <[email protected]>
drm/i915/display: Copy color pipeline from plane in the primary joiner pipe

Bartosz Golaszewski <[email protected]>

    device property: set fwnode->secondary to NULL in fwnode_init()

Rafael J. Wysocki <[email protected]>
cpufreq: intel_pstate: Use correct scaling factor on Raptor Lake-E

Huacai Chen <[email protected]>
LoongArch: Remove unused code to avoid build warning

Tiezhu Yang <[email protected]>
LoongArch: kprobes: Use larch_insn_text_copy() to patch instructions

Heechan Kang <[email protected]>
fwctl: pds: Validate RPC input size before parsing

Thomas Richter <[email protected]>
s390/pai: Fix missing PAI counter increments under heavy load

Thomas Richter <[email protected]>
s390/pai: Disable duplicate read of kernel PAI counter value

Peter Oberparleiter <[email protected]>
s390/cio: Restore GFP_DMA for CHSC allocation

Michael Bommarito <[email protected]>
RDMA/siw: Reject MPA FPDU length underflow before signed receive math

Qing Wang <[email protected]>
mm/slub: hold cpus_read_lock around flush_rcu_sheaves_on_cache()

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

Yongxing Mou <[email protected]>
phy: qcom: edp: Fix AUX_CFG8 programming for DP mode

Yongxing Mou <[email protected]>
phy: qcom: edp: Add eDP/DP mode switch support

Yongxing Mou <[email protected]>
phy: qcom: edp: Unify generic DP/eDP swing and pre-emphasis tables

Nitin Rawat <[email protected]>
phy: qcom-qmp-ufs: Fix kaanapali PHY PLL lock failure after SM8650 G4 fix

Wayne Chang <[email protected]>
phy: tegra: xusb: Fix per-pad high-speed termination calibration

Łukasz Lebiedziński <[email protected]>
phy: exynos5-usbdrd: fix USB 2.0 HS PHY tuning values for Exynos7870

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

Saurav Sachidanand <[email protected]>
i2c: tegra: fix pm_runtime leak on mutex_lock failure

Carlos López <[email protected]>
virt: sev-guest: Explicitly leak pages in unknown state

Osama Abdelkader <[email protected]>
riscv: kvm: return SBI_ERR_FAILURE for pmu_event_info() when OOM

Osama Abdelkader <[email protected]>
riscv: kvm: return SBI_ERR_FAILURE for pmu_snapshot_set_shmem() when OOM

Tina Zhang <[email protected]>
KVM: SVM: Disable AVIC IPI virtualization on Hygon Family 18h (erratum #1235)

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

Jeongjun Park <[email protected]>
ASoC: codecs: pcm512x: fix null-ptr dereference in pcm512x_overclock_xxx_put()

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

Dawei Feng <[email protected]>

    octeontx2-pf: avoid double free of pool->stack on AQ init failure

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

Jacob Keller <[email protected]>
ice: fix locking around wait_event_interruptible_locked_irq

Kohei Enju <[email protected]>
igc: fix potential skb leak in igc_fpe_xmit_smd_frame()

Dawei Feng <[email protected]>
octeontx2-pf: fix double free in rvu_rep_rsrc_init()

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()

Paolo Abeni <[email protected]>
mptcp: reset rcv wnd on disconnect

Shardul Bankar <[email protected]>
mptcp: do not drop partial packets

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

Sheroz Juraev <[email protected]>
wifi: iwlwifi: mld: stop TX during firmware restart

Johannes Berg <[email protected]>
wifi: iwlwifi: mvm: fix driver-set TX rates on old devices

Kyle Farnung <[email protected]>
wifi: ath11k: clear shared SRNG pointer state on restart

Jose Ignacio Tornos Martinez <[email protected]>
ice: fix VF queue configuration with low MTU values

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

Li Xiasong <[email protected]>
mptcp: pm: fix ADD_ADDR timer infinite retry on option space insufficient

Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: drop nanoseconds width specifier

Justin Iurman <[email protected]>
ipv6: ioam: add NULL check for idev in ipv6_hop_ioam()

Zhao Li <[email protected]>

    wifi: mac80211: capture fast-RX rate before mesh reuses skb->cb

Masami Hiramatsu (Google) <[email protected]>
ring-buffer: Flush and stop persistent ring buffer on panic

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

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

Rafael J. Wysocki <[email protected]>
ACPI: driver: Check ACPI_COMPANION() against NULL during probe

David Carlier <[email protected]>
net: ethtool: phy: avoid NULL deref when PHY driver is unbound

Quan Sun <[email protected]>
net: ethtool: fix NULL pointer dereference in phy_reply_size

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

Matt Fleming <[email protected]>
net/mlx5e: Fix use-after-free in mlx5e_tx_reporter_timeout_recover

Michael Bommarito <[email protected]>
net: hsr: defer node table free until after RCU readers

Nerijus Bendžiūnas <[email protected]>
net: phy: skip EEE advertisement write when autoneg is disabled

David Carlier <[email protected]>
net: devmem: reject dma-buf bind with non-page-aligned size or SG length

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

Shuai Zhang <[email protected]>
Bluetooth: hci_qca: Convert timeout from jiffies to ms

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()

SeongJae Park <[email protected]>
mm/damon: fix damos_stat tracepoint format for sz_applied

Luiz Capitulino <[email protected]>
selftests/mm: run_vmtests.sh: fix destructive tests invocation

Sunny Patel <[email protected]>
mm/migrate_device: fix spinlock leak in migrate_vma_insert_huge_pmd_page

David Hildenbrand (Arm) <[email protected]>
mm/page_alloc: fix initialization of tags of the huge zero folio with init_on_free

Muchun Song <[email protected]>
mm/memory_hotplug: fix memory block reference leak on remove

David Hildenbrand (Arm) <[email protected]>
mm: fix __vm_normal_page() to handle missing support for pmd_special()/pud_special()

Alistair Popple <[email protected]>
mm/memory: fix spurious warning when unmapping device-private/exclusive pages

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

Krishnamoorthi M <[email protected]>
spi: amd: Set correct bus number in ACPI probe path

Ard Biesheuvel <[email protected]>
efi: Allocate runtime workqueue before ACPI init

Rafael J. Wysocki <[email protected]>
ACPI: battery: Fix system wakeup on critical battery status

Cássio Gabriel <[email protected]>
ALSA: scarlett2: Allow flash writes ending at segment boundary

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

Illia Ostapyshyn <[email protected]>
scripts/gdb: mm: cast untyped symbols in x86_page_ops

Tom Lendacky <[email protected]>
x86/mm: Disable broadcast TLB flush when PCID is disabled

Alexander Sverdlin <[email protected]>
regulator: tps65219: fix irq_data.rdev not being assigned

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 proc_show_files()

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

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

DaeMyung Kang <[email protected]>
ksmbd: close durable scavenger races against m_fp_list lookups

Eder Zulian <[email protected]>
iommu/amd: Remove latent out-of-bounds access in IOMMU debugfs

Guanghui Feng <[email protected]>
iommu/amd: Fix illegal cap/mmio access in IOMMU debugfs

-------------

Diffstat:

 .../ABI/testing/sysfs-driver-uniwill-laptop        |  27 ++
 .../admin-guide/laptops/uniwill-laptop.rst         |  22 ++
 Documentation/admin-guide/pm/intel_pstate.rst      |  11 +-
 Documentation/arch/riscv/zicfilp.rst               |   2 +-
 Documentation/crypto/krb5.rst                      |  17 +-
 Documentation/netlink/specs/net_shaper.yaml        |   7 +
 Makefile                                           |   4 +-
 arch/alpha/include/asm/Kbuild                      |   1 +
 arch/arc/include/asm/Kbuild                        |   1 +
 arch/arm/boot/dts/renesas/r7s72100-genmai.dts      |   3 -
 arch/arm/boot/dts/renesas/r7s72100-rskrza1.dts     |   2 -
 arch/arm/include/asm/Kbuild                        |   1 +
 arch/arm/mach-versatile/integrator_cp.c            |  13 +-
 arch/arm64/boot/dts/renesas/r8a78000.dtsi          |   8 +-
 arch/arm64/include/asm/insn.h                      |   2 +-
 arch/arm64/include/asm/page.h                      |   2 +-
 arch/arm64/include/asm/ring_buffer.h               |  10 +
 arch/arm64/kvm/arm.c                               |   4 +-
 arch/arm64/kvm/vgic/vgic-its.c                     |   4 +
 arch/arm64/mm/fault.c                              |  11 +-
 arch/csky/include/asm/Kbuild                       |   1 +
 arch/hexagon/include/asm/Kbuild                    |   1 +
 arch/loongarch/include/asm/Kbuild                  |   1 +
 arch/loongarch/kernel/kprobes.c                    |  14 +-
 arch/loongarch/mm/init.c                           |   4 -
 arch/m68k/include/asm/Kbuild                       |   1 +
 arch/microblaze/include/asm/Kbuild                 |   1 +
 arch/mips/include/asm/Kbuild                       |   1 +
 arch/nios2/include/asm/Kbuild                      |   1 +
 arch/openrisc/include/asm/Kbuild                   |   1 +
 arch/parisc/include/asm/Kbuild                     |   1 +
 arch/powerpc/Kconfig.debug                         |   3 +-
 arch/powerpc/include/asm/Kbuild                    |   1 +
 arch/powerpc/kernel/time.c                         |   6 +-
 arch/powerpc/perf/hv-gpci.c                        |  24 +-
 arch/powerpc/platforms/82xx/km82xx.c               |   4 +-
 arch/riscv/errata/mips/errata.c                    |   2 +-
 arch/riscv/include/asm/Kbuild                      |   1 +
 arch/riscv/kernel/compat_signal.c                  |   2 +
 arch/riscv/kernel/ptrace.c                         |   4 +-
 arch/riscv/kvm/vcpu_pmu.c                          |  12 +-
 arch/riscv/mm/init.c                               |  25 ++
 arch/s390/include/asm/Kbuild                       |   1 +
 arch/s390/kernel/perf_pai.c                        |  31 ++-
 arch/sh/include/asm/Kbuild                         |   1 +
 arch/sparc/include/asm/Kbuild                      |   1 +
 arch/um/include/asm/Kbuild                         |   1 +
 arch/x86/include/asm/Kbuild                        |   1 +
 arch/x86/kernel/cpu/cpuid-deps.c                   |   1 +
 arch/x86/kernel/cpu/mce/core.c                     |  33 +--
 arch/x86/kvm/svm/avic.c                            |  12 +-
 arch/x86/xen/setup.c                               |   2 +-
 arch/xtensa/include/asm/Kbuild                     |   1 +
 block/bio-integrity.c                              |  19 +-
 block/blk-cgroup.c                                 |   2 +-
 block/blk-mq-debugfs.c                             |   1 +
 block/blk-mq.c                                     |  53 ++--
 block/blk-sysfs.c                                  |  35 ++-
 block/blk-zoned.c                                  | 250 ++++++++++++++---
 crypto/krb5/krb5_api.c                             |  54 +++-
 drivers/accel/qaic/qaic_data.c                     |  23 +-
 drivers/acpi/ac.c                                  |   6 +-
 drivers/acpi/acpi_pad.c                            |   6 +-
 drivers/acpi/acpi_tad.c                            |   6 +-
 drivers/acpi/battery.c                             |  10 +-
 drivers/acpi/button.c                              |   9 +-
 drivers/acpi/ec.c                                  |   6 +-
 drivers/acpi/hed.c                                 |   6 +-
 drivers/acpi/nfit/core.c                           |   6 +-
 drivers/acpi/pfr_telemetry.c                       |   6 +-
 drivers/acpi/pfr_update.c                          |   6 +-
 drivers/acpi/sbs.c                                 |   6 +-
 drivers/acpi/sbshc.c                               |   6 +-
 drivers/acpi/thermal.c                             |   2 +-
 drivers/acpi/tiny-power-button.c                   |   6 +-
 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/btintel_pcie.c                   |  20 +-
 drivers/bluetooth/btintel_pcie.h                   |   3 -
 drivers/bluetooth/btmtk.c                          |   2 +
 drivers/bluetooth/hci_ldisc.c                      |  48 +++-
 drivers/bluetooth/hci_qca.c                        |  33 ++-
 drivers/cpufreq/intel_pstate.c                     |   2 +-
 drivers/firmware/arm_ffa/bus.c                     |   4 +-
 drivers/firmware/arm_ffa/driver.c                  | 133 +++++++---
 drivers/firmware/efi/efi.c                         |  28 +-
 drivers/fwctl/pds/main.c                           |   3 +
 drivers/gpio/Kconfig                               |   1 -
 drivers/gpio/gpio-aggregator.c                     |  47 ++--
 drivers/gpio/gpiolib-cdev.c                        |  13 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c        |   9 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c            |   7 +-
 drivers/gpu/drm/amd/amdgpu/vce_v1_0.c              |  31 ++-
 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/drm_drv.c                          |   2 +
 drivers/gpu/drm/drm_gem.c                          |  36 ++-
 drivers/gpu/drm/i915/display/intel_dp.c            |   2 +-
 drivers/gpu/drm/i915/display/intel_plane.c         |   2 +-
 drivers/gpu/drm/mediatek/mtk_cec.c                 |   2 +-
 drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c            |   2 +-
 drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c         |   2 +-
 drivers/gpu/drm/mediatek/mtk_hdmi_v2.c             |   2 +-
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c              |   6 +
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c              |  48 +++-
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c              |   2 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.c            |  13 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h            |   1 +
 .../drm/msm/disp/dpu1/catalog/dpu_13_0_kaanapali.h |   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c        |  12 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_writeback.c      |   3 +-
 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_drv.c                      |  11 +-
 drivers/gpu/drm/msm/msm_drv.h                      |   7 -
 drivers/gpu/drm/msm/msm_gem.c                      |  33 ++-
 drivers/gpu/drm/msm/msm_gem_shrinker.c             |  44 ++-
 drivers/gpu/drm/msm/msm_gem_submit.c               |   6 +-
 drivers/gpu/drm/msm/msm_gem_vma.c                  |  12 +-
 drivers/gpu/drm/msm/msm_iommu.c                    |   5 +-
 drivers/gpu/drm/msm/msm_ringbuffer.c               |   6 +-
 drivers/gpu/drm/msm/registers/adreno/a6xx.xml      |   4 +
 drivers/gpu/drm/v3d/v3d_sched.c                    |  16 +-
 drivers/gpu/drm/v3d/v3d_submit.c                   |  22 +-
 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/regs/xe_gt_regs.h               |   3 +
 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_guc_submit.c                 |  16 +-
 drivers/gpu/drm/xe/xe_oa.c                         |   6 +-
 drivers/gpu/drm/xe/xe_tuning.c                     |   5 +
 drivers/gpu/drm/xe/xe_wa.c                         |  28 +-
 drivers/hid/hid-quirks.c                           |   2 +-
 drivers/hid/hid-uclogic-core.c                     |   4 +-
 .../intel-quickspi/quickspi-protocol.c             |   4 +-
 drivers/hwmon/lm90.c                               |  26 +-
 drivers/hwmon/pmbus/adm1266.c                      |  32 ++-
 drivers/i2c/busses/i2c-tegra.c                     |   4 +-
 drivers/infiniband/hw/mana/main.c                  |   1 +
 drivers/infiniband/sw/siw/siw_qp_rx.c              |  15 ++
 drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c       |   2 +-
 drivers/iommu/amd/debugfs.c                        |  43 ++-
 drivers/iommu/generic_pt/iommu_pt.h                | 176 ++++++------
 drivers/iommu/generic_pt/kunit_generic_pt.h        |  12 +
 drivers/iommu/generic_pt/pt_iter.h                 |  22 ++
 drivers/iommu/iommu.c                              | 118 +++++----
 drivers/irqchip/irq-ath79-cpu.c                    |   7 -
 drivers/net/dsa/mt7530.c                           |  47 ++--
 drivers/net/ethernet/airoha/airoha_eth.c           |  10 +-
 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/freescale/enetc/enetc_pf.c    |   4 +-
 drivers/net/ethernet/intel/ice/ice_dcb_lib.c       |   4 +-
 drivers/net/ethernet/intel/ice/ice_dpll.c          |   5 +
 drivers/net/ethernet/intel/ice/ice_dpll.h          |  32 +--
 drivers/net/ethernet/intel/ice/ice_main.c          |  10 +-
 drivers/net/ethernet/intel/ice/ice_ptp_hw.c        |  33 ++-
 drivers/net/ethernet/intel/ice/virt/queues.c       |   2 +-
 drivers/net/ethernet/intel/idpf/idpf_ptp.c         |   4 +-
 drivers/net/ethernet/intel/igc/igc_tsn.c           |   9 +-
 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 +-
 drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c |   2 +
 .../ethernet/marvell/octeontx2/nic/otx2_common.c   |   2 +
 drivers/net/ethernet/marvell/octeontx2/nic/rep.c   |   3 +-
 .../ethernet/mellanox/mlx5/core/en/reporter_tx.c   |   6 +-
 .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c   |   7 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c  |   2 +-
 .../net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c |   3 +-
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |  21 ++
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.h  |   1 +
 drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c  |   5 +
 .../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 +
 .../net/ethernet/stmicro/stmmac/dwmac-eic7700.c    | 128 ++++++---
 drivers/net/ethernet/ti/icssm/icssm_prueth.c       |   1 +
 drivers/net/ifb.c                                  |  11 +-
 drivers/net/ovpn/io.c                              |  12 +-
 drivers/net/ovpn/main.c                            |  12 +-
 drivers/net/ovpn/netlink.c                         |   8 +-
 drivers/net/ovpn/peer.c                            |  23 +-
 drivers/net/ovpn/peer.h                            |   1 -
 drivers/net/ovpn/stats.h                           |  16 ++
 drivers/net/ovpn/tcp.c                             |  19 +-
 drivers/net/ovpn/udp.c                             |   2 +-
 drivers/net/phy/dp83tc811.c                        |   1 +
 drivers/net/phy/phy-c45.c                          |   8 +
 drivers/net/phy/phy_device.c                       |   6 +-
 drivers/net/pse-pd/pse_core.c                      |   2 +-
 drivers/net/tap.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/wireless/ath/ath12k/mac.c              |   8 +-
 drivers/net/wireless/intel/iwlwifi/mld/link.c      |  13 +-
 drivers/net/wireless/intel/iwlwifi/mld/tx.c        |  15 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c  |  27 +-
 drivers/net/wireless/intel/iwlwifi/mvm/utils.c     |  14 +-
 drivers/net/wireless/microchip/wilc1000/wlan.c     |   2 +-
 drivers/net/wwan/iosm/iosm_ipc_imem.c              |   2 +
 drivers/nvme/host/ioctl.c                          |   5 +-
 drivers/nvme/host/pci.c                            |  40 ++-
 drivers/phy/apple/atc.c                            |  27 +-
 drivers/phy/marvell/phy-mvebu-a3700-utmi.c         |   5 +-
 drivers/phy/qualcomm/phy-qcom-edp.c                |  88 +++---
 drivers/phy/qualcomm/phy-qcom-qmp-ufs.c            |   1 +
 drivers/phy/qualcomm/phy-qcom-qmp-usbc.c           |   2 +-
 drivers/phy/samsung/phy-exynos5-usbdrd.c           |   7 +-
 drivers/phy/spacemit/phy-k1-usb2.c                 |   1 -
 drivers/phy/tegra/xusb-tegra186.c                  |  33 ++-
 drivers/phy/tegra/xusb.h                           |   1 +
 drivers/pinctrl/mediatek/pinctrl-moore.c           |  18 ++
 drivers/pinctrl/meson/pinctrl-amlogic-a4.c         |   6 +-
 drivers/pinctrl/qcom/pinctrl-ipq4019.c             |   2 +-
 drivers/pinctrl/qcom/pinctrl-msm.h                 |   5 +
 drivers/pinctrl/qcom/pinctrl-qcs615.c              |   6 +-
 drivers/pinctrl/qcom/pinctrl-sm8150.c              |   8 +-
 drivers/pinctrl/renesas/pinctrl-rzg2l.c            |  23 +-
 .../platform/surface/surface_aggregator_registry.c |   2 -
 drivers/platform/x86/adv_swbutton.c                |   6 +-
 drivers/platform/x86/asus-armoury.c                |  16 +-
 drivers/platform/x86/hp/hp_accel.c                 |   3 +
 drivers/platform/x86/intel/hid.c                   |   6 +-
 drivers/platform/x86/intel/int1092/intel_sar.c     |   7 +-
 drivers/platform/x86/intel/vbtn.c                  |   6 +-
 drivers/platform/x86/uniwill/uniwill-acpi.c        |  47 +++-
 drivers/regulator/tps65219-regulator.c             | 135 +++++++---
 drivers/s390/cio/chsc.c                            |   4 +-
 drivers/s390/cio/chsc_sch.c                        |  20 +-
 drivers/s390/cio/scm.c                             |   2 +-
 drivers/scsi/isci/host.c                           |   3 +
 drivers/scsi/sd.c                                  |   3 +-
 drivers/spi/spi-amd.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 +
 drivers/vfio/pci/vfio_pci_dmabuf.c                 |   6 +-
 drivers/virt/coco/sev-guest/sev-guest.c            |  10 +-
 fs/9p/v9fs_vfs.h                                   |  13 -
 fs/9p/vfs_inode.c                                  |   6 +-
 fs/9p/vfs_inode_dotl.c                             |  12 +-
 fs/afs/Makefile                                    |   1 +
 fs/afs/dir.c                                       |  79 +++---
 fs/afs/file.c                                      |  24 +-
 fs/afs/fsclient.c                                  |   4 +-
 fs/afs/inode.c                                     | 127 ++-------
 fs/afs/internal.h                                  |  45 ++--
 fs/afs/symlink.c                                   | 278 +++++++++++++++++++
 fs/afs/validation.c                                |  14 +-
 fs/afs/write.c                                     |   2 +-
 fs/afs/yfsclient.c                                 |   4 +-
 fs/btrfs/fs.h                                      |   1 +
 fs/btrfs/qgroup.c                                  |  81 ++++--
 fs/cachefiles/namei.c                              |   2 +
 fs/erofs/xattr.c                                   |  10 +-
 fs/erofs/zdata.c                                   |  15 +-
 fs/inode.c                                         |   8 +-
 fs/jfs/namei.c                                     |   2 +-
 fs/mnt_idmapping.c                                 |   2 +
 fs/netfs/buffered_read.c                           |  73 ++---
 fs/netfs/buffered_write.c                          | 174 +++++++-----
 fs/netfs/direct_read.c                             |  42 +--
 fs/netfs/direct_write.c                            |   6 +-
 fs/netfs/internal.h                                |   3 +
 fs/netfs/iterator.c                                |  26 +-
 fs/netfs/misc.c                                    |  41 ++-
 fs/netfs/read_collect.c                            |  19 +-
 fs/netfs/read_retry.c                              |  17 +-
 fs/netfs/read_single.c                             |  23 +-
 fs/netfs/write_collect.c                           |  15 +-
 fs/netfs/write_issue.c                             |  51 ++--
 fs/netfs/write_retry.c                             |   6 +-
 fs/nfsd/nfs4state.c                                |   7 +
 fs/nsfs.c                                          |   2 +-
 fs/orangefs/namei.c                                |   2 +-
 fs/smb/client/cifs_spnego.c                        |  16 ++
 fs/smb/client/cifsfs.c                             |  42 ++-
 fs/smb/client/cifssmb.c                            |   3 +-
 fs/smb/client/file.c                               |  13 +-
 fs/smb/client/fs_context.c                         | 163 ++++++++----
 fs/smb/client/inode.c                              |  14 +-
 fs/smb/client/netlink.c                            |   6 +-
 fs/smb/client/readdir.c                            |   3 +-
 fs/smb/client/smb2ops.c                            |  46 ++--
 fs/smb/client/smb2pdu.c                            |   3 +-
 fs/smb/client/smb2transport.c                      |   2 +
 fs/smb/server/oplock.c                             |   6 +-
 fs/smb/server/smb2pdu.c                            |  15 +-
 fs/smb/server/smbacl.c                             |  78 ++++--
 fs/smb/server/vfs_cache.c                          | 120 ++++++---
 fs/sysfs/group.c                                   |   2 +-
 fs/zonefs/super.c                                  |   6 +-
 include/asm-generic/kprobes.h                      |   2 +-
 include/asm-generic/ring_buffer.h                  |  13 +
 include/crypto/krb5.h                              |   9 +-
 include/drm/drm_device.h                           |   7 +
 include/drm/drm_gem.h                              |  20 +-
 include/linux/blkdev.h                             |  10 +-
 include/linux/cgroup.h                             |   1 +
 include/linux/fprobe.h                             |   5 +
 include/linux/fwnode.h                             |   1 +
 include/linux/generic_pt/iommu.h                   |  69 ++++-
 include/linux/gfp_types.h                          |  10 +-
 include/linux/highmem.h                            |   7 +-
 include/linux/iommu.h                              |   1 +
 include/linux/libata.h                             |   7 +-
 include/linux/list.h                               |  37 +++
 include/linux/netfilter/x_tables.h                 |   4 +-
 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/netfs.h                              | 295 ++++++++++++++++++++-
 include/linux/soc/airoha/airoha_offload.h          |   6 +-
 include/net/bluetooth/bluetooth.h                  |   1 +
 include/net/net_shaper.h                           |   1 +
 include/net/netfilter/nf_conntrack_expect.h        |   5 +-
 include/net/netfilter/nf_queue.h                   |   1 +
 include/net/tcp.h                                  |   7 +-
 include/trace/events/btrfs.h                       |   4 +-
 include/trace/events/damon.h                       |   2 +-
 include/trace/events/netfs.h                       |   8 +
 include/trace/events/rxrpc.h                       |   1 +
 io_uring/io_uring.c                                |   9 +-
 io_uring/net.c                                     |  26 +-
 io_uring/nop.c                                     |   4 +-
 io_uring/waitid.c                                  |   1 +
 kernel/cgroup/rstat.c                              |  37 ++-
 kernel/dma/debug.c                                 |   9 +-
 kernel/dma/mapping.c                               |   4 -
 kernel/irq_work.c                                  |   7 +
 kernel/liveupdate/kexec_handover.c                 |   2 +-
 kernel/rcu/srcutree.c                              |  12 +-
 kernel/sched/ext.c                                 |   5 +-
 kernel/trace/bpf_trace.c                           |   3 +-
 kernel/trace/fprobe.c                              |  23 +-
 kernel/trace/ring_buffer.c                         |  30 ++-
 kernel/trace/trace_events_hist.c                   |   6 +-
 kernel/trace/tracing_map.c                         |  17 +-
 lib/kunit/Kconfig                                  |   5 +-
 lib/tests/test_kprobes.c                           |  29 +-
 mm/damon/sysfs-schemes.c                           |   1 +
 mm/memcontrol.c                                    |   6 +-
 mm/memfd_luo.c                                     |   1 +
 mm/memory.c                                        |  24 +-
 mm/memory_hotplug.c                                |   2 +
 mm/migrate_device.c                                |   2 +-
 mm/page_alloc.c                                    |   8 +-
 mm/slab_common.c                                   |   2 +
 mm/slub.c                                          |   1 +
 net/batman-adv/bat_iv_ogm.c                        |  82 ++++--
 net/batman-adv/bat_v_ogm.c                         |  59 +++--
 net/batman-adv/bridge_loop_avoidance.c             | 109 +++++---
 net/batman-adv/distributed-arp-table.c             |   3 +
 net/batman-adv/fragmentation.c                     |  58 +++-
 net/batman-adv/gateway_client.c                    |   4 +
 net/batman-adv/mesh-interface.c                    |   1 +
 net/batman-adv/originator.c                        |   4 +-
 net/batman-adv/tp_meter.c                          | 117 +++++---
 net/batman-adv/translation-table.c                 |  55 +++-
 net/batman-adv/tvlv.c                              |  28 +-
 net/batman-adv/tvlv.h                              |   2 +-
 net/batman-adv/types.h                             |  59 +++--
 net/bluetooth/af_bluetooth.c                       |  99 +++++--
 net/bluetooth/bnep/core.c                          |   2 +-
 net/bluetooth/hci_sync.c                           |   6 +-
 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_multicast.c                          |  22 +-
 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/dev.c                                     |  21 +-
 net/core/devmem.c                                  |  11 +
 net/core/gro.c                                     |   3 +
 net/core/skmsg.c                                   |   9 +-
 net/ethtool/bitset.c                               |   8 +-
 net/ethtool/phy.c                                  |  36 ++-
 net/hsr/hsr_framereg.c                             |   4 +-
 net/ipv4/inet_connection_sock.c                    |   2 +-
 net/ipv4/netfilter/arp_tables.c                    |  53 +---
 net/ipv4/netfilter/arptable_filter.c               |  27 +-
 net/ipv4/netfilter/ip_tables.c                     |  59 +----
 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.c                                     |   3 -
 net/ipv4/tcp_ao.c                                  |   3 +-
 net/ipv4/tcp_input.c                               |  15 +-
 net/ipv4/tcp_ipv4.c                                |   3 +-
 net/ipv4/udp_offload.c                             |  22 +-
 net/ipv6/exthdrs.c                                 |  21 +-
 net/ipv6/netfilter/ip6_tables.c                    |  56 +---
 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/ipv6/tcp_ipv6.c                                |   3 +-
 net/l2tp/l2tp_core.c                               |   2 +-
 net/mac80211/mlme.c                                |   5 +-
 net/mac80211/parse.c                               | 107 +++++---
 net/mac80211/rx.c                                  |   6 +-
 net/mptcp/pm.c                                     |  56 +++-
 net/mptcp/protocol.c                               |  25 +-
 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_conntrack_broadcast.c             |   1 +
 net/netfilter/nf_conntrack_core.c                  |   7 +-
 net/netfilter/nf_conntrack_expect.c                |   1 +
 net/netfilter/nf_conntrack_h323_main.c             |  12 +-
 net/netfilter/nf_conntrack_helper.c                |   5 +
 net/netfilter/nf_conntrack_netlink.c               |  18 +-
 net/netfilter/nf_conntrack_sip.c                   |   2 +-
 net/netfilter/nf_queue.c                           |   4 +-
 net/netfilter/nfnetlink_queue.c                    |   2 +
 net/netfilter/nft_inner.c                          |   3 +-
 net/netfilter/x_tables.c                           | 177 ++++++++++---
 net/phonet/pep.c                                   |  19 +-
 net/rxrpc/ar-internal.h                            |   7 +-
 net/rxrpc/call_event.c                             |  22 +-
 net/rxrpc/call_object.c                            |   2 +
 net/rxrpc/insecure.c                               |   3 -
 net/rxrpc/recvmsg.c                                |  68 ++++-
 net/rxrpc/rxgk.c                                   |  62 +++--
 net/rxrpc/rxgk_common.h                            |  82 ++++++
 net/rxrpc/rxkad.c                                  |  86 +++---
 net/shaper/shaper.c                                | 224 +++++++++++-----
 net/shaper/shaper_nl_gen.c                         |   7 +-
 net/shaper/shaper_nl_gen.h                         |   2 +
 net/smc/af_smc.c                                   |   3 +-
 net/smc/smc_tracepoint.h                           |   2 +-
 net/tls/tls_sw.c                                   |  46 +++-
 net/unix/af_unix.c                                 |  11 +-
 net/vmw_vsock/virtio_transport_common.c            | 103 ++++---
 net/vmw_vsock/vmci_transport.c                     |   2 +-
 net/wireless/scan.c                                |   3 +
 scripts/gcc-plugins/gcc-common.h                   |   4 +-
 scripts/gdb/linux/mm.py                            |   6 +-
 scripts/package/PKGBUILD                           |   2 +-
 security/lsm_syscalls.c                            |   9 +-
 sound/core/pcm_lib.c                               |   3 +
 sound/core/seq/seq_ump_client.c                    |  22 +-
 sound/hda/codecs/ca0132.c                          |  44 ++-
 sound/hda/codecs/realtek/alc269.c                  |  12 +-
 sound/hda/codecs/side-codecs/cs35l41_hda.c         |   4 +-
 sound/hda/codecs/side-codecs/cs35l56_hda.c         |   1 +
 sound/pci/asihpi/hpicmn.c                          |   6 +
 sound/soc/amd/acp/acp-sdw-legacy-mach.c            |   2 +-
 sound/soc/codecs/cs-amp-lib.c                      |  15 +-
 sound/soc/codecs/cs35l56-sdw.c                     |   3 +-
 sound/soc/codecs/fs210x.c                          |   2 +-
 sound/soc/codecs/pcm512x.c                         |   6 +-
 sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c       |   6 -
 sound/soc/sdw_utils/soc_sdw_cs42l43.c              |  20 +-
 sound/soc/sdw_utils/soc_sdw_utils.c                |  34 ++-
 sound/soc/soc-utils.c                              |   1 +
 sound/soc/sof/amd/acp.c                            |   2 +-
 sound/usb/misc/ua101.c                             |   5 +-
 sound/usb/mixer_scarlett2.c                        |   9 +-
 tools/testing/selftests/mm/hmm-tests.c             |  50 ++++
 tools/testing/selftests/mm/run_vmtests.sh          |   2 +-
 tools/testing/selftests/net/lib/xdp_native.bpf.c   |  55 ++--
 tools/testing/selftests/net/mptcp/mptcp_connect.sh |   6 +-
 tools/testing/selftests/net/mptcp/mptcp_lib.sh     |  10 +-
 tools/testing/selftests/ublk/kublk.c               |  11 +
 503 files changed, 6399 insertions(+), 2940 deletions(-)
author maintainer
#1 lore raw

PATCH 1/461 iommu/amd: Fix illegal cap/mmio access in IOMMU debugfs

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Guanghui Feng <[email protected]>

[ Upstream commit 0e59645683b7b6fa20eceb21a6f420e4f7412943 ]

In the current AMD IOMMU debugfs, when multiple processes simultaneously access the IOMMU mmio/cap registers using the IOMMU debugfs, illegal access issues can occur in the following execution flow:

1. CPU1: Sets a valid access address using iommu_mmio/capability_write, and verifies the access address's validity in iommu_mmio/capability_show

2. CPU2: Sets an invalid address using iommu_mmio/capability_write

3. CPU1: accesses the IOMMU mmio/cap registers based on the invalid address, resulting in an illegal access.

This patch modifies the execution process to first verify the address's validity and then access it based on the same address, ensuring correctness and robustness.

Stable-dep-of: 8dfd3d8d7443 ("iommu/amd: Remove latent out-of-bounds access in IOMMU debugfs")

---
 drivers/iommu/amd/debugfs.c | 42 +++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 23 deletions(-)
drivers/iommu/amd/debugfs.c +19 -23
index 20b04996441d6..0584ca2f859d9 100644
@@ -26,22 +26,19 @@ static ssize_t iommu_mmio_write(struct file *filp, const char __user *ubuf,
 {
 	struct seq_file *m = filp->private_data;
 	struct amd_iommu *iommu = m->private;
-	int ret;
-
-	iommu->dbg_mmio_offset = -1;
+	int ret, dbg_mmio_offset = iommu->dbg_mmio_offset = -1;
 
 	if (cnt > OFS_IN_SZ)
 		return -EINVAL;
 
-	ret = kstrtou32_from_user(ubuf, cnt, 0, &iommu->dbg_mmio_offset);
+	ret = kstrtou32_from_user(ubuf, cnt, 0, &dbg_mmio_offset);
 	if (ret)
 		return ret;
 
-	if (iommu->dbg_mmio_offset > iommu->mmio_phys_end - sizeof(u64)) {
-		iommu->dbg_mmio_offset = -1;
-		return  -EINVAL;
-	}
+	if (dbg_mmio_offset > iommu->mmio_phys_end - sizeof(u64))
+		return -EINVAL;
 
+	iommu->dbg_mmio_offset = dbg_mmio_offset;
 	return cnt;
 }
 
@@ -49,14 +46,16 @@ static int iommu_mmio_show(struct seq_file *m, void *unused)
 {
 	struct amd_iommu *iommu = m->private;
 	u64 value;
+	int dbg_mmio_offset = iommu->dbg_mmio_offset;
 
-	if (iommu->dbg_mmio_offset < 0) {
+	if (dbg_mmio_offset < 0 || dbg_mmio_offset >
+			iommu->mmio_phys_end - sizeof(u64)) {
 		seq_puts(m, "Please provide mmio register's offset\n");
 		return 0;
 	}
 
-	value = readq(iommu->mmio_base + iommu->dbg_mmio_offset);
-	seq_printf(m, "Offset:0x%x Value:0x%016llx\n", iommu->dbg_mmio_offset, value);
+	value = readq(iommu->mmio_base + dbg_mmio_offset);
+	seq_printf(m, "Offset:0x%x Value:0x%016llx\n", dbg_mmio_offset, value);
 
 	return 0;
 }
@@ -67,23 +66,20 @@ static ssize_t iommu_capability_write(struct file *filp, const char __user *ubuf
 {
 	struct seq_file *m = filp->private_data;
 	struct amd_iommu *iommu = m->private;
-	int ret;
-
-	iommu->dbg_cap_offset = -1;
+	int ret, dbg_cap_offset = iommu->dbg_cap_offset = -1;
 
 	if (cnt > OFS_IN_SZ)
 		return -EINVAL;
 
-	ret = kstrtou32_from_user(ubuf, cnt, 0, &iommu->dbg_cap_offset);
+	ret = kstrtou32_from_user(ubuf, cnt, 0, &dbg_cap_offset);
 	if (ret)
 		return ret;
 
 	/* Capability register at offset 0x14 is the last IOMMU capability register. */
-	if (iommu->dbg_cap_offset > 0x14) {
-		iommu->dbg_cap_offset = -1;
+	if (dbg_cap_offset > 0x14)
 		return -EINVAL;
-	}
 
+	iommu->dbg_cap_offset = dbg_cap_offset;
 	return cnt;
 }
 
@@ -91,21 +87,21 @@ static int iommu_capability_show(struct seq_file *m, void *unused)
 {
 	struct amd_iommu *iommu = m->private;
 	u32 value;
-	int err;
+	int err, dbg_cap_offset = iommu->dbg_cap_offset;
 
-	if (iommu->dbg_cap_offset < 0) {
+	if (dbg_cap_offset < 0 || dbg_cap_offset > 0x14) {
 		seq_puts(m, "Please provide capability register's offset in the range [0x00 - 0x14]\n");
 		return 0;
 	}
 
-	err = pci_read_config_dword(iommu->dev, iommu->cap_ptr + iommu->dbg_cap_offset, &value);
+	err = pci_read_config_dword(iommu->dev, iommu->cap_ptr + dbg_cap_offset, &value);
 	if (err) {
 		seq_printf(m, "Not able to read capability register at 0x%x\n",
-			   iommu->dbg_cap_offset);
+			   dbg_cap_offset);
 		return 0;
 	}
 
-	seq_printf(m, "Offset:0x%x Value:0x%08x\n", iommu->dbg_cap_offset, value);
+	seq_printf(m, "Offset:0x%x Value:0x%08x\n", dbg_cap_offset, value);
 
 	return 0;
 }
Signature · 1 line
2.53.0
author maintainer
#2 lore raw

PATCH 2/461 iommu/amd: Remove latent out-of-bounds access in IOMMU debugfs

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Eder Zulian <[email protected]>

[ Upstream commit 8dfd3d8d74435344ee8dc9237596959c8b2a6cbe ]

In iommu_mmio_write() and iommu_capability_write(), the variables dbg_mmio_offset and dbg_cap_offset are declared as int. However, they are populated using kstrtou32_from_user(). If a user provides a sufficiently large value, it can become a negative integer.

Prior to this patch, the AMD IOMMU debugfs implementation was already protected by different mechanisms.

1. #define OFS_IN_SZ 8 ensures the user string <= 8 bytes, so e.g. 0xffffffff isn't a valid input.

if (cnt > OFS_IN_SZ)

     return -EINVAL;

2. Implicit type promotion in iommu_mmio_write(), dbg_mmio_offset is int and iommu->mmio_phys_end is u64

if (dbg_mmio_offset > iommu->mmio_phys_end - sizeof(u64))

      return -EINVAL;

3. The show handlers would currently catch the negative number and refuse to perform the read.

Replace kstrtou32_from_user() with kstrtos32_from_user() to parse the input, and check for negative values to explicitly prevent out-of-bounds memory accesses directly in iommu_mmio_write() and iommu_capability_write().

Fixes 7a4ee419e8c1 ("iommu/amd: Add debugfs support to dump IOMMU MMIO registers")
---
 drivers/iommu/amd/debugfs.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/iommu/amd/debugfs.c +5 -4
index 0584ca2f859d9..3909a1fb218e9 100644
@@ -31,11 +31,12 @@ static ssize_t iommu_mmio_write(struct file *filp, const char __user *ubuf,
 	if (cnt > OFS_IN_SZ)
 		return -EINVAL;
 
-	ret = kstrtou32_from_user(ubuf, cnt, 0, &dbg_mmio_offset);
+	ret = kstrtos32_from_user(ubuf, cnt, 0, &dbg_mmio_offset);
 	if (ret)
 		return ret;
 
-	if (dbg_mmio_offset > iommu->mmio_phys_end - sizeof(u64))
+	if (dbg_mmio_offset < 0 || dbg_mmio_offset >
+			iommu->mmio_phys_end - sizeof(u64))
 		return -EINVAL;
 
 	iommu->dbg_mmio_offset = dbg_mmio_offset;
@@ -71,12 +72,12 @@ static ssize_t iommu_capability_write(struct file *filp, const char __user *ubuf
 	if (cnt > OFS_IN_SZ)
 		return -EINVAL;
 
-	ret = kstrtou32_from_user(ubuf, cnt, 0, &dbg_cap_offset);
+	ret = kstrtos32_from_user(ubuf, cnt, 0, &dbg_cap_offset);
 	if (ret)
 		return ret;
 
 	/* Capability register at offset 0x14 is the last IOMMU capability register. */
-	if (dbg_cap_offset > 0x14)
+	if (dbg_cap_offset < 0 || dbg_cap_offset > 0x14)
 		return -EINVAL;
 
 	iommu->dbg_cap_offset = dbg_cap_offset;
Signature · 1 line
2.53.0
author maintainer
#3 lore raw

PATCH 3/461 ksmbd: close durable scavenger races against m_fp_list lookups

In reply to Greg Kroah-Hartman

7.0-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

Fixes d484d621d40f ("ksmbd: add durable scavenger timer")
---
 fs/smb/server/vfs_cache.c | 102 ++++++++++++++++++++++++++++----------
 1 file changed, 76 insertions(+), 26 deletions(-)
fs/smb/server/vfs_cache.c +76 -26
index 3551f01a3fa03..60b7a2d60238a 100644
@@ -418,6 +418,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)
@@ -510,6 +518,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);
 }
@@ -881,24 +903,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);
@@ -908,8 +943,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));
@@ -918,23 +951,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;
+		do {
+			expired_fp = NULL;
+			found_fp_timeout = false;
 
-			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 {
+			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);
@@ -942,10 +991,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
author maintainer
#4 lore raw

PATCH 4/461 smb: client: reject userspace cifs.spnego descriptions

In reply to Greg Kroah-Hartman

7.0-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.

Fixes f1d662a7d5e5 ("[CIFS] Add upcall files for cifs to use spnego/kerberos")
Assisted-by avom-custom-harness:gpt-5.5-qwen3.6-mod-mix
---
 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>
@@ -40,12 +41,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,
author maintainer
#5 lore raw

PATCH 5/461 ata: libata-scsi: improve readability of ata_scsi_qc_issue()

In reply to Greg Kroah-Hartman

7.0-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
@@ -1768,7 +1768,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
@@ -1787,38 +1787,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;
 }
 
 /**
author maintainer
#6 lore raw

PATCH 6/461 ata: libata-scsi: do not use the deferred QC feature for ATA_DEFER_PORT

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation")
---
 drivers/ata/libata-scsi.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/ata/libata-scsi.c +3 -2
@@ -1790,11 +1790,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:
@@ -1814,6 +1814,7 @@ defer_qc:
 		return 0;
 	}
 
+free_qc:
 	/* Force a requeue of the command to defer its execution. */
 	ata_qc_free(qc);
 
author maintainer
#7 lore raw

PATCH 7/461 ata: libata-scsi: do not use the deferred QC feature on PMPs with CBS

In reply to Greg Kroah-Hartman

7.0-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
@@ -1788,6 +1788,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
@@ -789,6 +789,7 @@ static int sil24_qc_defer(struct ata_que
 	struct 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:
@@ -826,7 +827,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
@@ -371,6 +371,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,
author maintainer
#8 lore raw

PATCH 8/461 ata: libata-scsi: do not needlessly defer commands when using PMP with FBS

In reply to Greg Kroah-Hartman

7.0-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").

Fixes 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
@@ -5579,6 +5579,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++) {
@@ -5661,7 +5662,6 @@ struct ata_port *ata_port_alloc(struct a
 	mutex_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);
@@ -6286,12 +6286,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
@@ -643,11 +643,11 @@ void ata_scsi_cmd_error_handler(struct S
 			if (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
@@ -658,8 +658,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_d
 	if (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
@@ -855,6 +855,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 */
@@ -900,9 +903,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() */
 
author maintainer
#9 lore raw

PATCH 9/461 sysfs: dont remove existing directory on update failure

In reply to Greg Kroah-Hartman

7.0-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.

Cc Rajat Jain <[email protected]>
Fixes c855cf2759d2 ("sysfs: Fix internal_create_group() for named group updates")
Cc stable <[email protected]>
Assisted-by gkh_clanker_t1000
---
 fs/sysfs/group.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/sysfs/group.c +1 -1
@@ -188,7 +188,7 @@ static int internal_create_group(struct
 	kernfs_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);
author maintainer
#10 lore raw

PATCH 10/461 mm/damon/sysfs-schemes: call missing mem_cgroup_iter_break()

In reply to Greg Kroah-Hartman

7.0-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
@@ -2537,6 +2537,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;
 		}
 	}
author maintainer
#11 lore raw

PATCH 11/461 ksmbd: fix null pointer dereference in compare_guid_key()

In reply to Greg Kroah-Hartman

7.0-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.

Fixes c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
---
 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))
author maintainer
#12 lore raw

PATCH 12/461 ksmbd: fix null pointer dereference in proc_show_files()

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeremy Laratro <[email protected]>

commit 904901561e61a2b559070b20c74a8c95491f30aa upstream.

When a SMB2 client opens a file with a durable v2 handle and then issues SMB2 SESSION_LOGOFF, session_fd_check() clears fp->tcon = NULL on the reconnectable file pointer but leaves the fp registered in global_ft.idr until the durable scavenger fires (up to fp->durable_timeout seconds later).

During that window any read of /proc/fs/ksmbd/files (mode 0400) panics the kernel because proc_show_files() walks global_ft.idr and unconditionally dereferences fp->tcon->id with no NULL guard.

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
  0xdffffc0000000000: 0000 [#1] SMP KASAN PTI
  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
  RIP: 0010:proc_show_files+0x118/0x740
  Call Trace:
   proc_show_files+0x118/0x740
   seq_read_iter+0x4ef/0xe10
   proc_reg_read_iter+0x1b7/0x280
   ...

Guard the dereference. A durable-disconnected fp legitimately has no tcon; report its tree id as 0 rather than oopsing.

Fixes b38f99c1217a ("ksmbd: add procfs interface for runtime monitoring and statistics")
---
 fs/smb/server/vfs_cache.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/smb/server/vfs_cache.c +1 -1
index 354c4d8a1cfb..913164c958b1 100644
@@ -81,7 +81,7 @@ static int proc_show_files(struct seq_file *m, void *v)
 	read_lock(&global_ft.lock);
 	idr_for_each_entry(global_ft.idr, fp, id) {
 		seq_printf(m, "%#-10x %#-10llx %#-10llx %#-10x",
-			   fp->tcon->id,
+			   fp->tcon ? fp->tcon->id : 0,
 			   fp->persistent_id,
 			   fp->volatile_id,
 			   atomic_read(&fp->refcount));
Signature · 1 line
2.54.0
author maintainer
#13 lore raw

PATCH 13/461 ksmbd: fix SID memory leak in set_posix_acl_entries_dacl() on overflow

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16 DACL size overflow")
---
 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 |=
author maintainer
#14 lore raw

PATCH 14/461 ksmbd: validate SID in parent security descriptor during ACL inheritance

In reply to Greg Kroah-Hartman

7.0-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(stru
 	return 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,
author maintainer
#15 lore raw

PATCH 15/461 regulator: tps65219: fix irq_data.rdev not being assigned

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexander Sverdlin <[email protected]>

commit f9b2d3b703d13df50c630997dfdc25648e96db0d upstream.

Commit 64a6b577490c ("regulator: tps65219: Remove debugging helper function") removed the tps65219_get_rdev_by_name() helper along with the irq_data.rdev assignment that depended on it. This left irq_data.rdev uninitialized for all IRQs, causing undefined behavior when regulator_notifier_call_chain() is called from the IRQ handler:

  Internal error: Oops: 0000000096000004
  pc : regulator_notifier_call_chain
  lr : tps65219_regulator_irq_handler
  Call trace:
   regulator_notifier_call_chain
   tps65219_regulator_irq_handler
   handle_nested_irq
   regmap_irq_thread
   irq_thread_fn
   irq_thread
   kthread
   ret_from_fork

Instead of restoring a dedicated lookup array, restructure the probe function to combine regulator registration with IRQ registration in the same loop. This way the rdev returned by devm_regulator_register() is naturally available for assigning to irq_data.rdev without any auxiliary data structure.

Non-regulator IRQs (SENSOR, TIMEOUT) that don't correspond to any registered regulator are registered with rdev=NULL, and the IRQ handler is protected with a NULL check to avoid crashing.

---
 drivers/regulator/tps65219-regulator.c |  135 +++++++++++++++++++++++----------
 1 file changed, 95 insertions(+), 40 deletions(-)
drivers/regulator/tps65219-regulator.c +95 -40
@@ -346,8 +346,9 @@ static irqreturn_t tps65219_regulator_ir
 		return IRQ_HANDLED;
 	}
 
-	regulator_notifier_call_chain(irq_data->rdev,
-				      irq_data->type->event, NULL);
+	if (irq_data->rdev)
+		regulator_notifier_call_chain(irq_data->rdev,
+					      irq_data->type->event, NULL);
 
 	dev_err(irq_data->dev, "Error IRQ trap %s for %s\n",
 		irq_data->type->event_name, irq_data->type->regulator_name);
@@ -398,14 +399,65 @@ static struct tps65219_chip_data chip_in
 	},
 };
 
-static int tps65219_regulator_probe(struct platform_device *pdev)
+static bool tps65219_is_regulator_name(const struct tps65219_chip_data *pmic,
+				       const char *name)
+{
+	int i;
+
+	for (i = 0; i < pmic->common_rdesc_size; i++)
+		if (!strcmp(pmic->common_rdesc[i].name, name))
+			return true;
+	for (i = 0; i < pmic->rdesc_size; i++)
+		if (!strcmp(pmic->rdesc[i].name, name))
+			return true;
+	return false;
+}
+
+static int tps65219_register_irqs(struct platform_device *pdev,
+				  struct tps65219 *tps,
+				  struct regulator_dev *rdev,
+				  struct tps65219_regulator_irq_type *irq_types,
+				  int nirqs,
+				  const char *regulator_name)
 {
 	struct tps65219_regulator_irq_data *irq_data;
+	int i, irq, error;
+
+	for (i = 0; i < nirqs; i++) {
+		if (strcmp(irq_types[i].regulator_name, regulator_name))
+			continue;
+
+		irq = platform_get_irq_byname(pdev, irq_types[i].irq_name);
+		if (irq < 0)
+			return -EINVAL;
+
+		irq_data = devm_kmalloc(tps->dev, sizeof(*irq_data), GFP_KERNEL);
+		if (!irq_data)
+			return -ENOMEM;
+
+		irq_data->dev = tps->dev;
+		irq_data->type = &irq_types[i];
+		irq_data->rdev = rdev;
+
+		error = devm_request_threaded_irq(tps->dev, irq, NULL,
+						  tps65219_regulator_irq_handler,
+						  IRQF_ONESHOT,
+						  irq_types[i].irq_name,
+						  irq_data);
+		if (error)
+			return dev_err_probe(tps->dev, error,
+					     "Failed to request %s IRQ %d\n",
+					     irq_types[i].irq_name, irq);
+	}
+	return 0;
+}
+
+static int tps65219_regulator_probe(struct platform_device *pdev)
+{
 	struct tps65219_regulator_irq_type *irq_type;
 	struct tps65219_chip_data *pmic;
 	struct regulator_dev *rdev;
 	int error;
-	int irq;
 	int i;
 
 	struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent);
@@ -425,6 +477,19 @@ static int tps65219_regulator_probe(stru
 			return dev_err_probe(tps->dev, PTR_ERR(rdev),
 					      "Failed to register %s regulator\n",
 					      pmic->common_rdesc[i].name);
+
+		error = tps65219_register_irqs(pdev, tps, rdev,
+					       pmic->common_irq_types,
+					       pmic->common_irq_size,
+					       pmic->common_rdesc[i].name);
+		if (error)
+			return error;
+		error = tps65219_register_irqs(pdev, tps, rdev,
+					       pmic->irq_types,
+					       pmic->dev_irq_size,
+					       pmic->common_rdesc[i].name);
+		if (error)
+			return error;
 	}
 
 	for (i = 0; i <  pmic->rdesc_size; i++) {
@@ -434,52 +499,42 @@ static int tps65219_regulator_probe(stru
 			return dev_err_probe(tps->dev, PTR_ERR(rdev),
 					     "Failed to register %s regulator\n",
 					     pmic->rdesc[i].name);
+
+		error = tps65219_register_irqs(pdev, tps, rdev,
+					       pmic->common_irq_types,
+					       pmic->common_irq_size,
+					       pmic->rdesc[i].name);
+		if (error)
+			return error;
+		error = tps65219_register_irqs(pdev, tps, rdev,
+					       pmic->irq_types,
+					       pmic->dev_irq_size,
+					       pmic->rdesc[i].name);
+		if (error)
+			return error;
 	}
 
+	/* Register non-regulator IRQs (TIMEOUT, SENSOR) with rdev=NULL */
 	for (i = 0; i < pmic->common_irq_size; ++i) {
 		irq_type = &pmic->common_irq_types[i];
-		irq = platform_get_irq_byname(pdev, irq_type->irq_name);
-		if (irq < 0)
-			return -EINVAL;
-
-		irq_data = devm_kmalloc(tps->dev, sizeof(*irq_data), GFP_KERNEL);
-		if (!irq_data)
-			return -ENOMEM;
-
-		irq_data->dev = tps->dev;
-		irq_data->type = irq_type;
-		error = devm_request_threaded_irq(tps->dev, irq, NULL,
-						  tps65219_regulator_irq_handler,
-						  IRQF_ONESHOT,
-						  irq_type->irq_name,
-						  irq_data);
+		if (tps65219_is_regulator_name(pmic, irq_type->regulator_name))
+			continue;
+		error = tps65219_register_irqs(pdev, tps, NULL,
+					       irq_type, 1,
+					       irq_type->regulator_name);
 		if (error)
-			return dev_err_probe(tps->dev, error,
-					     "Failed to request %s IRQ %d\n",
-					     irq_type->irq_name, irq);
+			return error;
 	}
 
 	for (i = 0; i < pmic->dev_irq_size; ++i) {
 		irq_type = &pmic->irq_types[i];
-		irq = platform_get_irq_byname(pdev, irq_type->irq_name);
-		if (irq < 0)
-			return -EINVAL;
-
-		irq_data = devm_kmalloc(tps->dev, sizeof(*irq_data), GFP_KERNEL);
-		if (!irq_data)
-			return -ENOMEM;
-
-		irq_data->dev = tps->dev;
-		irq_data->type = irq_type;
-		error = devm_request_threaded_irq(tps->dev, irq, NULL,
-						  tps65219_regulator_irq_handler,
-						  IRQF_ONESHOT,
-						  irq_type->irq_name,
-						  irq_data);
+		if (tps65219_is_regulator_name(pmic, irq_type->regulator_name))
+			continue;
+		error = tps65219_register_irqs(pdev, tps, NULL,
+					       irq_type, 1,
+					       irq_type->regulator_name);
 		if (error)
-			return dev_err_probe(tps->dev, error,
-					     "Failed to request %s IRQ %d\n",
-					     irq_type->irq_name, irq);
+			return error;
 	}
 
 	return 0;
author maintainer
#16 lore raw

PATCH 16/461 x86/mm: Disable broadcast TLB flush when PCID is disabled

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tom Lendacky <[email protected]>

commit 44126343d58c68adaa8343fbf1c07dd20078c35e upstream.

Booting with "nopcid" clears X86_FEATURE_PCID and keeps CR4.PCIDE from being set to one. On AMD CPUs that support INVLPGB, broadcast TLB flushing remains enabled.

There are two checks that decide whether the global ASID code runs, mm_global_asid() and consider_global_asid(), that key off of the X86_FEATURE_INVLPGB feature. Once an mm becomes active on more than three CPUs, consider_global_asid() assigns it a global ASID, after which flush_tlb_mm_range() takes the broadcast_tlb_flush() path using a non-zero PCID. Issuing an INVLPGB with a non-zero PCID while CR4.PCIDE is not set results in a #GP:

  Oops: general protection fault, kernel NULL pointer dereference 0x1: 0000 [#1] SMP NOPTI
  CPU: 158 UID: 0 PID: 3119 Comm: snap Not tainted 7.1.0-rc3 #1 PREEMPT(full)
  Hardware name: ...
  RIP: 0010:broadcast_tlb_flush
  Code: ... 89 da 48 83 c8 07 <0f> 01 fe eb 08 cc cc cc ...
  Call Trace:
   <TASK>
   flush_tlb_mm_range
   ptep_clear_flush
   wp_page_copy
   ? _raw_spin_unlock
   __handle_mm_fault
   handle_mm_fault
   do_user_addr_fault
   exc_page_fault
   asm_exc_page_fault

All processors that support broadcast TLB invalidation also have PCID support, so it is only the "nopcid" scenario that is of concern. In this situation just disable the broadcast TLB support using the CPUID dependency support by making X86_FEATURE_INVLPGB dependent on X86_FEATURE_PCID.

[ bp: Massage commit message. ]

---
 arch/x86/kernel/cpu/cpuid-deps.c |    1 +
 1 file changed, 1 insertion(+)
arch/x86/kernel/cpu/cpuid-deps.c +1 -0
@@ -92,6 +92,7 @@ static const struct cpuid_dep cpuid_deps
 	{ X86_FEATURE_FRED,			X86_FEATURE_LKGS      },
 	{ X86_FEATURE_SPEC_CTRL_SSBD,		X86_FEATURE_SPEC_CTRL },
 	{ X86_FEATURE_LASS,			X86_FEATURE_SMAP      },
+	{ X86_FEATURE_INVLPGB,			X86_FEATURE_PCID      },
 	{}
 };
 
author maintainer
#17 lore raw

PATCH 17/461 scripts/gdb: mm: cast untyped symbols in x86_page_ops

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Illia Ostapyshyn <[email protected]>

commit c416aee7e7d04fec2d2d30786b3c8393108b85d2 upstream.

The symbols phys_base, _text, and _end, used in x86_page_ops are either defined in assembly or implicitly by the linker. Thus, they lack type information and cause a conversion error after gdb.parse_and_eval. Explicitly cast these expressions to unsigned long.

Fixes 55f8b4518d14 ("scripts/gdb: implement x86_page_ops in mm.py")
Cc Florian Fainelli <[email protected]>
Cc Jan Kiszka <[email protected]>
Cc Kieran Bingham <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Hao Li <[email protected]>
Cc Harry Yoo <[email protected]>
Cc Seongjun Hong <[email protected]>
---
 scripts/gdb/linux/mm.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
scripts/gdb/linux/mm.py +3 -3
index d78908f6664d..dffadccbb01d 100644
@@ -40,11 +40,11 @@ class x86_page_ops():
 
         self.PAGE_OFFSET = int(gdb.parse_and_eval("page_offset_base"))
         self.VMEMMAP_START = int(gdb.parse_and_eval("vmemmap_base"))
-        self.PHYS_BASE = int(gdb.parse_and_eval("phys_base"))
+        self.PHYS_BASE = int(gdb.parse_and_eval("(unsigned long) phys_base"))
         self.START_KERNEL_map = 0xffffffff80000000
 
-        self.KERNEL_START = gdb.parse_and_eval("_text")
-        self.KERNEL_END = gdb.parse_and_eval("_end")
+        self.KERNEL_START = gdb.parse_and_eval("(unsigned long) &_text")
+        self.KERNEL_END = gdb.parse_and_eval("(unsigned long) &_end")
 
         self.VMALLOC_START = int(gdb.parse_and_eval("vmalloc_base"))
         if self.VMALLOC_START == 0xffffc90000000000:
Signature · 1 line
2.54.0
author maintainer
#18 lore raw

PATCH 18/461 smb: client: require net admin for CIFS SWN netlink

In reply to Greg Kroah-Hartman

7.0-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.

Fixes fed979a7e082 ("cifs: Set witness notification handler for messages from userspace daemon")
Assisted-by Claude:claude-opus-4-7
---
 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_genl
 static 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 = {
author maintainer
#19 lore raw

PATCH 19/461 smb: client: protect tc_count increment in smb2_find_smb_sess_tcon_unlocked()

In reply to Greg Kroah-Hartman

7.0-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().

Fixes 96c4af418586 ("cifs: Fix locking usage for tcon fields")
---
 fs/smb/client/smb2transport.c |    2 ++
 1 file changed, 2 insertions(+)
fs/smb/client/smb2transport.c +2 -0
@@ -176,7 +176,9 @@ smb2_find_smb_sess_tcon_unlocked(struct
 	list_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;
author maintainer
#20 lore raw

PATCH 20/461 smb: client: use data_len for SMB2 READ encrypted folioq copy

In reply to Greg Kroah-Hartman

7.0-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
@@ -4825,7 +4825,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)
@@ -4834,7 +4834,7 @@ handle_read_data(struct TCP_Server_Info
 				dequeue_mid(server, 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 */
author maintainer
#21 lore raw

PATCH 21/461 smb/server: promote S_DEL_ON_CLS to S_DEL_PENDING when close

In reply to Greg Kroah-Hartman

7.0-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
@@ -211,7 +211,7 @@ int ksmbd_query_inode_status(struct dent
 		return 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;
@@ -227,7 +227,7 @@ bool ksmbd_inode_pending_delete(struct k
 	int 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;
@@ -395,12 +395,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);
author maintainer
#22 lore raw

PATCH 22/461 hwmon: (pmbus/adm1266) widen blackbox-info buffer to I2C_SMBUS_BLOCK_MAX

In reply to Greg Kroah-Hartman

7.0-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);
author maintainer
#23 lore raw

PATCH 23/461 ALSA: ua101: Reject too-short USB descriptors

In reply to Greg Kroah-Hartman

7.0-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
@@ -894,8 +894,9 @@ find_format_descriptor(struct usb_interf
 		struct 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) &&
author maintainer
#24 lore raw

PATCH 24/461 ALSA: pcm: Dont setup bogus iov_iter for silencing

In reply to Greg Kroah-Hartman

7.0-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);
 }
author maintainer
#25 lore raw

PATCH 25/461 ALSA: asihpi: Fix potential OOB array access at reading cache

In reply to Greg Kroah-Hartman

7.0-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_in
 		return 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",
author maintainer
#26 lore raw

PATCH 26/461 ALSA: scarlett2: Allow flash writes ending at segment boundary

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Cássio Gabriel <[email protected]>

commit a69b677e47a80319ce148d61cc29a2b57006e78d upstream.

scarlett2_hwdep_write() rejects writes when offset + count is greater than or equal to the selected flash segment size. That incorrectly treats a write ending exactly at the end of the segment as out of space, although the last byte written is still within the segment.

Split invalid argument checks from the segment-space check, keep zero-length writes as no-ops, and compare count against the remaining segment size. This permits exact-end writes and avoids relying on offset + count before deciding whether the request is in bounds.

---
 sound/usb/mixer_scarlett2.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
sound/usb/mixer_scarlett2.c +5 -2
@@ -9185,12 +9185,15 @@ static long scarlett2_hwdep_write(struct
 	flash_size = private->flash_segment_blocks[segment_id] *
 		     SCARLETT2_FLASH_BLOCK_SIZE;
 
-	if (count < 0 || *offset < 0 || *offset + count >= flash_size)
-		return -ENOSPC;
+	if (count < 0 || *offset < 0)
+		return -EINVAL;
 
 	if (!count)
 		return 0;
 
+	if (*offset >= flash_size || count > flash_size - *offset)
+		return -ENOSPC;
+
 	/* Limit the *req size to SCARLETT2_FLASH_RW_MAX */
 	if (count > max_data_size)
 		count = max_data_size;
author maintainer
#27 lore raw

PATCH 27/461 ACPI: battery: Fix system wakeup on critical battery status

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Rafael J. Wysocki <[email protected]>

commit c35cb4fc7231702d1e9952aec1a442f3e27df6f5 upstream.

Commit 0a869409a981 ("ACPI: battery: Convert the driver to a platform one") changed the parent of the battery wakeup source to the platform device used for driver binding, but it forgot to update the acpi_pm_wakeup_event() call in acpi_battery_update() accordingly.

Do it now to unbreak waking up the system on critical battery status during suspend-to-idle and during transitions to ACPI S3/S4.

Fixes 0a869409a981 ("ACPI: battery: Convert the driver to a platform one")
Cc 7.0+ <[email protected]> # 7.0+
---
 drivers/acpi/battery.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/acpi/battery.c +3 -1
@@ -96,6 +96,7 @@ struct acpi_battery {
 	struct power_supply *bat;
 	struct power_supply_desc bat_desc;
 	struct acpi_device *device;
+	struct device *phys_dev;
 	struct notifier_block pm_nb;
 	struct list_head list;
 	unsigned long update_time;
@@ -1035,7 +1036,7 @@ static int acpi_battery_update(struct ac
 	if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
 	    (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
 	     (battery->capacity_now <= battery->alarm)))
-		acpi_pm_wakeup_event(&battery->device->dev);
+		acpi_pm_wakeup_event(battery->phys_dev);
 
 	return result;
 }
@@ -1228,6 +1229,7 @@ static int acpi_battery_probe(struct pla
 
 	platform_set_drvdata(pdev, battery);
 
+	battery->phys_dev = &pdev->dev;
 	battery->device = device;
 	strscpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
 	strscpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
author maintainer
#28 lore raw

PATCH 28/461 efi: Allocate runtime workqueue before ACPI init

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 5894cf571e14 ("acpi/prmt: Use EFI runtime sandbox to invoke PRM handlers")
---
 drivers/firmware/efi/efi.c |   28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)
drivers/firmware/efi/efi.c +16 -12
@@ -402,21 +402,11 @@ static void __init efi_debugfs_init(void
 static 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
@@ -428,9 +418,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);
author maintainer
#29 lore raw

PATCH 29/461 spi: amd: Set correct bus number in ACPI probe path

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Krishnamoorthi M <[email protected]>

commit 422bd00b71ab42163aa3b8f8370276fe4c1581e7 upstream.

On platforms where the HID2 SPI controller (AMDI0063) is enumerated via ACPI instead of PCI, amd_spi_probe() unconditionally sets bus_num to 0, while the PCI probe path assigns bus_num 2 for HID2 controller.

Align the ACPI probe path to use the same bus number so that userspace and SPI client drivers see a consistent bus assignment regardless of the enumeration method.

Fixes b644c2776652 ("spi: spi_amd: Add PCI-based driver for AMD HID2 SPI controller")
Cc [email protected] # v6.16+
---
 drivers/spi/spi-amd.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-amd.c +1 -1
@@ -868,7 +868,7 @@ static int amd_spi_probe(struct platform
 	dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr);
 
 	amd_spi->version = (uintptr_t)device_get_match_data(dev);
-	host->bus_num = 0;
+	host->bus_num = (amd_spi->version == AMD_HID2_SPI) ? 2 : 0;
 
 	return amd_spi_probe_common(dev, host);
 }
author maintainer
#30 lore raw

PATCH 30/461 io_uring/waitid: clear waitid info before copying it to userspace

In reply to Greg Kroah-Hartman

7.0-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.

Fixes f31ecf671ddc ("io_uring: add IORING_OP_WAITID support")
---
 io_uring/waitid.c |    1 +
 1 file changed, 1 insertion(+)
io_uring/waitid.c +1 -0
@@ -275,6 +275,7 @@ int io_waitid_prep(struct io_kiocb *req,
 	iw->options = READ_ONCE(sqe->file_index);
 	iw->head = NULL;
 	iw->infop = u64_to_user_ptr(READ_ONCE(sqe->addr2));
+	memset(&iw->info, 0, sizeof(iw->info));
 	return 0;
 }
 
author maintainer
#31 lore raw

PATCH 31/461 drivers/base/memory: fix memory block reference leak in poison accounting

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 5033091de814 ("mm/hwpoison: introduce per-memory_block hwpoison counter")
Cc Danilo Krummrich <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Naoya Horiguchi <[email protected]>
Cc "Rafael J. Wysocki" <[email protected]>
Cc Vishal Verma <[email protected]>
---
 drivers/base/memory.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/base/memory.c +6 -2
@@ -1230,8 +1230,10 @@ void memblk_nr_poison_inc(unsigned long
 	const 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)
@@ -1239,8 +1241,10 @@ void memblk_nr_poison_sub(unsigned long
 	const 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)
author maintainer
#32 lore raw

PATCH 32/461 ipv6: ioam: refresh hdr pointer before ioam6_event()

In reply to Greg Kroah-Hartman

7.0-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
@@ -955,9 +955,9 @@ static bool ipv6_hop_ioam(struct sk_buff
 		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));
+		/* 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);
 
author maintainer
#33 lore raw

PATCH 33/461 mm/memory: fix spurious warning when unmapping device-private/exclusive pages

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alistair Popple <[email protected]>

commit be3f38d05cc5a7c3f13e51994c5dd043ab604d28 upstream.

Device private and exclusive entries are only supported for anonymous folios. This condition is tested in __migrate_device_pages() and make_device_exclusive() using folio_test_anon(). However the unmap path tests this assumption using vma_is_anonymous().

This is wrong because whilst anonymous VMAs can only contain folios where folio_test_anon() is true the opposite relation does not hold. A folio for which folio_test_anon() is true does not imply vma_is_anonymous() is true. Such a condition can occur if for example a folio is part of a private filebacked mapping.

In this case vma_is_anonymous() is false as the mapping is filebacked, but folio_test_anon() may be true, thus permitting devices to migrate the folio to device private memory. This can lead to the following spurious warnings during process teardown:

[  772.737706] ------------[ cut here ]------------
[  772.739201] WARNING: mm/memory.c:1754 at unmap_page_range.cold+0x26/0x18a, CPU#17: hmm-tests/2041
[  772.742050] Modules linked in: test_hmm nvidia_uvm(O) nvidia(O)
[  772.743959] CPU: 17 UID: 0 PID: 2041 Comm: hmm-tests Tainted: G        W  O        7.0.0+ #387 PREEMPT(full)
[  772.747104] Tainted: [W]=WARN, [O]=OOT_MODULE
[  772.748509] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014
[  772.752117] RIP: 0010:unmap_page_range.cold+0x26/0x18a
[  772.753780] Code: 7e fe ff ff 48 89 4c 24 78 4c 89 44 24 38 e8 f2 ff b1 00 48 8b 4c 24 78 4c 8b 44 24 38 48 8b 44 24 18 48 83 78 48 00 74 04 90 <0f> 0b 90 48 89 ca b8 ff ff 37 00 48 c1 ea 03 48 c1 e0 2a 80 3c 02
[  772.759602] RSP: 0018:ffff888112607550 EFLAGS: 00010286
[  772.761310] RAX: ffff88811bbf4dc0 RBX: dffffc0000000000 RCX: ffffea03e9bfffd8
[  772.763583] RDX: 1ffff1102377e9c1 RSI: 0000000000000008 RDI: ffff88811bbf4e08
[  772.765914] RBP: 0000000000000006 R08: ffff8881059f7448 R09: ffffed10224c0e68
[  772.768184] R10: ffff888112607347 R11: 0000000000000001 R12: 0000000000000001
[  772.770461] R13: ffffea03e9bfffc0 R14: ffff888112607908 R15: ffffea03e9bfffc0
[  772.772782] FS:  00007f327caa2780(0000) GS:ffff888427b7d000(0000) knlGS:0000000000000000
[  772.775328] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  772.777187] CR2: 00007f327ca89000 CR3: 00000001994d5000 CR4: 00000000000006f0
[  772.779135] Call Trace:
[  772.779792]  <TASK>
[  772.780317]  ? dmirror_interval_invalidate+0x1a3/0x290 [test_hmm]
[  772.781873]  ? vm_normal_page_pud+0x2b0/0x2b0
[  772.782992]  ? __rwlock_init+0x150/0x150
[  772.784006]  ? lock_release+0x216/0x2b0
[  772.785008]  ? __mmu_notifier_invalidate_range_start+0x505/0x6e0
[  772.786522]  ? lock_release+0x216/0x2b0
[  772.787498]  ? unmap_single_vma+0xb6/0x210
[  772.788573]  unmap_vmas+0x27d/0x520
[  772.789506]  ? unmap_single_vma+0x210/0x210
[  772.790607]  ? mas_update_gap.part.0+0x620/0x620
[  772.791834]  unmap_region+0x19e/0x350
[  772.792769]  ? remove_vma+0x130/0x130
[  772.793684]  ? mas_alloc_nodes+0x1f2/0x300
[  772.794730]  vms_complete_munmap_vmas+0x8c1/0xe20
[  772.795926]  ? unmap_region+0x350/0x350
[  772.796917]  do_vmi_align_munmap+0x36a/0x4e0
[  772.798018]  ? lock_release+0x216/0x2b0
[  772.799024]  ? vma_shrink+0x620/0x620
[  772.799983]  do_vmi_munmap+0x150/0x2c0
[  772.800939]  __vm_munmap+0x161/0x2c0
[  772.801872]  ? expand_downwards+0xd60/0xd60
[  772.802948]  ? clockevents_program_event+0x1ef/0x540
[  772.804217]  ? lock_release+0x216/0x2b0
[  772.805158]  __x64_sys_munmap+0x59/0x80
[  772.805776]  do_syscall_64+0xfc/0x670
[  772.806336]  ? irqentry_exit+0xda/0x580
[  772.806976]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
[  772.807772] RIP: 0033:0x7f327cbb2717
[  772.808323] Code: 73 01 c3 48 8b 0d f9 76 0d 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 b8 0b 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d c9 76 0d 00 f7 d8 64 89 01 48
[  772.811337] RSP: 002b:00007ffde7f57d38 EFLAGS: 00000202 ORIG_RAX: 000000000000000b
[  772.812564] RAX: ffffffffffffffda RBX: 00007f327cc9c000 RCX: 00007f327cbb2717
[  772.813733] RDX: 0000000000000000 RSI: 0000000000400000 RDI: 00007f327c289000
[  772.814867] RBP: 0000000000421360 R08: 000000000000001a R09: 0000000000000000
[  772.815991] R10: 0000000000000003 R11: 0000000000000202 R12: 00007ffde7f57d74
[  772.817121] R13: 00007f327c689010 R14: 0000000000100000 R15: 00007f327c289000
[  772.818272]  </TASK>
[  772.818614] irq event stamp: 0
[  772.819159] hardirqs last  enabled at (0): [<0000000000000000>] 0x0
[  772.820174] hardirqs last disabled at (0): [<ffffffff82a57ab3>] copy_process+0x19f3/0x6440
[  772.821511] softirqs last  enabled at (0): [<ffffffff82a57b00>] copy_process+0x1a40/0x6440
[  772.822869] softirqs last disabled at (0): [<0000000000000000>] 0x0
[  772.823871] ---[ end trace 0000000000000000 ]---

Fix this by using the same check for folio_test_anon() in zap_nonpresent_ptes(). Also add a hmm-test case for this.

Fixes 999dad824c39 ("mm/shmem: persist uffd-wp bit across zapping for file-backed")
Cc David Hildenbrand <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc John Hubbard <[email protected]>
Cc Leon Romanovsky <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Peter Xu <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Thomas Hellström <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 mm/memory.c                            |    2 -
 tools/testing/selftests/mm/hmm-tests.c |   50 +++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)
mm/memory.c +1 -1
@@ -1750,7 +1750,7 @@ static inline int zap_nonpresent_ptes(st
 		 * consider uffd-wp bit when zap. For more information,
 		 * see zap_install_uffd_wp_if_needed().
 		 */
-		WARN_ON_ONCE(!vma_is_anonymous(vma));
+		WARN_ON_ONCE(!folio_test_anon(folio));
 		rss[mm_counter(folio)]--;
 		folio_remove_rmap_pte(folio, page, vma);
 		folio_put(folio);
tools/testing/selftests/mm/hmm-tests.c +50 -0

56 lines not on this page · raw message

author maintainer
#34 lore raw

PATCH 34/461 mm: fix __vm_normal_page() to handle missing support for pmd_special()/pud_special()

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Hildenbrand (Arm) <[email protected]>

commit c0c6ccd9828c3a1950623b546fa57292a77b5c73 upstream.

On x86 32-bit with THP enabled, zap_huge_pmd() is seen to generate a "WARNING: mm/memory.c:735 at __vm_normal_page+0x6a/0x7d", from the VM_WARN_ON_ONCE(is_zero_pfn(pfn) || is_huge_zero_pfn(pfn)); followed by "BUG: Bad rss-counter state"s, then later "BUG: Bad page state"s when reclaim gets to call shrink_huge_zero_folio_scan().

It's as if the _PAGE_SPECIAL bit never got set in the huge_zero pmd: and indeed, whereas pte_special() and pte_mkspecial() are subject to a dedicated CONFIG_ARCH_HAS_PTE_SPECIAL, pmd_special() and pmd_mkspecial() are subject to CONFIG_ARCH_SUPPORTS_PMD_PFNMAP, which is never enabled on any 32-bit architecture.

While the problem was exposed through commit d80a9cb1a64a ("mm/huge_memory: add and use normal_or_softleaf_folio_pmd()"), it was an oversight in commit af38538801c6 ("mm/memory: factor out common code from vm_normal_page_*()") and would result in other problems:
* huge zero folio accounted in smaps, pagemap (PAGE_IS_FILE) and numamaps as file-backed THP
* folio_walk_start() returning the folio even without FW_ZEROPAGE set. Callers seem to tolerate that, though.

... and triggering the VM_WARN_ON_ONE(), although never reported so far.

To fix it, teach vm_normal_page_pmd()/vm_normal_page_pud() to consider whether pmd_special/pud_special is actually implemented.

---
 mm/memory.c |   22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)
mm/memory.c +19 -3
@@ -625,6 +625,21 @@ static void print_bad_page_map(struct vm
 	dump_stack();
 	add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
 }
+
+static inline bool pgtable_level_has_pxx_special(enum pgtable_level level)
+{
+	switch (level) {
+	case PGTABLE_LEVEL_PTE:
+		return IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL);
+	case PGTABLE_LEVEL_PMD:
+		return IS_ENABLED(CONFIG_ARCH_SUPPORTS_PMD_PFNMAP);
+	case PGTABLE_LEVEL_PUD:
+		return IS_ENABLED(CONFIG_ARCH_SUPPORTS_PUD_PFNMAP);
+	default:
+		return false;
+	}
+}
+
 #define print_bad_pte(vma, addr, pte, page) \
 	print_bad_page_map(vma, addr, pte_val(pte), page, PGTABLE_LEVEL_PTE)
 
@@ -697,7 +712,7 @@ static inline struct page *__vm_normal_p
 		unsigned long addr, unsigned long pfn, bool special,
 		unsigned long long entry, enum pgtable_level level)
 {
-	if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL)) {
+	if (pgtable_level_has_pxx_special(level)) {
 		if (unlikely(special)) {
 #ifdef CONFIG_FIND_NORMAL_PAGE
 			if (vma->vm_ops && vma->vm_ops->find_normal_page)
@@ -712,8 +727,9 @@ static inline struct page *__vm_normal_p
 			return NULL;
 		}
 		/*
-		 * With CONFIG_ARCH_HAS_PTE_SPECIAL, any special page table
-		 * mappings (incl. shared zero folios) are marked accordingly.
+		 * With working pte_special()/pmd_special()..., any special page
+		 * table mappings (incl. shared zero folios) are marked
+		 * accordingly.
 		 */
 	} else {
 		if (unlikely(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))) {
author maintainer
#35 lore raw

PATCH 35/461 mm/memory_hotplug: fix memory block reference leak on remove

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 6b8f0798b85a ("mm/memory_hotplug: split memmap_on_memory requests across memblocks")
Cc Danilo Krummrich <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Miaohe Lin <[email protected]>
Cc Naoya Horiguchi <[email protected]>
Cc "Rafael J. Wysocki" <[email protected]>
Cc Vishal Verma <[email protected]>
---
 mm/memory_hotplug.c |    2 ++
 1 file changed, 2 insertions(+)
mm/memory_hotplug.c +2 -0
@@ -1430,6 +1430,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);
 
author maintainer
#36 lore raw

PATCH 36/461 mm/page_alloc: fix initialization of tags of the huge zero folio with init_on_free

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Hildenbrand (Arm) <[email protected]>

commit 6a288a4ddb4a994490505ab5f41c445f8e6b6467 upstream.

__GFP_ZEROTAGS semantics are currently a bit weird, but effectively this flag is only ever set alongside __GFP_ZERO and __GFP_SKIP_KASAN.

If we run with init_on_free, we will zero out pages during __free_pages_prepare(), to skip zeroing on the allocation path.

However, when allocating with __GFP_ZEROTAG set, post_alloc_hook() will consequently not only skip clearing page content, but also skip clearing tag memory.

Not clearing tags through __GFP_ZEROTAGS is irrelevant for most pages that will get mapped to user space through set_pte_at() later: set_pte_at() and friends will detect that the tags have not been initialized yet (PG_mte_tagged not set), and initialize them.

However, for the huge zero folio, which will be mapped through a PMD marked as special, this initialization will not be performed, ending up exposing whatever tags were still set for the pages.

The docs (Documentation/arch/arm64/memory-tagging-extension.rst) state that allocation tags are set to 0 when a page is first mapped to user space. That no longer holds with the huge zero folio when init_on_free is enabled.

Fix it by decoupling __GFP_ZEROTAGS from __GFP_ZERO, passing to tag_clear_highpages() whether we want to also clear page content.

Invert the meaning of the tag_clear_highpages() return value to have clearer semantics.

Reproduced with the huge zero folio by modifying the check_buffer_fill arm64/mte selftest to use a 2 MiB area, after making sure that pages have a non-0 tag set when freeing (note that, during boot, we will not actually initialize tags, but only set KASAN_TAG_KERNEL in the page flags).

	$ ./check_buffer_fill
	1..20
	...
	not ok 17 Check initial tags with private mapping, sync error mode and mmap memory
	not ok 18 Check initial tags with private mapping, sync error mode and mmap/mprotect memory
	...

This code needs more cleanups; we'll tackle that next, like decoupling __GFP_ZEROTAGS from __GFP_SKIP_KASAN.

[[email protected]: s/__GPF_ZERO/__GFP_ZERO/, per David]
Fixes adfb6609c680 ("mm/huge_memory: initialise the tags of the huge zero folio")
Cc Brendan Jackman <[email protected]>
Cc Dev Jain <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Liam Howlett <[email protected]>
Cc Lorenzo Stoakes (Oracle) <[email protected]>
Cc Mark Brown <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Will Deacon <[email protected]>
Cc Zi Yan <[email protected]>
---
 arch/arm64/include/asm/page.h |    2 +-
 arch/arm64/mm/fault.c         |   11 +++++++----
 include/linux/gfp_types.h     |   10 +++++-----
 include/linux/highmem.h       |    7 ++++---
 mm/page_alloc.c               |    8 ++++----
 5 files changed, 21 insertions(+), 17 deletions(-)
arch/arm64/include/asm/page.h +1 -1
@@ -33,7 +33,7 @@ struct folio *vma_alloc_zeroed_movable_f
 						unsigned long vaddr);
 #define vma_alloc_zeroed_movable_folio vma_alloc_zeroed_movable_folio
 
-bool tag_clear_highpages(struct page *to, int numpages);
+bool tag_clear_highpages(struct page *to, int numpages, bool clear_pages);
 #define __HAVE_ARCH_TAG_CLEAR_HIGHPAGES
 
 #define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
arch/arm64/mm/fault.c +7 -4
@@ -971,7 +971,7 @@ struct folio *vma_alloc_zeroed_movable_f
 	return vma_alloc_folio(flags, 0, vma, vaddr);
 }
 
-bool tag_clear_highpages(struct page *page, int numpages)
+bool tag_clear_highpages(struct page *page, int numpages, bool clear_pages)
 {
 	/*
 	 * Check if MTE is supported and fall back to clear_highpage().
@@ -979,13 +979,16 @@ bool tag_clear_highpages(struct page *pa
 	 * post_alloc_hook() will invoke tag_clear_highpages().
 	 */
 	if (!system_supports_mte())
-		return false;
+		return clear_pages;
 
 	/* Newly allocated pages, shouldn't have been tagged yet */
 	for (int i = 0; i < numpages; i++, page++) {
 		WARN_ON_ONCE(!try_page_mte_tagging(page));
-		mte_zero_clear_page_tags(page_address(page));
+		if (clear_pages)
+			mte_zero_clear_page_tags(page_address(page));
+		else
+			mte_clear_page_tags(page_address(page));
 		set_page_mte_tagged(page);
 	}
-	return true;
+	return false;
 }
include/linux/gfp_types.h +5 -5
@@ -273,11 +273,11 @@ enum {
  *
  * %__GFP_ZERO returns a zeroed page on success.
  *
- * %__GFP_ZEROTAGS zeroes memory tags at allocation time if the memory itself
- * is being zeroed (either via __GFP_ZERO or via init_on_alloc, provided that
- * __GFP_SKIP_ZERO is not set). This flag is intended for optimization: setting
- * memory tags at the same time as zeroing memory has minimal additional
- * performance impact.
+ * %__GFP_ZEROTAGS zeroes memory tags at allocation time. Setting memory tags at
+ * the same time as zeroing memory (e.g., with __GFP_ZERO) has minimal
+ * additional performance impact. However, __GFP_ZEROTAGS also zeroes the tags
+ * even if memory is not getting zeroed at allocation time (e.g.,
+ * with init_on_free).
  *
  * %__GFP_SKIP_KASAN makes KASAN skip unpoisoning on page allocation.
  * Used for userspace and vmalloc pages; the latter are unpoisoned by
include/linux/highmem.h +4 -3
@@ -347,10 +347,11 @@ static inline void clear_highpage_kasan_
 
 #ifndef __HAVE_ARCH_TAG_CLEAR_HIGHPAGES
 
-/* Return false to let people know we did not initialize the pages */
-static inline bool tag_clear_highpages(struct page *page, int numpages)
+/* Returns true if the caller has to initialize the pages */
+static inline bool tag_clear_highpages(struct page *page, int numpages,
+		bool clear_pages)
 {
-	return false;
+	return clear_pages;
 }
 
 #endif
mm/page_alloc.c +4 -4
@@ -1847,9 +1847,9 @@ static inline bool should_skip_init(gfp_
 inline void post_alloc_hook(struct page *page, unsigned int order,
 				gfp_t gfp_flags)
 {
+	const bool zero_tags = gfp_flags & __GFP_ZEROTAGS;
 	bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) &&
 			!should_skip_init(gfp_flags);
-	bool zero_tags = init && (gfp_flags & __GFP_ZEROTAGS);
 	int i;
 
 	set_page_private(page, 0);
@@ -1871,11 +1871,11 @@ inline void post_alloc_hook(struct page
 	 */
 
 	/*
-	 * If memory tags should be zeroed
-	 * (which happens only when memory should be initialized as well).
+	 * Clearing tags can efficiently clear the memory for us as well, if
+	 * required.
 	 */
 	if (zero_tags)
-		init = !tag_clear_highpages(page, 1 << order);
+		init = tag_clear_highpages(page, 1 << order, /* clear_pages= */init);
 
 	if (!should_skip_kasan_unpoison(gfp_flags) &&
 	    kasan_unpoison_pages(page, order, init)) {
author maintainer
#37 lore raw

PATCH 37/461 mm/migrate_device: fix spinlock leak in migrate_vma_insert_huge_pmd_page

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sunny Patel <[email protected]>

commit 63451de16e0a08be40f9ab5e7c5c8f5c79676fb1 upstream.

When check_stable_address_space() fails after the PMD spinlock has been acquired via pmd_lock(), the code jumps directly to the abort label, bypassing the spin_unlock() call in unlock_abort. This causes the PMD spinlock to be permanently held, leading to a deadlock.

Change the goto target from abort to unlock_abort to ensure the spinlock is always released on this error path.

Fixes a30b48bf1b24 ("mm/migrate_device: implement THP migration of zone device pages")
Cc Alistair Popple <[email protected]>
Cc Byungchul Park <[email protected]>
Cc Gregory Price <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Joshua Hahn <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Rakie Kim <[email protected]>
---
 mm/migrate_device.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/migrate_device.c +1 -1
@@ -856,7 +856,7 @@ static int migrate_vma_insert_huge_pmd_p
 	ptl = pmd_lock(vma->vm_mm, pmdp);
 	csa_ret = check_stable_address_space(vma->vm_mm);
 	if (csa_ret)
-		goto abort;
+		goto unlock_abort;
 
 	/*
 	 * Check for userfaultfd but do not deliver the fault. Instead,
author maintainer
#38 lore raw

PATCH 38/461 selftests/mm: run_vmtests.sh: fix destructive tests invocation

In reply to Greg Kroah-Hartman

7.0-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.

Fixes f16ff3b692ad ("selftests/mm: run_vmtests.sh: add missing tests")
Cc David Hildenbrand <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 tools/testing/selftests/mm/run_vmtests.sh |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/mm/run_vmtests.sh +1 -1
@@ -103,7 +103,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 ;;
author maintainer
#39 lore raw

PATCH 39/461 mm/damon: fix damos_stat tracepoint format for sz_applied

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: SeongJae Park <[email protected]>

commit 620072fd783290ad92c2d445a47b0a61b161f352 upstream.

The print format is wrongly marking sz_applied as sz_tried. Fix it.

Fixes 804c26b961da ("mm/damon/core: add trace point for damos stat per apply interval")
Cc "Masami Hiramatsu (Google)" <[email protected]>
Cc Mathieu Desnoyers <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc <[email protected]> # 7.0.x
---
 include/trace/events/damon.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/trace/events/damon.h +1 -1
@@ -41,7 +41,7 @@ TRACE_EVENT(damos_stat_after_apply_inter
 	),
 
 	TP_printk("ctx_idx=%u scheme_idx=%u nr_tried=%lu sz_tried=%lu "
-			"nr_applied=%lu sz_tried=%lu sz_ops_filter_passed=%lu "
+			"nr_applied=%lu sz_applied=%lu sz_ops_filter_passed=%lu "
 			"qt_exceeds=%lu nr_snapshots=%lu",
 			__entry->context_idx, __entry->scheme_idx,
 			__entry->nr_tried, __entry->sz_tried,
author maintainer
#40 lore raw

PATCH 40/461 net: wwan: iosm: fix potential memory leaks in ipc_imem_init()

In reply to Greg Kroah-Hartman

7.0-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
@@ -1425,6 +1425,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:
author maintainer
#41 lore raw

PATCH 41/461 Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del()

In reply to Greg Kroah-Hartman

7.0-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_kill

This 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 invert
conn->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.

Fixes 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
---
 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
@@ -309,6 +309,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
@@ -759,6 +759,8 @@ static void iso_sock_cleanup_listen(stru
 	while ((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 */
@@ -1364,8 +1366,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(s
 	while ((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;
@@ -497,8 +499,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
@@ -498,6 +498,8 @@ static void sco_sock_cleanup_listen(stru
 	while ((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;
@@ -759,8 +761,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;
author maintainer
#42 lore raw

PATCH 42/461 Bluetooth: ISO: drop ISO_END frames received without prior ISO_START

In reply to Greg Kroah-Hartman

7.0-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.

Fixes ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type")
Assisted-by Claude:claude-opus-4-7
---
 net/bluetooth/iso.c |    5 +++++
 1 file changed, 5 insertions(+)
net/bluetooth/iso.c +5 -0
@@ -2594,6 +2594,11 @@ int iso_recv(struct hci_dev *hdev, u16 h
 		break;
 
 	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;
author maintainer
#43 lore raw

PATCH 43/461 Bluetooth: bnep: Fix UAF read of dev->name

In reply to Greg Kroah-Hartman

7.0-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:
author maintainer
#44 lore raw

PATCH 44/461 Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 3b799254cf6f ("Bluetooth: hci_uart: Cancel init work before unregistering")
---
 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 tt
 	if (!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(struct
 		percpu_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);
author maintainer
#45 lore raw

PATCH 45/461 Bluetooth: L2CAP: ecred_reconfigure: send packed pdu, not stack pointer

In reply to Greg Kroah-Hartman

7.0-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).

Fixes 1c08108f3014 ("Bluetooth: L2CAP: Avoid -Wflex-array-member-not-at-end warnings")
Assisted-by Claude:claude-opus-4-7
---
 net/bluetooth/l2cap_core.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +1 -1
@@ -7275,7 +7275,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)
author maintainer
#46 lore raw

PATCH 46/461 Bluetooth: hci_qca: Convert timeout from jiffies to ms

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Shuai Zhang <[email protected]>

commit 375ba7484132662a4a8c7547d088fb6275c00282 upstream.

Since the timer uses jiffies as its unit rather than ms, the timeout value must be converted from ms to jiffies when configuring the timer. Otherwise, the intended 8s timeout is incorrectly set to approximately 33s.

To improve readability, embed msecs_to_jiffies() directly in the macro definitions and drop the _MS suffix from macros that now yield jiffies
values: MEMDUMP_TIMEOUT, FW_DOWNLOAD_TIMEOUT, IBS_DISABLE_SSR_TIMEOUT, CMD_TRANS_TIMEOUT, and IBS_BTSOC_TX_IDLE_TIMEOUT.

IBS_WAKE_RETRANS_TIMEOUT_MS and IBS_HOST_TX_IDLE_TIMEOUT_MS are intentionally left unchanged. Their values are stored in the struct fields wake_retrans and tx_idle_delay, which hold ms values at runtime and can be modified via debugfs. The msecs_to_jiffies() conversion happens at each call site against the field value, so it cannot be embedded in the macro.

Wake timer depends on commit c347ca17d62a

Fixes d841502c79e3 ("Bluetooth: hci_qca: Collect controller memory dump during SSR")
---
 drivers/bluetooth/hci_qca.c |   33 ++++++++++++++++-----------------
 1 file changed, 16 insertions(+), 17 deletions(-)
drivers/bluetooth/hci_qca.c +16 -17
@@ -48,13 +48,12 @@
 #define HCI_MAX_IBS_SIZE	10
 
 #define IBS_WAKE_RETRANS_TIMEOUT_MS	100
-#define IBS_BTSOC_TX_IDLE_TIMEOUT_MS	200
+#define IBS_BTSOC_TX_IDLE_TIMEOUT	msecs_to_jiffies(200)
 #define IBS_HOST_TX_IDLE_TIMEOUT_MS	2000
-#define CMD_TRANS_TIMEOUT_MS		100
-#define MEMDUMP_TIMEOUT_MS		8000
-#define IBS_DISABLE_SSR_TIMEOUT_MS \
-	(MEMDUMP_TIMEOUT_MS + FW_DOWNLOAD_TIMEOUT_MS)
-#define FW_DOWNLOAD_TIMEOUT_MS		3000
+#define CMD_TRANS_TIMEOUT		msecs_to_jiffies(100)
+#define MEMDUMP_TIMEOUT			msecs_to_jiffies(8000)
+#define FW_DOWNLOAD_TIMEOUT		msecs_to_jiffies(3000)
+#define IBS_DISABLE_SSR_TIMEOUT		(MEMDUMP_TIMEOUT + FW_DOWNLOAD_TIMEOUT)
 
 /* susclk rate */
 #define SUSCLK_RATE_32KHZ	32768
@@ -1093,7 +1092,7 @@ static void qca_controller_memdump(struc
 
 			queue_delayed_work(qca->workqueue,
 					   &qca->ctrl_memdump_timeout,
-					   msecs_to_jiffies(MEMDUMP_TIMEOUT_MS));
+					   MEMDUMP_TIMEOUT);
 			skb_pull(skb, sizeof(qca_memdump->ram_dump_size));
 			qca_memdump->current_seq_no = 0;
 			qca_memdump->received_dump = 0;
@@ -1366,7 +1365,7 @@ static int qca_set_baudrate(struct hci_d
 
 	if (hu->serdev)
 		serdev_device_wait_until_sent(hu->serdev,
-		      msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
+		      CMD_TRANS_TIMEOUT);
 
 	/* Give the controller time to process the request */
 	switch (qca_soc_type(hu)) {
@@ -1398,8 +1397,8 @@ static inline void host_set_baudrate(str
 
 static int qca_send_power_pulse(struct hci_uart *hu, bool on)
 {
+	int timeout = CMD_TRANS_TIMEOUT;
 	int ret;
-	int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
 	u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE;
 
 	/* These power pulses are single byte command which are sent
@@ -1604,7 +1603,7 @@ static void qca_wait_for_dump_collection
 	struct qca_data *qca = hu->priv;
 
 	wait_on_bit_timeout(&qca->flags, QCA_MEMDUMP_COLLECTION,
-			    TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT_MS);
+			    TASK_UNINTERRUPTIBLE, MEMDUMP_TIMEOUT);
 
 	clear_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
 }
@@ -2577,7 +2576,7 @@ static void qca_serdev_remove(struct ser
 static void qca_serdev_shutdown(struct serdev_device *serdev)
 {
 	int ret;
-	int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS);
+	int timeout = CMD_TRANS_TIMEOUT;
 	struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
 	struct hci_uart *hu = &qcadev->serdev_hu;
 	struct hci_dev *hdev = hu->hdev;
@@ -2634,7 +2633,7 @@ static int __maybe_unused qca_suspend(st
 	bool tx_pending = false;
 	int ret = 0;
 	u8 cmd;
-	u32 wait_timeout = 0;
+	unsigned long wait_timeout = 0;
 
 	set_bit(QCA_SUSPENDING, &qca->flags);
 
@@ -2655,15 +2654,15 @@ static int __maybe_unused qca_suspend(st
 	if (test_bit(QCA_IBS_DISABLED, &qca->flags) ||
 	    test_bit(QCA_SSR_TRIGGERED, &qca->flags)) {
 		wait_timeout = test_bit(QCA_SSR_TRIGGERED, &qca->flags) ?
-					IBS_DISABLE_SSR_TIMEOUT_MS :
-					FW_DOWNLOAD_TIMEOUT_MS;
+					IBS_DISABLE_SSR_TIMEOUT :
+					FW_DOWNLOAD_TIMEOUT;
 
 		/* QCA_IBS_DISABLED flag is set to true, During FW download
 		 * and during memory dump collection. It is reset to false,
 		 * After FW download complete.
 		 */
 		wait_on_bit_timeout(&qca->flags, QCA_IBS_DISABLED,
-			    TASK_UNINTERRUPTIBLE, msecs_to_jiffies(wait_timeout));
+			    TASK_UNINTERRUPTIBLE, wait_timeout);
 
 		if (test_bit(QCA_IBS_DISABLED, &qca->flags)) {
 			bt_dev_err(hu->hdev, "SSR or FW download time out");
@@ -2715,7 +2714,7 @@ static int __maybe_unused qca_suspend(st
 
 	if (tx_pending) {
 		serdev_device_wait_until_sent(hu->serdev,
-					      msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
+					      CMD_TRANS_TIMEOUT);
 		serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
 	}
 
@@ -2724,7 +2723,7 @@ static int __maybe_unused qca_suspend(st
 	 */
 	ret = wait_event_interruptible_timeout(qca->suspend_wait_q,
 			qca->rx_ibs_state == HCI_IBS_RX_ASLEEP,
-			msecs_to_jiffies(IBS_BTSOC_TX_IDLE_TIMEOUT_MS));
+			IBS_BTSOC_TX_IDLE_TIMEOUT);
 	if (ret == 0) {
 		ret = -ETIMEDOUT;
 		goto error;
author maintainer
#47 lore raw

PATCH 47/461 Bluetooth: MGMT: validate Add Extended Advertising Data length

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 12410572833a ("Bluetooth: Break add adv into two mgmt commands")
Assisted-by Claude:claude-opus-4-7
---
 net/bluetooth/mgmt.c |    6 ++++++
 1 file changed, 6 insertions(+)
net/bluetooth/mgmt.c +6 -0
@@ -9110,9 +9110,15 @@ static int add_ext_adv_data(struct sock
 	struct 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);
author maintainer
#48 lore raw

PATCH 48/461 Bluetooth: serialize accept_q access

In reply to Greg Kroah-Hartman

7.0-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
@@ -398,6 +398,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

author maintainer
#49 lore raw

PATCH 49/461 phonet/pep: disable BH around forwarded sk_receive_skb()

In reply to Greg Kroah-Hartman

7.0-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:879

Wrap 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:
author maintainer
#50 lore raw

PATCH 50/461 net: bcmgenet: keep RBUF EEE/PM disabled

In reply to Greg Kroah-Hartman

7.0-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
@@ -1368,13 +1368,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);
author maintainer
#51 lore raw

PATCH 51/461 net: devmem: reject dma-buf bind with non-page-aligned size or SG length

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Carlier <[email protected]>

commit 4eb82ba543421e9e38cc14e4e82058b78850df50 upstream.

net_devmem_bind_dmabuf() trusts dmabuf->size and sg_dma_len() to be PAGE_SIZE multiples without checking:

- tx_vec is sized dmabuf->size / PAGE_SIZE, and net_devmem_get_niov_at() only bounds-checks virt_addr < dmabuf->size before indexing tx_vec[virt_addr / PAGE_SIZE]. With size = N*PAGE_SIZE + r (1 <= r < PAGE_SIZE), sendmsg() at iov_base = N*PAGE_SIZE passes the bound check and reads tx_vec[N] -- one past.

- owner->area.num_niovs = len / PAGE_SIZE while gen_pool_add_owner() covers the full byte len, so a non-page-multiple non-final sg desyncs num_niovs from the gen_pool region for every later sg, on both RX and TX.

dma-buf does not require page-aligned sizes, so the bind path has to enforce what its own indexing assumes. Reject both with -EINVAL.

The size check is TX-only (only tx_vec is sized off dmabuf->size); the SG-length check covers both directions.

---
 net/core/devmem.c |   11 +++++++++++
 1 file changed, 11 insertions(+)
net/core/devmem.c +11 -0
@@ -241,6 +241,11 @@ net_devmem_bind_dmabuf(struct net_device
 	}
 
 	if (direction == DMA_TO_DEVICE) {
+		if (!IS_ALIGNED(dmabuf->size, PAGE_SIZE)) {
+			err = -EINVAL;
+			NL_SET_ERR_MSG(extack, "TX dma-buf size must be a multiple of PAGE_SIZE");
+			goto err_unmap;
+		}
 		binding->tx_vec = kvmalloc_objs(struct net_iov *,
 						dmabuf->size / PAGE_SIZE);
 		if (!binding->tx_vec) {
@@ -267,6 +272,12 @@ net_devmem_bind_dmabuf(struct net_device
 		size_t len = sg_dma_len(sg);
 		struct net_iov *niov;
 
+		if (!IS_ALIGNED(len, PAGE_SIZE)) {
+			err = -EINVAL;
+			NL_SET_ERR_MSG(extack, "dma-buf SG length must be PAGE_SIZE aligned");
+			goto err_free_chunks;
+		}
+
 		owner = kzalloc_node(sizeof(*owner), GFP_KERNEL,
 				     dev_to_node(&dev->dev));
 		if (!owner) {
author maintainer
#52 lore raw

PATCH 52/461 net: phy: skip EEE advertisement write when autoneg is disabled

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Nerijus Bendžiūnas <[email protected]>

commit 960e77ce14a83ef7f226e8e4b4d75765633ba48b upstream.

genphy_c45_an_config_eee_aneg() writes the EEE advertisement to the auto-negotiation device's MMD register space (MDIO_MMD_AN, register MDIO_AN_EEE_ADV). These registers are read by the link partner only during auto-negotiation, so writing them while autoneg is disabled cannot influence the link. On some PHYs (e.g. Broadcom BCM54213PE) the write nevertheless reaches the chip and disturbs the receive datapath.

Concretely, running

ethtool -s eth0 speed 100 duplex full autoneg off ethtool --set-eee eth0 eee off

leaves eth0 with TX working and RX completely silent on a Raspberry Pi 4 / CM4 board (bcmgenet + BCM54213PE in rgmii-rxid). Switching back to autoneg recovers the link.

Prior to commit f26a29a038ee ("net: phy: ensure that genphy_c45_an_config_eee_aneg() sees new value of phydev->eee_cfg.eee_enabled"), the disable path was effectively a no-op because the helper read
the stale eee_cfg.eee_enabled, so the underlying PHY behavior never
surfaced.

Bisected on rpi-6.12.y between commits 83943264 (good) and effcbc88 (bad) to f26a29a038ee.

Fixes f26a29a038ee ("net: phy: ensure that genphy_c45_an_config_eee_aneg() sees new value of phydev->eee_cfg.eee_enabled")
---
 drivers/net/phy/phy-c45.c |    8 ++++++++
 1 file changed, 8 insertions(+)
drivers/net/phy/phy-c45.c +8 -0
@@ -940,6 +940,14 @@ EXPORT_SYMBOL_GPL(genphy_c45_read_eee_ab
  */
 int genphy_c45_an_config_eee_aneg(struct phy_device *phydev)
 {
+	/* Writing MMD AN advertisements while autoneg is disabled has no
+	 * effect on link-partner negotiation, but on some PHYs (e.g. the
+	 * Broadcom BCM54213PE) the write itself disturbs the receive
+	 * datapath. Skip it.
+	 */
+	if (phydev->autoneg == AUTONEG_DISABLE)
+		return 0;
+
 	if (!phydev->eee_cfg.eee_enabled) {
 		__ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
 
author maintainer
#53 lore raw

PATCH 53/461 net: hsr: defer node table free until after RCU readers

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Michael Bommarito <[email protected]>

commit aaec7096f9961eb223b5b149abe9495525c205d9 upstream.

HSR node-list and node-status generic-netlink operations run under rcu_read_lock(). They walk hsr->node_db through hsr_get_next_node() and hsr_get_node_data(), but RTM_DELLINK teardown removes the same node table with plain list_del() and frees each node immediately.

That lets a generic-netlink reader hold a struct hsr_node pointer across hsr_dellink(). In a KASAN build, widening the reader window after hsr_get_next_node() obtains the node reproduces a slab-use-after-free when the reader copies node->macaddress_A; the freeing stack is hsr_del_nodes() from hsr_dellink().

Use list_del_rcu() and defer the free through the existing hsr_free_node_rcu() callback. This matches the lifetime rule used by the HSR prune paths, which already delete nodes with list_del_rcu() and call_rcu().

Fixes b9a1e627405d ("hsr: implement dellink to clean up resources")
---
 net/hsr/hsr_framereg.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/hsr/hsr_framereg.c +2 -2
@@ -163,8 +163,8 @@ void hsr_del_nodes(struct list_head *nod
 	struct hsr_node *tmp;
 
 	list_for_each_entry_safe(node, tmp, node_db, mac_list) {
-		list_del(&node->mac_list);
-		hsr_free_node(node);
+		list_del_rcu(&node->mac_list);
+		call_rcu(&node->rcu_head, hsr_free_node_rcu);
 	}
 }
 
author maintainer
#54 lore raw

PATCH 54/461 net/mlx5e: Fix use-after-free in mlx5e_tx_reporter_timeout_recover

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matt Fleming <[email protected]>

commit 7d260c5d2d89eb2c8c528d54b576b3aae3e20231 upstream.

mlx5e_tx_reporter_timeout_recover() accesses sq->netdev after mlx5e_safe_reopen_channels() has torn down and freed the channel (and its embedded SQs). Replace the three sq->netdev references with priv->netdev which is safe because priv outlives channel teardown.

The netdev_err() call already used priv->netdev for this reason; make the trylock/unlock and health_channel_eq_recover calls consistent.

This fixes the following KASAN splat:

  BUG: KASAN: use-after-free in mlx5e_tx_reporter_timeout_recover+0x1dd/0x360 [mlx5_core]
  Read of size 8 at addr ffff889860ed0b28 by task kworker/u113:2/5277

  Call Trace:
   mlx5e_tx_reporter_timeout_recover+0x1dd/0x360 [mlx5_core]
   devlink_health_reporter_recover+0xa2/0x150
   devlink_health_report+0x254/0x7c0
   mlx5e_reporter_tx_timeout+0x297/0x380 [mlx5_core]
   mlx5e_tx_timeout_work+0x109/0x170 [mlx5_core]
   process_one_work+0x677/0xf20
   worker_thread+0x51f/0xd90
   kthread+0x3a5/0x810
   ret_from_fork+0x208/0x400
   ret_from_fork_asm+0x1a/0x30
Fixes 83ac0304a2d7 ("net/mlx5e: Fix deadlocks between devlink and netdev instance locks")
---
 drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +3 -3
@@ -160,13 +160,13 @@ static int mlx5e_tx_reporter_timeout_rec
 	 * channels are being closed for other reason and this work is not
 	 * relevant anymore.
 	 */
-	while (!netdev_trylock(sq->netdev)) {
+	while (!netdev_trylock(priv->netdev)) {
 		if (!test_bit(MLX5E_STATE_CHANNELS_ACTIVE, &priv->state))
 			return 0;
 		msleep(20);
 	}
 
-	err = mlx5e_health_channel_eq_recover(sq->netdev, eq, sq->cq.ch_stats);
+	err = mlx5e_health_channel_eq_recover(priv->netdev, eq, sq->cq.ch_stats);
 	if (!err) {
 		to_ctx->status = 0; /* this sq recovered */
 		goto out;
@@ -186,7 +186,7 @@ static int mlx5e_tx_reporter_timeout_rec
 		   "mlx5e_safe_reopen_channels failed recovering from a tx_timeout, err(%d).\n",
 		   err);
 out:
-	netdev_unlock(sq->netdev);
+	netdev_unlock(priv->netdev);
 	return err;
 }
 
author maintainer
#55 lore raw

PATCH 55/461 net: ifb: report ethtool stats over num_tx_queues

In reply to Greg Kroah-Hartman

7.0-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_d
 
 	switch (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(struct
 	struct 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);
 	}
author maintainer
#56 lore raw

PATCH 56/461 net: pse-pd: fix sign on -ENOENT check in of_load_pse_pis()

In reply to Greg Kroah-Hartman

7.0-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
@@ -210,7 +210,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);
author maintainer
#57 lore raw

PATCH 57/461 netfilter: ip6t_hbh: reject oversized option lists

In reply to Greg Kroah-Hartman

7.0-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 xt
 		pr_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");
author maintainer
#58 lore raw

PATCH 58/461 netfilter: nf_queue: hold bridge skb->dev while queued

In reply to Greg Kroah-Hartman

7.0-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.

Fixes ac2863445686 ("netfilter: bridge: add nf_afinfo to enable queuing to userspace")
---
 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_q
 	if (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
@@ -1198,6 +1198,8 @@ dev_cmp(struct nf_queue_entry *entry, un
 	if (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;
author maintainer
#59 lore raw

PATCH 59/461 netfilter: ipset: stop hash:* range iteration at end

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 48596a8ddc46 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses")
---
 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, st
 
 	if (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, st
 			return 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, st
 
 	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++) {
@@ -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;
 }
author maintainer
#60 lore raw

PATCH 60/461 netfilter: nft_inner: Fix IPv6 inner_thoff desync

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 3a07327d10a0 ("netfilter: nft_inner: support for inner tunnel header matching")
Assisted-by GLM:5.1 Z.ai
---
 net/netfilter/nft_inner.c |    1 -
 1 file changed, 1 deletion(-)
net/netfilter/nft_inner.c +0 -1
@@ -163,7 +163,6 @@ static int nft_inner_parse_l2l3(const st
 			return -1;
 
 		if (fragoff == 0) {
-			thoff = nhoff + sizeof(_ip6h);
 			ctx->flags |= NFT_PAYLOAD_CTX_INNER_TH;
 			ctx->inner_thoff = thoff;
 			ctx->l4proto = l4proto;
author maintainer
#61 lore raw

PATCH 61/461 net: ethtool: fix NULL pointer dereference in phy_reply_size

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Quan Sun <[email protected]>

[ Upstream commit 4908f1395fb1b832ceec11584af649874a2732ea ]

In phy_prepare_data(), several strings such as 'name', 'drvname', 'upstream_sfp_name', and 'downstream_sfp_name' are allocated using kstrdup(). However, these allocations were not checked for failure.

If kstrdup() fails for 'name', it returns NULL while the function continues. This leads to a kernel NULL pointer dereference and panic later in phy_reply_size() when it unconditionally calls strlen() on the NULL pointer.

While other strings like 'upstream_sfp_name' might be checked before access in certain code paths, failing to handle these allocations consistently can lead to incomplete data reporting or hidden bugs.

Fix this by adding proper NULL checks for all kstrdup() calls in phy_prepare_data() and implement a centralized error handling path using goto labels to ensure all previously allocated resources are freed on failure.

Fixes 9dd2ad5e92b9 ("net: ethtool: phy: Convert the PHY_GET command to generic phy dump")

Stable-dep-of: e3adf69f8eb1 ("net: ethtool: phy: avoid NULL deref when PHY driver is unbound")

---
 net/ethtool/phy.c |   32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)
net/ethtool/phy.c +30 -2
@@ -76,6 +76,7 @@ static int phy_prepare_data(const struct
 	struct nlattr **tb = info->attrs;
 	struct phy_device_node *pdn;
 	struct phy_device *phydev;
+	int ret;
 
 	/* RTNL is held by the caller */
 	phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PHY_HEADER,
@@ -88,8 +89,17 @@ static int phy_prepare_data(const struct
 		return -EOPNOTSUPP;
 
 	rep_data->phyindex = phydev->phyindex;
+
 	rep_data->name = kstrdup(dev_name(&phydev->mdio.dev), GFP_KERNEL);
+	if (!rep_data->name)
+		return -ENOMEM;
+
 	rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
+	if (!rep_data->drvname) {
+		ret = -ENOMEM;
+		goto err_free_name;
+	}
+
 	rep_data->upstream_type = pdn->upstream_type;
 
 	if (pdn->upstream_type == PHY_UPSTREAM_PHY) {
@@ -97,15 +107,33 @@ static int phy_prepare_data(const struct
 		rep_data->upstream_index = upstream->phyindex;
 	}
 
-	if (pdn->parent_sfp_bus)
+	if (pdn->parent_sfp_bus) {
 		rep_data->upstream_sfp_name = kstrdup(sfp_get_name(pdn->parent_sfp_bus),
 						      GFP_KERNEL);
+		if (!rep_data->upstream_sfp_name) {
+			ret = -ENOMEM;
+			goto err_free_drvname;
+		}
+	}
 
-	if (phydev->sfp_bus)
+	if (phydev->sfp_bus) {
 		rep_data->downstream_sfp_name = kstrdup(sfp_get_name(phydev->sfp_bus),
 							GFP_KERNEL);
+		if (!rep_data->downstream_sfp_name) {
+			ret = -ENOMEM;
+			goto err_free_upstream_sfp;
+		}
+	}
 
 	return 0;
+
+err_free_upstream_sfp:
+	kfree(rep_data->upstream_sfp_name);
+err_free_drvname:
+	kfree(rep_data->drvname);
+err_free_name:
+	kfree(rep_data->name);
+	return ret;
 }
 
 static int phy_fill_reply(struct sk_buff *skb,
author maintainer
#62 lore raw

PATCH 62/461 net: ethtool: phy: avoid NULL deref when PHY driver is unbound

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Carlier <[email protected]>

[ Upstream commit e3adf69f8eb121a9128c2b0029efd050d3649153 ]

phydev->drv can become NULL while the phy_device is still attached to its net_device, namely after the PHY driver is unbound via sysfs:

echo <mdio_id> > /sys/bus/mdio_bus/drivers/<phy_drv>/unbind

phy_remove() clears phydev->drv but doesn't call phy_detach(), so the phy_device stays in the link topology xarray and ethnl_req_get_phydev() still hands it back. ETHTOOL_MSG_PHY_GET then oopses on:

	rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);

drvname is already treated as optional by phy_reply_size(), phy_fill_reply() and phy_cleanup_data(), so just skip the allocation when there is no driver bound.

---
 net/ethtool/phy.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
net/ethtool/phy.c +6 -4
@@ -94,10 +94,12 @@ static int phy_prepare_data(const struct
 	if (!rep_data->name)
 		return -ENOMEM;
 
-	rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
-	if (!rep_data->drvname) {
-		ret = -ENOMEM;
-		goto err_free_name;
+	if (phydev->drv) {
+		rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
+		if (!rep_data->drvname) {
+			ret = -ENOMEM;
+			goto err_free_name;
+		}
 	}
 
 	rep_data->upstream_type = pdn->upstream_type;
author maintainer
#63 lore raw

PATCH 63/461 ACPI: driver: Check ACPI_COMPANION() against NULL during probe

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: "Rafael J. Wysocki" <[email protected]>

[ Upstream commit e4865a56d013e86e46ea6acea15bb6eae01898ff ]

Since every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), platform drivers that rely on the existence of a device's ACPI companion object should verify its presence.

Accordingly, add requisite ACPI_COMPANION() or ACPI_HANDLE() checks against NULL to 13 platform drivers handling core ACPI devices.

Also change the value returned by the ACPI thermal zone driver when the device's ACPI companion is not present to -ENODEV for consistency with the other drivers.

Cc 7.0+ <[email protected]> # 7.0+
[ reordered variable declaration to add NULL check before pre-existing stable-only code that dereferences the pointer ]
---
 drivers/acpi/ac.c                |    6 +++++-
 drivers/acpi/acpi_pad.c          |    6 +++++-
 drivers/acpi/acpi_tad.c          |    6 +++++-
 drivers/acpi/battery.c           |    6 +++++-
 drivers/acpi/button.c            |    9 +++++++--
 drivers/acpi/ec.c                |    6 +++++-
 drivers/acpi/hed.c               |    6 +++++-
 drivers/acpi/nfit/core.c         |    6 +++++-
 drivers/acpi/pfr_telemetry.c     |    6 +++++-
 drivers/acpi/pfr_update.c        |    6 +++++-
 drivers/acpi/sbs.c               |    6 +++++-
 drivers/acpi/sbshc.c             |    6 +++++-
 drivers/acpi/thermal.c           |    2 +-
 drivers/acpi/tiny-power-button.c |    6 +++++-
 14 files changed, 68 insertions(+), 15 deletions(-)
drivers/acpi/ac.c +5 -1
@@ -203,11 +203,15 @@ static const struct dmi_system_id ac_dmi
 
 static int acpi_ac_probe(struct platform_device *pdev)
 {
-	struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
 	struct power_supply_config psy_cfg = {};
+	struct acpi_device *adev;
 	struct acpi_ac *ac;
 	int result;
 
+	adev = ACPI_COMPANION(&pdev->dev);
+	if (!adev)
+		return -ENODEV;
+
 	ac = kzalloc_obj(struct acpi_ac);
 	if (!ac)
 		return -ENOMEM;
drivers/acpi/acpi_pad.c +5 -1
@@ -426,9 +426,13 @@ static void acpi_pad_notify(acpi_handle
 
 static int acpi_pad_probe(struct platform_device *pdev)
 {
-	struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+	struct acpi_device *adev;
 	acpi_status status;
 
+	adev = ACPI_COMPANION(&pdev->dev);
+	if (!adev)
+		return -ENODEV;
+
 	strscpy(acpi_device_name(adev), ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME);
 	strscpy(acpi_device_class(adev), ACPI_PROCESSOR_AGGREGATOR_CLASS);
 
drivers/acpi/acpi_tad.c +5 -1
@@ -593,12 +593,16 @@ static void acpi_tad_remove(struct platf
 static int acpi_tad_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	acpi_handle handle = ACPI_HANDLE(dev);
 	struct acpi_tad_driver_data *dd;
+	acpi_handle handle;
 	acpi_status status;
 	unsigned long long caps;
 	int ret;
 
+	handle = ACPI_HANDLE(dev);
+	if (!handle)
+		return -ENODEV;
+
 	ret = acpi_install_cmos_rtc_space_handler(handle);
 	if (ret < 0) {
 		dev_info(dev, "Unable to install space handler\n");
drivers/acpi/battery.c +5 -1
@@ -1216,10 +1216,14 @@ static void sysfs_battery_cleanup(struct
 
 static int acpi_battery_probe(struct platform_device *pdev)
 {
-	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
 	struct acpi_battery *battery;
+	struct acpi_device *device;
 	int result;
 
+	device = ACPI_COMPANION(&pdev->dev);
+	if (!device)
+		return -ENODEV;
+
 	if (device->dep_unmet)
 		return -EPROBE_DEFER;
 
drivers/acpi/button.c +7 -2
@@ -531,15 +531,20 @@ static int acpi_lid_input_open(struct in
 
 static int acpi_button_probe(struct platform_device *pdev)
 {
-	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
 	acpi_notify_handler handler;
+	struct acpi_device *device;
 	struct acpi_button *button;
 	struct input_dev *input;
-	const char *hid = acpi_device_hid(device);
 	acpi_status status;
 	char *name, *class;
+	const char *hid;
 	int error = 0;
 
+	device = ACPI_COMPANION(&pdev->dev);
+	if (!device)
+		return -ENODEV;
+
+	hid = acpi_device_hid(device);
 	if (!strcmp(hid, ACPI_BUTTON_HID_LID) &&
 	     lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED)
 		return -ENODEV;
drivers/acpi/ec.c +5 -1
@@ -1679,10 +1679,14 @@ static int acpi_ec_setup(struct acpi_ec
 
 static int acpi_ec_probe(struct platform_device *pdev)
 {
-	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+	struct acpi_device *device;
 	struct acpi_ec *ec;
 	int ret;
 
+	device = ACPI_COMPANION(&pdev->dev);
+	if (!device)
+		return -ENODEV;
+
 	strscpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
 	strscpy(acpi_device_class(device), ACPI_EC_CLASS);
 
drivers/acpi/hed.c +5 -1
@@ -50,9 +50,13 @@ static void acpi_hed_notify(acpi_handle
 
 static int acpi_hed_probe(struct platform_device *pdev)
 {
-	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+	struct acpi_device *device;
 	int err;
 
+	device = ACPI_COMPANION(&pdev->dev);
+	if (!device)
+		return -ENODEV;
+
 	/* Only one hardware error device */
 	if (hed_handle)
 		return -EINVAL;
drivers/acpi/nfit/core.c +5 -1
@@ -3341,12 +3341,16 @@ static int acpi_nfit_probe(struct platfo
 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_nfit_desc *acpi_desc;
 	struct device *dev = &pdev->dev;
-	struct acpi_device *adev = ACPI_COMPANION(dev);
 	struct acpi_table_header *tbl;
+	struct acpi_device *adev;
 	acpi_status status = AE_OK;
 	acpi_size sz;
 	int rc = 0;
 
+	adev = ACPI_COMPANION(&pdev->dev);
+	if (!adev)
+		return -ENODEV;
+
 	rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
 					     acpi_nfit_notify, dev);
 	if (rc)
drivers/acpi/pfr_telemetry.c +5 -1
@@ -360,10 +360,14 @@ static void pfrt_log_put_idx(void *data)
 
 static int acpi_pfrt_log_probe(struct platform_device *pdev)
 {
-	acpi_handle handle = ACPI_HANDLE(&pdev->dev);
 	struct pfrt_log_device *pfrt_log_dev;
+	acpi_handle handle;
 	int ret;
 
+	handle = ACPI_HANDLE(&pdev->dev);
+	if (!handle)
+		return -ENODEV;
+
 	if (!acpi_has_method(handle, "_DSM")) {
 		dev_dbg(&pdev->dev, "Missing _DSM\n");
 		return -ENODEV;
drivers/acpi/pfr_update.c +5 -1
@@ -538,10 +538,14 @@ static void pfru_put_idx(void *data)
 
 static int acpi_pfru_probe(struct platform_device *pdev)
 {
-	acpi_handle handle = ACPI_HANDLE(&pdev->dev);
 	struct pfru_device *pfru_dev;
+	acpi_handle handle;
 	int ret;
 
+	handle = ACPI_HANDLE(&pdev->dev);
+	if (!handle)
+		return -ENODEV;
+
 	if (!acpi_has_method(handle, "_DSM")) {
 		dev_dbg(&pdev->dev, "Missing _DSM\n");
 		return -ENODEV;
drivers/acpi/sbs.c +5 -1
@@ -631,11 +631,15 @@ static void acpi_sbs_callback(void *cont
 
 static int acpi_sbs_probe(struct platform_device *pdev)
 {
-	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+	struct acpi_device *device;
 	struct acpi_sbs *sbs;
 	int result = 0;
 	int id;
 
+	device = ACPI_COMPANION(&pdev->dev);
+	if (!device)
+		return -ENODEV;
+
 	sbs = kzalloc_obj(struct acpi_sbs);
 	if (!sbs) {
 		result = -ENOMEM;
drivers/acpi/sbshc.c +5 -1
@@ -240,11 +240,15 @@ static int smbus_alarm(void *context)
 
 static int acpi_smbus_hc_probe(struct platform_device *pdev)
 {
-	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+	struct acpi_device *device;
 	int status;
 	unsigned long long val;
 	struct acpi_smb_hc *hc;
 
+	device = ACPI_COMPANION(&pdev->dev);
+	if (!device)
+		return -ENODEV;
+
 	status = acpi_evaluate_integer(device->handle, "_EC", NULL, &val);
 	if (ACPI_FAILURE(status)) {
 		pr_err("error obtaining _EC.\n");
drivers/acpi/thermal.c +1 -1
@@ -790,7 +790,7 @@ static int acpi_thermal_probe(struct pla
 	int i;
 
 	if (!device)
-		return -EINVAL;
+		return -ENODEV;
 
 	tz = kzalloc_obj(struct acpi_thermal);
 	if (!tz)
drivers/acpi/tiny-power-button.c +5 -1
@@ -38,9 +38,13 @@ static u32 acpi_tiny_power_button_event(
 
 static int acpi_tiny_power_button_probe(struct platform_device *pdev)
 {
-	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+	struct acpi_device *device;
 	acpi_status status;
 
+	device = ACPI_COMPANION(&pdev->dev);
+	if (!device)
+		return -ENODEV;
+
 	if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
 		status = acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
 							  acpi_tiny_power_button_event,
author maintainer
#64 lore raw

PATCH 64/461 sched_ext: Fix missing warning in scx_set_task_state() default case

In reply to Greg Kroah-Hartman

7.0-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
@@ -2936,7 +2936,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;
 	}
 
author maintainer
#65 lore raw

PATCH 65/461 sched_ext: Avoid UAF in scx_root_enable_workfn() init failure path

In reply to Greg Kroah-Hartman

7.0-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().

Fixes f0e1a0643a59 ("sched_ext: Implement BPF extensible scheduler class")
Cc [email protected] # v6.12+
[ kept `scx_init_task()` call site instead of `__scx_init_task()`/`task_rq_lock` ]
---
 kernel/sched/ext.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/ext.c +1 -1
@@ -5239,10 +5239,10 @@ static void scx_enable_workfn(struct kth
 
 		ret = scx_init_task(p, task_group(p), false);
 		if (ret) {
-			put_task_struct(p);
 			scx_task_iter_stop(&sti);
 			scx_error(sch, "ops.init_task() failed (%d) for %s[%d]",
 				  ret, p->comm, p->pid);
+			put_task_struct(p);
 			goto err_disable_unlock_all;
 		}
 
author maintainer
#66 lore raw

PATCH 66/461 l2tp: use list_del_rcu in l2tp_session_unhash

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 89b768ec2dfef ("l2tp: use rcu list add/del when updating lists")
---
 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 l
 		spin_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) {
author maintainer
#67 lore raw

PATCH 67/461 qed: fix double free in qed_cxt_tables_alloc()

In reply to Greg Kroah-Hartman

7.0-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
@@ -1036,11 +1036,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;
 		}
author maintainer
#68 lore raw

PATCH 68/461 ring-buffer: Fix reporting of missed events in iterator

In reply to Greg Kroah-Hartman

7.0-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.

Cc Mathieu Desnoyers <[email protected]>
Fixes c9b7a4a72ff64 ("ring-buffer/tracing: Have iterator acknowledge dropped events")
---
 kernel/trace/ring_buffer.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
kernel/trace/ring_buffer.c +3 -5
@@ -5283,6 +5283,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;
@@ -5897,10 +5898,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);
 
@@ -6062,7 +6060,7 @@ void ring_buffer_iter_advance(struct rin
 	unsigned 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);
author maintainer
#69 lore raw

PATCH 69/461 ring-buffer: Flush and stop persistent ring buffer on panic

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Masami Hiramatsu (Google) <[email protected]>

commit a494d3c8d5392bcdff83c2a593df0c160ff9f322 upstream.

On real hardware, panic and machine reboot may not flush hardware cache to memory. This means the persistent ring buffer, which relies on a coherent state of memory, may not have its events written to the buffer and they may be lost. Moreover, there may be inconsistency with the counters which are used for validation of the integrity of the persistent ring buffer which may cause all data to be discarded.

To avoid this issue, stop recording of the ring buffer on panic and flush the cache of the ring buffer's memory.

---
 arch/alpha/include/asm/Kbuild        |    1 +
 arch/arc/include/asm/Kbuild          |    1 +
 arch/arm/include/asm/Kbuild          |    1 +
 arch/arm64/include/asm/ring_buffer.h |   10 ++++++++++
 arch/csky/include/asm/Kbuild         |    1 +
 arch/hexagon/include/asm/Kbuild      |    1 +
 arch/loongarch/include/asm/Kbuild    |    1 +
 arch/m68k/include/asm/Kbuild         |    1 +
 arch/microblaze/include/asm/Kbuild   |    1 +
 arch/mips/include/asm/Kbuild         |    1 +
 arch/nios2/include/asm/Kbuild        |    1 +
 arch/openrisc/include/asm/Kbuild     |    1 +
 arch/parisc/include/asm/Kbuild       |    1 +
 arch/powerpc/include/asm/Kbuild      |    1 +
 arch/riscv/include/asm/Kbuild        |    1 +
 arch/s390/include/asm/Kbuild         |    1 +
 arch/sh/include/asm/Kbuild           |    1 +
 arch/sparc/include/asm/Kbuild        |    1 +
 arch/um/include/asm/Kbuild           |    1 +
 arch/x86/include/asm/Kbuild          |    1 +
 arch/xtensa/include/asm/Kbuild       |    1 +
 include/asm-generic/ring_buffer.h    |   13 +++++++++++++
 kernel/trace/ring_buffer.c           |   22 ++++++++++++++++++++++
 23 files changed, 65 insertions(+)
 create mode 100644 arch/arm64/include/asm/ring_buffer.h
 create mode 100644 include/asm-generic/ring_buffer.h
arch/alpha/include/asm/Kbuild +1 -0
@@ -5,4 +5,5 @@ generic-y += agp.h
 generic-y += asm-offsets.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
+generic-y += ring_buffer.h
 generic-y += text-patching.h
arch/arc/include/asm/Kbuild +1 -0
@@ -5,5 +5,6 @@ generic-y += extable.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
 generic-y += parport.h
+generic-y += ring_buffer.h
 generic-y += user.h
 generic-y += text-patching.h
arch/arm/include/asm/Kbuild +1 -0
@@ -3,6 +3,7 @@ generic-y += early_ioremap.h
 generic-y += extable.h
 generic-y += flat.h
 generic-y += parport.h
+generic-y += ring_buffer.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
arch/arm64/include/asm/ring_buffer.h new file +10 -0
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _ASM_ARM64_RING_BUFFER_H
+#define _ASM_ARM64_RING_BUFFER_H
+
+#include <asm/cacheflush.h>
+
+/* Flush D-cache on persistent ring buffer */
+#define arch_ring_buffer_flush_range(start, end)	dcache_clean_pop(start, end)
+
+#endif /* _ASM_ARM64_RING_BUFFER_H */
arch/csky/include/asm/Kbuild +1 -0
@@ -9,6 +9,7 @@ generic-y += qrwlock.h
 generic-y += qrwlock_types.h
 generic-y += qspinlock.h
 generic-y += parport.h
+generic-y += ring_buffer.h
 generic-y += user.h
 generic-y += vmlinux.lds.h
 generic-y += text-patching.h
arch/hexagon/include/asm/Kbuild +1 -0
@@ -5,4 +5,5 @@ generic-y += extable.h
 generic-y += iomap.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
+generic-y += ring_buffer.h
 generic-y += text-patching.h
arch/loongarch/include/asm/Kbuild +1 -0
@@ -10,5 +10,6 @@ generic-y += qrwlock.h
 generic-y += user.h
 generic-y += ioctl.h
 generic-y += mmzone.h
+generic-y += ring_buffer.h
 generic-y += statfs.h
 generic-y += text-patching.h
arch/m68k/include/asm/Kbuild +1 -0
@@ -3,5 +3,6 @@ generated-y += syscall_table.h
 generic-y += extable.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
+generic-y += ring_buffer.h
 generic-y += spinlock.h
 generic-y += text-patching.h
arch/microblaze/include/asm/Kbuild +1 -0
@@ -5,6 +5,7 @@ generic-y += extable.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
 generic-y += parport.h
+generic-y += ring_buffer.h
 generic-y += syscalls.h
 generic-y += tlb.h
 generic-y += user.h
arch/mips/include/asm/Kbuild +1 -0
@@ -12,5 +12,6 @@ generic-y += mcs_spinlock.h
 generic-y += parport.h
 generic-y += qrwlock.h
 generic-y += qspinlock.h
+generic-y += ring_buffer.h
 generic-y += user.h
 generic-y += text-patching.h
arch/nios2/include/asm/Kbuild +1 -0
@@ -5,6 +5,7 @@ generic-y += cmpxchg.h
 generic-y += extable.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
+generic-y += ring_buffer.h
 generic-y += spinlock.h
 generic-y += user.h
 generic-y += text-patching.h
arch/openrisc/include/asm/Kbuild +1 -0
@@ -8,4 +8,5 @@ generic-y += spinlock_types.h
 generic-y += spinlock.h
 generic-y += qrwlock_types.h
 generic-y += qrwlock.h
+generic-y += ring_buffer.h
 generic-y += user.h
arch/parisc/include/asm/Kbuild +1 -0
@@ -4,4 +4,5 @@ generated-y += syscall_table_64.h
 generic-y += agp.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
+generic-y += ring_buffer.h
 generic-y += user.h
arch/powerpc/include/asm/Kbuild +1 -0
@@ -5,4 +5,5 @@ generated-y += syscall_table_spu.h
 generic-y += agp.h
 generic-y += mcs_spinlock.h
 generic-y += qrwlock.h
+generic-y += ring_buffer.h
 generic-y += early_ioremap.h
arch/riscv/include/asm/Kbuild +1 -0
@@ -14,5 +14,6 @@ generic-y += ticket_spinlock.h
 generic-y += qrwlock.h
 generic-y += qrwlock_types.h
 generic-y += qspinlock.h
+generic-y += ring_buffer.h
 generic-y += user.h
 generic-y += vmlinux.lds.h
arch/s390/include/asm/Kbuild +1 -0
@@ -7,3 +7,4 @@ generated-y += unistd_nr.h
 generic-y += asm-offsets.h
 generic-y += mcs_spinlock.h
 generic-y += mmzone.h
+generic-y += ring_buffer.h
arch/sh/include/asm/Kbuild +1 -0
@@ -3,4 +3,5 @@ generated-y += syscall_table.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
 generic-y += parport.h
+generic-y += ring_buffer.h
 generic-y += text-patching.h
arch/sparc/include/asm/Kbuild +1 -0
@@ -4,4 +4,5 @@ generated-y += syscall_table_64.h
 generic-y += agp.h
 generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
+generic-y += ring_buffer.h
 generic-y += text-patching.h
arch/um/include/asm/Kbuild +1 -0
@@ -17,6 +17,7 @@ generic-y += module.lds.h
 generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
+generic-y += ring_buffer.h
 generic-y += runtime-const.h
 generic-y += softirq_stack.h
 generic-y += switch_to.h
arch/x86/include/asm/Kbuild +1 -0
@@ -14,3 +14,4 @@ generic-y += early_ioremap.h
 generic-y += fprobe.h
 generic-y += mcs_spinlock.h
 generic-y += mmzone.h
+generic-y += ring_buffer.h
arch/xtensa/include/asm/Kbuild +1 -0
@@ -6,5 +6,6 @@ generic-y += mcs_spinlock.h
 generic-y += parport.h
 generic-y += qrwlock.h
 generic-y += qspinlock.h
+generic-y += ring_buffer.h
 generic-y += user.h
 generic-y += text-patching.h
include/asm-generic/ring_buffer.h new file +13 -0
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Generic arch dependent ring_buffer macros.
+ */
+#ifndef __ASM_GENERIC_RING_BUFFER_H__
+#define __ASM_GENERIC_RING_BUFFER_H__
+
+#include <linux/cacheflush.h>
+
+/* Flush cache on ring buffer range if needed. Do nothing by default. */
+#define arch_ring_buffer_flush_range(start, end)	do { } while (0)
+
+#endif /* __ASM_GENERIC_RING_BUFFER_H__ */
kernel/trace/ring_buffer.c +22 -0
@@ -6,6 +6,7 @@
  */
 #include <linux/sched/isolation.h>
 #include <linux/trace_recursion.h>
+#include <linux/panic_notifier.h>
 #include <linux/trace_events.h>
 #include <linux/ring_buffer.h>
 #include <linux/trace_clock.h>
@@ -30,6 +31,7 @@
 #include <linux/oom.h>
 #include <linux/mm.h>
 
+#include <asm/ring_buffer.h>
 #include <asm/local64.h>
 #include <asm/local.h>
 #include <asm/setup.h>
@@ -589,6 +591,7 @@ struct trace_buffer {
 
 	unsigned long			range_addr_start;
 	unsigned long			range_addr_end;
+	struct notifier_block		flush_nb;
 
 	struct ring_buffer_meta		*meta;
 
@@ -2472,6 +2475,16 @@ static void rb_free_cpu_buffer(struct ri
 	kfree(cpu_buffer);
 }
 
+/* Stop recording on a persistent buffer and flush cache if needed. */
+static int rb_flush_buffer_cb(struct notifier_block *nb, unsigned long event, void *data)
+{
+	struct trace_buffer *buffer = container_of(nb, struct trace_buffer, flush_nb);
+
+	ring_buffer_record_off(buffer);
+	arch_ring_buffer_flush_range(buffer->range_addr_start, buffer->range_addr_end);
+	return NOTIFY_DONE;
+}
+
 static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
 					 int order, unsigned long start,
 					 unsigned long end,
@@ -2591,6 +2604,12 @@ static struct trace_buffer *alloc_buffer
 
 	mutex_init(&buffer->mutex);
 
+	/* Persistent ring buffer needs to flush cache before reboot. */
+	if (start && end) {
+		buffer->flush_nb.notifier_call = rb_flush_buffer_cb;
+		atomic_notifier_chain_register(&panic_notifier_list, &buffer->flush_nb);
+	}
+
 	return_ptr(buffer);
 
  fail_free_buffers:
@@ -2678,6 +2697,9 @@ ring_buffer_free(struct trace_buffer *bu
 {
 	int cpu;
 
+	if (buffer->range_addr_start && buffer->range_addr_end)
+		atomic_notifier_chain_unregister(&panic_notifier_list, &buffer->flush_nb);
+
 	cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);
 
 	irq_work_sync(&buffer->irq_work.work);
author maintainer
#70 lore raw

PATCH 70/461 wifi: mac80211: capture fast-RX rate before mesh reuses skb->cb

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zhao Li <[email protected]>

commit d71c841be5d9e586ee7f36c0dc8ed4db0d9a1349 upstream.

ieee80211_invoke_fast_rx() reads RX status through IEEE80211_SKB_RXCB(skb), which aliases the same skb->cb storage that ieee80211_rx_mesh_data() reuses as IEEE80211_TX_INFO. In the unicast forward path, mesh_data does:

	info = IEEE80211_SKB_CB(fwd_skb);
	memset(info, 0, sizeof(*info));

on the same skb the caller still names via rx->skb, then either queues the skb for TX (success) or kfree_skb()'s it (no-route) before returning RX_QUEUED. The caller's RX_QUEUED arm then calls sta_stats_encode_rate(status) on memory that is either zeroed (success path) or freed (no-route path). The latter is KASAN slab-use-after-free in ieee80211_prepare_and_rx_handle.

Fix by encoding the rate from status before invoking ieee80211_rx_mesh_data(), so the RX_QUEUED arm consumes a value captured while status was still backed by valid memory.

Fixes 3468e1e0c639 ("wifi: mac80211: add mesh fast-rx support")
---
 net/mac80211/rx.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
net/mac80211/rx.c +5 -1
@@ -4941,6 +4941,7 @@ static bool ieee80211_invoke_fast_rx(str
 		u8 sa[ETH_ALEN];
 	} addrs __aligned(2);
 	struct ieee80211_sta_rx_stats *stats;
+	u32 encoded_rate;
 
 	/* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
 	 * to a common data structure; drivers can implement that per queue
@@ -5048,11 +5049,14 @@ static bool ieee80211_invoke_fast_rx(str
 	/* push the addresses in front */
 	memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs));
 
+	/* capture before mesh forward may memset or free skb->cb */
+	encoded_rate = sta_stats_encode_rate(status);
+
 	res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
 	switch (res) {
 	case RX_QUEUED:
 		stats->last_rx = jiffies;
-		stats->last_rate = sta_stats_encode_rate(status);
+		stats->last_rate = encoded_rate;
 		return true;
 	case RX_CONTINUE:
 		break;
author maintainer
#71 lore raw

PATCH 71/461 ipv6: ioam: add NULL check for idev in ipv6_hop_ioam()

In reply to Greg Kroah-Hartman

7.0-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
@@ -910,16 +910,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 */
@@ -972,7 +983,7 @@ ignore:
 	return true;
 
 drop:
-	kfree_skb_reason(skb, SKB_DROP_REASON_IP_INHDR);
+	kfree_skb_reason(skb, drop_reason);
 	return false;
 }
 
author maintainer
#72 lore raw

PATCH 72/461 selftests: mptcp: drop nanoseconds width specifier

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Matthieu Baerts (NGI0) <[email protected]>

commit 01ff78e4b3d98689184c52d97f9575dfbdc3b10f upstream.

Using the format specifier +%s%3N with GNU date is honoured, and only prints 3 digits of the nanoseconds portion of the seconds since epoch, which corresponds to the milliseconds.

The uutils implementation of date currently does not honour this, and always prints all 9 digits. This is a known issue [1], but can be worked around by adapting this test to use nanoseconds instead of microseconds, and then divide it by 1e6.

This fix is similar to what has been done on systemd side [2], and it is needed to run the selftests on Ubuntu 26.04, containing uutils 0.8.0.

Note that the Fixes tag is there even if this patch doesn't fix an issue in the kernel selftests, but it is useful for those using uutils 0.8.0.

---
 tools/testing/selftests/net/mptcp/mptcp_connect.sh |    6 +++---
 tools/testing/selftests/net/mptcp/mptcp_lib.sh     |   10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_connect.sh +3 -3
@@ -401,7 +401,7 @@ do_transfer()
 	mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}"
 
 	local start
-	start=$(date +%s%3N)
+	start=$(date +%s%N)
 	ip netns exec ${connector_ns} \
 		./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
 			$extra_args $connect_addr < "$cin" > "$cout" &
@@ -423,7 +423,7 @@ do_transfer()
 	fi
 
 	local stop
-	stop=$(date +%s%3N)
+	stop=$(date +%s%N)
 
 	if $capture; then
 		sleep 1
@@ -439,7 +439,7 @@ do_transfer()
 	fi
 
 	local duration
-	duration=$((stop-start))
+	duration=$(((stop-start) / 1000000))
 	printf "(duration %05sms) " "${duration}"
 	if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ] || [ ${timeout_pid} -ne 0 ]; then
 		mptcp_lib_pr_fail "client exit code $retc, server $rets"
tools/testing/selftests/net/mptcp/mptcp_lib.sh +5 -5
@@ -28,7 +28,7 @@ declare -rx MPTCP_LIB_AF_INET6=10
 MPTCP_LIB_SUBTESTS=()
 MPTCP_LIB_SUBTESTS_DUPLICATED=0
 MPTCP_LIB_SUBTEST_FLAKY=0
-MPTCP_LIB_SUBTESTS_LAST_TS_MS=
+MPTCP_LIB_SUBTESTS_LAST_TS_NS=
 MPTCP_LIB_TEST_COUNTER=0
 MPTCP_LIB_TEST_FORMAT="%02u %-50s"
 MPTCP_LIB_IP_MPTCP=0
@@ -236,7 +236,7 @@ mptcp_lib_kversion_ge() {
 }
 
 mptcp_lib_subtests_last_ts_reset() {
-	MPTCP_LIB_SUBTESTS_LAST_TS_MS="$(date +%s%3N)"
+	MPTCP_LIB_SUBTESTS_LAST_TS_NS="$(date +%s%N)"
 }
 mptcp_lib_subtests_last_ts_reset
 
@@ -255,7 +255,7 @@ __mptcp_lib_result_check_duplicated() {
 __mptcp_lib_result_add() {
 	local result="${1}"
 	local time="time="
-	local ts_prev_ms
+	local ts_prev_ns
 	shift
 
 	local id=$((${#MPTCP_LIB_SUBTESTS[@]} + 1))
@@ -265,9 +265,9 @@ __mptcp_lib_result_add() {
 	# not to add two '#'
 	[[ "${*}" != *"#"* ]] && time="# ${time}"
 
-	ts_prev_ms="${MPTCP_LIB_SUBTESTS_LAST_TS_MS}"
+	ts_prev_ns="${MPTCP_LIB_SUBTESTS_LAST_TS_NS}"
 	mptcp_lib_subtests_last_ts_reset
-	time+="$((MPTCP_LIB_SUBTESTS_LAST_TS_MS - ts_prev_ms))ms"
+	time+="$(((MPTCP_LIB_SUBTESTS_LAST_TS_NS - ts_prev_ns) / 1000000))ms"
 
 	MPTCP_LIB_SUBTESTS+=("${result} ${id} - ${KSFT_TEST}: ${*} ${time}")
 }
author maintainer
#73 lore raw

PATCH 73/461 mptcp: pm: fix ADD_ADDR timer infinite retry on option space insufficient

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Li Xiasong <[email protected]>

commit 51e398a3b8961b26a8c0a4ba9a777c5339791707 upstream.

When TCP option space is insufficient (e.g., when sending ADD_ADDR with an IPv6 address and port while tcp_timestamps is enabled), the original code jumped to out_unlock without clearing the addr_signal flag. This caused mptcp_pm_add_timer to keep rescheduling indefinitely, not sending ADD_ADDR, preventing subsequent addresses in the endpoint list from being announced.

Handle this case by clearing the ADD_ADDR signal and skipping the matching ADD_ADDR retransmission entry. The skip path cancels the matching timer (with id check) and advances PM state progression, preserving forward progress to subsequent PM work.

This cancellation is inherently best-effort. A concurrent add_timer callback may already be running and may acquire pm.lock before the cancel path updates entry state. In that case, one final ADD_ADDR transmit attempt can still be executed.

Once the cancel path sets entry->retrans_times to ADD_ADDR_RETRANS_MAX, the callback-side retrans_times check suppresses further ADD_ADDR retransmissions.

Note that when an ADD_ADDR is being prepared, a pure-ACK is queued. On the output side, it means that it is fine to skip non-pure-ACK packets, when drop_other_suboptions is set: a pure-ACK will be processed soon after.

---
 net/mptcp/pm.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 46 insertions(+), 10 deletions(-)
net/mptcp/pm.c +46 -10
@@ -364,7 +364,13 @@ static void mptcp_pm_add_timer(struct ti
 
 	spin_lock_bh(&msk->pm.lock);
 
-	if (!mptcp_pm_should_add_signal_addr(msk)) {
+	/* The cancel path (mptcp_pm_del_add_timer()) can race with this
+	 * callback. Once cancel updates retrans_times to MAX, suppress further
+	 * retransmissions here. If this callback acquires pm.lock first, one
+	 * final transmit attempt is still possible.
+	 */
+	if (entry->retrans_times < ADD_ADDR_RETRANS_MAX &&
+	    !mptcp_pm_should_add_signal_addr(msk)) {
 		pr_debug("retransmit ADD_ADDR id=%d\n", entry->addr.id);
 		mptcp_pm_announce_addr(msk, &entry->addr, false);
 		mptcp_pm_add_addr_send_ack(msk);
@@ -414,8 +420,12 @@ mptcp_pm_del_add_timer(struct mptcp_sock
 	/* Note: entry might have been removed by another thread.
 	 * We hold rcu_read_lock() to ensure it is not freed under us.
 	 */
-	if (stop_timer)
-		sk_stop_timer_sync(sk, &entry->add_timer);
+	if (stop_timer) {
+		if (check_id)
+			sk_stop_timer(sk, &entry->add_timer);
+		else
+			sk_stop_timer_sync(sk, &entry->add_timer);
+	}
 
 	rcu_read_unlock();
 	return entry;
@@ -882,6 +892,7 @@ bool mptcp_pm_add_addr_signal(struct mpt
 			      struct mptcp_addr_info *addr, bool *echo,
 			      bool *drop_other_suboptions)
 {
+	bool skip_add_addr = false;
 	int ret = false;
 	u8 add_addr;
 	u8 family;
@@ -903,24 +914,49 @@ bool mptcp_pm_add_addr_signal(struct mpt
 	}
 
 	*echo = mptcp_pm_should_add_signal_echo(msk);
-	port = !!(*echo ? msk->pm.remote.port : msk->pm.local.port);
-
-	family = *echo ? msk->pm.remote.family : msk->pm.local.family;
-	if (remaining < mptcp_add_addr_len(family, *echo, port))
-		goto out_unlock;
-
 	if (*echo) {
 		*addr = msk->pm.remote;
 		add_addr = msk->pm.addr_signal & ~BIT(MPTCP_ADD_ADDR_ECHO);
+		port = !!msk->pm.remote.port;
+		family = msk->pm.remote.family;
 	} else {
 		*addr = msk->pm.local;
 		add_addr = msk->pm.addr_signal & ~BIT(MPTCP_ADD_ADDR_SIGNAL);
+		port = !!msk->pm.local.port;
+		family = msk->pm.local.family;
 	}
-	WRITE_ONCE(msk->pm.addr_signal, add_addr);
+
+	if (remaining < mptcp_add_addr_len(family, *echo, port)) {
+		struct net *net = sock_net((struct sock *)msk);
+
+		if (!*drop_other_suboptions)
+			goto out_unlock;
+
+		if (*echo) {
+			MPTCP_INC_STATS(net, MPTCP_MIB_ECHOADDTXDROP);
+		} else {
+			skip_add_addr = true;
+			MPTCP_INC_STATS(net, MPTCP_MIB_ADDADDRTXDROP);
+		}
+		goto drop_signal_mark;
+	}
+
 	ret = true;
 
+drop_signal_mark:
+	WRITE_ONCE(msk->pm.addr_signal, add_addr);
+
 out_unlock:
 	spin_unlock_bh(&msk->pm.lock);
+
+	/* On pure-ACK option-space exhaustion, stop retrying this ADD_ADDR:
+	 * clear the signal bit, cancel the matching retransmission timer, and
+	 * let the PM state machine progress.
+	 */
+	if (skip_add_addr) {
+		mptcp_pm_del_add_timer(msk, addr, true);
+		mptcp_pm_subflow_established(msk);
+	}
 	return ret;
 }
 
author maintainer
#74 lore raw

PATCH 74/461 vsock/vmci: fix UAF when peer resets connection during handshake

In reply to Greg Kroah-Hartman

7.0-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
@@ -1164,7 +1164,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;
 	}
 
author maintainer
#75 lore raw

PATCH 75/461 vsock/virtio: reset connection on receiving queue overflow

In reply to Greg Kroah-Hartman

7.0-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.

Fixes ae6fcfbf5f03 ("vsock/virtio: discard packets if credit is not respected")
---
 net/vmw_vsock/virtio_transport_common.c |   20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)
net/vmw_vsock/virtio_transport_common.c +15 -5
@@ -1350,7 +1350,7 @@ destroy:
 	return err;
 }
 
-static void
+static bool
 virtio_transport_recv_enqueue(struct vsock_sock *vsk,
 			      struct sk_buff *skb)
 {
@@ -1365,10 +1365,8 @@ virtio_transport_recv_enqueue(struct vso
 	spin_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++;
@@ -1408,6 +1406,8 @@ out:
 	spin_unlock_bh(&vvs->rx_lock);
 	if (free_pkt)
 		kfree_skb(skb);
+
+	return can_enqueue;
 }
 
 static int
@@ -1420,7 +1420,17 @@ virtio_transport_recv_connected(struct s
 
 	switch (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:
author maintainer
#76 lore raw

PATCH 76/461 ice: fix VF queue configuration with low MTU values

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jose Ignacio Tornos Martinez <[email protected]>

commit 3ba4dd024d26372733d1c02e13e076c6016e3320 upstream.

The ice driver's VF queue configuration validation rejects databuffer_size values below 1024 bytes, which prevents VFs from using MTU values below 871 bytes.

The iavf driver calculates databuffer_size based on the MTU using:
databuffer_size = ALIGN(MTU + LIBETH_RX_LL_LEN, 128)

where LIBETH_RX_LL_LEN = 26 (ETH_HLEN + 2*VLAN_HLEN + ETH_FCS_LEN).

For MTU values below 871:
MTU 870: 870 + 26 = 896, aligned to 128 = 896 (< 1024, rejected) MTU 871: 871 + 26 = 897, aligned to 128 = 1024 (>= 1024, accepted)

The 1024-byte minimum seems unnecessarily restrictive, because the hardware supports databuffer_size as low as 128 bytes (the alignment boundary), which should allow MTU values down to the standard minimum of 68 bytes.

I haven't found the reason why the limit was configured in the commit 9c7dd7566d18 ("ice: add validation in OP_CONFIG_VSI_QUEUES VF message"), so with no more information and since it is working, change the minimum databuffer_size validation from 1024 to 128 bytes to allow standard low MTU values while still preventing invalid configurations.

---
 drivers/net/ethernet/intel/ice/virt/queues.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/ice/virt/queues.c +1 -1
@@ -840,7 +840,7 @@ int ice_vc_cfg_qs_msg(struct ice_vf *vf,
 
 			if (qpi->rxq.databuffer_size != 0 &&
 			    (qpi->rxq.databuffer_size > ((16 * 1024) - 128) ||
-			     qpi->rxq.databuffer_size < 1024))
+			     qpi->rxq.databuffer_size < 128))
 				goto error_param;
 
 			ring->rx_buf_len = qpi->rxq.databuffer_size;
author maintainer
#77 lore raw

PATCH 77/461 wifi: ath11k: clear shared SRNG pointer state on restart

In reply to Greg Kroah-Hartman

7.0-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
@@ -1387,14 +1387,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;
author maintainer
#78 lore raw

PATCH 78/461 wifi: iwlwifi: mvm: fix driver-set TX rates on old devices

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johannes Berg <[email protected]>

commit fb84b5cbcaab3ca0f4e961d92a40ed7f3aac483b upstream.

On old devices such as 7265D, rates are still encoded in version 1 format, which doesn't use the CCK/OFDM rate index (0-3/0-7) but rather their PLCP value (e.g. 10 for 1 Mbps CCK rate.)

While introducing v3 rates, I changed the driver from internally handling v1 rates and converting to v2, to internally handling v3 and converting to v1 or v2 according to the firmware. I accordingly changed the code in iwl_mvm_mac80211_idx_to_hwrate() to no longer have different values for different APIs. This was correct.

However, I later reverted this part of the change, because it was reported that I had broken beacon rates, causing a FW assert/crash. This caused TX_CMD rates to be set incorrectly, potentially causing a warning when reported back from the device as having been used.

Fix this (hopefully correctly now) by handling beacon rates in the TX_CMD that's embedded in the beacon template command separately. Restore iwl_mvm_mac80211_idx_to_hwrate() to return only the rate index, not PLCP value, fixing the real TX_CMD.

---
 drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c |   27 ++++++++++++++--------
 drivers/net/wireless/intel/iwlwifi/mvm/utils.c    |   14 +++--------
 2 files changed, 22 insertions(+), 19 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +18 -9
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -927,13 +927,18 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(stru
 
 u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
 {
-	u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
 	bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
+	u16 flags = 0;
 
 	if (rate_idx <= IWL_LAST_CCK_RATE)
 		flags |= is_new_rate ? IWL_MAC_BEACON_CCK
 			  : IWL_MAC_BEACON_CCK_V1;
 
+	if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
+		flags |= iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
+	else
+		flags |= iwl_fw_rate_idx_to_plcp(rate_idx);
+
 	return flags;
 }
 
@@ -962,6 +967,7 @@ static void iwl_mvm_mac_ctxt_set_tx(stru
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct ieee80211_tx_info *info;
+	u32 rate_n_flags = 0;
 	u8 rate;
 	u32 tx_flags;
 
@@ -981,18 +987,21 @@ static void iwl_mvm_mac_ctxt_set_tx(stru
 			 IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
 		iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
 
-		tx_params->rate_n_flags =
-			cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
-				    RATE_MCS_ANT_POS);
+		rate_n_flags |= BIT(mvm->mgmt_last_antenna_idx) <<
+					RATE_MCS_ANT_POS;
 	}
 
 	rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
 
-	tx_params->rate_n_flags |=
-		cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
-	if (rate == IWL_FIRST_CCK_RATE)
-		tx_params->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
+	if (rate < IWL_FIRST_OFDM_RATE)
+		rate_n_flags |= RATE_MCS_MOD_TYPE_CCK;
+	else
+		rate_n_flags |= RATE_MCS_MOD_TYPE_LEGACY_OFDM;
+
+	rate_n_flags |= iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate);
 
+	tx_params->rate_n_flags = iwl_mvm_v3_rate_to_fw(rate_n_flags,
+							mvm->fw_rates_ver);
 }
 
 int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
drivers/net/wireless/intel/iwlwifi/mvm/utils.c +4 -10
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -159,15 +159,9 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(
 
 u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)
 {
-	if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
-		/* In the new rate legacy rates are indexed:
-		 * 0 - 3 for CCK and 0 - 7 for OFDM.
-		 */
-		return (rate_idx >= IWL_FIRST_OFDM_RATE ?
-			rate_idx - IWL_FIRST_OFDM_RATE :
-			rate_idx);
-
-	return iwl_fw_rate_idx_to_plcp(rate_idx);
+	return rate_idx >= IWL_FIRST_OFDM_RATE ?
+		rate_idx - IWL_FIRST_OFDM_RATE :
+		rate_idx;
 }
 
 u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)
author maintainer
#79 lore raw

PATCH 79/461 wifi: iwlwifi: mld: stop TX during firmware restart

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sheroz Juraev <[email protected]>

commit 2becb38a3e217ef2b2f42fddd7db7a25905ec291 upstream.

When iwlwifi firmware crashes (e.g., NMI_INTERRUPT_UNKNOWN on Intel BE201/Wi-Fi 7), iwl_mld_nic_error() sets mld->fw_status.in_hw_restart to true. However, iwl_mld_tx_from_txq() does not check this flag before dequeuing frames from mac80211 and pushing them to the transport layer.

Since the firmware is dead, iwl_trans_tx() returns -EIO for each frame, which then gets freed immediately. Under high-throughput conditions (e.g., Tailscale UDP traffic or active SSH sessions), this creates a tight dequeue-send-fail-free loop that wastes CPU cycles and generates rapid skb allocation churn, leading to memory pressure from slab fragmentation.

The RX path already has this guard (iwl_mld_rx_mpdu checks in_hw_restart at rx.c:1906), and so does the TXQ allocation worker (iwl_mld_add_txqs_wk at tx.c:156). Add the same guard to iwl_mld_tx_from_txq() to stop all TX during firmware restart.

Frames left in mac80211's TXQs are naturally drained after restart completes, when queue reallocation triggers iwl_mld_tx_from_txq() via iwl_mld_add_txq_list(), or when new upper-layer traffic invokes wake_tx_queue.

Tested on ASUS Zenbook 14 UX3405CA with Intel BE201 (Wi-Fi 7) on kernel 6.19.5 where the firmware crashes approximately every 10-15 minutes under Tailscale traffic.

---
 drivers/net/wireless/intel/iwlwifi/mld/tx.c |   10 ++++++++++
 1 file changed, 10 insertions(+)
drivers/net/wireless/intel/iwlwifi/mld/tx.c +10 -0
@@ -971,6 +971,16 @@ void iwl_mld_tx_from_txq(struct iwl_mld
 	u8 zero_addr[ETH_ALEN] = {};
 
 	/*
+	 * Don't transmit during firmware restart. The firmware is dead,
+	 * so iwl_trans_tx() would return -EIO for each frame. Avoid the
+	 * overhead of dequeuing from mac80211 only to immediately free
+	 * the skbs, and the potential memory pressure from rapid skb
+	 * allocation churn during high-throughput restart scenarios.
+	 */
+	if (unlikely(mld->fw_status.in_hw_restart))
+		return;
+
+	/*
 	 * No need for threads to be pending here, they can leave the first
 	 * taker all the work.
 	 *
author maintainer
#80 lore raw

PATCH 80/461 ipv4: raw: reject IP_HDRINCL packets with ihl < 5

In reply to Greg Kroah-Hartman

7.0-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)) {
author maintainer
#81 lore raw

PATCH 81/461 ixgbevf: fix use-after-free in VEPA multicast source pruning

In reply to Greg Kroah-Hartman

7.0-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
@@ -1221,6 +1221,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;
 		}
 
author maintainer
#82 lore raw

PATCH 82/461 rbd: eliminate a race in lock_dwork draining on unmap

In reply to Greg Kroah-Hartman

7.0-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);
@@ -6548,10 +6536,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);
 }
 
 /*
author maintainer
#83 lore raw

PATCH 83/461 mptcp: do not drop partial packets

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Shardul Bankar <[email protected]>

commit 50c2d91c5dfa0e465826ec1f8dbad9cdc254bd85 upstream.

When a packet arrives with map_seq < ack_seq < end_seq, the beginning of the packet has already been acknowledged but the end contains new data. Currently the entire packet is dropped as "old data," forcing the sender to retransmit.

Instead, skip the already-acked bytes by adjusting the skb offset and enqueue only the new portion. Update bytes_received and ack_seq to reflect the new data consumed.

A previous attempt at this fix has been sent by Paolo Abeni [1], but had issues [2]: it also added a zero-window check and changed rcv_wnd_sent initialization, which caused test regressions. This version addresses only the partial packet handling without modifying receive window accounting.

---
 net/mptcp/protocol.c |   24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)
net/mptcp/protocol.c +19 -5
@@ -397,12 +397,26 @@ static bool __mptcp_move_skb(struct sock
 		return false;
 	}
 
-	/* old data, keep it simple and drop the whole pkt, sender
-	 * will retransmit as needed, if needed.
+	/* Completely old data? */
+	if (!after64(MPTCP_SKB_CB(skb)->end_seq, msk->ack_seq)) {
+		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
+		mptcp_drop(sk, skb);
+		return false;
+	}
+
+	/* Partial packet: map_seq < ack_seq < end_seq.
+	 * Skip the already-acked bytes and enqueue the new data.
 	 */
-	MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_DUPDATA);
-	mptcp_drop(sk, skb);
-	return false;
+	copy_len = MPTCP_SKB_CB(skb)->end_seq - msk->ack_seq;
+	MPTCP_SKB_CB(skb)->offset += msk->ack_seq - MPTCP_SKB_CB(skb)->map_seq;
+	MPTCP_SKB_CB(skb)->map_seq += msk->ack_seq -
+				      MPTCP_SKB_CB(skb)->map_seq;
+	msk->bytes_received += copy_len;
+	WRITE_ONCE(msk->ack_seq, msk->ack_seq + copy_len);
+
+	skb_set_owner_r(skb, sk);
+	__skb_queue_tail(&sk->sk_receive_queue, skb);
+	return true;
 }
 
 static void mptcp_stop_rtx_timer(struct sock *sk)
author maintainer
#84 lore raw

PATCH 84/461 mptcp: reset rcv wnd on disconnect

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Paolo Abeni <[email protected]>

commit 0981f90e1a05773a4c29c6e720f5ea1e3c8f1876 upstream.

If the MPTCP socket fallback to TCP before the MP handshake completion, the IASN remain 0, and the rcv_wnd_sent field is not explicitly initialized, just incremented over time with the data transfer.

At disconnect time such value is not cleared. If the next connection falls back to TCP before the MP handshake completion, the data transfer will keep incrementing the receive window end sequence starting from the last value used in the previous connection: the announced window will be unrelated from the actual receiver buffer size and likely too big.

Address the issue zeroing the field at disconnect time.

---
 net/mptcp/protocol.c |    1 +
 1 file changed, 1 insertion(+)
net/mptcp/protocol.c +1 -0
@@ -3470,6 +3470,7 @@ static int mptcp_disconnect(struct sock
 
 	/* for fallback's sake */
 	WRITE_ONCE(msk->ack_seq, 0);
+	atomic64_set(&msk->rcv_wnd_sent, 0);
 
 	WRITE_ONCE(sk->sk_shutdown, 0);
 	sk_error_report(sk);
author maintainer
#85 lore raw

PATCH 85/461 lsm: hold cred_guard_mutex for lsm_set_self_attr()

In reply to Greg Kroah-Hartman

7.0-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
@@ -57,7 +57,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(&current->signal->cred_guard_mutex);
+	if (rc < 0)
+		return rc;
+	rc = security_setselfattr(attr, ctx, size, flags);
+	mutex_unlock(&current->signal->cred_guard_mutex);
+	return rc;
 }
 
 /**
author maintainer
#86 lore raw

PATCH 86/461 octeontx2-af: CGX: add bounds check to cgx_speed_mbps index

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 61071a871ea6 ("octeontx2-af: Forward CGX link notifications to PFs")
Cc Sunil Goutham <[email protected]>
Cc Linu Cherian <[email protected]>
Cc Geetha sowjanya <[email protected]>
Cc hariprasad <[email protected]>
Cc Subbaraya Sundeep <[email protected]>
Cc Andrew Lunn <[email protected]>
Cc stable <[email protected]>
---
 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
@@ -1294,13 +1294,18 @@ static inline void link_status_user_form
 					   struct 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);
author maintainer
#87 lore raw

PATCH 87/461 octeontx2-pf: fix double free in rvu_rep_rsrc_init()

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dawei Feng <[email protected]>

commit e8fb3de2a8effcaf62bec2c56b93d8bb480371d1 upstream.

rvu_rep_rsrc_init() allocates queue memory before calling otx2_init_hw_resources(). When hardware resource setup fails, otx2_init_hw_resources() already unwinds the partially initialized SQ, CQ, and aura state before returning an error. The representor error path then calls otx2_free_hw_resources() again and can free the same resources a second time.

Fix this by splitting the cleanup labels so that a failure from otx2_init_hw_resources() only releases queue memory. Keep the otx2_free_hw_resources() call for failures that happen after hardware resource initialization completed successfully.

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 validation was not performed because reproducing this path requires OcteonTX2 representor hardware.

---
 drivers/net/ethernet/marvell/octeontx2/nic/rep.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/marvell/octeontx2/nic/rep.c +2 -1
@@ -609,7 +609,7 @@ static int rvu_rep_rsrc_init(struct otx2
 
 	err = otx2_init_hw_resources(priv);
 	if (err)
-		goto err_free_rsrc;
+		goto err_free_mem;
 
 	/* Set maximum frame size allowed in HW */
 	err = otx2_hw_set_mtu(priv, priv->hw.max_mtu);
@@ -621,6 +621,7 @@ static int rvu_rep_rsrc_init(struct otx2
 
 err_free_rsrc:
 	otx2_free_hw_resources(priv);
+err_free_mem:
 	otx2_free_queue_mem(qset);
 	return err;
 }
author maintainer
#88 lore raw

PATCH 88/461 igc: fix potential skb leak in igc_fpe_xmit_smd_frame()

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kohei Enju <[email protected]>

commit e935c37b8a94bb256fada6395a5d05e1c0c6bdaf upstream.

When igc_fpe_init_tx_descriptor() fails, no one takes care of an allocated skb, leaking it. [1]
Use dev_kfree_skb_any() on failure.

Tested on an I226 adapter with the following command, while injecting faults in igc_fpe_init_tx_descriptor() to trigger the error path.

 # ethtool --set-mm $DEV verify-enabled on tx-enabled on pmac-enabled on

[1]
unreferenced object 0xffff888113c6cdc0 (size 224):
...
backtrace (crc be3d3fda):

    kmem_cache_alloc_node_noprof+0x3b1/0x410
    __alloc_skb+0xde/0x830
    igc_fpe_xmit_smd_frame.isra.0+0xad/0x1b0
    igc_fpe_send_mpacket+0x37/0x90
    ethtool_mmsv_verify_timer+0x15e/0x300
---
 drivers/net/ethernet/intel/igc/igc_tsn.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/igc/igc_tsn.c +7 -1
@@ -109,10 +109,16 @@ static int igc_fpe_xmit_smd_frame(struct
 	__netif_tx_lock(nq, cpu);
 
 	err = igc_fpe_init_tx_descriptor(ring, skb, type);
-	igc_flush_tx_descriptors(ring);
+	if (err)
+		goto err_free_skb_any;
 
+	igc_flush_tx_descriptors(ring);
 	__netif_tx_unlock(nq);
+	return 0;
 
+err_free_skb_any:
+	__netif_tx_unlock(nq);
+	dev_kfree_skb_any(skb);
 	return err;
 }
 
author maintainer
#89 lore raw

PATCH 89/461 ice: fix locking around wait_event_interruptible_locked_irq

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jacob Keller <[email protected]>

commit 89bbff099bfc94888eb942d5b981592bbbe0c856 upstream.

Commit 50327223a8bb ("ice: add lock to protect low latency interface") introduced a wait queue used to protect the low latency timer interface. The queue is used with the wait_event_interruptible_locked_irq macro, which unlocks the wait queue lock while sleeping. The irq variant uses spin_lock_irq and spin_unlock_irq to manage this. The wait queue lock was previously locked using spin_lock_irqsave. This difference in lock variants could lead to issues, since wait_event would unlock the wait queue and restore interrupts while sleeping.

The ice_read_phy_tstamp_ll_e810() function is ultimately called through ice_read_phy_tstamp, which is called from ice_ptp_process_tx_tstamp or ice_ptp_clear_unexpected_tx_ready. The former is called through the miscellaneous IRQ thread function, while the latter is called from the service task work queue thread. Neither of these functions has interrupts disabled, so use spin_lock_irq instead of spin_lock_irqsave.

---
 drivers/net/ethernet/intel/ice/ice_ptp_hw.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/net/ethernet/intel/ice/ice_ptp_hw.c +4 -5
@@ -4503,18 +4503,17 @@ static int
 ice_read_phy_tstamp_ll_e810(struct ice_hw *hw, u8 idx, u8 *hi, u32 *lo)
 {
 	struct ice_e810_params *params = &hw->ptp.phy.e810;
-	unsigned long flags;
 	u32 val;
 	int err;
 
-	spin_lock_irqsave(&params->atqbal_wq.lock, flags);
+	spin_lock_irq(&params->atqbal_wq.lock);
 
 	/* Wait for any pending in-progress low latency interrupt */
 	err = wait_event_interruptible_locked_irq(params->atqbal_wq,
 						  !(params->atqbal_flags &
 						    ATQBAL_FLAGS_INTR_IN_PROGRESS));
 	if (err) {
-		spin_unlock_irqrestore(&params->atqbal_wq.lock, flags);
+		spin_unlock_irq(&params->atqbal_wq.lock);
 		return err;
 	}
 
@@ -4529,7 +4528,7 @@ ice_read_phy_tstamp_ll_e810(struct ice_h
 				       REG_LL_PROXY_H);
 	if (err) {
 		ice_debug(hw, ICE_DBG_PTP, "Failed to read PTP timestamp using low latency read\n");
-		spin_unlock_irqrestore(&params->atqbal_wq.lock, flags);
+		spin_unlock_irq(&params->atqbal_wq.lock);
 		return err;
 	}
 
@@ -4539,7 +4538,7 @@ ice_read_phy_tstamp_ll_e810(struct ice_h
 	/* Read the low 32 bit value and set the TS valid bit */
 	*lo = rd32(hw, REG_LL_PROXY_L) | TS_VALID;
 
-	spin_unlock_irqrestore(&params->atqbal_wq.lock, flags);
+	spin_unlock_irq(&params->atqbal_wq.lock);
 
 	return 0;
 }
author maintainer
#90 lore raw

PATCH 90/461 ice: fix setting promisc mode while adding VID filter

In reply to Greg Kroah-Hartman

7.0-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
@@ -3682,7 +3682,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;
 	}
 
author maintainer
#91 lore raw

PATCH 91/461 ice: restore PTP Rx timestamp config after ethtool set-channels

In reply to Greg Kroah-Hartman

7.0-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
@@ -4104,6 +4104,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:
author maintainer
#92 lore raw

PATCH 92/461 wifi: cfg80211: advance loop vars in cfg80211_merge_profile()

In reply to Greg Kroah-Hartman

7.0-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.

Fixes fe806e4992c9 ("cfg80211: support profile split between elements")
---
 net/wireless/scan.c |    3 +++
 1 file changed, 3 insertions(+)
net/wireless/scan.c +3 -0
@@ -2462,6 +2462,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;
author maintainer
#93 lore raw

PATCH 93/461 af_unix: Fix UAF read of tail->len in unix_stream_data_wait()

In reply to Greg Kroah-Hartman

7.0-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") added sendpage() 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: Support MSG_SPLICE_PAGES") and commit 57d44a354a43 ("unix: Convert unix_stream_sendpage() to use MSG_SPLICE_PAGES") refactored sendmsg(), and now data is always added to a new skb.

That means this fix is not suitable for kernels before 6.5.

Fixes 2b514574f7e8 ("net: af_unix: implement splice for stream af_unix sockets")
---
 net/unix/af_unix.c |   11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)
net/unix/af_unix.c +2 -9
@@ -2707,8 +2707,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;
@@ -2721,7 +2720,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) ||
@@ -2917,7 +2915,6 @@ static int unix_stream_read_generic(stru
 	int 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;
@@ -2963,7 +2960,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)
@@ -2997,8 +2993,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);
@@ -3015,7 +3010,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;
@@ -3090,7 +3084,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)
author maintainer
#94 lore raw

PATCH 94/461 wifi: mac80211: consume only present negotiated TTLM maps

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 8f500fbc6c65 ("wifi: mac80211: process and save negotiated TID to Link mapping request")
Assisted-by Claude:claude-opus-4-7
---
 net/mac80211/mlme.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/mlme.c +1 -1
@@ -8070,6 +8070,7 @@ ieee80211_parse_neg_ttlm(struct ieee8021
 					 "No active links for TID %d", tid);
 				return -EINVAL;
 			}
+			pos += map_size;
 		} else {
 			map = 0;
 		}
@@ -8088,7 +8089,6 @@ ieee80211_parse_neg_ttlm(struct ieee8021
 		default:
 			return -EINVAL;
 		}
-		pos += map_size;
 	}
 	return 0;
 }
author maintainer
#95 lore raw

PATCH 95/461 octeontx2-pf: avoid double free of pool->stack on AQ init failure

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dawei Feng <[email protected]>

commit 9b244c242bec48b37e82b89787afd6a4c43457e1 upstream.

otx2_pool_aq_init() frees pool->stack when mailbox sync or retry allocation fails, but leaves the pointer unchanged. Later, otx2_sq_aura_pool_init() unwinds the partial setup through otx2_aura_pool_free(), which frees pool->stack again. The CN20K-specific cn20k_pool_aq_init() implementation has the same bug in
its corresponding error path.

Set pool->stack to NULL immediately after the local free so the shared cleanup path does not free the same stack again while cleaning up partially initialized pool state.

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 validation was not performed because reproducing this path requires OcteonTX2/CN20K hardware.

Fixes caa2da34fd25 ("octeontx2-pf: Initialize and config queues")
Fixes d322fbd17203 ("octeontx2-pf: Initialize cn20k specific aura and pool contexts")
---
 drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c       |    2 ++
 drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c |    2 ++
 2 files changed, 4 insertions(+)
drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c +2 -0
@@ -353,11 +353,13 @@ static int cn20k_pool_aq_init(struct otx
 		err = otx2_sync_mbox_msg(&pfvf->mbox);
 		if (err) {
 			qmem_free(pfvf->dev, pool->stack);
+			pool->stack = NULL;
 			return err;
 		}
 		aq = otx2_mbox_alloc_msg_npa_cn20k_aq_enq(&pfvf->mbox);
 		if (!aq) {
 			qmem_free(pfvf->dev, pool->stack);
+			pool->stack = NULL;
 			return -ENOMEM;
 		}
 	}
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +2 -0
@@ -1482,11 +1482,13 @@ int otx2_pool_aq_init(struct otx2_nic *p
 		err = otx2_sync_mbox_msg(&pfvf->mbox);
 		if (err) {
 			qmem_free(pfvf->dev, pool->stack);
+			pool->stack = NULL;
 			return err;
 		}
 		aq = otx2_mbox_alloc_msg_npa_aq_enq(&pfvf->mbox);
 		if (!aq) {
 			qmem_free(pfvf->dev, pool->stack);
+			pool->stack = NULL;
 			return -ENOMEM;
 		}
 	}
author maintainer
#96 lore raw

PATCH 96/461 cifs: Fix busy dentry used after unmounting

In reply to Greg Kroah-Hartman

7.0-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 = 0

Fix it by flushing 'deferredclose_wq' before calling kill_anon_super.

Fetch a reproducer in https://bugzilla.kernel.org/show_bug.cgi?id=221548.

Fixes 340cea84f691c ("cifs: open files should not hold ref on superblock")
---
 fs/smb/client/cifsfs.c |    2 ++
 1 file changed, 2 insertions(+)
fs/smb/client/cifsfs.c +2 -0
@@ -340,6 +340,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);
author maintainer
#97 lore raw

PATCH 97/461 tracing: Do not call map->ops->elt_free() if elt_alloc() fails

In reply to Greg Kroah-Hartman

7.0-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(struct
 	kfree(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);
 }
author maintainer
#98 lore raw

PATCH 98/461 ASoC: codecs: pcm512x: fix null-ptr dereference in pcm512x_overclock_xxx_put()

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeongjun Park <[email protected]>

commit 09e8f9a9aa19aa8c1b0cc7a0ebc68f6ecf86a660 upstream.

In the pcm512x chipset driver, pcm512x_overclock_xxx_put() is defined as a general mixer kcontrol instead of a DAPM kcontrol, so struct snd_soc_dapm_context must not be accessed via snd_soc_dapm_kcontrol_to_dapm().

This causes a NULL pointer dereference, so it must be modified to use snd_soc_component_to_dapm().

---
 sound/soc/codecs/pcm512x.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
sound/soc/codecs/pcm512x.c +3 -3
@@ -235,7 +235,7 @@ static int pcm512x_overclock_pll_put(str
 				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
+	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
 
 	switch (snd_soc_dapm_get_bias_level(dapm)) {
@@ -264,7 +264,7 @@ static int pcm512x_overclock_dsp_put(str
 				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
+	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
 
 	switch (snd_soc_dapm_get_bias_level(dapm)) {
@@ -293,7 +293,7 @@ static int pcm512x_overclock_dac_put(str
 				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
+	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
 
 	switch (snd_soc_dapm_get_bias_level(dapm)) {
author maintainer
#99 lore raw

PATCH 99/461 arm64: probes: Handle probes on hinted conditional branch instructions

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 7f86d128e437 ("arm64: add HWCAP for FEAT_HBC (hinted conditional branches)")
---
 arch/arm64/include/asm/insn.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/insn.h +1 -1
@@ -409,7 +409,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)
author maintainer
#100 lore raw

PATCH 100/461 KVM: arm64: vgic-its: Reject restored DTE with out-of-range num_eventid_bits

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 57a9a117154c ("KVM: arm64: vgic-its: Device table save/restore")
Assisted-by Claude:claude-opus-4-7
---
 arch/arm64/kvm/vgic/vgic-its.c |    4 ++++
 1 file changed, 4 insertions(+)
arch/arm64/kvm/vgic/vgic-its.c +4 -0
@@ -2307,6 +2307,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;
 
author maintainer
#101 lore raw

PATCH 101/461 KVM: arm64: vgic: Free private_irqs when init fails after allocation

In reply to Greg Kroah-Hartman

7.0-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.

Fixes 03b3d00a70b5 ("KVM: arm64: vgic: Allocate private interrupts on demand")
Cc Will Deacon <[email protected]>
Assisted-by Claude:claude-opus-4-7
---
 arch/arm64/kvm/arm.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm64/kvm/arm.c +3 -1
@@ -540,8 +540,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpu
 	kvm_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)
author maintainer
#102 lore raw

PATCH 102/461 KVM: SVM: Disable AVIC IPI virtualization on Hygon Family 18h (erratum #1235)

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Tina Zhang <[email protected]>

commit 9a12fa5213cfc391e0eed63902d3be98f0913765 upstream.

Hygon Family 18h CPUs are derived from AMD Family 17h (Zen1) silicon and share the same erratum #1235: hardware may read a stale IsRunning=1 bit during ICR write emulation and silently fail to generate an AVIC_IPI_FAILURE_TARGET_NOT_RUNNING VM-Exit on the sending vCPU.

The absence of the VM-Exit causes KVM to miss the required wakeup of blocking target vCPUs, leading to hung vCPUs and unbounded delays in guest execution.

Extend the existing AMD Family 17h erratum #1235 workaround to also cover Hygon Family 18h. With IPI virtualization disabled, KVM never sets IsRunning=1 in the Physical ID table, so every non-self IPI generates a VM-Exit and is correctly emulated.

Fixes 8de4a1c8164e ("KVM: SVM: Disable (x2)AVIC IPI virtualization if CPU has erratum #1235")

Message-ID: <[email protected]>

---
 arch/x86/kvm/svm/avic.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
arch/x86/kvm/svm/avic.c +7 -5
@@ -1289,12 +1289,14 @@ bool __init avic_hardware_setup(void)
 	}
 
 	/*
-	 * Disable IPI virtualization for AMD Family 17h CPUs (Zen1 and Zen2)
-	 * due to erratum 1235, which results in missed VM-Exits on the sender
-	 * and thus missed wake events for blocking vCPUs due to the CPU
-	 * failing to see a software update to clear IsRunning.
+	 * Disable IPI virtualization for AMD Family 17h (Zen1 and Zen2) and
+	 * Hygon Family 18h (derived from AMD Zen1) CPUs due to erratum 1235,
+	 * which results in missed VM-Exits on the sender and thus missed wake
+	 * events for blocking vCPUs due to the CPU failing to see a software
+	 * update to clear IsRunning.
 	 */
-	enable_ipiv = enable_ipiv && boot_cpu_data.x86 != 0x17;
+	if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18)
+		enable_ipiv = false;
 
 	amd_iommu_register_ga_log_notifier(&avic_ga_log_notifier);
 
author maintainer
#103 lore raw

PATCH 103/461 riscv: kvm: return SBI_ERR_FAILURE for pmu_snapshot_set_shmem() when OOM

In reply to Greg Kroah-Hartman

7.0-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;
+	}
 
 	/* No need to check writable slot explicitly as kvm_vcpu_write_guest does it internally */
 	if (kvm_vcpu_write_guest(vcpu, saddr, kvpmu->sdata, snapshot_area_size)) {
author maintainer
#104 lore raw

PATCH 104/461 riscv: kvm: return SBI_ERR_FAILURE for pmu_event_info() when OOM

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Osama Abdelkader <[email protected]>

commit 0e9d0e7a7c78db7aa1c13796c65cfe0aefa54a5b upstream.

kvm_riscv_vcpu_pmu_event_info() 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 completing 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
@@ -482,8 +482,10 @@ int kvm_riscv_vcpu_pmu_event_info(struct
 	}
 
 	einfo = kzalloc(shmem_size, GFP_KERNEL);
-	if (!einfo)
-		return -ENOMEM;
+	if (!einfo) {
+		ret = SBI_ERR_FAILURE;
+		goto out;
+	}
 
 	ret = kvm_vcpu_read_guest(vcpu, shmem, einfo, shmem_size);
 	if (ret) {
author maintainer
#105 lore raw

PATCH 105/461 virt: sev-guest: Explicitly leak pages in unknown state

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Carlos López <[email protected]>

commit fd948c3f96b18ff9ba7d3e8eae13d196593e1aaf upstream.

When set_memory_{encrypted,decrypted}() fail, the user cannot know at which point the function failed, meaning that the pages are left in an unknown state from the point of view of the caller.

Since the pages may be left in an unencrypted state, they are not suitable for general use, and cannot be returned safely to the buddy allocator. Avoid the issue by never freeing the pages, and then do the proper accounting by calling snp_leak_pages().

Fixes 3e385c0d6ce8 ("virt: sev-guest: Move SNP Guest Request data pages handling under snp_cmd_mutex")
---
 drivers/virt/coco/sev-guest/sev-guest.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/virt/coco/sev-guest/sev-guest.c +7 -3
@@ -176,6 +176,7 @@ static int get_ext_report(struct snp_gue
 	struct snp_guest_req req = {};
 	int ret, npages = 0, resp_len;
 	sockptr_t certs_address;
+	u64 pfn;
 
 	if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data))
 		return -EINVAL;
@@ -215,10 +216,11 @@ static int get_ext_report(struct snp_gue
 	if (!req.certs_data)
 		return -ENOMEM;
 
+	pfn = PHYS_PFN(virt_to_phys(req.certs_data));
 	ret = set_memory_decrypted((unsigned long)req.certs_data, npages);
 	if (ret) {
 		pr_err("failed to mark page shared, ret=%d\n", ret);
-		free_pages_exact(req.certs_data, npages << PAGE_SHIFT);
+		snp_leak_pages(pfn, npages);
 		return -EFAULT;
 	}
 
@@ -272,10 +274,12 @@ e_free:
 	kfree(report_resp);
 e_free_data:
 	if (npages) {
-		if (set_memory_encrypted((unsigned long)req.certs_data, npages))
+		if (set_memory_encrypted((unsigned long)req.certs_data, npages)) {
 			WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n");
-		else
+			snp_leak_pages(pfn, npages);
+		} else {
 			free_pages_exact(req.certs_data, npages << PAGE_SHIFT);
+		}
 	}
 	return ret;
 }
author maintainer
#106 lore raw

PATCH 106/461 i2c: tegra: fix pm_runtime leak on mutex_lock failure

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Saurav Sachidanand <[email protected]>

commit 57cf4e8d6a57dc2ef5810f4852a23ba4c71b74bb upstream.

If tegra_i2c_mutex_lock() fails, the function returns without calling pm_runtime_put(), leaking the runtime PM reference acquired by the preceding pm_runtime_get_sync(). This prevents the device from ever entering runtime suspend.

Add the missing pm_runtime_put() before returning on lock failure.

---
 drivers/i2c/busses/i2c-tegra.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-tegra.c +3 -1
@@ -1522,8 +1522,10 @@ static int tegra_i2c_xfer(struct i2c_ada
 	}
 
 	ret = tegra_i2c_mutex_lock(i2c_dev);
-	if (ret)
+	if (ret) {
+		pm_runtime_put(i2c_dev->dev);
 		return ret;
+	}
 
 	for (i = 0; i < num; i++) {
 		enum msg_end_type end_type = MSG_END_STOP;
author maintainer
#107 lore raw

PATCH 107/461 drm/bridge: chipone-icn6211: use devm_drm_bridge_add in i2c probe

In reply to Greg Kroah-Hartman

7.0-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
@@ -758,7 +758,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);
 }
author maintainer
#108 lore raw

PATCH 108/461 spi: qup: fix error pointer deref after DMA setup failure

In reply to Greg Kroah-Hartman

7.0-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;
 }
 
author maintainer
#109 lore raw

PATCH 109/461 phy: exynos5-usbdrd: fix USB 2.0 HS PHY tuning values for Exynos7870

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Łukasz Lebiedziński <[email protected]>

commit 5a759b120e31aa3ed914d98b51eb1755235250f2 upstream.

The existing PHYPARAM0 tuning values for Exynos7870 are incorrect, causing the USB 2.0 PHY to fail high-speed negotiation and fall back to full-speed (12Mbps) operation.

Fix TXVREFTUNE (transmitter voltage reference) from 14 to 3, TXRESTUNE (transmitter impedance) from 3 to 2, and SQRXTUNE (squelch threshold) from 6 to 5. Also explicitly set TXPREEMPPULSETUNE to 0, which was previously missing from the tuning table despite being included in the register mask.

All values are derived from the vendor kernel for the Samsung Galaxy A6 (SM-A600FN), as no public hardware documentation is available for the Exynos7870 USB DRD PHY. With these corrections, the PHY successfully negotiates high-speed (480Mbps) operation.

---
 drivers/phy/samsung/phy-exynos5-usbdrd.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/phy/samsung/phy-exynos5-usbdrd.c +4 -3
@@ -1958,13 +1958,14 @@ const struct exynos5_usbdrd_phy_tuning e
 			      PHYPARAM0_TXPREEMPAMPTUNE | PHYPARAM0_TXHSXVTUNE |
 			      PHYPARAM0_TXFSLSTUNE | PHYPARAM0_SQRXTUNE |
 			      PHYPARAM0_OTGTUNE | PHYPARAM0_COMPDISTUNE),
-			     (FIELD_PREP_CONST(PHYPARAM0_TXVREFTUNE, 14) |
+			     (FIELD_PREP_CONST(PHYPARAM0_TXVREFTUNE, 3) |
 			      FIELD_PREP_CONST(PHYPARAM0_TXRISETUNE, 1) |
-			      FIELD_PREP_CONST(PHYPARAM0_TXRESTUNE, 3) |
+			      FIELD_PREP_CONST(PHYPARAM0_TXRESTUNE, 2) |
+			      FIELD_PREP_CONST(PHYPARAM0_TXPREEMPPULSETUNE, 0) |
 			      FIELD_PREP_CONST(PHYPARAM0_TXPREEMPAMPTUNE, 0) |
 			      FIELD_PREP_CONST(PHYPARAM0_TXHSXVTUNE, 0) |
 			      FIELD_PREP_CONST(PHYPARAM0_TXFSLSTUNE, 3) |
-			      FIELD_PREP_CONST(PHYPARAM0_SQRXTUNE, 6) |
+			      FIELD_PREP_CONST(PHYPARAM0_SQRXTUNE, 5) |
 			      FIELD_PREP_CONST(PHYPARAM0_OTGTUNE, 2) |
 			      FIELD_PREP_CONST(PHYPARAM0_COMPDISTUNE, 3))),
 	PHY_TUNING_ENTRY_LAST
author maintainer
#110 lore raw

PATCH 110/461 phy: tegra: xusb: Fix per-pad high-speed termination calibration

In reply to Greg Kroah-Hartman

7.0-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
@@ -435,6 +435,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 {
author maintainer
#111 lore raw

PATCH 111/461 phy: qcom-qmp-ufs: Fix kaanapali PHY PLL lock failure after SM8650 G4 fix

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Nitin Rawat <[email protected]>

commit 80305760d7a55b884fb9023c490b75568d1ea0b1 upstream.

Commit 81af9e40e2e4 ("phy: qcom: qmp-ufs: Fix SM8650 PCS table for Gear 4") moved QPHY_V6_PCS_UFS_PLL_CNTL register configuration from the shared sm8650_ufsphy_g5_pcs table to the SM8650-specific sm8650_ufsphy_pcs base table to fix Gear 4 operation on SM8650.

However, this change inadvertently broke kaanapali and SM8750 SoCs which also rely on the shared sm8650_ufsphy_g5_pcs table for Gear 5 configuration but use their own sm8750_ufsphy_pcs base table. After the change, kaanapali PHYs are left without the required PLL_CNTL = 0x33 setting, causing the PHY PLL to remain at its hardware reset default value, preventing PLL lock and resulting in DME_LINKSTARTUP timeouts.

Fix this by adding the missing QPHY_V6_PCS_UFS_PLL_CNTL = 0x33 entry to the sm8750_ufsphy_pcs table, mirroring what the original commit already did for sm8650_ufsphy_pcs.

---
 drivers/phy/qualcomm/phy-qcom-qmp-ufs.c |    1 +
 1 file changed, 1 insertion(+)
drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +1 -0
@@ -1112,6 +1112,7 @@ static const struct qmp_phy_init_tbl sm8
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0x40),
+	QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68),
 	QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4, 0x0e),
author maintainer
#112 lore raw

PATCH 112/461 phy: qcom: edp: Unify generic DP/eDP swing and pre-emphasis tables

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Yongxing Mou <[email protected]>

commit fd672888cccd6b855154efe0ac78e7ce3e8ab088 upstream.

The current eDP and DP swing/pre-emphasis tables do not match the HPG requirements for the supported platforms, correct the table accordingly.

The generic tables which can be shared as follows:

DP mode:

	-sa8775p/sc7280/sc8280xp/x1e80100
	-glymur
	-sc8180x
eDP mode(low vdiff):
	-glymur/sa8775p/sc8280xp/x1e80100
	-sc7280
	-sc8180x

The proper tables for SC8180X and SC7280 will be added in a later patch, since they need separate table.

---
 drivers/phy/qualcomm/phy-qcom-edp.c |   41 ++++++++----------------------------
 1 file changed, 10 insertions(+), 31 deletions(-)
drivers/phy/qualcomm/phy-qcom-edp.c +10 -31
@@ -116,17 +116,17 @@ struct qcom_edp {
 };
 
 static const u8 dp_swing_hbr_rbr[4][4] = {
-	{ 0x08, 0x0f, 0x16, 0x1f },
+	{ 0x07, 0x0f, 0x16, 0x1f },
 	{ 0x11, 0x1e, 0x1f, 0xff },
 	{ 0x16, 0x1f, 0xff, 0xff },
 	{ 0x1f, 0xff, 0xff, 0xff }
 };
 
 static const u8 dp_pre_emp_hbr_rbr[4][4] = {
-	{ 0x00, 0x0d, 0x14, 0x1a },
+	{ 0x00, 0x0e, 0x15, 0x1a },
 	{ 0x00, 0x0e, 0x15, 0xff },
 	{ 0x00, 0x0e, 0xff, 0xff },
-	{ 0x03, 0xff, 0xff, 0xff }
+	{ 0x04, 0xff, 0xff, 0xff }
 };
 
 static const u8 dp_swing_hbr2_hbr3[4][4] = {
@@ -158,7 +158,7 @@ static const u8 edp_swing_hbr_rbr[4][4]
 };
 
 static const u8 edp_pre_emp_hbr_rbr[4][4] = {
-	{ 0x05, 0x12, 0x17, 0x1d },
+	{ 0x05, 0x11, 0x17, 0x1d },
 	{ 0x05, 0x11, 0x18, 0xff },
 	{ 0x06, 0x11, 0xff, 0xff },
 	{ 0x00, 0xff, 0xff, 0xff }
@@ -172,10 +172,10 @@ static const u8 edp_swing_hbr2_hbr3[4][4
 };
 
 static const u8 edp_pre_emp_hbr2_hbr3[4][4] = {
-	{ 0x08, 0x11, 0x17, 0x1b },
-	{ 0x00, 0x0c, 0x13, 0xff },
-	{ 0x05, 0x10, 0xff, 0xff },
-	{ 0x00, 0xff, 0xff, 0xff }
+	{ 0x0c, 0x15, 0x19, 0x1e },
+	{ 0x0b, 0x15, 0x19, 0xff },
+	{ 0x0e, 0x14, 0xff, 0xff },
+	{ 0x0d, 0xff, 0xff, 0xff }
 };
 
 static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
@@ -193,27 +193,6 @@ static const u8 edp_phy_vco_div_cfg_v4[4
 	0x01, 0x01, 0x02, 0x00,
 };
 
-static const u8 edp_pre_emp_hbr_rbr_v5[4][4] = {
-	{ 0x05, 0x11, 0x17, 0x1d },
-	{ 0x05, 0x11, 0x18, 0xff },
-	{ 0x06, 0x11, 0xff, 0xff },
-	{ 0x00, 0xff, 0xff, 0xff }
-};
-
-static const u8 edp_pre_emp_hbr2_hbr3_v5[4][4] = {
-	{ 0x0c, 0x15, 0x19, 0x1e },
-	{ 0x0b, 0x15, 0x19, 0xff },
-	{ 0x0e, 0x14, 0xff, 0xff },
-	{ 0x0d, 0xff, 0xff, 0xff }
-};
-
-static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v5 = {
-	.swing_hbr_rbr = &edp_swing_hbr_rbr,
-	.swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
-	.pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr_v5,
-	.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v5,
-};
-
 static const u8 edp_phy_aux_cfg_v5[DP_AUX_CFG_SIZE] = {
 	0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03, 0x02, 0x02, 0x00,
 };
@@ -564,7 +543,7 @@ static const struct qcom_edp_phy_cfg sa8
 	.is_edp = false,
 	.aux_cfg = edp_phy_aux_cfg_v5,
 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
-	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
+	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
 	.ver_ops = &qcom_edp_phy_ops_v4,
 };
 
@@ -945,7 +924,7 @@ static const struct phy_ver_ops qcom_edp
 static struct qcom_edp_phy_cfg glymur_phy_cfg = {
 	.aux_cfg = edp_phy_aux_cfg_v8,
 	.vco_div_cfg = edp_phy_vco_div_cfg_v8,
-	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
+	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
 	.ver_ops = &qcom_edp_phy_ops_v8,
 };
 
author maintainer
#113 lore raw

PATCH 113/461 phy: qcom: edp: Add eDP/DP mode switch support

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Yongxing Mou <[email protected]>

commit 3011c365a329cf2db6d55e8d684550dc88350436 upstream.

The eDP PHY supports both eDP/DP modes, each requiring a different swing/pre-emphasis table. However, the driver currently uses a fixed static table for eDP programming rather than selecting the appropriate table based on the current mode. Add separate tables for eDP and DP modes, and select the appropriate table dynamically based on the current mode.

Glymur's DP mode table differs from the other platforms, add a dedicated table for it.

This also fixes the table mismatch for X1E80100 (eDP) and SA8775P (DP).

---
 drivers/phy/qualcomm/phy-qcom-edp.c |   46 ++++++++++++++++++++++++++----------
 1 file changed, 34 insertions(+), 12 deletions(-)
drivers/phy/qualcomm/phy-qcom-edp.c +34 -12
@@ -87,7 +87,8 @@ struct qcom_edp_phy_cfg {
 	bool is_edp;
 	const u8 *aux_cfg;
 	const u8 *vco_div_cfg;
-	const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
+	const struct qcom_edp_swing_pre_emph_cfg *dp_swing_pre_emph_cfg;
+	const struct qcom_edp_swing_pre_emph_cfg *edp_swing_pre_emph_cfg;
 	const struct phy_ver_ops *ver_ops;
 };
 
@@ -150,6 +151,20 @@ static const struct qcom_edp_swing_pre_e
 	.pre_emphasis_hbr3_hbr2 = &dp_pre_emp_hbr2_hbr3,
 };
 
+static const u8 dp_pre_emp_hbr_rbr_v8[4][4] = {
+	{ 0x00, 0x0e, 0x15, 0x1a },
+	{ 0x00, 0x0e, 0x15, 0xff },
+	{ 0x00, 0x0e, 0xff, 0xff },
+	{ 0x00, 0xff, 0xff, 0xff }
+};
+
+static const struct qcom_edp_swing_pre_emph_cfg dp_phy_swing_pre_emph_cfg_v8 = {
+	.swing_hbr_rbr = &dp_swing_hbr_rbr,
+	.swing_hbr3_hbr2 = &dp_swing_hbr2_hbr3,
+	.pre_emphasis_hbr_rbr = &dp_pre_emp_hbr_rbr_v8,
+	.pre_emphasis_hbr3_hbr2 = &dp_pre_emp_hbr2_hbr3,
+};
+
 static const u8 edp_swing_hbr_rbr[4][4] = {
 	{ 0x07, 0x0f, 0x16, 0x1f },
 	{ 0x0d, 0x16, 0x1e, 0xff },
@@ -246,7 +261,7 @@ static int qcom_edp_phy_init(struct phy
 	 * when more information becomes available about why this is
 	 * even needed.
 	 */
-	if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
+	if (edp->cfg->dp_swing_pre_emph_cfg && !edp->is_edp)
 		aux_cfg[8] = 0xb7;
 
 	writel(0xfc, edp->edp + DP_PHY_MODE);
@@ -270,7 +285,7 @@ out_disable_supplies:
 
 static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configure_opts_dp *dp_opts)
 {
-	const struct qcom_edp_swing_pre_emph_cfg *cfg = edp->cfg->swing_pre_emph_cfg;
+	const struct qcom_edp_swing_pre_emph_cfg *cfg;
 	unsigned int v_level = 0;
 	unsigned int p_level = 0;
 	u8 ldo_config;
@@ -278,12 +293,14 @@ static int qcom_edp_set_voltages(struct
 	u8 emph;
 	int i;
 
+	if (edp->is_edp)
+		cfg = edp->cfg->edp_swing_pre_emph_cfg;
+	else
+		cfg = edp->cfg->dp_swing_pre_emph_cfg;
+
 	if (!cfg)
 		return 0;
 
-	if (edp->is_edp)
-		cfg = &edp_phy_swing_pre_emph_cfg;
-
 	for (i = 0; i < dp_opts->lanes; i++) {
 		v_level = max(v_level, dp_opts->voltage[i]);
 		p_level = max(p_level, dp_opts->pre[i]);
@@ -543,7 +560,8 @@ static const struct qcom_edp_phy_cfg sa8
 	.is_edp = false,
 	.aux_cfg = edp_phy_aux_cfg_v5,
 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
-	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
+	.dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
+	.edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
 	.ver_ops = &qcom_edp_phy_ops_v4,
 };
 
@@ -556,7 +574,8 @@ static const struct qcom_edp_phy_cfg sc7
 static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
 	.aux_cfg = edp_phy_aux_cfg_v4,
 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
-	.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
+	.dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
+	.edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
 	.ver_ops = &qcom_edp_phy_ops_v4,
 };
 
@@ -564,7 +583,8 @@ static const struct qcom_edp_phy_cfg sc8
 	.is_edp = true,
 	.aux_cfg = edp_phy_aux_cfg_v4,
 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
-	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
+	.dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
+	.edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
 	.ver_ops = &qcom_edp_phy_ops_v4,
 };
 
@@ -745,7 +765,8 @@ static const struct phy_ver_ops qcom_edp
 static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
 	.aux_cfg = edp_phy_aux_cfg_v4,
 	.vco_div_cfg = edp_phy_vco_div_cfg_v4,
-	.swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
+	.dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
+	.edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
 	.ver_ops = &qcom_edp_phy_ops_v6,
 };
 
@@ -924,7 +945,8 @@ static const struct phy_ver_ops qcom_edp
 static struct qcom_edp_phy_cfg glymur_phy_cfg = {
 	.aux_cfg = edp_phy_aux_cfg_v8,
 	.vco_div_cfg = edp_phy_vco_div_cfg_v8,
-	.swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
+	.dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg_v8,
+	.edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
 	.ver_ops = &qcom_edp_phy_ops_v8,
 };
 
@@ -942,7 +964,7 @@ static int qcom_edp_phy_power_on(struct
 	if (ret)
 		return ret;
 
-	if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
+	if (edp->cfg->edp_swing_pre_emph_cfg && !edp->is_edp)
 		ldo_config = 0x1;
 
 	writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
author maintainer
#114 lore raw

PATCH 114/461 phy: qcom: edp: Fix AUX_CFG8 programming for DP mode

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Yongxing Mou <[email protected]>

commit bf237a9fcbbf9d658522f7315ffc04bf2d49be42 upstream.

AUX_CFG8 depends on whether the PHY is operating in eDP or DP mode, not the selected swing/pre-emphasis table. All supported platforms already have the proper tables, so remove the unnecessary check.

---
 drivers/phy/qualcomm/phy-qcom-edp.c |    7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/phy/qualcomm/phy-qcom-edp.c +1 -6
@@ -256,12 +256,7 @@ static int qcom_edp_phy_init(struct phy
 	       DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
 	       edp->edp + DP_PHY_PD_CTL);
 
-	/*
-	 * TODO: Re-work the conditions around setting the cfg8 value
-	 * when more information becomes available about why this is
-	 * even needed.
-	 */
-	if (edp->cfg->dp_swing_pre_emph_cfg && !edp->is_edp)
+	if (!edp->is_edp)
 		aux_cfg[8] = 0xb7;
 
 	writel(0xfc, edp->edp + DP_PHY_MODE);
author maintainer
#115 lore raw

PATCH 115/461 scsi: isci: Fix use-after-free in device removal path

In reply to Greg Kroah-Hartman

7.0-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().

Fixes 6f231dda6808 ("isci: Intel(R) C600 Series Chipset Storage Control Unit Driver")
Assisted-by Claude:claude-opus-4-7
Assisted-by Codex:gpt-5-4
---
 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
author maintainer
#116 lore raw

PATCH 116/461 spi: ep93xx: fix error pointer deref after DMA setup failure

In reply to Greg Kroah-Hartman

7.0-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 d
 	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;
 	}
 
author maintainer
#117 lore raw

PATCH 117/461 spi: sprd: fix error pointer deref after DMA setup failure

In reply to Greg Kroah-Hartman

7.0-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
@@ -991,7 +991,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);
 
author maintainer
#118 lore raw

PATCH 118/461 spi: ti-qspi: fix use-after-free after DMA setup failure

In reply to Greg Kroah-Hartman

7.0-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
@@ -867,6 +867,7 @@ static int ti_qspi_probe(struct platform
 		dev_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;
author maintainer
#119 lore raw

PATCH 119/461 mm/slub: hold cpus_read_lock around flush_rcu_sheaves_on_cache()

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Qing Wang <[email protected]>

commit 67ea9d353d0ba12bdbc9183ff568dead9e949b80 upstream.

flush_rcu_sheaves_on_cache() calls queue_work_on() in a for_each_online_cpu() loop, which requires the cpu to stay online. But cpus_read_lock() is not held in kvfree_rcu_barrier_on_cache() and the set of "online cpus" is subject to change.

There are two paths that call flush_rcu_sheaves_on_cache():

// has cpus_read_lock()
flush_all_rcu_sheaves()

    -> flush_rcu_sheaves_on_cache()

// no cpus_read_lock()
kvfree_rcu_barrier_on_cache()

    -> flush_rcu_sheaves_on_cache()

Fix this by holding cpus_read_lock() in kvfree_rcu_barrier_on_cache().

Why not move cpus_read_lock() from flush_all_rcu_sheaves() into flush_rcu_sheaves_on_cache()? The reason is it would introduce a new lock order (slab_mutex -> cpu_hotplug_lock). The reverse order (cpu_hotplug_lock -> slab_mutex) is established by

- cpuhp_setup_state_nocalls(..., slub_cpu_setup, ...)
- kmem_cache_destroy()

The two orders together would form an AB-BA deadlock.

Finally, add lockdep_assert_cpus_held() in flush_rcu_sheaves_on_cache() to catch the same problem in the future.

Fixes 0f35040de593 ("mm/slab: introduce kvfree_rcu_barrier_on_cache() for cache destruction")
---
 mm/slab_common.c |    2 ++
 mm/slub.c        |    1 +
 2 files changed, 3 insertions(+)
mm/slab_common.c +2 -0
@@ -2110,7 +2110,9 @@ EXPORT_SYMBOL_GPL(kvfree_rcu_barrier);
 void kvfree_rcu_barrier_on_cache(struct kmem_cache *s)
 {
 	if (cache_has_sheaves(s)) {
+		cpus_read_lock();
 		flush_rcu_sheaves_on_cache(s);
+		cpus_read_unlock();
 		rcu_barrier();
 	}
 
mm/slub.c +1 -0
@@ -4038,6 +4038,7 @@ void flush_rcu_sheaves_on_cache(struct k
 	struct slub_flush_work *sfw;
 	unsigned int cpu;
 
+	lockdep_assert_cpus_held();
 	mutex_lock(&flush_lock);
 
 	for_each_online_cpu(cpu) {
author maintainer
#120 lore raw

PATCH 120/461 RDMA/siw: Reject MPA FPDU length underflow before signed receive math

In reply to Greg Kroah-Hartman

7.0-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_queue

Add 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.
author maintainer
#121 lore raw

PATCH 121/461 s390/cio: Restore GFP_DMA for CHSC allocation

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Peter Oberparleiter <[email protected]>

commit ea34567db0a6b3a7ce78ba421592344315c8f90e upstream.

Re-add GFP_DMA when allocating memory for CHSC control blocks. On some supported machines, CHSC cannot access memory outside the DMA zone, causing CHSC command failures.

Fixes a3a64a4def8d ("s390/cio: remove unneeded DMA zone allocation")
---
 drivers/s390/cio/chsc.c     |    4 ++--
 drivers/s390/cio/chsc_sch.c |   20 ++++++++++----------
 drivers/s390/cio/scm.c      |    2 +-
 3 files changed, 13 insertions(+), 13 deletions(-)
drivers/s390/cio/chsc.c +2 -2
@@ -1142,8 +1142,8 @@ int __init chsc_init(void)
 {
 	int ret;
 
-	sei_page = (void *)get_zeroed_page(GFP_KERNEL);
-	chsc_page = (void *)get_zeroed_page(GFP_KERNEL);
+	sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	chsc_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!sei_page || !chsc_page) {
 		ret = -ENOMEM;
 		goto out_err;
drivers/s390/cio/chsc_sch.c +10 -10
@@ -292,7 +292,7 @@ static int chsc_ioctl_start(void __user
 	if (!css_general_characteristics.dynio)
 		/* It makes no sense to try. */
 		return -EOPNOTSUPP;
-	chsc_area = (void *)get_zeroed_page(GFP_KERNEL);
+	chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL);
 	if (!chsc_area)
 		return -ENOMEM;
 	request = kzalloc_obj(*request);
@@ -340,7 +340,7 @@ static int chsc_ioctl_on_close_set(void
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
-	on_close_chsc_area = (void *)get_zeroed_page(GFP_KERNEL);
+	on_close_chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL);
 	if (!on_close_chsc_area) {
 		ret = -ENOMEM;
 		goto out_free_request;
@@ -392,7 +392,7 @@ static int chsc_ioctl_start_sync(void __
 	struct chsc_sync_area *chsc_area;
 	int ret, ccode;
 
-	chsc_area = (void *)get_zeroed_page(GFP_KERNEL);
+	chsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!chsc_area)
 		return -ENOMEM;
 	if (copy_from_user(chsc_area, user_area, PAGE_SIZE)) {
@@ -438,7 +438,7 @@ static int chsc_ioctl_info_channel_path(
 		u8 data[PAGE_SIZE - 20];
 	} __attribute__ ((packed)) *scpcd_area;
 
-	scpcd_area = (void *)get_zeroed_page(GFP_KERNEL);
+	scpcd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!scpcd_area)
 		return -ENOMEM;
 	cd = kzalloc_obj(*cd);
@@ -500,7 +500,7 @@ static int chsc_ioctl_info_cu(void __use
 		u8 data[PAGE_SIZE - 20];
 	} __attribute__ ((packed)) *scucd_area;
 
-	scucd_area = (void *)get_zeroed_page(GFP_KERNEL);
+	scucd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!scucd_area)
 		return -ENOMEM;
 	cd = kzalloc_obj(*cd);
@@ -563,7 +563,7 @@ static int chsc_ioctl_info_sch_cu(void _
 		u8 data[PAGE_SIZE - 20];
 	} __attribute__ ((packed)) *sscud_area;
 
-	sscud_area = (void *)get_zeroed_page(GFP_KERNEL);
+	sscud_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!sscud_area)
 		return -ENOMEM;
 	cud = kzalloc_obj(*cud);
@@ -625,7 +625,7 @@ static int chsc_ioctl_conf_info(void __u
 		u8 data[PAGE_SIZE - 20];
 	} __attribute__ ((packed)) *sci_area;
 
-	sci_area = (void *)get_zeroed_page(GFP_KERNEL);
+	sci_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!sci_area)
 		return -ENOMEM;
 	ci = kzalloc_obj(*ci);
@@ -696,7 +696,7 @@ static int chsc_ioctl_conf_comp_list(voi
 		u32 res;
 	} __attribute__ ((packed)) *cssids_parm;
 
-	sccl_area = (void *)get_zeroed_page(GFP_KERNEL);
+	sccl_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!sccl_area)
 		return -ENOMEM;
 	ccl = kzalloc_obj(*ccl);
@@ -756,7 +756,7 @@ static int chsc_ioctl_chpd(void __user *
 	int ret;
 
 	chpd = kzalloc_obj(*chpd);
-	scpd_area = (void *)get_zeroed_page(GFP_KERNEL);
+	scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!scpd_area || !chpd) {
 		ret = -ENOMEM;
 		goto out_free;
@@ -796,7 +796,7 @@ static int chsc_ioctl_dcal(void __user *
 		u8 data[PAGE_SIZE - 36];
 	} __attribute__ ((packed)) *sdcal_area;
 
-	sdcal_area = (void *)get_zeroed_page(GFP_KERNEL);
+	sdcal_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!sdcal_area)
 		return -ENOMEM;
 	dcal = kzalloc_obj(*dcal);
drivers/s390/cio/scm.c +1 -1
@@ -229,7 +229,7 @@ int scm_update_information(void)
 	size_t num;
 	int ret;
 
-	scm_info = (void *)__get_free_page(GFP_KERNEL);
+	scm_info = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
 	if (!scm_info)
 		return -ENOMEM;
 
author maintainer
#122 lore raw

PATCH 122/461 s390/pai: Disable duplicate read of kernel PAI counter value

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Richter <[email protected]>

commit 3fe7ecab1a0856aafe1026a35af1621a5c18d53f upstream.

The PAI crypto counter design allows for user space and kernel space PAI counter increment recording. This is achieved by splitting the recording page in half. The upper part of the 4KB page records user space increments of PAI crypto counter and the lower half records kernel space increments. The page itself looks like:

lowcore ptr ---> ++++++++++++++++++++++++

                  |user space area       |
                  +----------------------+
                  |kernel space area     |
                  ++++++++++++++++++++++++

User space and kernel space entries are handled via a kernel_offset value when wrting. For PAI crypto counters this offset is 2048 or half of a page size.

For PAI NNPA counter design this distinction was not needed. There is no user and kernel space part for the page pointed to by lowcore. The set up is:

lowcore ptr ---> ++++++++++++++++++++++++

                  |user + kernel space   |
                  |area                  |
                  |                      |
                  ++++++++++++++++++++++++

There is always only one counter value recorded and saved.

Depending on number of CPUs and machine load, the number of PAI NNPA counter increment differs between counting (perf stat) and recording (perf record). The number reported by sampling was double the number shown by counting.

This was caused by a double read of the PAI NNPA values in function pai_copy(). The first part of that function reads the kernel space part. The offset into the kernel page part must be larger than zero. The second part of that function reads the user space part, which begins of offset zero. This works fine for PAI crypto counters.

It fails for PAI NNPA counters because the PMU device driver does not support that feature and has a kernel_offset value of 0x0. Executing both user and kernel space read out might end up reading user space value twice.
For the PAI NNPA PMU prohibit the kernel space part read out.

Fixes f12473541356 ("s390/pai_crypto: Rename paicrypt_copy() to pai_copy()")
---
 arch/s390/kernel/perf_pai.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/perf_pai.c +1 -1
@@ -651,7 +651,7 @@ static void pai_have_sample(struct perf_
 	rawsize = pai_copy(cpump->save, cpump->area, pp,
 			   (unsigned long *)PAI_SAVE_AREA(event),
 			   event->attr.exclude_user,
-			   event->attr.exclude_kernel);
+			   !pp->kernel_offset ? true : event->attr.exclude_kernel);
 	if (rawsize)			/* No incremented counters */
 		pai_push_sample(rawsize, cpump, event);
 }
author maintainer
#123 lore raw

PATCH 123/461 s390/pai: Fix missing PAI counter increments under heavy load

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Richter <[email protected]>

commit 99269799bf2448aebccee164df56c22a7b85b02c upstream.

Machines with a larger number of CPUs and under heavy load sometimes loose PAI counter increments during recording using events -e CRYPTO_ÂLL or -e NNPA_ALL. Counting is not affected. This happens when several PAI crypto counters are incremented during the same cryptographic operation.

During schedule out the functions

paiXXX_sched_task() (with XXX either crypt or ext)

+--> pai_have_samples()
   +--> pai_have_sample()
	+--> pai_copy()
	+--> pai_push_sample()

are called to read out PAI counter values.
In pai_copy() the current values of PAI counters are read from the PMU memory mapped page and compared to the values read during last schedule out operation, which have been saved in a backup page named PAI_SAVE_AREA(event). For each PAI counter a delta is calculated and when the delta is positive, that PAI counter was incremented by hardware. This positve delta is reported as raw data record attached to a sample.
After all deltas have been calculated, the new PAI counter values are saved in the backup page PAI_SAVE_AREA(event). However this is done in pai_push_sample(), leaving a small window for missing hardware triggered updates. Here is one scenario:

PAI counter idx: 0 1 2 3 4 5 6 7 .... N

                   +---+---+---+---+---+---+---+---+    +---+
  PAI counter page:|   |   | X |   |   |   |   |   |....| Y |
                   +---+---+---+---+---+---+---+---+    +---+

In pai_copy() each PAI counter value is read and compared to its old value. This is done in a loop. When PAI counter indexed N is read, the hardware might increment PAI counter indexed 2 again, updating its value from X to X+1.
Later pai_push_sample() simply mem-copies the complete PAI counter page to a backup page and the increment of X+1 is lost, because the backup page now contains the new value.

Read each PAI counter and save this value in the backup page when there is a positive delta. This omits any time window between read and store. This also reduced the work load as only modified PAI counters are saved.

Fixes fe861b0c8d06 ("s390/pai: save PAI counter value page in event structure")
---
 arch/s390/kernel/perf_pai.c |   29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)
arch/s390/kernel/perf_pai.c +20 -9
@@ -186,6 +186,13 @@ static u64 pai_getctr(unsigned long *pag
 	return page[nr];
 }
 
+static void pai_setctr(unsigned long *page, int nr, unsigned long offset, u64 v)
+{
+	if (offset)
+		nr += offset / sizeof(*page);
+	page[nr] = v;
+}
+
 /* Read the counter values. Return value from location in CMP. For base
  * event xxx_ALL sum up all events. Returns counter value.
  */
@@ -551,6 +558,8 @@ static void paicrypt_del(struct perf_eve
 /* Create raw data and save it in buffer. Calculate the delta for each
  * counter between this invocation and the last invocation.
  * Returns number of bytes copied.
+ * After reading from PAI counter page, save the read value to the old
+ * page to calculate PAI counter deltas.
  * Saves only entries with positive counter difference of the form
  * 2 bytes: Number of counter
  * 8 bytes: Value of counter
@@ -562,16 +571,22 @@ static size_t pai_copy(struct pai_userda
 	int i, outidx = 0;
 
 	for (i = 1; i <= pp->num_avail; i++) {
-		u64 val = 0, val_old = 0;
+		u64 val = 0, val_old = 0, val_k = 0, val_old_k = 0;
 
 		if (!exclude_kernel) {
-			val += pai_getctr(page, i, pp->kernel_offset);
-			val_old += pai_getctr(page_old, i, pp->kernel_offset);
+			val_k = pai_getctr(page, i, pp->kernel_offset);
+			val_old_k = pai_getctr(page_old, i, pp->kernel_offset);
+			if (val_k != val_old_k)
+				pai_setctr(page_old, i, pp->kernel_offset, val_k);
 		}
 		if (!exclude_user) {
-			val += pai_getctr(page, i, 0);
-			val_old += pai_getctr(page_old, i, 0);
+			val = pai_getctr(page, i, 0);
+			val_old = pai_getctr(page_old, i, 0);
+			if (val != val_old)
+				pai_setctr(page_old, i, 0, val);
 		}
+		val += val_k;
+		val_old += val_old_k;
 		if (val >= val_old)
 			val -= val_old;
 		else
@@ -602,8 +617,6 @@ static size_t pai_copy(struct pai_userda
 static int pai_push_sample(size_t rawsize, struct pai_map *cpump,
 			   struct perf_event *event)
 {
-	int idx = PAI_PMU_IDX(event);
-	struct pai_pmu *pp = &pai_pmu[idx];
 	struct perf_sample_data data;
 	struct perf_raw_record raw;
 	struct pt_regs regs;
@@ -634,8 +647,6 @@ static int pai_push_sample(size_t rawsiz
 
 	overflow = perf_event_overflow(event, &data, &regs);
 	perf_event_update_userpage(event);
-	/* Save crypto counter lowcore page after reading event data. */
-	memcpy((void *)PAI_SAVE_AREA(event), cpump->area, pp->area_size);
 	return overflow;
 }
 
author maintainer
#124 lore raw

PATCH 124/461 fwctl: pds: Validate RPC input size before parsing

In reply to Greg Kroah-Hartman

7.0-stable review patch. If anyone has any objections, please let me know.

------------------

From: Heechan Kang <[email protected]>

commit e7537735028c3ad4b0bfc02ff8fa2a1a28aa04fe upstream.

The fwctl core allocates the device-specific RPC input buffer with fwctl_rpc.in_len and passes that buffer to the driver callback.

pdsfc_fw_rpc() casts the buffer to struct fwctl_rpc_pds and then calls pdsfc_validate_rpc(), which reads fields from that structure before checking that the input buffer is large enough to contain it. A short in_len can make pds_fwctl read beyond the allocation.

Reject pds RPC buffers that are smaller than struct fwctl_rpc_pds before parsing any pds-specific fields.

---
 drivers/fwctl/pds/main.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/fwctl/pds/main.c +3 -0
@@ -362,6 +362,9 @@ static void *pdsfc_fw_rpc(struct fwctl_u
 	void *out = NULL;
 	int err;
 
+	if (in_len < sizeof(*rpc))
+		return ERR_PTR(-EINVAL);
+
 	err = pdsfc_validate_rpc(pdsfc, rpc, scope);
 	if (err)
 		return ERR_PTR(err);