Skip to contentSkip to conversation

7.2.8-rc1 review

PATCH In review Greg Kroah-Hartman 16 participants 454 messages Sep 23 – Sep 25 Stable branch Page 1 of 4

lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 7.2.8-rc1 review

This is the start of the stable review cycle for the 7.2.8 release. There are 438 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 Fri, 25 Sep 2026 14:05:46 +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.2.8-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.2.y
and the diffstat can be found below.

thanks,

greg k-h

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

Greg Kroah-Hartman <[email protected]>

    Linux 7.2.8-rc1

Namjae Jeon <[email protected]>
ksmbd: fix partial normalized name responses

Mario Limonciello <[email protected]>
drm/amdgpu: restrict BAR0 fallback read to SR-IOV VFs only

Vadim Nikitushkin <[email protected]>
drm/ttm: fix swapped-out resources never leaving their bulk_move range

Iván Ezequiel Rodriguez <[email protected]>
ntsync: reject wait ioctls with zero owner

Mario Limonciello <[email protected]>
drm/amdgpu: Fix GPU PCIe link capability reporting

chong li <[email protected]>
drm/amdgpu: reduce early full GPU access during SR-IOV init

Arun Easi <[email protected]>
scsi: fnic: Fix missed link-up when critical IRQ targets offline CPU

Karan Tilak Kumar <[email protected]>
scsi: fnic: Bump up version number

Karan Tilak Kumar <[email protected]>
scsi: fnic: Make debug logging protocol independent

Qi Zheng <[email protected]>
fs: fix missed removal of super_fs_objects_eligible()

Usama Arif <[email protected]>
fs/super: skip non-memcg-aware nr_cached_objects in memcg slab shrink

Frank Sorenson <[email protected]>
smb: client: fix missing iov bounds check in parse_posix_sids()

Frank Sorenson <[email protected]>
smb: client: fix missing lower-bound check on DFS referral string offsets

Frank Sorenson <[email protected]>

    smb: client: fix server->total_read for compound encrypted PDUs

Frank Sorenson <[email protected]>
smb: client: fix reparse buffer bounds in cifs_query_reparse_point()

Frank Sorenson <[email protected]>
smb: client: fix potential OOB read in smb3_enum_snapshots()

Frank Sorenson <[email protected]>
smb: client: fix OOB struct field reads in move_smb2_ea_to_cifs()

Frank Sorenson <[email protected]>
smb: client: fix next_buffer UAF and NextCommand bounds in compound PDUs

Paulo Alcantara <[email protected]>
smb: client: fix fattr leaking on wsl_to_fattr() failure

Paulo Alcantara <[email protected]>
smb: client: fix unaligned access in WSL reparse point parser

Paulo Alcantara <[email protected]>
smb: client: fix smbd_connection leak on cifs_get_tcp_session() error

Frank Sorenson <[email protected]>
smb: client: reject short Next offsets in parse_server_interfaces()

Joseph Qi <[email protected]>
smb: client: fix use-after-free of iface in cifs_try_adding_channels()

Paulo Alcantara <[email protected]>
smb: client: fix rlist race and missing initialization

April Cardenas <[email protected]>
smb/client: send lease break ACKs thru correct session for multiuser mounts

Paulo Alcantara <[email protected]>
smb: client: cancel reconnect work in clean_demultiplex_info()

Vladimir Marioukhine <[email protected]>
drm/amdkfd: implement restore_mqd callbacks for GFX12/12.1

David Francis <[email protected]>
drm/amdkfd: Avoid integer underflow with ffs in EOP ring size calc

David Francis <[email protected]>
drm/amdkfd: Avoid integer underflow in EOP ring size calculation.

Mario Limonciello <[email protected]>
drm/amdgpu: Skip KFD mapping clear before initialization

Mike Lothian <[email protected]>
drm/amdgpu: hold a runtime PM reference for P2P dma-buf attachments

Chengjun Yao <[email protected]>
drm/amdgpu: fix rmmio iounmap skipped on device removal

Tvrtko Ursulin <[email protected]>
drm/sched: Fix virtual runtime race

Jonghyuk Kim(MalHyuk) <[email protected]>
drm/msm: RCU-free the scheduler-containing ring and VM objects

Guangshuo Li <[email protected]>
drm/msm/hdmi_phy: fix runtime PM cleanup on probe failure

Saim Shujah <[email protected]>
drm/msm/dpu: clear pending peripheral flush state

Guangshuo Li <[email protected]>
drm/msm/adreno: fix autosuspend cleanup during teardown

Sophie D <[email protected]>
drm/gud: Ignore damage clips in full update mode

Sajal Gupta <[email protected]>
drm/gud: fix out-of-bounds write in gud_plane_atomic_check()

Devin Wittmayer <[email protected]>
wifi: mac80211: refuse to make a monitor active when it has no queue

Ivan Pustogarov <[email protected]>
wifi: mac80211: avoid out-of-bounds read for empty PREQ elements

Rik van Riel <[email protected]>
wifi: mac80211: avoid WARN in set_bitrate_mask when sdata not in driver

Zhao Li <[email protected]>
wifi: mwifiex: validate action frame fixed fields

Linmao Li <[email protected]>
wifi: mwifiex: prevent authentication frame length truncation

Pengpeng Hou <[email protected]>
wifi: mwifiex: validate scan response extents

Doruk Tan Ozturk <[email protected]>
wifi: mwifiex: bound the pairwise-cipher OUI walk to the IE length

Shengzhuo Wei <[email protected]>
wifi: p54: require a full exp_if record in PDR_INTERFACE_LIST

Shengzhuo Wei <[email protected]>
wifi: p54: validate curve data length in the calibration curve converters

Tianchu Chen <[email protected]>
wifi: wilc1000: fix RX buffer OOB-write in wilc_wlan_handle_isr_ext()

Ali Ahmet Memis <[email protected]>
wifi: wilc1000: fix out-of-bounds read in P2P public action frames

Runyu Xiao <[email protected]>
wifi: wlcore: release runtime PM ref on regdomain config failure

Fan Wu <[email protected]>
wifi: wcn36xx: Fix potential use-after-free in TX ack timer teardown

Tianchu Chen <[email protected]>
wifi: rsi: fix heap OOB write on key removal

Daehyeon Ko <[email protected]>
wifi: libipw: reject TKIP frames without a full MIC

Jiangshan Yi <[email protected]>
wifi: libertas_tf: fix UAF in lbtf_free_adapter()

Stanislaw Gruszka <[email protected]>
wifi: iwlegacy: fix broadcast stations deallocation

Jiangshan Yi <[email protected]>
wifi: brcmsmac: fix UAF in brcms_free_timer()

Wentao Liang <[email protected]>
watchdog: starfive-wdt: Fix runtime PM leak in starfive_wdt_pm_start()

Wentao Liang <[email protected]>
watchdog: sp5100_tco: Fix pci_dev reference leak in sp5100_tco_init()

Tzung-Bi Shih <[email protected]>
watchdog: rzv2h: Avoid division by zero

Tzung-Bi Shih <[email protected]>
watchdog: rtd119x: Avoid division by zero

Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Propagate error code in resume()

Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Fix premature reset during timeout update

Tzung-Bi Shih <[email protected]>
watchdog: digicolor: Avoid division by zero

Li Jun <[email protected]>
watchdog: da9063: fix suspend/resume handling of HW_RUNNING watchdog

Thomas Richard (congatec GmbH) <[email protected]>
hwmon: (cgbc-hwmon) Add missing sensors

Thomas Richard (congatec GmbH) <[email protected]>
hwmon: (cgbc-hwmon) Fix current sensors ID lookup

Guangshuo Li <[email protected]>
hwmon: (w83793) release probe data through kref

Guangshuo Li <[email protected]>
hwmon: (w83791d) remove fan/pwm 4-5 sysfs group on remove

Yibo Tan <[email protected]>
hwmon: (pwm-fan) Stop RPM timer before freeing tach data

Sanman Pradhan <[email protected]>

    hwmon: (pmbus/tps53679) Select page 0 for single-page TPS53676

Sanman Pradhan <[email protected]>
hwmon: (pmbus/tps53679) Fix TPS53676 phase page decoding

Nuno Sá <[email protected]>
hwmon: (pmbus/core) increase number of phases and add new mask

Muhammad Bilal <[email protected]>
hwmon: (hp-wmi-sensors) Fix use-after-free in fungible_show()

Iván Ezequiel Rodriguez <[email protected]>
Input: zero ff_effect before compat copy in input_ff_effect_from_user

Dmitry Torokhov <[email protected]>
Input: synaptics-rmi4 - fix GPF in suspend and resume when unbound

Raphaël Larocque <[email protected]>
Input: synaptics - disable InterTouch on ThinkPad T440p (board id 2722)

Hans de Goede <[email protected]>

    Input: soc_button_array - check btns_desc->package.count

Hans de Goede <[email protected]>
Input: soc_button_array - fix MS Surface Pro 11 probe failure

Dmitry Torokhov <[email protected]>
Input: rmi_smbus - fix out-of-bounds read in rmi_smb_write_block()

Chris Sommers <[email protected]>
Input: i8042 - add quirk for Acer Aspire Go 15 AG15-42P

Runyu Xiao <[email protected]>
Input: hp_sdc - shut down kicker timer on module exit

Iván Ezequiel Rodriguez <[email protected]>
Input: evdev - zero absinfo before partial copy in EVIOCSABS

Linkai Gong <[email protected]>
Input: cyttsp5 - clamp the HID report size before memcpy

Alexei Turtanov <[email protected]>
Input: atkbd - skip deactivate for Xiaomi Redmi Book Pro 16 2026

Alvin Šipraga <[email protected]>
Input: adp5588-keys - cache GPIO state before registering the gpiochip

Diogo Ivo (Schneider Electric) <[email protected]>
mmc: sdhci_am654: Fallback to DT-provided itap delay on DDR50 tuning failure

Diogo Ivo (Schneider Electric) <[email protected]>
mmc: sdhci_am654: Clear ITAPDLY on tuning failure

Diogo Ivo (Schneider Electric) <[email protected]>
mmc: sdhci_am654: Reset command and data lines on failed tuning

Diogo Ivo (Schneider Electric) <[email protected]>
mmc: sdhci_am654: Move tuning_loop to local variable

Xu Rao <[email protected]>
mmc: spi: reset bytes_xfered before retrying CRC failures

Runyu Xiao <[email protected]>
mmc: sh_mmcif: initialize IRQ-thread mutex before requesting interrupt

Felix Gu <[email protected]>
mmc: sdio_uart: fix xmit_fifo leak when the port table is full

Myeonghun Pak <[email protected]>
mmc: sdhci-of-aspeed: Remove children before releasing SDC resources

Florian Maillard <[email protected]>
mmc: rtsx_pci_sdmmc: ignore broken write-protect on ThinkPad X260

Fan Wu <[email protected]>
mmc: mxcmmc: cancel data work and watchdog on remove

Fan Wu <[email protected]>
mmc: mmci: Fix use-after-free in busy-timeout work

Fan Wu <[email protected]>
mmc: hsq: Fix use-after-free in retry work

Zhu Ling <[email protected]>
mmc: core: Fix OF node reference leak on card add failure

Fan Wu <[email protected]>
mmc: core: Cancel SDIO IRQ work before freeing host

Bartosz Golaszewski <[email protected]>
power: sequencing: fix NULL-pointer dereference in pwrseq_device_register()

Bartosz Golaszewski <[email protected]>
power: sequencing: fix NULL-pointer dereference in pwrseq_unit_new()

Bartosz Golaszewski <[email protected]>
power: sequencing: don't call .post_enable() if pwrseq_unit_enable() failed

Christian Göttsche <[email protected]>
selinux: always fill AVC decision in avc_has_perm_noaudit()

Karl Mehltretter <[email protected]>
selinux: recheck intermediate backing files on mprotect()

Karl Mehltretter <[email protected]>
selinux: preserve user SID across nested backing files

Shuhei Takeshita <[email protected]>
IB/hfi1: Fix the PIO_CRED credit-return mmap

Shuhei Takeshita <[email protected]>
IB/hfi1: Resolve the credit-return buffer through the send context's node

Shuangpeng Bai <[email protected]>
IB/mlx4: Fix use-after-free on pkey sysfs registration failure

Guangshuo Li <[email protected]>
i2c: imx: disable autosuspend on remove

Shengzhuo Wei <[email protected]>
i2c: imx: release DMA channels on probe error

Liu Zhenlong <[email protected]>
i2c: qcom-cci: fix device_node refcount leak in cci_probe()/cci_remove()

Linkai Gong <[email protected]>
i2c: atr: fix dangling adapter pointer on add failure

Shengzhuo Wei <[email protected]>
i2c: at91: release DMA channels on remove and probe error

fangqiurong <[email protected]>
sched_ext: Close the pre-enable ops error claim window

Wanwu Li <[email protected]>
sched_ext: Fix NULL sched deref in kfunc sub-sched error paths

Jarkko Sakkinen <[email protected]>
KEYS: trusted: Fix tpm2_load_cmd() boundary check

Maoyi Xie <[email protected]>
keys: translate request_key_auth pid for the reading procfs instance

Cen Zhang <[email protected]>
KEYS: encrypted: fix integer overflow of datablob_len

Wenjie Qi <[email protected]>
mm: filemap: retain mapped dropbehind folios

Lorenzo Stoakes (ARM) <[email protected]>
mm/vma: correctly unaccount on mmap_prepare() failure

Jiayuan Chen <[email protected]>
mm/shrinker: fix bogus set_shrinker_bit() with cgroup.memory=nokmem

Lorenzo Stoakes (ARM) <[email protected]>

    mm/mremap: account mm->locked_vm correctly for MREMAP_DONTUNMAP

Shakeel Butt <[email protected]>
mm/mlock: use the IRQ-safe accessor for NR_MLOCK in __munlock_folio()

Lorenzo Stoakes (ARM) <[email protected]>
mm/huge_memory: bypass THP tuneables for huge pfnmap mappings

Nhat Pham <[email protected]>
mm, swap: fix SWAP_USAGE_OFFLIST_BIT collision with real usage count

Yifei Gao <[email protected]>
memstick: ms_block: destroy io_queue workqueue on removal

Shakeel Butt <[email protected]>
memcg: avoid charging the root memcg from obj_cgroup_charge_pages()

Théo Lebrun <[email protected]>
mips: select CONFIG_WEAK_REORDERING_BEYOND_LLSC from CONFIG_EYEQ

Alexey Klimov <[email protected]>
soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node

Zhiling Zou <[email protected]>
xfrm: save input state data before secpath resets

Siwei Zhang <[email protected]>
xfrm: use hlist_del_init_rcu for state_cache and state_cache_input

Chengfeng Ye <[email protected]>
xfrm: serialize state GC with device state flush

Alberto Carboneri <[email protected]>
scsi: core: Validate MODE SENSE lengths in scsi_cdl_enable()

Mark Amirkan <[email protected]>
net/packet: avoid truncating TPACKET_V3 private size

Mark Amirkan <[email protected]>
net/packet: clear RX owner on VNET header error

Jamal Hadi Salim <[email protected]>
net/sched: hhf: cap hh_flows_limit at change time

Xuanqiang Luo <[email protected]>
net/sched: act_api: release tail references on DELACTION failure

Guanglei Zhu <[email protected]>
net: wwan: mhi_wwan_mbim: check skb_copy_bits() return value

Guanglei Zhu <[email protected]>
net: wwan: mhi_wwan_mbim: guard against a cyclic NDP chain

Guanglei Zhu <[email protected]>
net: wwan: t7xx: validate the netif index in t7xx_ccmni_recv_skb()

Ahmed Naseef <[email protected]>
net: phy: mediatek: do not report link and per-speed LED rules together

Mark Amirkan <[email protected]>
net: lan743x: fix RX checksum use-after-free

Gris Ge <[email protected]>
net: ip_tunnel: initialize options_len before referencing options

Zhiling Zou <[email protected]>
ipv6: xfrm: use full sockets in local error paths

David Hu <[email protected]>
dma-buf: Split sgl by largest page-aligned chunk

David Hu <[email protected]>
dma-buf: Fix silent overflow for phys vec to sgt

Christian König <[email protected]>
dma-buf/dma-fence: fix checking signaling bit for timeline and driver name v3

Alexander Chesnokov <[email protected]>
dmaengine: ti: k3-udma-glue: fix NULL dereference in k3_udma_glue_release_rx_chn()

Christian Lugnberg <[email protected]>
dmaengine: sun6i: fix undefined behaviour in sun6i_dma_tx_status

Christian Lugnberg <[email protected]>
dmaengine: sun6i: fix non-atomic read of DMA position registers

Abdurrahman Hussain <[email protected]>
gpiolib: of: don't mark hog nodes OF_POPULATED before a chip is found

Michail Tatas <[email protected]>
gpiolib: Put fwnode reference on failure

Guanghui Yang <[email protected]>
btrfs: clear free space tree creation state on rebuild failure

Anand Jain <[email protected]>
btrfs: derive f_fsid with dev_t only when temp_fsid is active

Filipe Manana <[email protected]>
btrfs: fix creation of compressed inline extents that don't save space

Hongling Zeng <[email protected]>
btrfs: take commit root semaphore when iterating in mark_block_group_to_copy()

Radek Podgorny <[email protected]>
Bluetooth: keep dst_type with dst when reusing an LE connection

Chengfeng Ye <[email protected]>
Bluetooth: hci_sync: Serialize local codec list cleanup

Laxman Acharya Padhya <[email protected]>
Bluetooth: hci_codec: validate vendor codec count length

Aamir Ahmed <[email protected]>
Bluetooth: eir: validate service data length before reading UUID

Nicolas Thibert <[email protected]>
Bluetooth: btusb: fix NXP IW610 composite device handling

Mark Rutland <[email protected]>
arm64: percpu: Fix LSE operations on {8,16}-bit types

Mark Rutland <[email protected]>
arm64: percpu: Fix this_cpu_and() mask generation

Mark Rutland <[email protected]>
arm64: percpu: Fix this_cpu_write() casting

Dinh Nguyen <[email protected]>
arm64: dts: socfpga: change access permission from 755 to 644

Koichiro Den <[email protected]>
arm64: dts: renesas: r8a779f0: Set UFS lane count

Bradley Morgan <[email protected]>
arm64: hibernate: pass HVC_SET_VECTORS args to the resume hvc

Thomas Huth <[email protected]>
kselftest/arm64: Fix size of thread_data values for pthread_join()

Wyatt Feng <[email protected]>
net: xfrm: reject unrepresentable espintcp transport headers

Jeff Layton <[email protected]>
nfsd: fix handling of NFSEXP_PNFS in the netlink codepath

Zhiling Zou <[email protected]>
openvswitch: avoid reallocating confirmed conntrack labels

Jeffin Philip <[email protected]>
RDMA/core: fix refcount bug in iwpm_get_nlmsg_request()

Quanye Yang <[email protected]>
RDMA/ucma: Serialize join and leave on copy_to_user failure

Hao-Qun Huang <[email protected]>
spi: virtio: Use the per-transfer bits per word

Itai Handler <[email protected]>
spi: spi-zynqmp-gqspi: stop the controller on shutdown

Frieder Schrempf <[email protected]>
spi: fsl-qspi: Reprogram the clock rate when the operation frequency changes

Ian Luites <[email protected]>
soundwire: dmi-quirks: Disable ghost Realtek on Asus GX651AX

Donggeun Yoo <[email protected]>
swiotlb: use the adjusted address for the highmem page lookup

Inbal Schussheim <[email protected]>
tcp: exclude old ACKs from tcp fast path

Chang S. Bae <[email protected]>
x86/microcode/intel: Reject problematic loading on Granite Rapids systems

Chang S. Bae <[email protected]>
x86/build/64: Prevent native builds from generating EGPR use

Lyude Paul <[email protected]>
drm/nouveau/gsp/r570: Enable S/R Display workaround in GSP

Lyude Paul <[email protected]>
drm/nouveau/gsp/r570: Set GcOff = 0 in fbsr

Lyude Paul <[email protected]>
drm/nouveau/gsp: Increase delay for magic sleep in r535_gsp_fini()

Lyude Paul <[email protected]>
Revert "nouveau/gsp: fix suspend/resume regression on r570 firmware"

Chunfeng Song <[email protected]>
rust: net: phy: fix off-by-one bit positions in device status accessors

Thomas Gleixner <[email protected]>
signal: Prevent exec() race

Aohan Mei <[email protected]>
rds: ib: use rds_conn_drop() on protocol version mismatch

Thomas Gleixner <[email protected]>
posix-cpu-timers: Prevent freeing a timer which is queued on the expiry list

Claudiu Beznea <[email protected]>
phy: renesas: rcar-gen3-usb2: Avoid long delay in atomic context

Richard Zhu <[email protected]>
PCI: imx6: Move clock enable after core reset assertion

Seunguk Shin <[email protected]>
fs/dax: check zero or empty entry before converting xarray entry

Hyunwoo Kim <[email protected]>
exec: Cleanup POSIX timers right after de_thread()

Wentao Liang <[email protected]>
cifs: Fix server use-after-free in cifs_chan_skip_or_disable()

Wentao Liang <[email protected]>
ata: libahci_platform: Fix device reference leak in ahci_platform_get_resources()

Niklas Cassel <[email protected]>
ata: libahci: clear PxCLBU and PxFBU for AHCI_HFLAG_32BIT_ONLY

Michal Koutný <[email protected]>
cgroup: Avoid iteration of dying tasks with zero refcount

Jiangshan Yi <[email protected]>

    ASoC: codecs: rt712-sdca-dmic: fix uninitialized stream_config->type

Yuho Choi <[email protected]>
ALSA: virtio: reset device before deleting virtqueues

Xiang Mei <[email protected]>
ALSA: usb-audio: Clamp implicit feedback packet count to URB capacity

Takashi Iwai <[email protected]>
ALSA: core: Fix potential UAF after asynchronous card release

David Howells <[email protected]>
9p: Fix v9fs_issue_write() to update i_size and remote_i_size

Jeremy Nyberg <[email protected]>
Input: xpad - fix PDP Marvel Xbox 360 controller

Roberts Kursitis <[email protected]>
Input: xpad - add support for Azeron devices

Erich Sartison <[email protected]>
Input: xpad - add support for Victrix Pro BFG Controller

Li Jun <[email protected]>
watchdog: da9062: fix suspend/resume handling of HW_RUNNING watchdog

James Seo <[email protected]>
hwmon: (hp-wmi-sensors) Improve raw WMI string handling

Cong Nguyen <[email protected]>
hwmon: (gpio-fan) return IRQ_HANDLED from the shared alarm IRQ handler

hpp.iscas <[email protected]>
Input: eeti_ts - publish the OF module alias

Matthew Schwartz <[email protected]>
x86/fred: Reconstruct the #GP context for rejected INT instructions

Andrea Righi <[email protected]>
sched/core: Avoid false migration warning for proxy donors

Vinay Belgaumkar <[email protected]>
perf: Fix null pointer access in is_include_guest_event()

Filipe Manana <[email protected]>
btrfs: check if there is space for chunk item when validating sys chunk array

Filipe Manana <[email protected]>
btrfs: abort transaction on failure to update inode for hole punching and reflinking

Francis Marlou Pacaro <[email protected]>
drm/amd/display: fix MALL hysteresis timer underflow at high refresh rates

Dmitriy Chumachenko <[email protected]>
drm/amdgpu: check ras and obj before dereference

Eric Dumazet <[email protected]>
net: skbuff: do not leave stale header offsets after pskb_carve()

Dmitriy Okunev <[email protected]>
net: mvpp2: prevent buffer overflow in page_pool allocation

James Clark <[email protected]>
net: macb: fix ordering around PTP timestamp read

Jinke Han <[email protected]>
x86/kprobes: Fix crash when probing CS CALL instructions

Daniel Zahka <[email protected]>

    net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()

Lorenzo Bianconi <[email protected]>
net: stmmac: preserve real_num_tx_queues on mqprio setup failure

Eric Dumazet <[email protected]>
net: prevent torn reads in netdev_tc_txq

Lorenzo Bianconi <[email protected]>
net: stmmac: propagate FPE preemption-class mapping errors

Linus Walleij <[email protected]>
net: ethernet: cortina: Ack RX overrun interrupt correctly

Eric Dumazet <[email protected]>
net: lock the socket in sock_gettstamp()

Jakub Kicinski <[email protected]>
eth: fbnic: ring the doorbell if a burst ends in a drop

Yige Jiang <[email protected]>
net: netsec: fix device_node reference leak on phy_np

Farhad Alemi <[email protected]>
net: remove WARN_ON_ONCE() from the dev_fill_forward_path() loop check

Lorenzo Bianconi <[email protected]>
net: pass net_device_path_ctx to dev_fill_forward_path()

Pablo Neira Ayuso <[email protected]>
net: pass dst via net_device_path in dev_fill_forward_path()

Pablo Neira Ayuso <[email protected]>
net: do not advance stack index from dev_fwd_path()

Jamal Hadi Salim <[email protected]>
net/sched: codel: bound the dropping loop per dequeue call

Vijendar Mukunda <[email protected]>
ASoC: amd: acp: fix ffs() operator precedence for SoundWire link ID

Vijendar Mukunda <[email protected]>
ASoC: amd: acp: refactor codec config count in SOF SoundWire machine driver

Kuninori Morimoto <[email protected]>
ASoC: sdw_utils: tidyup asoc_sdw_parse_sdw_endpoints()

Kuninori Morimoto <[email protected]>
ASoC: sdw_utils: tidyup .count_sidecar

Vijendar Mukunda <[email protected]>
ASoC: amd: acp: bounds-check SoundWire link ID in machine drivers

Richard Fitzgerald <[email protected]>
ASoC: cs-amp-lib: Prevent NULL pointer if efi variable is zero length

HyeongJun An <[email protected]>
ASoC: hdmi-codec: Report a change when the channel status moves

Sasha Levin <[email protected]>
ASoC: ux500: Parenthesize MSP_{RX,TX}_CLKPOL_BIT() arguments

Daniel Linjama <[email protected]>
btrfs: handle lack of space when cleaning up verity items

Raag Jadav <[email protected]>
drm/xe/i2c: Disable IRQ on unbind

Peter Zijlstra <[email protected]>
futex: Also allocate private hash on vfork()

Nemesa Garg <[email protected]>
Revert "drm/i915/display: Clear SEL_FETCH_PLANE_CTL on plane disable"

Shivaprasad G Bhat <[email protected]>
powerpc/iommu: Fix the overflow validation in iommu_tce_check_ioba

Amit Machhiwal <[email protected]>
KVM: PPC: Book3S HV: fix secure device page leak on uv_page_in() failure

Amit Machhiwal <[email protected]>
KVM: PPC: Book3S HV: fix use-after-free in kvmhv_emulate_tlbie_all_lpid()

Eric Dumazet <[email protected]>

    netlink: do not free nlk->groups while lockless readers can use it

Nikolay Aleksandrov <[email protected]>
net: bridge: vlan: fix bugs caused by switchdev deletion errors

Lorenzo Bianconi <[email protected]>
net: stmmac: do not overwrite phc_index when no PTP clock is registered

Eric Dumazet <[email protected]>
drop_monitor: fix out-of-bounds write in reset_per_cpu_data()

Eric Dumazet <[email protected]>
drop_monitor: use raw_cpu_ptr() in tracepoint probes

Eric Dumazet <[email protected]>
drop_monitor: use timer_shutdown_sync() to prevent timer rearming during teardown

Eric Dumazet <[email protected]>
drop_monitor: synchronize tracepoint unregistration on error path

Eric Dumazet <[email protected]>
pppoatm: ensure a writable skb header and linear data

Lorenzo Bianconi <[email protected]>
net: stmmac: fix TSO header length truncation

Kuniyuki Iwashima <[email protected]>
af_unix: Unify scc_index when finalising SCC in __unix_walk_scc().

Juan Perdomo <[email protected]>
Bluetooth: RFCOMM: avoid socket lock inversion in listener cleanup

Sai Teja Aluvala <[email protected]>
Bluetooth: btintel_pcie: fix off-by-one bounds check in RX submit

Tzung-Bi Shih <[email protected]>
Bluetooth: btmtksdio: Fix PM runtime reference leak in shutdown

Chris Lu <[email protected]>
Bluetooth: btmtksdio, btmtkuart: validate WMT event length before struct access

Chris Lu <[email protected]>
Bluetooth: btmtk: fix wrong status for short WMT FUNC_CTRL events

Luiz Augusto von Dentz <[email protected]>
Bluetooth: ISO: set BT_LISTEN before requesting a BIG sync

Luiz Augusto von Dentz <[email protected]>
Bluetooth: ISO: Fix parent socket leak in iso_conn_ready()

Ibrahim Abdelkader <[email protected]>
Bluetooth: hci_qca: Do not write to the serial port after it is closed

Radek Podgorny <[email protected]>
Bluetooth: put the peer's on-air address on air when we cannot resolve

Weiming Shi <[email protected]>
Bluetooth: coredump: Quiesce dump work on unregister

Chandrashekar Devegowda <[email protected]>
Bluetooth: btintel_pcie: validate TX skb length in send_sync

ThangNN99 <[email protected]>
Bluetooth: hci_core: Fix queuing tx_work after workqueue is drained

Baineng Shou <[email protected]>
dmaengine: mmp_pdma: fix wrong sg length in mmp_pdma_prep_slave_sg()

Namjae Jeon <[email protected]>
ksmbd: keep compound responses on query info errors

Namjae Jeon <[email protected]>
ksmbd: fix partial file information responses

Namjae Jeon <[email protected]>
ksmbd: return buffer overflow for partial filesystem info

Eric Dumazet <[email protected]>
tcp: do not let tcp_rmem be set below 4096

Kuniyuki Iwashima <[email protected]>
tcp: Don't call skb_clone_and_charge_r() for close()d listener in tcp_v6_do_rcv().

Nikolay Aleksandrov <[email protected]>
net: bridge: mst: move switchdev call outside rcu

Karl Mehltretter <[email protected]>
wifi: brcmfmac: fix lost 802.1x TX completion wakeup

Hohyun Sim <[email protected]>
net: fddi: skfp: fix NULL deref when setting the MAC address while down

Dong Chenchen <[email protected]>
ipv4: icmp: reject RTN_UNREACHABLE input routes in icmp_route_lookup

Kuniyuki Iwashima <[email protected]>
sysctl: Check range in proc_dointvec_ms_jiffies_minmax

Nicolai Buchwitz <[email protected]>
net: bcmgenet: restore the hardware filters on open

Daniel Golle <[email protected]>
net: dsa: mxl862xx: disable the stats poll on teardown

Andrea Mayer <[email protected]>
seg6: set IPSKB_L3SLAVE from IP6SKB_L3SLAVE on IPIP decapsulation

Dmitry Baryshkov <[email protected]>
drm/msm/dsi: round the byte clock rate after reparenting to the PHY PLL

Filipe Manana <[email protected]>
btrfs: tree-checker: print dev extent offset in error message

Nicolas Escande <[email protected]>
wifi: ath11k: cleanup arsta in ath11k_mac_peer_cleanup_all()

Slavin Liu <[email protected]>
ALSA: hda: trace PCM open only after assigning a stream

Karl Mehltretter <[email protected]>
drm/vc4: Use managed KMS polling to fix UAF on unbind

Shuicheng Lin <[email protected]>
drm/xe/shrinker: Take a runtime PM ref before shrinking non-system memory

Shuicheng Lin <[email protected]>
drm/xe/shrinker: Return the freed page count through a parameter

Shuicheng Lin <[email protected]>
drm/xe/mmio_gem: Revoke drm_vma_node on xe_mmio_gem destroy

Ilia Levi <[email protected]>
drm/xe/mmio_gem: use write-back mapping for dummy page

Ilia Levi <[email protected]>
drm/xe/mmio_gem: forbid VMA split

Zihan Xi <[email protected]>
wifi: virt_wifi: don't transfer operstate before register

Namjae Jeon <[email protected]>
ksmbd: follow SMB2 session expiration semantics

Namjae Jeon <[email protected]>
ksmbd: extend procfs server statistics

Namjae Jeon <[email protected]>
ksmbd: fix malformed procfs status output

Xiang Mei <[email protected]>
ALSA: 6fire: fix OOB write from device-reported iso length

Takashi Iwai <[email protected]>
ALSA: usb: 6fire: Avoid embedded URBs

Runyu Xiao <[email protected]>
gpio: virtuser: skip free_irq when no IRQ is installed

Ulises Mendez Martinez <[email protected]>
objtool: Validate disassembler headers in libopcodes probe

Karl Mehltretter <[email protected]>
Input: trackpoint - fix the inertia attribute name in the ABI document

Gabor Juhos <[email protected]>
spi: spi-qpic-snand: avoid writing QPIC_EBI2_ECC_BUF_CFG register

Richard Fitzgerald <[email protected]>
ASoC: soc-pcm: Apply snd_soc_dai_link_ch_map.codec_ch_mask to codec params

Richard Fitzgerald <[email protected]>
ASoC: Add codec_ch_mask to snd_soc_dai_link_ch_map

Richard Fitzgerald <[email protected]>
ASoC: Rename snd_soc_dai_link_ch_map.ch_mask to cpu_ch_mask

William Bright <[email protected]>
drm/msm/dp: fix link bandwidth check when wide bus is enabled

Jesse Casco <[email protected]>
drm/msm/dp: skip PUSH_IDLE when the link was never enabled

Nguyen Ngoc Thang <[email protected]>

    ALSA: pcm: set timer->private_data before registering the PCM timer

AngeloGioacchino Del Regno <[email protected]>
phy: mediatek: phy-mtk-hdmi-mt8195: Fix TMDS clk bit ratio setting

AngeloGioacchino Del Regno <[email protected]>
phy: mediatek: phy-mtk-hdmi-mt8195: Fix PLL calc divisor overflow

Namjae Jeon <[email protected]>
ntfs: ignore interrupted inode reads as corruption

Namjae Jeon <[email protected]>
ntfs: propagate folio errors

Namjae Jeon <[email protected]>
ntfs: protect runlist updates with the runlist lock

Namjae Jeon <[email protected]>
ntfs: account for MFT records added during allocation

Namjae Jeon <[email protected]>
ntfs: repack $MFT/$ATTRIBUTE LIST

Namjae Jeon <[email protected]>
ntfs: use dynamic MFT tail reservation

Takashi Iwai <[email protected]>
ALSA: bcd2000: Fix race between rawmidi and disconnect

Kuniyuki Iwashima <[email protected]>
neighbour: Skip default parms when resumed in neightbl_dump_info().

Kuniyuki Iwashima <[email protected]>
neighbour: Don't render blackhole_netdev via RTM_GETNEIGHTBL.

Kuniyuki Iwashima <[email protected]>
neighbour: Enforce min/max to NDTPA_INTERVAL_PROBE_TIME_MS.

Kuniyuki Iwashima <[email protected]>
neighbour: Add missing RCU annotation for neightbl_dump_info().

Karl Mehltretter <[email protected]>
keys: fix lost wakeup when reaping a dead key type

Jérémy Jean <[email protected]>
smb: client: validate absolute native symlink targets before NT fixups

Thadeu Lima de Souza Cascardo <[email protected]>
drm: Fix drm_pending_vblank_event leak in error path for out_fence_ptr

Catalin Marinas <[email protected]>
arm64: mte: Fix PTRACE_{PEEK,POKE}MTETAGS error documentation

Breno Leitao <[email protected]>
arm64: hibernate: clone only the linear map that exists at runtime

Shouping Wang <[email protected]>
perf/arm-cmn: Fix wp_dev_sel2 setting for multi-DTM configurations

Pablo Neira Ayuso <[email protected]>
netfilter: flowtable: hold reference on ct until flow is released

Pablo Neira Ayuso <[email protected]>
netfilter: nf_nat: unregister and release hooks on error

Fernando Fernandez Mancera <[email protected]>
netfilter: nf_tables: fix device name and prefix match in hook lookup

Theodor Arsenij Larionov Trichkine <[email protected]>
netfilter: nft_nat: fully initialise new_addr in netmap setup

Karl Mehltretter <[email protected]>
dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels

Karl Mehltretter <[email protected]>
drm/msm/adreno: Fix the skip_gpu parameter description

Karl Mehltretter <[email protected]>
drm/msm: Fix the separate_gpu_kms parameter description

David Laight <[email protected]>

    x86/div64: Fix addition of large constants in mul_u64_add_u64_div_u64()

Jérémy Jean <[email protected]>
RDMA/siw: Bound fragmented header copies by the remaining length

Leon Romanovsky <[email protected]>
RDMA/efa: Keep EQ resources alive while IRQ is registered

Leon Romanovsky <[email protected]>
RDMA/efa: Keep admin queues alive while IRQ is registered

Alex Bereza <[email protected]>
dmaengine: xilinx_dma: Fix hardware buffer descriptor chain after cyclic DMA

Sascha Hauer <[email protected]>
dmaengine: pxa: fix double counting of the hw descriptors

Alex Bereza <[email protected]>
dmaengine: xilinx_dma: Fix hardware buffer descriptor reuse order

Karl Mehltretter <[email protected]>
scsi: qla2xxx: Fix the ql2xfc2target parameter description

Karl Mehltretter <[email protected]>

    scsi: pm80xx: Fix the use_msix, use_tasklet and read_wwn parameter descriptions

Meijing Zhao <[email protected]>
mm: memblock: show all region flags in debugfs

Johannes Berg <[email protected]>
wifi: mac80211: set up the TX info early to fix failure paths

Johannes Berg <[email protected]>
wifi: mac80211: mesh: release the channel if start fails

Johannes Berg <[email protected]>
wifi: mac80211: mesh: reset the CSA state when leaving

Johannes Berg <[email protected]>
wifi: mac80211: add HE 6 GHz capability in the scan elems len

Johannes Berg <[email protected]>
wifi: mac80211: don't access the TSF of a down interface

Johannes Berg <[email protected]>
wifi: mac80211: don't RCU-dereference the mesh CSA settings we just set

Johannes Berg <[email protected]>
wifi: mac80211: don't allow link changes when iface is down

Johannes Berg <[email protected]>
wifi: mac80211: require a peer station for TDLS setup confirm

Johannes Berg <[email protected]>
wifi: mac80211: reset the AP_VLAN tailroom counter on ifdown

Johannes Berg <[email protected]>
wifi: mac80211: don't allow injecting frames wider than the chanctx

Johannes Berg <[email protected]>
wifi: mac80211_hwsim: don't hand frames to mac80211 while stopping

Johannes Berg <[email protected]>
wifi: cfg80211: get the wiphy out of a dying network namespace

Johannes Berg <[email protected]>
wifi: mac80211: unlist vifs when their netdev is unregistered

Johannes Berg <[email protected]>
wifi: cfg80211: undo netns switch if renaming the wiphy fails

Johannes Berg <[email protected]>
wifi: cfg80211: restore netns_immutable on failures

Johannes Berg <[email protected]>
wifi: mac80211: only operate on TDLS peers in the TDLS code

Johannes Berg <[email protected]>
wifi: mac80211: reset the LED state when ifup fails

Johannes Berg <[email protected]>
wifi: mac80211: reset state when starting AP fails

Johannes Berg <[email protected]>
wifi: mac80211: abort chanswitch when leaving a mesh

Johannes Berg <[email protected]>
wifi: mac80211: suppress chanctx warning for debugfs reset

Johannes Berg <[email protected]>
wifi: mac80211: don't offload TC setup on AP_VLAN interfaces

Johannes Berg <[email protected]>
wifi: mac80211: don't warn when an IBSS has no channel to scan

Johannes Berg <[email protected]>
wifi: mac80211: don't start a ROC while scanning

Johannes Berg <[email protected]>
wifi: cfg80211: fix NAN regulatory enforcement

Johannes Berg <[email protected]>
wifi: cfg80211: ibss: ref BSS entry for joined event

Johannes Berg <[email protected]>
wifi: cfg80211: don't filter by BSS type when removing stale entries

Johannes Berg <[email protected]>
wifi: cfg80211: only group hidden BSSes with beacon entries

Johannes Berg <[email protected]>
wifi: cfg80211: don't free driver-owned scan requests

Shivank Garg <[email protected]>
dmaengine: wait for RCU readers before releasing dma_device

Shivank Garg <[email protected]>
dmaengine: fix use-after-free in dma_chan_put() and dma_release_channel()

Shivank Garg <[email protected]>
dmaengine: Fix device kref underflow in dma_chan_put()

Donggeun Yoo <[email protected]>
dma-mapping: don't trace the DMA address when the allocation fails

Donggeun Yoo <[email protected]>
dma-coherent: report a failed reserved memory assignment

Orgad Shaneh <[email protected]>
MIPS: Octeon: apply USB FDT fixups also when USB is modular

Julian Braha <[email protected]>
mips: econet: fix unmet dependencies for ECONET

Bard Liao <[email protected]>

    soundwire: cadence_master: wait and cancel cdns->work before clock stop

Johannes Berg <[email protected]>

    wifi: cfg80211: check IP header size in cfg80211_classify8021d()

Johannes Berg <[email protected]>
wifi: cfg80211: don't get the radio mask for netdev-less wdevs

Carolina Jubran <[email protected]>
IB/IPoIB: Avoid restoring OPER_UP after multicast flush

Shmulik Cohen <[email protected]>
wifi: libipw: reject too-short association responses

Shmulik Cohen <[email protected]>
wifi: libipw: reject too-short beacon and probe responses

Bogdan Nicolae <[email protected]>
wifi: brcmfmac: cyw: pass PMKID to firmware if present

Peng Hao <[email protected]>
wifi: mwifiex: fix IRQ leak using wrong index in MSI-X error path

Mariano Baragiola <[email protected]>
wifi: virt_wifi: free skb when disconnected

Lachlan Hodges <[email protected]>
wifi: mac80211: include TIM bitmap control for buffered S1G mcast traffic

Ruoyu Wang <[email protected]>
dmaengine: sprd: Fix runtime PM reference leak in probe

Troy Mitchell <[email protected]>
dmaengine: mmp_pdma: fix wrong extended DRCMR base for SpacemiT K3

Quanye Yang <[email protected]>
RDMA/rtrs-clt: Fix CQ pool leak when connect is interrupted

Jacob Moroni <[email protected]>
RDMA/irdma: Enforce local fence for IB_WR_REG_MR

Cheng Xu <[email protected]>
RDMA/erdma: Use IRQ-safe XArray helpers for QP and CQ tables

Li RongQing <[email protected]>
RDMA/mad: Fix receive buffer leak when PKey enforcement fails

Li RongQing <[email protected]>

    RDMA/uverbs: Fix potential leak of resources->collection in flow_resources_alloc()

Sriharsha Basavapatna <[email protected]>
RDMA/bnxt_re: Avoid exposing umdbr to userspace

Ryan Mehri <[email protected]>
RDMA/rtrs: guard against null kobj name

Linkai Gong <[email protected]>
RDMA/bnxt_re: check create_singlethread_workqueue() in DCB setup

Yehyeong Lee <[email protected]>
IB/isert: wait for deferred control PDU completions before releasing the connection

Yehyeong Lee <[email protected]>
IB/iser: reject a remote invalidation of an unregistered direction

Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g087: Switch GBETH TX queue scheduling to WRR

Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g077: Switch GBETH TX queue scheduling to WRR

Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g047: Switch GBETH TX queue scheduling to WRR

Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g056: Switch GBETH TX queue scheduling to WRR

Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g057: Switch GBETH TX queue scheduling to WRR

Biju Das <[email protected]>
power: sequencing: Fix build issue with COMPILE_TEST

Or Har-Toov <[email protected]>
RDMA/uverbs: Fix mmap_lock/disassociation_lock circular dependency

Krystian Kaniewski <[email protected]>
RDMA/core: Reject unregistering netdevs in ib_get_eth_speed

Or Har-Toov <[email protected]>
RDMA/mlx5: Remove warn on missing representor in query_port_speed

Michael Bommarito <[email protected]>
RDMA/rxe: insert mcg into mcg_tree only after rxe_mcast_add() succeeds

Weiming Shi <[email protected]>
RDMA/rxe: Restore HMM_PFN_WRITE check in ODP write paths

Xixin Liu <[email protected]>
clk: scpi: register scpi-cpufreq once and clear on failure

Xixin Liu <[email protected]>
clk: scpi: bound-check DVFS index in scpi_dvfs_recalc_rate

Xixin Liu <[email protected]>
firmware: arm_scpi: reject DVFS OPP count above MAX_DVFS_OPPS

Cen Zhang (Microsoft Security FORGE Labs) <[email protected]>
xfrm: hold net_device reference under RCU in bundle creation

Gang Yan <[email protected]>
RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB access

Norbert Szetei <[email protected]>
RDMA/rxe: validate access flags before swapping the MR's PD

Guoqing Jiang <[email protected]>
RDMA/siw: Clear association under lock if siw_qp_modify fails in siw_accept

Pengpeng Hou <[email protected]>
ARM: socfpga: select the PL310 erratum 753970 workaround

Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: fix the pin groups of the vsync PWM

Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: khadas-vim4: add the PWM-driven supplies

Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: fix the pin groups of two PWM outputs

Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: khadas-vim4: allow the SD card to be power cycled

Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: use the real UART pclk

Maher Azzouzi <[email protected]>
esp: downgrade zerocopy managed frags before mutating skb frags

Eric Dumazet <[email protected]>
xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject()

Kyle Zeng <[email protected]>
xfrm: fix compat ALLOCSPI request use-after-free

Henry Martin <[email protected]>
xfrm: iptfs: fix runt reassembly panic from short inner tot_len

Aleksandr Nogikh <[email protected]>
xfrm: add missing RCU read lock in xfrm_send_migrate_state()

Roshan Kumar <[email protected]>
xfrm: iptfs: fix stack OOB read in iptfs_skb_reset_frag_walk()

Jens Axboe <[email protected]>
sunvdc: fix -EIO issue due to lack of retries

Günther Noack <[email protected]>
selftests/landlock: Add audit test for whiteout object creation

Günther Noack <[email protected]>
selftests/landlock: Add tests for whiteout object creation

Günther Noack <[email protected]>
selftests/landlock: Use an actual chardev for MAKE_CHAR audit test

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

Diffstat:

 .../ABI/testing/sysfs-devices-platform-trackpoint  |   2 +-
 .../arch/arm64/memory-tagging-extension.rst        |   5 +-
 Documentation/hwmon/cgbc-hwmon.rst                 |  42 +-
 Documentation/netlink/specs/rt-neigh.yaml          |   3 +
 Documentation/networking/ip-sysctl.rst             |   4 +-
 Makefile                                           |   4 +-
 arch/arm/mach-socfpga/Kconfig                      |   2 +-
 .../boot/dts/altera/socfpga_stratix10_socdk.dtsi   |   0
 .../dts/altera/socfpga_stratix10_socdk_emmc.dts    |   0
 .../boot/dts/amlogic/amlogic-t7-a311d2-an400.dts   |   2 +-
 .../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts  | 113 +++-
 arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi        |  44 +-
 arch/arm64/boot/dts/renesas/r8a779f0.dtsi          |   1 +
 arch/arm64/boot/dts/renesas/r9a09g047.dtsi         |  10 +
 arch/arm64/boot/dts/renesas/r9a09g056.dtsi         |  10 +
 arch/arm64/boot/dts/renesas/r9a09g057.dtsi         |  10 +
 arch/arm64/boot/dts/renesas/r9a09g077.dtsi         |  27 +
 arch/arm64/boot/dts/renesas/r9a09g087.dtsi         |  27 +
 arch/arm64/include/asm/percpu.h                    |  20 +-
 arch/arm64/kernel/hibernate-asm.S                  |   2 +
 arch/arm64/kernel/hibernate.c                      |   4 +-
 arch/arm64/kernel/mte.c                            |   2 +-
 arch/mips/Kconfig                                  |   4 +-
 arch/mips/cavium-octeon/octeon-platform.c          |   4 +-
 arch/powerpc/kernel/iommu.c                        |   2 +-
 arch/powerpc/kvm/book3s_hv_nested.c                |   2 +
 arch/powerpc/kvm/book3s_hv_uvmem.c                 |   5 +-
 arch/x86/Kconfig.cpu                               |  11 +
 arch/x86/Makefile                                  |   5 +
 arch/x86/entry/entry_fred.c                        |  11 +-
 arch/x86/include/asm/div64.h                       |   2 +-
 arch/x86/include/asm/text-patching.h               |   4 +-
 arch/x86/kernel/alternative.c                      |   6 +-
 arch/x86/kernel/cpu/microcode/intel.c              |  26 +
 arch/x86/kernel/kprobes/core.c                     |   5 +-
 drivers/ata/libahci.c                              |  15 +-
 drivers/ata/libahci_platform.c                     |   2 +-
 drivers/block/sunvdc.c                             |   9 +-
 drivers/bluetooth/btintel_pcie.c                   |   8 +-
 drivers/bluetooth/btmtk.c                          |   7 +-
 drivers/bluetooth/btmtksdio.c                      |  24 +-
 drivers/bluetooth/btmtkuart.c                      |  20 +-
 drivers/bluetooth/btusb.c                          |  17 +
 drivers/bluetooth/hci_qca.c                        |  14 +-
 drivers/clk/clk-scpi.c                             |   8 +-
 drivers/dma-buf/Kconfig                            |   2 +-
 drivers/dma-buf/dma-buf-mapping.c                  |  31 +-
 drivers/dma-buf/dma-fence.c                        |  14 +-
 drivers/dma/dmaengine.c                            |  10 +-
 drivers/dma/mmp_pdma.c                             |   5 +-
 drivers/dma/pxa_dma.c                              |   3 +-
 drivers/dma/sprd-dma.c                             |   3 +-
 drivers/dma/sun6i-dma.c                            |   9 +-
 drivers/dma/ti/k3-udma-glue.c                      |   5 +-
 drivers/dma/xilinx/xilinx_dma.c                    |  26 +-
 drivers/firmware/arm_scpi.c                        |   4 +-
 drivers/gpio/gpio-virtuser.c                       |   3 +-
 drivers/gpio/gpiolib-of.c                          |   6 +-
 drivers/gpio/gpiolib-shared.c                      |   9 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h                |   3 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c         |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         | 145 ++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c        |  43 +-
 drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c              |   7 +-
 drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c             |   2 +-
 .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c  |   7 +-
 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c   |   2 +-
 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c   |   2 +-
 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c   |  61 +-
 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c |  70 +-
 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c    |   6 +-
 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c    |   5 +-
 .../drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c    |  13 +-
 drivers/gpu/drm/drm_atomic_uapi.c                  |  13 +-
 drivers/gpu/drm/gud/gud_pipe.c                     |   7 +-
 drivers/gpu/drm/i915/display/intel_cursor.c        |  15 +-
 drivers/gpu/drm/i915/display/skl_universal_plane.c |  15 +-
 drivers/gpu/drm/msm/adreno/adreno_device.c         |   2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.c            |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c         |   1 +
 drivers/gpu/drm/msm/dp/dp_display.c                |  21 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c                 |  36 +-
 drivers/gpu/drm/msm/hdmi/hdmi_phy.c                |   8 +-
 drivers/gpu/drm/msm/msm_drv.c                      |   2 +-
 drivers/gpu/drm/msm/msm_gem.h                      |   3 +
 drivers/gpu/drm/msm/msm_gem_vma.c                  |   2 +-
 drivers/gpu/drm/msm/msm_ringbuffer.c               |   2 +-
 drivers/gpu/drm/msm/msm_ringbuffer.h               |   1 +
 .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c |   2 +-
 .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c  |   8 +-
 .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/fbsr.c |   8 +-
 .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c  |   3 +-
 .../drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/gsp.h |   8 +
 drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h    |   2 +-
 drivers/gpu/drm/scheduler/sched_entity.c           |   8 +-
 drivers/gpu/drm/scheduler/sched_rq.c               |  20 +-
 drivers/gpu/drm/ttm/ttm_bo.c                       |   2 +-
 drivers/gpu/drm/vc4/vc4_kms.c                      |   2 +-
 drivers/gpu/drm/xe/xe_i2c.c                        |   3 +
 drivers/gpu/drm/xe/xe_mmio_gem.c                   |  33 +-
 drivers/gpu/drm/xe/xe_mmio_gem.h                   |   2 +-
 drivers/gpu/drm/xe/xe_shrinker.c                   | 124 ++--
 drivers/hwmon/cgbc-hwmon.c                         | 129 ++--
 drivers/hwmon/gpio-fan.c                           |   4 +-
 drivers/hwmon/hp-wmi-sensors.c                     |  32 +-
 drivers/hwmon/pmbus/pmbus.h                        |   3 +-
 drivers/hwmon/pmbus/tps53679.c                     |  11 +-
 drivers/hwmon/pwm-fan.c                            |  13 +-
 drivers/hwmon/w83791d.c                            |   1 +
 drivers/hwmon/w83793.c                             |   4 +-
 drivers/i2c/busses/i2c-at91-core.c                 |   3 +
 drivers/i2c/busses/i2c-at91-master.c               |  12 +-
 drivers/i2c/busses/i2c-at91.h                      |   1 +
 drivers/i2c/busses/i2c-imx.c                       |   3 +
 drivers/i2c/busses/i2c-qcom-cci.c                  |  20 +-
 drivers/i2c/i2c-atr.c                              |   1 +
 drivers/infiniband/core/iwpm_util.c                |   9 +-
 drivers/infiniband/core/mad.c                      |   3 +-
 drivers/infiniband/core/rdma_core.c                |   1 -
 drivers/infiniband/core/ucma.c                     |   7 +-
 drivers/infiniband/core/uverbs_flow.c              |   1 +
 drivers/infiniband/core/uverbs_main.c              |  25 +-
 drivers/infiniband/core/verbs.c                    |  12 +-
 drivers/infiniband/hw/bnxt_re/main.c               |  10 +-
 drivers/infiniband/hw/bnxt_re/uapi.c               |   6 +-
 drivers/infiniband/hw/efa/efa_com.c                |   7 +-
 drivers/infiniband/hw/efa/efa_com.h                |   1 +
 drivers/infiniband/hw/efa/efa_main.c               |  35 +-
 drivers/infiniband/hw/erdma/erdma_main.c           |   4 +-
 drivers/infiniband/hw/erdma/erdma_verbs.c          |  18 +-
 drivers/infiniband/hw/hfi1/file_ops.c              |  23 +-
 drivers/infiniband/hw/irdma/verbs.c                |   2 +-
 drivers/infiniband/hw/mlx4/sysfs.c                 |   4 +
 drivers/infiniband/hw/mlx5/main.c                  |   7 +-
 drivers/infiniband/sw/rxe/rxe_mcast.c              |  50 +-
 drivers/infiniband/sw/rxe/rxe_mr.c                 |   3 +-
 drivers/infiniband/sw/rxe/rxe_odp.c                |  16 +-
 drivers/infiniband/sw/rxe/rxe_verbs.c              |  13 +-
 drivers/infiniband/sw/siw/siw_cm.c                 |   7 +-
 drivers/infiniband/sw/siw/siw_qp_rx.c              |   2 +-
 drivers/infiniband/ulp/ipoib/ipoib.h               |   7 +
 drivers/infiniband/ulp/ipoib/ipoib_ib.c            |  12 +-
 drivers/infiniband/ulp/ipoib/ipoib_multicast.c     |  16 +-
 drivers/infiniband/ulp/iser/iser_initiator.c       |  16 +-
 drivers/infiniband/ulp/isert/ib_isert.c            |  22 +
 drivers/infiniband/ulp/isert/ib_isert.h            |   2 +
 drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h       |   2 +-
 drivers/infiniband/ulp/rtrs/rtrs-clt.c             |   8 +
 drivers/infiniband/ulp/rtrs/rtrs-clt.h             |   2 +
 drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h       |   2 +-
 drivers/input/evdev.c                              |   2 +
 drivers/input/input-compat.c                       |   2 +
 drivers/input/joystick/xpad.c                      |  10 +-
 drivers/input/keyboard/adp5588-keys.c              |  12 +-
 drivers/input/keyboard/atkbd.c                     |   8 +
 drivers/input/misc/soc_button_array.c              |  16 +-
 drivers/input/mouse/synaptics.c                    |   8 +
 drivers/input/rmi4/rmi_driver.c                    |  13 +
 drivers/input/rmi4/rmi_smbus.c                     |  10 +-
 drivers/input/serio/hp_sdc.c                       |   2 +-
 drivers/input/serio/i8042-acpipnpio.h              |   7 +
 drivers/input/touchscreen/cyttsp5.c                |   1 +
 drivers/input/touchscreen/eeti_ts.c                |   1 +
 drivers/memstick/core/ms_block.c                   |   2 +
 drivers/misc/ntsync.c                              |   3 +
 drivers/mmc/core/bus.c                             |   2 +-
 drivers/mmc/core/host.c                            |   1 +
 drivers/mmc/core/sdio_uart.c                       |   3 +
 drivers/mmc/host/mmc_hsq.c                         |   8 +-
 drivers/mmc/host/mmc_spi.c                         |   1 +
 drivers/mmc/host/mmci.c                            |   3 +
 drivers/mmc/host/mxcmmc.c                          |   4 +
 drivers/mmc/host/rtsx_pci_sdmmc.c                  |   5 +
 drivers/mmc/host/sdhci-of-aspeed.c                 |   5 +-
 drivers/mmc/host/sdhci_am654.c                     |  43 +-
 drivers/mmc/host/sh_mmcif.c                        |   3 +-
 drivers/net/dsa/mxl862xx/mxl862xx.c                |  23 +-
 drivers/net/ethernet/airoha/airoha_ppe.c           |  17 +-
 drivers/net/ethernet/broadcom/genet/bcmgenet.c     |  19 +-
 drivers/net/ethernet/cadence/macb_ptp.c            |   9 +
 drivers/net/ethernet/cortina/gemini.c              |   2 +-
 drivers/net/ethernet/intel/igc/igc_tsn.c           |   6 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |   7 +-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c    |   3 +-
 drivers/net/ethernet/mediatek/mtk_ppe_offload.c    |  17 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c  |   2 +-
 drivers/net/ethernet/meta/fbnic/fbnic_txrx.c       |  42 +-
 drivers/net/ethernet/meta/fbnic/fbnic_txrx.h       |   9 +-
 drivers/net/ethernet/microchip/lan743x_main.c      |   2 +-
 drivers/net/ethernet/sfc/falcon/tx.c               |   8 +-
 drivers/net/ethernet/sfc/siena/tx.c                |   8 +-
 drivers/net/ethernet/socionext/netsec.c            |   2 +
 drivers/net/ethernet/stmicro/stmmac/hwif.h         |   2 +-
 .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c   |   2 -
 drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c   |  14 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |   6 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c    |  99 ++-
 drivers/net/fddi/skfp/skfddi.c                     |   3 +-
 drivers/net/phy/mediatek/mtk-phy-lib.c             |  27 +-
 drivers/net/wireless/ath/ath11k/mac.c              |  25 +-
 drivers/net/wireless/ath/wcn36xx/dxe.c             |   2 +-
 .../wireless/broadcom/brcm80211/brcmfmac/core.c    |   2 +
 .../broadcom/brcm80211/brcmfmac/cyw/core.c         |   5 +-
 .../broadcom/brcm80211/brcmsmac/mac80211_if.c      |   4 +
 .../wireless/intel/ipw2x00/libipw_crypto_tkip.c    |  12 +-
 drivers/net/wireless/intel/ipw2x00/libipw_rx.c     |   6 +
 drivers/net/wireless/intel/iwlegacy/common.c       |   2 +-
 drivers/net/wireless/intersil/p54/eeprom.c         |  22 +-
 drivers/net/wireless/marvell/libertas_tf/main.c    |   2 +-
 drivers/net/wireless/marvell/mwifiex/cfg80211.c    |  12 +-
 drivers/net/wireless/marvell/mwifiex/pcie.c        |   2 +-
 drivers/net/wireless/marvell/mwifiex/scan.c        |  54 +-
 drivers/net/wireless/marvell/mwifiex/util.c        |  10 +-
 drivers/net/wireless/microchip/wilc1000/cfg80211.c |  14 +
 drivers/net/wireless/microchip/wilc1000/wlan.c     |   9 +
 drivers/net/wireless/rsi/rsi_91x_mgmt.c            |   2 -
 drivers/net/wireless/ti/wlcore/main.c              |   4 +-
 drivers/net/wireless/virtual/mac80211_hwsim_main.c |  39 +-
 drivers/net/wireless/virtual/virt_wifi.c           |   4 +-
 drivers/net/wwan/mhi_wwan_mbim.c                   |  28 +-
 drivers/net/wwan/t7xx/t7xx_netdev.c                |   4 +
 drivers/pci/controller/dwc/pci-imx6.c              |  12 +-
 drivers/perf/arm-cmn.c                             |  10 +-
 drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c         |   4 +-
 drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h         |   3 +
 drivers/phy/renesas/phy-rcar-gen3-usb2.c           | 310 +++++++--
 drivers/power/sequencing/Kconfig                   |   3 +-
 drivers/power/sequencing/core.c                    |  11 +-
 drivers/scsi/fnic/fdls_disc.c                      | 726 +++++++++++----------
 drivers/scsi/fnic/fip.c                            | 117 ++--
 drivers/scsi/fnic/fip.h                            |   2 +-
 drivers/scsi/fnic/fnic.h                           |  68 +-
 drivers/scsi/fnic/fnic_fcs.c                       | 126 ++--
 drivers/scsi/fnic/fnic_isr.c                       |  41 +-
 drivers/scsi/fnic/fnic_main.c                      |  89 ++-
 drivers/scsi/fnic/fnic_scsi.c                      | 210 +++---
 drivers/scsi/pm8001/pm8001_init.c                  |   6 +-
 drivers/scsi/qla2xxx/qla_os.c                      |   2 +-
 drivers/scsi/scsi.c                                |  24 +-
 drivers/soc/samsung/exynos-pmu.c                   |   7 +-
 drivers/soundwire/cadence_master.c                 |   7 +
 drivers/soundwire/dmi-quirks.c                     |   7 +
 drivers/spi/spi-fsl-qspi.c                         |   5 +-
 drivers/spi/spi-qpic-snand.c                       |   4 -
 drivers/spi/spi-virtio.c                           |   2 +-
 drivers/spi/spi-zynqmp-gqspi.c                     |  34 +
 drivers/watchdog/da9062_wdt.c                      |   4 +-
 drivers/watchdog/da9063_wdt.c                      |   4 +-
 drivers/watchdog/digicolor_wdt.c                   |  13 +-
 drivers/watchdog/msc313e_wdt.c                     |  16 +-
 drivers/watchdog/rtd119x_wdt.c                     |   7 +-
 drivers/watchdog/rzv2h_wdt.c                       |   7 +-
 drivers/watchdog/sp5100_tco.c                      |   6 +-
 drivers/watchdog/starfive-wdt.c                    |   2 +-
 fs/9p/vfs_addr.c                                   |  28 +-
 fs/btrfs/dev-replace.c                             |   1 +
 fs/btrfs/disk-io.c                                 |   4 +
 fs/btrfs/file.c                                    |   4 +-
 fs/btrfs/free-space-tree.c                         |  14 +-
 fs/btrfs/inode.c                                   |  18 +-
 fs/btrfs/super.c                                   |   8 +-
 fs/btrfs/tree-checker.c                            |   2 +-
 fs/btrfs/verity.c                                  |  18 +-
 fs/dax.c                                           |   9 +-
 fs/exec.c                                          |  29 +-
 fs/nfsd/export.c                                   |   3 +-
 fs/ntfs/attrib.c                                   | 259 ++++++--
 fs/ntfs/attrib.h                                   |   9 +
 fs/ntfs/attrlist.c                                 | 224 ++++++-
 fs/ntfs/attrlist.h                                 |   2 +
 fs/ntfs/compress.c                                 |   2 +-
 fs/ntfs/file.c                                     |   3 +-
 fs/ntfs/inode.c                                    |  35 +-
 fs/ntfs/mft.c                                      | 445 ++++++++++---
 fs/ntfs/mft.h                                      |   2 +-
 fs/ntfs/namei.c                                    |   2 +-
 fs/ntfs/super.c                                    |  12 +-
 fs/ntfs/volume.h                                   |  12 +-
 fs/smb/client/cifssmb.c                            |   2 +-
 fs/smb/client/connect.c                            |   9 +
 fs/smb/client/file.c                               |   4 +-
 fs/smb/client/misc.c                               |  12 +-
 fs/smb/client/reparse.c                            |  58 +-
 fs/smb/client/reparse.h                            |   7 +-
 fs/smb/client/sess.c                               | 104 +--
 fs/smb/client/smb2inode.c                          |  11 +
 fs/smb/client/smb2ops.c                            |  51 +-
 fs/smb/client/smb2pdu.c                            |  13 +-
 fs/smb/client/trace.h                              |   1 +
 fs/smb/server/connection.c                         |  84 ++-
 fs/smb/server/connection.h                         |   3 +
 fs/smb/server/mgmt/user_session.c                  | 199 ++++--
 fs/smb/server/mgmt/user_session.h                  |   8 +-
 fs/smb/server/misc.h                               |   7 +-
 fs/smb/server/proc.c                               | 159 ++++-
 fs/smb/server/server.c                             |   9 +-
 fs/smb/server/smb2pdu.c                            | 126 ++--
 fs/smb/server/smb2pdu.h                            |   3 +-
 fs/smb/server/smb_common.h                         |   2 +-
 fs/smb/server/stats.h                              |  58 +-
 fs/smb/server/vfs_cache.c                          |  26 +-
 fs/smb/server/vfs_cache.h                          |   1 +
 fs/super.c                                         |   1 +
 include/keys/request_key_auth-type.h               |   2 +-
 include/linux/dma-fence.h                          |   6 +
 include/linux/ieee80211-mesh.h                     |   4 +-
 include/linux/netdevice.h                          |  13 +-
 include/net/bluetooth/coredump.h                   |   2 +
 include/net/codel.h                                |   5 +
 include/net/codel_impl.h                           |  16 +-
 include/net/mac80211.h                             |   5 +-
 include/net/sock.h                                 |   2 +
 include/rdma/uverbs_types.h                        |   2 -
 include/sound/soc.h                                |   3 +-
 include/sound/soc_sdw_utils.h                      |  31 +-
 include/trace/events/dma.h                         |   2 +-
 include/uapi/rdma/bnxt_re-abi.h                    |   2 +-
 kernel/cgroup/cgroup.c                             |   7 +-
 kernel/dma/coherent.c                              |   3 +-
 kernel/dma/swiotlb.c                               |   4 +-
 kernel/events/core.c                               |   4 +
 kernel/exit.c                                      |  11 +-
 kernel/fork.c                                      |   4 +-
 kernel/sched/core.c                                |   9 +-
 kernel/sched/ext/ext.c                             |  27 +-
 kernel/sched/ext/idle.c                            |  11 +-
 kernel/signal.c                                    | 117 +++-
 kernel/time/jiffies.c                              |   2 +-
 kernel/time/posix-cpu-timers.c                     |  40 +-
 mm/filemap.c                                       |   2 +-
 mm/huge_memory.c                                   |  86 ++-
 mm/memblock.c                                      |  18 +-
 mm/memcontrol.c                                    |   2 +-
 mm/mlock.c                                         |   2 +-
 mm/mremap.c                                        |   9 +-
 mm/shrinker.c                                      |   2 +
 mm/swapfile.c                                      |   2 +-
 mm/vma.c                                           |   6 +-
 net/atm/pppoatm.c                                  |  42 +-
 net/bluetooth/coredump.c                           |  65 +-
 net/bluetooth/eir.c                                |  10 +-
 net/bluetooth/hci_codec.c                          |  36 +-
 net/bluetooth/hci_conn.c                           |  21 +
 net/bluetooth/hci_core.c                           |  18 +-
 net/bluetooth/hci_sync.c                           |   2 +
 net/bluetooth/iso.c                                |  53 +-
 net/bluetooth/rfcomm/sock.c                        |  13 +-
 net/bridge/br_mst.c                                |  20 +-
 net/bridge/br_vlan.c                               |  31 +-
 net/core/dev.c                                     | 110 +++-
 net/core/drop_monitor.c                            |  18 +-
 net/core/neighbour.c                               |  35 +-
 net/core/skbuff.c                                  |  32 +-
 net/core/sock.c                                    |  16 +-
 net/ipv4/esp4.c                                    |   6 +
 net/ipv4/icmp.c                                    |  17 +-
 net/ipv4/ip_tunnel_core.c                          |  16 +-
 net/ipv4/sysctl_net_ipv4.c                         |   4 +-
 net/ipv4/tcp_input.c                               |   3 +-
 net/ipv4/tcp_ulp.c                                 |   4 +
 net/ipv6/esp6.c                                    |   6 +
 net/ipv6/seg6_local.c                              |   3 +
 net/ipv6/tcp_ipv6.c                                |   3 +-
 net/ipv6/xfrm6_output.c                            |  10 +-
 net/mac80211/cfg.c                                 |  18 +-
 net/mac80211/debugfs.c                             |   2 +-
 net/mac80211/debugfs_netdev.c                      |   9 +
 net/mac80211/ieee80211_i.h                         |   2 +-
 net/mac80211/iface.c                               |  39 +-
 net/mac80211/main.c                                |   4 +
 net/mac80211/mesh.c                                |  34 +-
 net/mac80211/offchannel.c                          |   7 +
 net/mac80211/pm.c                                  |   8 +-
 net/mac80211/scan.c                                |   2 +-
 net/mac80211/tdls.c                                |  40 +-
 net/mac80211/tx.c                                  | 107 +--
 net/netfilter/nf_flow_table_core.c                 |  12 +-
 net/netfilter/nf_flow_table_path.c                 |   7 +-
 net/netfilter/nf_nat_core.c                        |  46 +-
 net/netfilter/nf_tables_api.c                      |  22 +-
 net/netfilter/nft_nat.c                            |   2 +-
 net/netlink/af_netlink.c                           |  42 +-
 net/netlink/diag.c                                 |  18 +-
 net/openvswitch/conntrack.c                        |   2 +-
 net/packet/af_packet.c                             |   4 +-
 net/packet/internal.h                              |   2 +-
 net/psp/psp_sock.c                                 |   4 +
 net/rds/ib_cm.c                                    |   2 +-
 net/sched/act_api.c                                |  11 +-
 net/sched/sch_hhf.c                                |   9 +-
 net/sched/sch_mqprio.c                             |   4 +-
 net/sched/sch_mqprio_lib.c                         |   7 +-
 net/sched/sch_taprio.c                             |  26 +-
 net/unix/garbage.c                                 |  17 +-
 net/wireless/core.c                                | 150 +++--
 net/wireless/core.h                                |  16 +-
 net/wireless/ibss.c                                |  38 +-
 net/wireless/rdev-ops.h                            |   3 +
 net/wireless/reg.c                                 |   2 +-
 net/wireless/scan.c                                |  43 +-
 net/wireless/util.c                                |  38 +-
 net/xfrm/espintcp.c                                |   6 +-
 net/xfrm/xfrm_input.c                              |  22 +-
 net/xfrm/xfrm_iptfs.c                              |  12 +-
 net/xfrm/xfrm_policy.c                             |  20 +-
 net/xfrm/xfrm_state.c                              |   9 +-
 net/xfrm/xfrm_user.c                               |  18 +-
 rust/kernel/net/phy.rs                             |  38 +-
 scripts/generate_rust_target.rs                    |   5 +
 security/keys/encrypted-keys/encrypted.c           |  20 +-
 security/keys/gc.c                                 |   4 +-
 security/keys/request_key_auth.c                   |  12 +-
 security/keys/trusted-keys/trusted_tpm2.c          |  12 +-
 security/selinux/avc.c                             |   5 +-
 security/selinux/hooks.c                           | 158 ++++-
 security/selinux/include/objsec.h                  |  10 +-
 sound/core/init.c                                  |   3 +-
 sound/core/pcm_timer.c                             |   7 +-
 sound/hda/common/controller.c                      |   2 +-
 sound/soc/amd/acp/acp-sdw-legacy-mach.c            |  16 +-
 sound/soc/amd/acp/acp-sdw-sof-mach.c               |  21 +-
 sound/soc/codecs/cs-amp-lib.c                      |   2 +
 sound/soc/codecs/hdmi-codec.c                      |   6 +-
 sound/soc/codecs/rt712-sdca-dmic.c                 |  14 +-
 sound/soc/intel/boards/sof_sdw.c                   |   2 +-
 sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c       |   4 +-
 sound/soc/sdw_utils/soc_sdw_utils.c                |   9 +-
 sound/soc/soc-pcm.c                                |  18 +-
 sound/soc/ux500/ux500_msp_i2s.h                    |   4 +-
 sound/usb/6fire/comm.c                             |  42 +-
 sound/usb/6fire/comm.h                             |   2 +-
 sound/usb/6fire/midi.c                             |  43 +-
 sound/usb/6fire/midi.h                             |   2 +-
 sound/usb/6fire/pcm.c                              | 138 ++--
 sound/usb/6fire/pcm.h                              |   5 +-
 sound/usb/bcd2000/bcd2000.c                        |  33 +-
 sound/usb/card.h                                   |   1 +
 sound/usb/endpoint.c                               |  12 +-
 sound/virtio/virtio_card.c                         |   4 +-
 tools/objtool/Makefile                             |   8 +-
 .../selftests/arm64/mte/check_gcr_el1_cswitch.c    |   2 +-
 tools/testing/selftests/landlock/fs_test.c         | 197 +++++-
 442 files changed, 6831 insertions(+), 2723 deletions(-)
author maintainer
#1 lore raw

PATCH 1/438 selftests/landlock: Use an actual chardev for MAKE_CHAR audit test

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

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

From: Günther Noack <[email protected]>

[ Upstream commit 173b1bd8730825e1f6862dbd07856e7d68447a41 ]

By passing a (0, 0) device number, the audit test for LANDLOCK_ACCESS_FS_MAKE_CHAR was accidentally creating a whiteout object rather than a char device. In preparation to treating whiteout objects differently, use an actual character device instead.

---
 tools/testing/selftests/landlock/fs_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/landlock/fs_test.c +1 -1
index 86e08aa6e0a7e..e82b56a74c5f5 100644
@@ -7436,7 +7436,7 @@ TEST_F(audit_layout1, make_char)
 
 	enforce_fs(_metadata, ACCESS_ALL, NULL);
 
-	EXPECT_EQ(-1, mknod(file1_s1d3, S_IFCHR | 0644, 0));
+	EXPECT_EQ(-1, mknod(file1_s1d3, S_IFCHR | 0644, makedev(7, 0)));
 	EXPECT_EQ(EACCES, errno);
 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.make_char",
 				    dir_s1d3));
Signature · 1 line
2.53.0
author maintainer
#2 lore raw

PATCH 2/438 selftests/landlock: Add tests for whiteout object creation

In reply to Greg Kroah-Hartman

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

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

From: Günther Noack <[email protected]>

[ Upstream commit ee890889b30b22f9a21636061def7a04e4f89380 ]

Add tests to check that whiteout object creation is guarded by LANDLOCK_ACCESS_FS_MAKE_REG, in the cases where these are created from userspace:

* Conventional creation with mknod()
* Linking or renaming an existing whiteout object
* renameat2() with RENAME_WHITEOUT,
which creates a new whiteout object in the source location
* renameat2() with RENAME_EXCHANGE,
with one of the renamed objects being a whiteout object

---
 tools/testing/selftests/landlock/fs_test.c | 176 +++++++++++++++++++++
 1 file changed, 176 insertions(+)
tools/testing/selftests/landlock/fs_test.c +176 -0
index e82b56a74c5f5..871a5b819b989 100644
@@ -2247,6 +2247,170 @@ TEST_F_FORK(layout1, rename_file)
 			       RENAME_EXCHANGE));
 }
 
+TEST_F_FORK(layout1, rename_whiteout_denied)
+{
+	/* The affected file is a FIFO. */
+	ASSERT_EQ(0, unlink(file1_s3d3));
+	ASSERT_EQ(0, mknod(file1_s3d3, S_IFIFO | 0600, 0));
+
+	/* Deny MAKE_REG, but allow MAKE_FIFO. */
+	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, NULL);
+
+	/*
+	 * Try to rename a file with RENAME_WHITEOUT.
+	 * file1_s3d3 is in dir_s3d2 (tmpfs), so it supports RENAME_WHITEOUT.
+	 * Denied, because whiteout creation is guarded with MAKE_REG.
+	 */
+	EXPECT_EQ(-1, renameat2(AT_FDCWD, file1_s3d3, AT_FDCWD,
+				TMP_DIR "/s3d1/s3d2/s3d3/f2", RENAME_WHITEOUT));
+	EXPECT_EQ(EACCES, errno);
+}
+
+static bool is_whiteout(const char *const path)
+{
+	struct stat st;
+
+	if (stat(path, &st) == -1)
+		return false;
+
+	return S_ISCHR(st.st_mode) && st.st_rdev == makedev(0, 0);
+}
+
+static bool is_fifo(const char *const path)
+{
+	struct stat st;
+
+	return stat(path, &st) == 0 && S_ISFIFO(st.st_mode);
+}
+
+TEST_F_FORK(layout1, rename_whiteout_allowed)
+{
+	const struct rule rules[] = {
+		{
+			.path = dir_s3d3,
+			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
+		},
+		{},
+	};
+
+	/* The affected file is a FIFO. */
+	ASSERT_EQ(0, unlink(file1_s3d3));
+	ASSERT_EQ(0, mknod(file1_s3d3, S_IFIFO | 0600, 0));
+
+	/* Allow MAKE_REG below dir_s3d3. */
+	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, rules);
+
+	/*
+	 * Rename a file with RENAME_WHITEOUT within the same directory.
+	 * Allowed, because MAKE_REG is granted for the whiteout object which
+	 * gets created in the source location.
+	 */
+	EXPECT_EQ(0, renameat2(AT_FDCWD, file1_s3d3, AT_FDCWD,
+			       TMP_DIR "/s3d1/s3d2/s3d3/f2", RENAME_WHITEOUT));
+
+	/* A whiteout object took the place of the moved FIFO. */
+	EXPECT_TRUE(is_whiteout(file1_s3d3));
+	EXPECT_TRUE(is_fifo(TMP_DIR "/s3d1/s3d2/s3d3/f2"));
+}
+
+TEST_F_FORK(layout1, rename_whiteout_reparenting)
+{
+	const struct rule rules[] = {
+		{
+			.path = dir_s3d2,
+			.access = LANDLOCK_ACCESS_FS_REFER,
+		},
+		{
+			.path = dir_s3d3,
+			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
+		},
+		{},
+	};
+
+	/* The moved files are FIFOs. */
+	ASSERT_EQ(0, unlink(file1_s3d3));
+	ASSERT_EQ(0, mknod(file1_s3d3, S_IFIFO | 0600, 0));
+	ASSERT_EQ(0, unlink(file1_s3d4));
+	ASSERT_EQ(0, mknod(file1_s3d4, S_IFIFO | 0600, 0));
+
+	/* Allow REFER below dir_s3d2, but MAKE_REG only below dir_s3d3. */
+	enforce_fs(_metadata,
+		   LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER,
+		   rules);
+
+	/*
+	 * The whiteout object is created in the source directory: Moving the
+	 * FIFO out of dir_s3d4 is denied because MAKE_REG is not granted
+	 * there, even though it is granted in the destination directory
+	 * dir_s3d3.
+	 */
+	EXPECT_EQ(-1, renameat2(AT_FDCWD, file1_s3d4, AT_FDCWD,
+				TMP_DIR "/s3d1/s3d2/s3d3/f2", RENAME_WHITEOUT));
+	EXPECT_EQ(EACCES, errno);
+
+	/*
+	 * Moving the FIFO out of dir_s3d3 is allowed, because MAKE_REG is
+	 * granted there for the created whiteout object.
+	 */
+	EXPECT_EQ(0, renameat2(AT_FDCWD, file1_s3d3, AT_FDCWD,
+			       TMP_DIR "/s3d1/s3d2/s3d4/f2", RENAME_WHITEOUT));
+
+	/* A whiteout object took the place of the moved FIFO. */
+	EXPECT_TRUE(is_whiteout(file1_s3d3));
+	EXPECT_TRUE(is_fifo(TMP_DIR "/s3d1/s3d2/s3d4/f2"));
+}
+
+TEST_F_FORK(layout1, rename_whiteout_exchange)
+{
+	const char *const whiteout_s3d3 = TMP_DIR "/s3d1/s3d2/s3d3/f2";
+	const struct rule rules[] = {
+		{
+			.path = dir_s3d2,
+			.access = LANDLOCK_ACCESS_FS_REFER,
+		},
+		{
+			.path = dir_s3d3,
+			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
+		},
+		{},
+	};
+
+	/* The exchanged files are FIFOs and an existing whiteout object. */
+	ASSERT_EQ(0, unlink(file1_s3d3));
+	ASSERT_EQ(0, mknod(file1_s3d3, S_IFIFO | 0600, 0));
+	ASSERT_EQ(0, mknod(whiteout_s3d3, S_IFCHR | 0600, makedev(0, 0)));
+	ASSERT_EQ(0, unlink(file1_s3d4));
+	ASSERT_EQ(0, mknod(file1_s3d4, S_IFIFO | 0600, 0));
+
+	/* Allow REFER below dir_s3d2, but MAKE_REG only below dir_s3d3. */
+	enforce_fs(_metadata,
+		   LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER,
+		   rules);
+
+	/*
+	 * With RENAME_EXCHANGE, the whiteout object moves into the source
+	 * directory of the rename: Exchanging the FIFO in dir_s3d4 with the
+	 * whiteout object is denied because MAKE_REG is not granted in
+	 * dir_s3d4, even though it is granted in the whiteout object's own
+	 * directory dir_s3d3.
+	 */
+	EXPECT_EQ(-1, renameat2(AT_FDCWD, file1_s3d4, AT_FDCWD, whiteout_s3d3,
+				RENAME_EXCHANGE));
+	EXPECT_EQ(EACCES, errno);
+
+	/*
+	 * Exchanging the FIFO in dir_s3d3 with the whiteout object is
+	 * allowed, because MAKE_REG is granted in the directory into which
+	 * the whiteout object moves.
+	 */
+	EXPECT_EQ(0, renameat2(AT_FDCWD, file1_s3d3, AT_FDCWD, whiteout_s3d3,
+			       RENAME_EXCHANGE));
+
+	/* The FIFO and the whiteout object swapped places. */
+	EXPECT_TRUE(is_whiteout(file1_s3d3));
+	EXPECT_TRUE(is_fifo(whiteout_s3d3));
+}
+
 TEST_F_FORK(layout1, rename_dir)
 {
 	const struct rule rules[] = {
@@ -3270,6 +3434,18 @@ TEST_F_FORK(layout1, make_char)
 		       makedev(1, 3));
 }
 
+TEST_F_FORK(layout1, make_whiteout)
+{
+	/*
+	 * Creates a whiteout object (creation guarded by MAKE_REG).
+	 *
+	 * Contrary to the other character devices, this does not require
+	 * CAP_MKNOD, cf. vfs_mknod().
+	 */
+	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, S_IFCHR,
+		       makedev(0, 0));
+}
+
 TEST_F_FORK(layout1, make_block)
 {
 	/* Creates a /dev/loop0 device. */
Signature · 1 line
2.53.0
author maintainer
#3 lore raw

PATCH 3/438 selftests/landlock: Add audit test for whiteout object creation

In reply to Greg Kroah-Hartman

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

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

From: Günther Noack <[email protected]>

[ Upstream commit 8c46c6acbebe0d8544fd1b55e5ddf36828d7b9ea ]

Add audit_layout1.make_whiteout: This test looks similar to audit_layout1.make_char, but creates a whiteout object through mknod(). Since whiteout object creation is now guarded with LANDLOCK_ACCESS_FS_MAKE_REG rather than LANDLOCK_ACCESS_FS_MAKE_CHAR, it also needs to log the matching denial to audit.

---
 tools/testing/selftests/landlock/fs_test.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
tools/testing/selftests/landlock/fs_test.c +19 -0
index 871a5b819b989..a9130ed70af5c 100644
@@ -7622,6 +7622,25 @@ TEST_F(audit_layout1, make_char)
 	EXPECT_EQ(1, records.domain);
 }
 
+TEST_F(audit_layout1, make_whiteout)
+{
+	struct audit_records records;
+
+	EXPECT_EQ(0, unlink(file1_s1d3));
+
+	enforce_fs(_metadata, ACCESS_ALL, NULL);
+
+	/* Whiteout creation is denied and logged as fs.make_reg. */
+	EXPECT_EQ(-1, mknod(file1_s1d3, S_IFCHR | 0644, makedev(0, 0)));
+	EXPECT_EQ(EACCES, errno);
+	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.make_reg",
+				    dir_s1d3));
+
+	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
+	EXPECT_EQ(0, records.access);
+	EXPECT_EQ(1, records.domain);
+}
+
 TEST_F(audit_layout1, make_dir)
 {
 	struct audit_records records;
Signature · 1 line
2.53.0
author maintainer
#4 lore raw

PATCH 4/438 sunvdc: fix -EIO issue due to lack of retries

In reply to Greg Kroah-Hartman

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

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

From: Jens Axboe <[email protected]>

[ Upstream commit 5067d4ba713961d8ccea1e06cd4c453793f3121e ]

John reports that since commit:

a11f6ca9aef9 ("sunvdc: Do not spin in an infinite loop when vio_ldc_send() returns EAGAIN")

users of Linux inside Solaris ldom see occasional -EIO errors because the request send loop now times out. The current loop does 10 retries, and inside vio_ldc_send() a further 1000 1usec retries are done as well. Even with 10.5 msec of busy loop retries that's apparently not enough to always succeed.

Rather than introduce continued busy looping, requeue the request and have the delayed queue kicking retry the request after another 10ms. This obviously isn't ideal, but there's seemingly no way to wait for this type of event. And if 10ms of busy looping was not enough to make progress, then presumably this is an edge condition and we just need to guarantee to make forward progress at some later point in time. That's more suitably done through letting the CPU tend to other work, rather than sitting in a tight loop retrying.

[stian: rebased on top of the cookie-unmap fix, without which every
requeued attempt leaks LDC map table entries; tested on an UltraSPARC T4 LDOM where the vdc_tx_trigger failure condition was reproduced and absorbed by the requeue with no I/O error]

---
 drivers/block/sunvdc.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/block/sunvdc.c +8 -1
index 24ad56536ed60..2be8231dcd5b4 100644
@@ -556,6 +556,7 @@ static blk_status_t vdc_queue_rq(struct blk_mq_hw_ctx *hctx,
 	struct vdc_port *port = hctx->queue->queuedata;
 	struct vio_dring_state *dr;
 	unsigned long flags;
+	int ret;
 
 	dr = &port->vio.drings[VIO_DRIVER_TX_RING];
 
@@ -577,7 +578,13 @@ static blk_status_t vdc_queue_rq(struct blk_mq_hw_ctx *hctx,
 		return BLK_STS_DEV_RESOURCE;
 	}
 
-	if (__send_request(bd->rq) < 0) {
+	ret = __send_request(bd->rq);
+	if (ret == -EAGAIN) {
+		spin_unlock_irqrestore(&port->vio.lock, flags);
+		/* already spun for 10msec, defer 10msec and retry */
+		blk_mq_delay_kick_requeue_list(hctx->queue, 10);
+		return BLK_STS_DEV_RESOURCE;
+	} else if (ret < 0) {
 		spin_unlock_irqrestore(&port->vio.lock, flags);
 		return BLK_STS_IOERR;
 	}
Signature · 1 line
2.53.0
author maintainer
#5 lore raw

PATCH 5/438 xfrm: iptfs: fix stack OOB read in iptfs_skb_reset_frag_walk()

In reply to Greg Kroah-Hartman

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

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

From: Roshan Kumar <[email protected]>

[ Upstream commit d042487dc118e494db2e2c1382310255c90ff544 ]

iptfs_skb_reset_frag_walk() advances to the fragment containing @offset with an unbounded loop:

	while (offset >= walk->past + walk->frags[walk->fragi].len)
		walk->past += walk->frags[walk->fragi++].len;

walk->fragi is advanced and walk->frags[walk->fragi] is dereferenced without ever checking fragi against walk->nr_frags. When the requested offset is at or beyond the total length spanned by the walk's fragments, fragi runs past nr_frags and off the end of the fixed-size on-stack frags[MAX_SKB_FRAGS + 1] array, reading out-of-bounds stack memory.

The two callers behave differently: iptfs_skb_add_frags() already guards against this with

	if (!walk->nr_frags ||
	    offset >= walk->total + walk->initial_offset)
		return len;

but iptfs_skb_can_add_frags() has no such guard and calls iptfs_skb_reset_frag_walk() unconditionally, so it performs the out-of-range walk. Its own "fragi < walk->nr_frags" bound check runs only afterwards, too late to prevent the read.

This is reachable from the receive path: a crafted IP-TFS (AGGFRAG) payload delivered to an IPTFS SA drives iptfs_reassem_cont() -> iptfs_skb_can_add_frags() with an offset past the fragment total, e.g.:

  BUG: KASAN: stack-out-of-bounds in iptfs_skb_reset_frag_walk+0x235/0x250
  Read of size 4 at addr ffff888008ad7210 by task repro/345
   iptfs_skb_reset_frag_walk+0x235/0x250 net/xfrm/xfrm_iptfs.c:392
   iptfs_skb_can_add_frags+0x155/0x310  net/xfrm/xfrm_iptfs.c:420
   iptfs_reassem_cont+0xcf8/0x1140      net/xfrm/xfrm_iptfs.c:902
   iptfs_input_ordered+0x552/0x670      net/xfrm/xfrm_iptfs.c:1280
   iptfs_input+0x3d6/0xde0              net/xfrm/xfrm_iptfs.c:1741
   xfrm_input+0x282f/0x6140             net/xfrm/xfrm_input.c:700
   xfrm4_esp_rcv+0x93/0x120             net/ipv4/xfrm4_protocol.c:104
   ip_rcv+0x278/0x2d0                   net/ipv4/ip_input.c:612

Give iptfs_skb_can_add_frags() the same up-front guard that iptfs_skb_add_frags() already has, so the walk is never entered with an out-of-range offset. When it triggers, the caller falls back to the existing linearize-and-copy path, which is safe.

Fixes 5f2b6a909574 ("xfrm: iptfs: add skb-fragment sharing code")
---
 net/xfrm/xfrm_iptfs.c | 8 ++++++++
 1 file changed, 8 insertions(+)
net/xfrm/xfrm_iptfs.c +8 -0
index 597aedeac26eb..2ce15c472cc4d 100644
@@ -416,6 +416,14 @@ static bool iptfs_skb_can_add_frags(const struct sk_buff *skb,
 	if (skb_has_frag_list(skb) || skb->pp_recycle != walk->pp_recycle)
 		return false;
 
+	/* Reject an @offset that is at or beyond the end of the walk's data
+	 * before calling iptfs_skb_reset_frag_walk(), whose fragment-advance
+	 * loop is otherwise unbounded and would index past walk->frags[].
+	 * This mirrors the guard already present in iptfs_skb_add_frags().
+	 */
+	if (!walk->nr_frags || offset >= walk->total + walk->initial_offset)
+		return false;
+
 	/* Make offset relative to current frag after setting that */
 	offset = iptfs_skb_reset_frag_walk(walk, offset);
 
Signature · 1 line
2.53.0
author maintainer
#6 lore raw

PATCH 6/438 xfrm: add missing RCU read lock in xfrm_send_migrate_state()

In reply to Greg Kroah-Hartman

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

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

From: Aleksandr Nogikh <[email protected]>

[ Upstream commit 42d100f5232f39b8ea7b00a7c2482325c7f032a4 ]

xfrm_nlmsg_multicast() requires the RCU read lock to be held because it safely dereferences the net->xfrm.nlsk pointer using rcu_dereference(). When it is called from xfrm_send_migrate_state(), the RCU read lock is not held, which triggers a suspicious RCU usage warning:

WARNING: suspicious RCU usage
net/xfrm/xfrm_user.c:1630 suspicious rcu_dereference_check() usage!

Call Trace:
 lockdep_rcu_suspicious+0x13f/0x1d0 kernel/locking/lockdep.c:6876
 xfrm_nlmsg_multicast+0x1d8/0x1f0 net/xfrm/xfrm_user.c:1630
 xfrm_send_migrate_state+0x870/0xae0 net/xfrm/xfrm_user.c:3340
 xfrm_do_migrate_state+0x1749/0x1e90 net/xfrm/xfrm_user.c:3507
 xfrm_user_rcv_msg+0x7a8/0xf30 net/xfrm/xfrm_user.c:3907

Fix this by wrapping the xfrm_nlmsg_multicast() call in xfrm_send_migrate_state() with rcu_read_lock() and rcu_read_unlock().

Fixes a9d155ea9b44 ("xfrm: add XFRM_MSG_MIGRATE_STATE for single SA migration")
Assisted-by Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by [email protected]
---
 net/xfrm/xfrm_user.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
net/xfrm/xfrm_user.c +5 -1
index 6266a92cf3020..980dbeb5a57de 100644
@@ -3337,7 +3337,11 @@ static int xfrm_send_migrate_state(struct net *net,
 		return err;
 	}
 
-	return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE);
+	rcu_read_lock();
+	err = xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE);
+	rcu_read_unlock();
+
+	return err;
 }
 
 static int xfrm_do_migrate_state(struct sk_buff *skb, struct nlmsghdr *nlh,
Signature · 1 line
2.53.0
author maintainer
#7 lore raw

PATCH 7/438 xfrm: iptfs: fix runt reassembly panic from short inner tot_len

In reply to Greg Kroah-Hartman

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

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

From: Henry Martin <[email protected]>

[ Upstream commit dc33262be1fe43d0eb0b84fb58c6ed42e2f64a8c ]

When the start of an inner packet is split across two outer packets such that fewer than 4 bytes land at the end of the first one, __input_process_payload() saves those bytes as a runt and skips the iplen/iphlen validation performed for in-place packets. When the continuation packet arrives, iptfs_reassem_cont() only requires the declared inner length to be >= sizeof(ra_runt) (6) before allocating the reassembly skb with that attacker-controlled length.

However, __iptfs_iphlen() always returns the fixed minimum IP header size (20 for IPv4, 40 for IPv6), so for an inner IPv4 tot_len in [6, 19] the header-completion copy writes past the declared packet length, and the subsequent "ipremain -= copylen" underflows to ~4GB, leaving the payload copy length bounded only by blkoff (up to 64KB). At runtime the skb_put() tailroom check turns this into skb_over_panic(), i.e. an unprivileged kernel panic (DoS), reachable locally via userns+netns IPTFS SAs and remotely against IPTFS VPN gateways when the decrypted outer skb is linear (e.g. AF_PACKET taps, tun/tap delivery).

Align the runt path with the normal path by requiring the declared inner length to cover at least the IP header size. This also subsumes the previous >= sizeof(ra_runt) check, since the minimum IP header is always larger than the runt buffer.

This issue was found by the autokbug dynamic kernel fuzzer at Tencent Yunding Lab.

Fixes 075694765446 ("xfrm: iptfs: handle received fragmented inner packets")
---
 net/xfrm/xfrm_iptfs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/xfrm/xfrm_iptfs.c +2 -2
index 2ce15c472cc4d..6920940a35b49 100644
@@ -828,8 +828,8 @@ static u32 iptfs_reassem_cont(struct xfrm_iptfs_data *xtfs, u64 seq,
 		 * allocate an in progress skb
 		 */
 		ipremain = __iptfs_iplen(xtfs->ra_runt);
-		if (ipremain < sizeof(xtfs->ra_runt)) {
-			/* length has to be at least runtsize large */
+		if (ipremain < __iptfs_iphlen(xtfs->ra_runt)) {
+			/* length has to be at least the IP header size */
 			XFRM_INC_STATS(xs_net(xtfs->x),
 				       LINUX_MIB_XFRMINIPTFSERROR);
 			goto abandon;
Signature · 1 line
2.53.0
author maintainer
#8 lore raw

PATCH 8/438 xfrm: fix compat ALLOCSPI request use-after-free

In reply to Greg Kroah-Hartman

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

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

From: Kyle Zeng <[email protected]>

[ Upstream commit d1ebd9081879fd9ae9c8fb7e8928f19cc88ae320 ]

xfrm_state_netlink() builds the ALLOCSPI response with dump_one_state(), which already calls alloc_compat() with the response skb and header.

xfrm_alloc_userspi() then calls alloc_compat() again, but passes the original request skb and its header. For a compat request, the translator therefore interprets the 228-byte compat xfrm_userspi_info as the 232-byte native layout and reads four bytes past the declared payload. It also publishes the translated child through the request's frag_list.

A multicast clone of the request shares skb_shared_info and can observe that child. xfrm_user_rcv_msg() frees it after the request handler returns, racing a compat receiver which may still be copying from it and resulting in a use-after-free.

Remove the redundant conversion. The response keeps its correct compat translation from dump_one_state(), and no child is attached to the inbound request.

Fixes 5f3eea6b7e8f ("xfrm/compat: Attach xfrm dumps to 64=>32 bit translator")
Assisted-by Codex:gpt-5.6-sol Codex:gpt-5.5-cyber
---
 net/xfrm/xfrm_user.c | 12 ------------
 1 file changed, 12 deletions(-)
net/xfrm/xfrm_user.c +0 -12
index 980dbeb5a57de..a2587c7e796b4 100644
@@ -1877,7 +1877,6 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct net *net = sock_net(skb->sk);
 	struct xfrm_state *x;
 	struct xfrm_userspi_info *p;
-	struct xfrm_translator *xtr;
 	struct sk_buff *resp_skb;
 	xfrm_address_t *daddr;
 	int family;
@@ -1943,17 +1942,6 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
 		goto out;
 	}
 
-	xtr = xfrm_get_translator();
-	if (xtr) {
-		err = xtr->alloc_compat(skb, nlmsg_hdr(skb));
-
-		xfrm_put_translator(xtr);
-		if (err) {
-			kfree_skb(resp_skb);
-			goto out;
-		}
-	}
-
 	err = nlmsg_unicast(xfrm_net_nlsk(net, skb), resp_skb, NETLINK_CB(skb).portid);
 
 out:
Signature · 1 line
2.53.0
author maintainer
#9 lore raw

PATCH 9/438 xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject()

In reply to Greg Kroah-Hartman

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

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

From: Eric Dumazet <[email protected]>

[ Upstream commit d2f5082f9e84653fa1a9e8aebaaff23e688f5e19 ]

syzbot reported a suspicious RCU usage warning in ip6_pkt_drop():

WARNING: suspicious RCU usage in ip6_pkt_drop include/net/addrconf.h:389 suspicious rcu_dereference_check() usage!

  Call Trace:
   __in6_dev_get_safely include/net/addrconf.h:389 [inline]
   ip6_pkt_drop+0x596/0x610 net/ipv6/route.c:4620
   ip6_pkt_discard+0x1c/0x30 net/ipv6/route.c:4651
   xfrm_trans_reinject+0x324/0x630 net/xfrm/xfrm_input.c:806
   process_one_work kernel/workqueue.c:3322 [inline]
   process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
   worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486

When commit 4f4920669d21 ("xfrm: Reinject transport-mode packets through workqueue") converted xfrm_trans_reinject from a tasklet to a workqueue, the reinjection loop ceased running in softirq context. Workqueue workers run in process context where local_bh_disable() does not enter an RCU read-side critical section under CONFIG_PREEMPT_RCU.

Because finish callbacks (such as ip6_rcv_finish) expect to run under an RCU read lock (performing route lookups, l3mdev lookups, and accessing RCU-protected data structures), invoking them in workqueue context without rcu_read_lock() triggers RCU lockdep warnings.

Furthermore, packets queued to the workqueue via xfrm_trans_queue_net() may carry non-refcounted (noref) dst entries (e.g. from ip_route_input_noref). Additionally, on netdevice unregistration, dst_dev_put() replaces dst->dev with blackhole_netdev, so dst entries do not keep skb->dev alive while queued in the workqueue.

Fix these issues by:
1. Calling skb_dst_force(skb) in xfrm_trans_queue_net() while still in the caller's RCU section to ensure dst is reference-counted before queuing.
2. Holding a reference on skb->dev via dev_hold()/dev_put() across workqueue deferral so skb->dev remains valid during finish() callback processing.
3. Acquiring rcu_read_lock() around the finish callback invocation loop in xfrm_trans_reinject().

Fixes 4f4920669d21 ("xfrm: Reinject transport-mode packets through workqueue")
Cc Steffen Klassert <[email protected]>
Cc Liu Jian <[email protected]>
---
 net/xfrm/xfrm_input.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
net/xfrm/xfrm_input.c +11 -0
index eecab337bd0a7..8f6109eada7ea 100644
@@ -800,12 +800,17 @@ static void xfrm_trans_reinject(struct work_struct *work)
 	spin_unlock_bh(&trans->queue_lock);
 
 	local_bh_disable();
+	rcu_read_lock();
 	while ((skb = __skb_dequeue(&queue))) {
 		struct net *net = XFRM_TRANS_SKB_CB(skb)->net;
+		struct net_device *dev = skb->dev;
 
 		XFRM_TRANS_SKB_CB(skb)->finish(net, NULL, skb);
+		if (dev)
+			dev_put(dev);
 		put_net(net);
 	}
+	rcu_read_unlock();
 	local_bh_enable();
 }
 
@@ -821,12 +826,18 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
 	if (skb_queue_len(&trans->queue) >= READ_ONCE(net_hotdata.max_backlog))
 		return -ENOBUFS;
 
+	if (skb_dst(skb) && !skb_dst_force(skb))
+		return -EHOSTUNREACH;
+
 	BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb));
 
 	hold_net = maybe_get_net(net);
 	if (!hold_net)
 		return -ENODEV;
 
+	if (skb->dev)
+		dev_hold(skb->dev);
+
 	XFRM_TRANS_SKB_CB(skb)->finish = finish;
 	XFRM_TRANS_SKB_CB(skb)->net = hold_net;
 	spin_lock_bh(&trans->queue_lock);
Signature · 1 line
2.53.0
author maintainer
#10 lore raw

PATCH 10/438 esp: downgrade zerocopy managed frags before mutating skb frags

In reply to Greg Kroah-Hartman

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

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

From: Maher Azzouzi <[email protected]>

[ Upstream commit f89416eb3db151170a6f3c6dfc5239d26cdce4d2 ]

On the out-of-place output path (esp->inplace == false) ESP rewrites the skb frag array: esp_output_head() appends a trailer frag and esp_output_tail() replaces the frags with a destination page, both referenced with get_page().

When the skb carries zerocopy managed frags (SKBFL_MANAGED_FRAG_REFS) the payload frags are owned by the ubuf and must not be referenced or unreferenced individually, but ESP mutates the frag array without ever downgrading the skb. This breaks the managed-frag invariant two ways:

- esp_ssg_unref() walks the source scatterlist and drops a page reference for every frag, including the ubuf-owned payload frags, pushing their refcount below the GUP pin bias while the pages are still pinned, i.e. a use-after-free of the zerocopy pages;

- esp_output_tail() installs its destination page as frag 0 with get_page() but leaves SKBFL_MANAGED_FRAG_REFS set, so skb_release_data() takes the skip_unref branch and never drops that reference, leaking the x->xfrag page at packet rate.

Fix this the way every other frag-mutating site does (__ip_append_data(), __ip6_append_data(), tcp_sendmsg_locked()) and call skb_zcopy_downgrade_managed() before ESP touches the frag array: it takes a real reference on each existing frag and clears SKBFL_MANAGED_FRAG_REFS, so the per-frag unref in esp_ssg_unref() and the frag release in skb_release_data() are both balanced and no mixed-ownership frag array is left behind.

Fixes 753f1ca4e1e5 ("net: introduce managed frags infrastructure")
---
 net/ipv4/esp4.c | 6 ++++++
 net/ipv6/esp6.c | 6 ++++++
 2 files changed, 12 insertions(+)
net/ipv4/esp4.c +6 -0
index dfc81ee969ae0..faa48f5b97395 100644
@@ -441,6 +441,12 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
 
 			esp->inplace = false;
 
+			/* Take real page refs and clear SKBFL_MANAGED_FRAG_REFS before
+			 * we mutate the frag array, so the per-frag unref stays balanced
+			 * for zerocopy managed frags (see __ip_append_data()).
+			 */
+			skb_zcopy_downgrade_managed(skb);
+
 			allocsize = ALIGN(tailen, L1_CACHE_BYTES);
 
 			spin_lock_bh(&x->lock);
net/ipv6/esp6.c +6 -0
index 296b57926abb9..a3a3857eed98a 100644
@@ -470,6 +470,12 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
 
 			esp->inplace = false;
 
+			/* Take real page refs and clear SKBFL_MANAGED_FRAG_REFS before
+			 * we mutate the frag array, so the per-frag unref stays balanced
+			 * for zerocopy managed frags (see __ip_append_data()).
+			 */
+			skb_zcopy_downgrade_managed(skb);
+
 			allocsize = ALIGN(tailen, L1_CACHE_BYTES);
 
 			spin_lock_bh(&x->lock);
Signature · 1 line
2.53.0
author maintainer
#11 lore raw

PATCH 11/438 arm64: dts: amlogic: t7: use the real UART pclk

In reply to Greg Kroah-Hartman

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

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

From: Lucas Tanure <[email protected]>

[ Upstream commit 882de800bf583dd15969836088789edbf035a944 ]

uart_a listed the 24MHz crystal for all three of its clocks because the T7 clock controller driver did not exist when these boards were added.

That leaves the real UART bus clock without a user, so the kernel turns it off when it disables unused clocks at the end of boot, and the board hangs.

Update the board DTS files to point uart_a's pclk to CLKID_SYS_UART_A instead of the dummy crystal clock.

Fixes 4fef056588f5 ("arm64: dts: amlogic-t7-a311d2-khadas-vim4: add initial device-tree")
Fixes 6f048cc7a635 ("arm64: dts: add board AN400")
Assisted-by Claude:claude-fable-5
---
 arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts       | 2 +-
 arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts +1 -1
index cab2ee9ea0d31..ca7536f772ff1 100644
@@ -33,7 +33,7 @@ xtal: xtal-clk {
 };
 
 &uart_a {
-	clocks = <&xtal>, <&xtal>, <&xtal>;
+	clocks = <&xtal>, <&clkc_periphs CLKID_SYS_UART_A>, <&xtal>;
 	clock-names = "xtal", "pclk", "baud";
 	status = "okay";
 };
arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts +1 -1
index c41525a34b721..75d81ad6830df 100644
@@ -266,6 +266,6 @@ &sd_emmc_c {
 
 &uart_a {
 	status = "okay";
-	clocks = <&xtal>, <&xtal>, <&xtal>;
+	clocks = <&xtal>, <&clkc_periphs CLKID_SYS_UART_A>, <&xtal>;
 	clock-names = "xtal", "pclk", "baud";
 };
Signature · 1 line
2.53.0
author maintainer
#12 lore raw

PATCH 12/438 arm64: dts: amlogic: t7: khadas-vim4: allow the SD card to be power cycled

In reply to Greg Kroah-Hartman

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

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

From: Lucas Tanure <[email protected]>

[ Upstream commit c793a084ab3088744516aef437b4239d0d98623f ]

SD cards start at 3.3V and switch to 1.8V to reach UHS-I speeds. Some cards refuse that switch, and the SD specification says the only way to recover is to power the card off and start again.

SD_3V3 is marked regulator-always-on, so the supply never goes off, the card stays stuck half way through the switch, and the MMC core retries forever:

mmc1: error -95 whilst initialising SD card

Drop regulator-always-on. regulator-boot-on still turns the supply on at boot, and a card that refuses the switch now falls back to high speed instead of failing to initialise.

Fixes 8c45bf9ae4ef ("arm64: dts: amlogic: t7: khadas-vim4: Add power regulators")
Assisted-by Claude:claude-fable-5
---
 arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 1 -
 1 file changed, 1 deletion(-)
arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts +0 -1
index 75d81ad6830df..c94afaaf8826e 100644
@@ -71,7 +71,6 @@ sd_3v3: regulator-sdcard-3v3 {
 		vin-supply = <&vddao_3v3>;
 		gpio = <&gpio GPIOD_11 GPIO_ACTIVE_LOW>;
 		regulator-boot-on;
-		regulator-always-on;
 	};
 
 	sdio_pwrseq: sdio-pwrseq {
Signature · 1 line
2.53.0
author maintainer
#13 lore raw

PATCH 13/438 arm64: dts: amlogic: t7: fix the pin groups of two PWM outputs

In reply to Greg Kroah-Hartman

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

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

From: Lucas Tanure <[email protected]>

[ Upstream commit ae7be5c58a819259e5eb98a3abfa60842478f2ae ]

Two of the PWM outputs can each appear on more than one pin, but the description named a single group that does not exist, so anything using it refused to start.

Name the real groups instead, one entry per pin, the same way the other multi-pin PWM output is already described.

Fixes 2a2a7b9701a7 ("arm64: dts: amlogic: t7: Add PWM pinctrl nodes")
Assisted-by Claude:claude-opus-5
---
 arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 32 ++++++++++++++++++---
 1 file changed, 28 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi +28 -4
index cc371fcd18967..66605b200b708 100644
@@ -458,9 +458,25 @@ mux {
 					};
 				};
 
-				pwm_ao_g_pins: pwm-ao-g {
+				pwm_ao_g_d11_pins: pwm-ao-g-d11 {
 					mux {
-						groups = "pwm_ao_g";
+						groups = "pwm_ao_g_d11";
+						function = "pwm_ao_g";
+						bias-disable;
+					};
+				};
+
+				pwm_ao_g_d7_pins: pwm-ao-g-d7 {
+					mux {
+						groups = "pwm_ao_g_d7";
+						function = "pwm_ao_g";
+						bias-disable;
+					};
+				};
+
+				pwm_ao_g_e_pins: pwm-ao-g-e {
+					mux {
+						groups = "pwm_ao_g_e";
 						function = "pwm_ao_g";
 						bias-disable;
 					};
@@ -474,9 +490,17 @@ mux {
 					};
 				};
 
-				pwm_ao_h_pins: pwm-ao-h {
+				pwm_ao_h_d5_pins: pwm-ao-h-d5 {
+					mux {
+						groups = "pwm_ao_h_d5";
+						function = "pwm_ao_h";
+						bias-disable;
+					};
+				};
+
+				pwm_ao_h_d10_pins: pwm-ao-h-d10 {
 					mux {
-						groups = "pwm_ao_h";
+						groups = "pwm_ao_h_d10";
 						function = "pwm_ao_h";
 						bias-disable;
 					};
Signature · 1 line
2.53.0
author maintainer
#14 lore raw

PATCH 14/438 arm64: dts: amlogic: t7: khadas-vim4: add the PWM-driven supplies

In reply to Greg Kroah-Hartman

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

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

From: Lucas Tanure <[email protected]>

[ Upstream commit 1e5a53bd16ac501e68463e84023d1bff543cc696 ]

The board powers its two CPU clusters, the GPU, the NPU, the memory and the always-on domain from regulators steered by PWM outputs. None of them were described, so Linux treated those outputs as unused and switched them off part way through boot. The supplies then drifted away from the levels the bootloader had set, which showed up as random hangs and memory corruption.

Describe each supply so it has an owner and is left alone.

The voltage ranges are read off the feedback networks on the board schematic. VDDNPU is deliberately not the range in Amlogic's own device tree: this board fits a different feedback resistor, which puts it about 40mV higher at both ends.

Fixes 8c45bf9ae4ef ("arm64: dts: amlogic: t7: khadas-vim4: Add power regulators")
Assisted-by Claude:claude-opus-5
---
 .../amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 110 +++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts +109 -1
index c94afaaf8826e..77abfd555ec5b 100644
@@ -104,6 +104,66 @@ vcc5v0_usb: regulator-vcc-usb {
 		enable-active-high;
 	};
 
+	vdd_ddr: regulator-vddddr {
+		/*
+		 * SY8003ADFC Regulator.
+		 */
+		compatible = "pwm-regulator";
+		regulator-name = "VDDDDR";
+		regulator-min-microvolt = <690000>;
+		regulator-max-microvolt = <890000>;
+		pwm-supply = <&dc_in>;
+		pwms = <&pwm_ao_gh 0 1500 0>;
+		pwm-dutycycle-range = <100 0>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	vdd_ee: regulator-vddee {
+		/*
+		 * MP8756GD Regulator.
+		 */
+		compatible = "pwm-regulator";
+		regulator-name = "VDDEE";
+		regulator-min-microvolt = <700000>;
+		regulator-max-microvolt = <922000>;
+		pwm-supply = <&dc_in>;
+		pwms = <&pwm_ao_ab 0 1500 0>;
+		pwm-dutycycle-range = <100 0>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	vdd_gpu: regulator-vddgpu {
+		/*
+		 * SY8003ADFC Regulator.
+		 */
+		compatible = "pwm-regulator";
+		regulator-name = "VDDGPU";
+		regulator-min-microvolt = <700000>;
+		regulator-max-microvolt = <922000>;
+		pwm-supply = <&dc_in>;
+		pwms = <&pwm_ao_ef 0 1500 0>;
+		pwm-dutycycle-range = <100 0>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	vdd_npu: regulator-vddnpu {
+		/*
+		 * SY8003ADFC Regulator.
+		 */
+		compatible = "pwm-regulator";
+		regulator-name = "VDDNPU";
+		regulator-min-microvolt = <733000>;
+		regulator-max-microvolt = <933000>;
+		pwm-supply = <&dc_in>;
+		pwms = <&pwm_ao_ef 1 1500 0>;
+		pwm-dutycycle-range = <100 0>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
 	vddao_1v8: regulator-vddao-1v8 {
 		compatible = "regulator-fixed";
 		regulator-name = "VDDAO_1V8";
@@ -122,6 +182,36 @@ vddao_3v3: regulator-vddao-3v3 {
 		regulator-always-on;
 	};
 
+	vddcpu_a: regulator-vddcpu-a {
+		/*
+		 * MP8756GD Regulator.
+		 */
+		compatible = "pwm-regulator";
+		regulator-name = "VDDCPU_A";
+		regulator-min-microvolt = <689000>;
+		regulator-max-microvolt = <1049000>;
+		pwm-supply = <&dc_in>;
+		pwms = <&pwm_ao_cd 1 1500 0>;
+		pwm-dutycycle-range = <100 0>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	vddcpu_b: regulator-vddcpu-b {
+		/*
+		 * MP8756GD Regulator.
+		 */
+		compatible = "pwm-regulator";
+		regulator-name = "VDDCPU_B";
+		regulator-min-microvolt = <689000>;
+		regulator-max-microvolt = <1049000>;
+		pwm-supply = <&dc_in>;
+		pwms = <&pwm_ao_ab 1 1500 0>;
+		pwm-dutycycle-range = <100 0>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
 	vddio_1v8: regulator-vddio-1v8 {
 		compatible = "regulator-fixed";
 		regulator-name = "VDDIO_1V8";
@@ -172,9 +262,27 @@ &pwm_ab {
 	pinctrl-names = "default";
 };
 
+&pwm_ao_ab {
+	status = "okay";
+	pinctrl-0 = <&pwm_ao_a_pins>, <&pwm_ao_b_pins>;
+	pinctrl-names = "default";
+};
+
 &pwm_ao_cd {
 	status = "okay";
-	pinctrl-0 = <&pwm_ao_c_d_pins>;
+	pinctrl-0 = <&pwm_ao_c_d_pins>, <&pwm_ao_d_pins>;
+	pinctrl-names = "default";
+};
+
+&pwm_ao_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_ao_e_pins>, <&pwm_ao_f_pins>;
+	pinctrl-names = "default";
+};
+
+&pwm_ao_gh {
+	status = "okay";
+	pinctrl-0 = <&pwm_ao_g_e_pins>;
 	pinctrl-names = "default";
 };
 
Signature · 1 line
2.53.0
author maintainer
#15 lore raw

PATCH 15/438 arm64: dts: amlogic: t7: fix the pin groups of the vsync PWM

In reply to Greg Kroah-Hartman

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

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

From: Lucas Tanure <[email protected]>

[ Upstream commit 406292fd75f95aa3010fec95b5beb5a8b7e3ba3a ]

The vsync PWM output can appear on either of two pins, but the description named a single group that does not exist, so anything using it would refuse to start.

Name the real groups instead, one entry per pin. No board describes this output yet, so nothing changes today.

Fixes 2a2a7b9701a7 ("arm64: dts: amlogic: t7: Add PWM pinctrl nodes")
Assisted-by Claude:claude-opus-5
---
 arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi +10 -2
index 66605b200b708..1711e24cce17b 100644
@@ -546,9 +546,17 @@ mux {
 					};
 				};
 
-				pwm_vs_pins: pwm-vs {
+				pwm_vs_y_pins: pwm-vs-y {
 					mux {
-						groups = "pwm_vs";
+						groups = "pwm_vs_y";
+						function = "pwm_vs";
+						bias-disable;
+					};
+				};
+
+				pwm_vs_h_pins: pwm-vs-h {
+					mux {
+						groups = "pwm_vs_h";
 						function = "pwm_vs";
 						bias-disable;
 					};
Signature · 1 line
2.53.0
author maintainer
#16 lore raw

PATCH 16/438 ARM: socfpga: select the PL310 erratum 753970 workaround

In reply to Greg Kroah-Hartman

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

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

From: Pengpeng Hou <[email protected]>

[ Upstream commit cfc1e9a543e3589ba200795b6e7fd8ef4314efdf ]

ARCH_INTEL_SOCFPGA selects CACHE_L2X0 and several PL310 erratum workarounds. The 753970 workaround is still conditioned on PL310, but that Kconfig symbol no longer exists, so this one selection is always disabled.

Select PL310_ERRATA_753970 directly, consistently with the other PL310 workarounds required by the platform.

Fixes fbc125afdc50 ("ARM: socfpga: Turn on ARM errata for L2 cache")
---
 arch/arm/mach-socfpga/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-socfpga/Kconfig +1 -1
index eb72c240c2486..528c5c1368c37 100644
@@ -16,7 +16,7 @@ menuconfig ARCH_INTEL_SOCFPGA
 	select ARM_ERRATA_775420
 	select PL310_ERRATA_588369
 	select PL310_ERRATA_727915
-	select PL310_ERRATA_753970 if PL310
+	select PL310_ERRATA_753970
 	select PL310_ERRATA_769419
 	select RESET_CONTROLLER
 
Signature · 1 line
2.53.0
author maintainer
#17 lore raw

PATCH 17/438 RDMA/siw: Clear association under lock if siw_qp_modify fails in siw_accept

In reply to Greg Kroah-Hartman

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

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

From: Guoqing Jiang <[email protected]>

[ Upstream commit 32cd87f54dd1070020e664ccb0312a9f0fea79b4 ]

We need to clear cep before release state_lock as siw_qp_llp_close and siw_qp_modify->siw_qp_llp_close did.

Otherwise if siw_qp_modify() fails in siw_accept(), the QP's state_lock is released before the error path cleanup. A concurrent ibv_modify_qp() transitioning the QP to ERROR can race in this window:

siw_accept() ibv_modify_qp(ERROR)
---------------------- ----------------------
siw_qp_modify() fails
up_write(&qp->state_lock)

                                     down_write(&qp->state_lock)
                                     nextstate_from_idle():
				     if (qp->cep)
                                       siw_cep_put(qp->cep) <- frees cep
                                       qp->cep = NULL
  goto error
    cep->qp = NULL                   <- UAF

Clear qp->cep and drop the association reference taken by siw_cep_get(), all under the write lock held from the initial down_write(&qp->state_lock). Thread B therefore sees qp->cep == NULL, skips its own put, and cannot free the cep before siw_accept() is done with it.

---
 drivers/infiniband/sw/siw/siw_cm.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/infiniband/sw/siw/siw_cm.c +5 -2
index 0245b25e72718..ed49818793dde 100644
@@ -1719,9 +1719,12 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
 			   SIW_QP_ATTR_STATE | SIW_QP_ATTR_LLP_HANDLE |
 				   SIW_QP_ATTR_ORD | SIW_QP_ATTR_IRD |
 				   SIW_QP_ATTR_MPA);
+	if (rv) {
+		qp->cep = NULL;
+		siw_cep_put(cep);
+		goto error_unlock;
+	}
 	up_write(&qp->state_lock);
-	if (rv)
-		goto error;
 
 	siw_dbg_cep(cep, "[QP %u]: send mpa reply, %d byte pdata\n",
 		    qp_id(qp), params->private_data_len);
Signature · 1 line
2.53.0
author maintainer
#18 lore raw

PATCH 18/438 RDMA/rxe: validate access flags before swapping the MRs PD

In reply to Greg Kroah-Hartman

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

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

From: Norbert Szetei <[email protected]>

[ Upstream commit ae36a5b609ae79f4de966328b78d2584be9719a4 ]

rxe_rereg_user_mr() reassigns mr->ibmr.pd first and only then validates the IB_MR_REREG_ACCESS argument:

	if (flags & IB_MR_REREG_PD) {
		rxe_put(old_pd);
		rxe_get(pd);
		mr->ibmr.pd = ibpd;
	}

	if (flags & IB_MR_REREG_ACCESS) {
		if (access & ~RXE_ACCESS_SUPPORTED_MR)
			return ERR_PTR(-EOPNOTSUPP);
		mr->access = access;
	}

Both flags pass the entry check because RXE_MR_REREG_SUPPORTED is IB_MR_REREG_PD | IB_MR_REREG_ACCESS, so a caller can reach the access check with mr->ibmr.pd already reassigned.

mr->ibmr.pd is owned by the core, which adjusts pd->usecnt only on the success path: ib_uverbs_rereg_mr() jumps to put_new_uobj on a driver error without undoing the reassignment, so mr->pd == new_pd while the usecnts still charge the MR to orig_pd. ib_dereg_mr_user() then decrements new_pd, whose count can reach zero while a memory window still references it; uverbs_free_pd() frees the PD on that count alone and rxe_mw_cleanup() writes to freed memory:

  BUG: KASAN: slab-use-after-free in __rxe_put+0x31/0xa0
  Write of size 4 at addr ffff8881301dd690 by task rxe_poc/591
   __rxe_put+0x31/0xa0
   rxe_mw_cleanup+0x42/0x200
   __rxe_cleanup+0x115/0x370
   rxe_dealloc_mw+0x4c/0x80
  Allocated by task 591:
   ib_uverbs_alloc_pd+0x258/0x540
  Freed by task 591:
   ib_dealloc_pd_user+0x174/0x210
   uverbs_free_pd+0x8d/0xc0
   ib_uverbs_dealloc_pd+0x18e/0x1d0

Validate the access flags before mutating any state so the callback either applies every requested change or none.

---
 drivers/infiniband/sw/rxe/rxe_verbs.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/infiniband/sw/rxe/rxe_verbs.c +7 -6
index 1ec130fee8ea7..f8c29fc5961d7 100644
@@ -1327,19 +1327,20 @@ static struct ib_mr *rxe_rereg_user_mr(struct ib_mr *ibmr, int flags,
 	if (err)
 		return ERR_PTR(err);
 
+	if ((flags & IB_MR_REREG_ACCESS) &&
+	    (access & ~RXE_ACCESS_SUPPORTED_MR)) {
+		rxe_err_mr(mr, "access = %#x not supported\n", access);
+		return ERR_PTR(-EOPNOTSUPP);
+	}
+
 	if (flags & IB_MR_REREG_PD) {
 		rxe_put(old_pd);
 		rxe_get(pd);
 		mr->ibmr.pd = ibpd;
 	}
 
-	if (flags & IB_MR_REREG_ACCESS) {
-		if (access & ~RXE_ACCESS_SUPPORTED_MR) {
-			rxe_err_mr(mr, "access = %#x not supported\n", access);
-			return ERR_PTR(-EOPNOTSUPP);
-		}
+	if (flags & IB_MR_REREG_ACCESS)
 		mr->access = access;
-	}
 
 	return NULL;
 }
Signature · 1 line
2.53.0
author maintainer
#19 lore raw

PATCH 19/438 RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB access

In reply to Greg Kroah-Hartman

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

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

From: Gang Yan <[email protected]>

[ Upstream commit d10e2a08799e858d3e71ea4169bcd018f216d444 ]

mr_check_range() validates that [iova, iova+length) falls within the registered MR range using wraparound-prone arithmetic:

    if (iova < mr->ibmr.iova ||
        iova + length > mr->ibmr.iova + mr->ibmr.length)

A remote peer can craft an RDMA-Write/Read RETH so that iova + length wraps to 0 (e.g. iova=0xfffffffffffffff8, length=8), bypassing the check. rxe_mr_iova_to_index() then computes a huge index (int idx, only guarded by WARN_ON) and rxe_mr_copy_xarray() dereferences mr->page_info[huge], causing an out-of-bounds read/write and a kernel oops that is triggerable by an unauthenticated remote peer.

Rewrite the check in overflow-safe form; the first two clauses guarantee that the subsequent subtractions do not underflow:

    if (iova < mr->ibmr.iova ||
        length > mr->ibmr.length ||
        iova - mr->ibmr.iova > mr->ibmr.length - length)

With the fix, mr_check_range() returns -EINVAL for the crafted iova and the responder reports REMOTE_ACCESS_ERROR instead of triggering the OOB.

---
 drivers/infiniband/sw/rxe/rxe_mr.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/infiniband/sw/rxe/rxe_mr.c +2 -1
index 875eceb55fdfa..71d9ea4772890 100644
@@ -33,7 +33,8 @@ int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length)
 	case IB_MR_TYPE_USER:
 	case IB_MR_TYPE_MEM_REG:
 		if (iova < mr->ibmr.iova ||
-		    iova + length > mr->ibmr.iova + mr->ibmr.length) {
+		    length > mr->ibmr.length ||
+		    iova - mr->ibmr.iova > mr->ibmr.length - length) {
 			rxe_dbg_mr(mr, "iova/length out of range\n");
 			return -EINVAL;
 		}
Signature · 1 line
2.53.0
author maintainer
#20 lore raw

PATCH 20/438 xfrm: hold net_device reference under RCU in bundle creation

In reply to Greg Kroah-Hartman

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

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

From: Cen Zhang (Microsoft Security FORGE Labs) <[email protected]>

[ Upstream commit 9fa903b24b1f46b4ff5443bcd4aca23e5c57f9c1 ]

xfrm_bundle_create() and xfrm_create_dummy_bundle() read dst->dev into a local pointer without taking a device reference, then pass it to xfrm_fill_dst(). A concurrent RTM_DELLINK replaces dst->dev via dst_dev_put() and frees the old net_device, causing a use-after-free when xfrm6_fill_dst() later dereferences the stale dev pointer.

  BUG: KASAN: slab-use-after-free in xfrm6_fill_dst+0x82c/0x860
  (net/ipv6/xfrm6_policy.c:86 netdev_hold())
  Read of size 8 at addr ffff8880142fe588 by task exploit/153
  Call Trace:
   xfrm6_fill_dst+0x82c/0x860
   xfrm_resolve_and_create_bundle+0x21d4/0x2bd0
   xfrm_lookup_with_ifid+0x485/0x1640
   ip6_dst_lookup_flow+0x19b/0x1e0
   udpv6_sendmsg+0x1443/0x2dd0

Fix this by reading dst->dev via dst_dev_rcu() and keeping the RCU read-side critical section active until xfrm_fill_dst() has taken the required device references.

Fixes 25ee3286dcbc ("[IPSEC]: Merge common code into xfrm_bundle_create")
Fixes a0073fe18e71 ("xfrm: Add a state resolution packet queue")
Assisted-by GitHub-Copilot:claude-opus-4.6
---
 net/xfrm/xfrm_policy.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)
net/xfrm/xfrm_policy.c +15 -5
index 932a313b9460a..513c9f2283347 100644
@@ -2770,9 +2770,12 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 	xdst0->path = dst;
 
 	err = -ENODEV;
-	dev = dst->dev;
-	if (!dev)
+	rcu_read_lock();
+	dev = dst_dev_rcu(dst);
+	if (!dev) {
+		rcu_read_unlock();
 		goto free_dst;
+	}
 
 	xfrm_init_path(xdst0, dst, nfheader_len);
 	xfrm_init_pmtu(bundle, nx);
@@ -2780,8 +2783,10 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 	for (xdst_prev = xdst0; xdst_prev != (struct xfrm_dst *)dst;
 	     xdst_prev = (struct xfrm_dst *) xfrm_dst_child(&xdst_prev->u.dst)) {
 		err = xfrm_fill_dst(xdst_prev, dev, fl);
-		if (err)
+		if (err) {
+			rcu_read_unlock();
 			goto free_dst;
+		}
 
 		xdst_prev->u.dst.header_len = header_len;
 		xdst_prev->u.dst.trailer_len = trailer_len;
@@ -2789,6 +2794,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 		trailer_len -= xdst_prev->u.dst.xfrm->props.trailer_len;
 	}
 
+	rcu_read_unlock();
 	return &xdst0->u.dst;
 
 put_states:
@@ -3058,11 +3064,15 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
 	xfrm_init_path((struct xfrm_dst *)dst1, dst, 0);
 
 	err = -ENODEV;
-	dev = dst->dev;
-	if (!dev)
+	rcu_read_lock();
+	dev = dst_dev_rcu(dst);
+	if (!dev) {
+		rcu_read_unlock();
 		goto free_dst;
+	}
 
 	err = xfrm_fill_dst(xdst, dev, fl);
+	rcu_read_unlock();
 	if (err)
 		goto free_dst;
 
Signature · 1 line
2.53.0
author maintainer
#21 lore raw

PATCH 21/438 firmware: arm_scpi: reject DVFS OPP count above MAX_DVFS_OPPS

In reply to Greg Kroah-Hartman

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

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

From: Xixin Liu <[email protected]>

[ Upstream commit 32471d84a487c7fd74532bc96be56f8028cf4a3f ]

scpi_dvfs_get_info() already rejected a zero opp_count, but still trusted any larger value from the SCP firmware. The shared-memory reply only holds MAX_DVFS_OPPS entries in buf.opps[]; a bigger count over-reads that array and then sizes the allocated OPP table incorrectly (garbage OPPs / OOB). The missing upper bound dates back to the original SCPI DVFS support.

Reject zero and out-of-range counts in one check and return -EINVAL.

Fixes 8cb7cf56c9fe ("firmware: add support for ARM System Control and Power Interface(SCPI) protocol")
---
 drivers/firmware/arm_scpi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/arm_scpi.c +2 -2
index 2acad5fa5a286..6eeb0ad9b0085 100644
@@ -631,8 +631,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
 	if (ret)
 		return ERR_PTR(ret);
 
-	if (!buf.opp_count)
-		return ERR_PTR(-ENOENT);
+	if (!buf.opp_count || buf.opp_count > MAX_DVFS_OPPS)
+		return ERR_PTR(-EINVAL);
 
 	info = kmalloc_obj(*info);
 	if (!info)
Signature · 1 line
2.53.0
author maintainer
#22 lore raw

PATCH 22/438 clk: scpi: bound-check DVFS index in scpi_dvfs_recalc_rate

In reply to Greg Kroah-Hartman

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

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

From: Xixin Liu <[email protected]>

[ Upstream commit 70f4b78d560e592cbf3325b162424737d032fc1d ]

dvfs_get_idx() may return an out-of-range index if the SCP firmware is buggy or returns a stale value. Only negative indexes were rejected, so a large index walked past info->opps and could treat garbage as a clock rate (KASAN OOB / wrong frequency to consumers). The missing upper bound dates back to the original SCPI clock driver.

Treat indexes >= opp count as invalid and return 0, same as idx < 0.

Fixes cd52c2a4b5c4 ("clk: add support for clocks provided by SCP(System Control Processor)")
---
 drivers/clk/clk-scpi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/clk-scpi.c +1 -1
index 24cee7c9fda6c..3c33a9e3c6909 100644
@@ -85,7 +85,7 @@ static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw,
 	int idx = clk->scpi_ops->dvfs_get_idx(clk->id);
 	const struct scpi_opp *opp;
 
-	if (idx < 0)
+	if (idx < 0 || idx >= clk->info->count)
 		return 0;
 
 	opp = clk->info->opps + idx;
Signature · 1 line
2.53.0
author maintainer
#23 lore raw

PATCH 23/438 clk: scpi: register scpi-cpufreq once and clear on failure

In reply to Greg Kroah-Hartman

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

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

From: Xixin Liu <[email protected]>

[ Upstream commit ab06cf8152dace327cd873188e4a036c4e0b5944 ]

scpi_clocks_probe() walks clock children and, for each DVFS provider, calls platform_device_register_simple("scpi-cpufreq", -1, ...). Two related bugs:

Since all DVFS providers register the fixed scpi-cpufreq device using PLATFORM_DEVID_NONE, a second registration fails with -EEXIST and overwrites the pointer to the successfully registered device. The first device can then no longer be unregistered.

Register the virtual device only once. If registration fails, reset the pointer to NULL so a subsequent DVFS provider can retry and the global pointer only represents a successfully registered device.

Fixes 9490f01e2471 ("clk: scpi: add support for cpufreq virtual device")
Fixes 67bcc2c5f1da ("clk: scpi: don't add cpufreq device if the scpi dvfs node is disabled")

(sudeep.holla: reworded the commit message to improve readability)

---
 drivers/clk/clk-scpi.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/clk/clk-scpi.c +5 -1
index 3c33a9e3c6909..e1891351c221a 100644
@@ -284,10 +284,14 @@ static int scpi_clocks_probe(struct platform_device *pdev)
 		if (match->data != &scpi_dvfs_ops)
 			continue;
 		/* Add the virtual cpufreq device if it's DVFS clock provider */
+		if (cpufreq_dev)
+			continue;
 		cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
 							      -1, NULL, 0);
-		if (IS_ERR(cpufreq_dev))
+		if (IS_ERR(cpufreq_dev)) {
 			pr_warn("unable to register cpufreq device");
+			cpufreq_dev = NULL;
+		}
 	}
 	return 0;
 }
Signature · 1 line
2.53.0
author maintainer
#24 lore raw

PATCH 24/438 RDMA/rxe: Restore HMM_PFN_WRITE check in ODP write paths

In reply to Greg Kroah-Hartman

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

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

From: Weiming Shi <[email protected]>

[ Upstream commit 769001ce838d907ecaa95f1d0a4e8fc86f761f9f ]

Commit 0b261d7c1cd3 ("RDMA/rxe: Break endless pagefault loop for RO pages") dropped the access permission test from rxe_check_pagefault() and left only HMM_PFN_VALID. A page faulted in read-only, for example a page-cache folio behind a PROT_READ file mapping, then satisfies the check and ODP write operations (RDMA WRITE, RDMA READ response, SEND payload, atomics) modify it through kmap without ever breaking CoW.

An unprivileged user can register an ODP MR over such a mapping and have incoming RDMA traffic overwrite the page cache of a file it only holds O_RDONLY, including /etc/passwd or setuid binaries. This is the same primitive class as Dirty COW and CVE-2022-2590.

mlx5 has the missing invariant: its ODP path sets the device write bit only for pfns that carry HMM_PFN_WRITE. Restore it in rxe by requiring HMM_PFN_WRITE in rxe_check_pagefault() for every operation except RXE_PAGEFAULT_RDONLY. A write to a non-writable VMA now fails the one fault attempt with -EPERM from hmm_vma_fault() instead of re-faulting forever. For a writable VMA the fault breaks CoW and the write lands in the private page.

Keep pmem flushes on the read-only check. arch_wb_cache_pmem() never modifies memory, and the FLUSH access bits do not make the umem writable, so classifying flushes as writes would make every flush against a flush-only MR fail.

---
 drivers/infiniband/sw/rxe/rxe_odp.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/infiniband/sw/rxe/rxe_odp.c +11 -5
index 1b1c4a0c71100..0f24a55c06371 100644
@@ -125,19 +125,23 @@ int rxe_odp_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length,
 }
 
 static inline bool rxe_check_pagefault(struct ib_umem_odp *umem_odp, u64 iova,
-				       int length)
+				       int length, bool write)
 {
 	bool need_fault = false;
+	u64 access = HMM_PFN_VALID;
 	u64 addr;
 	int idx;
 
+	if (write)
+		access |= HMM_PFN_WRITE;
+
 	addr = iova & (~(BIT(umem_odp->page_shift) - 1));
 
 	/* Skim through all pages that are to be accessed. */
 	while (addr < iova + length) {
 		idx = (addr - ib_umem_start(umem_odp)) >> umem_odp->page_shift;
 
-		if (!(umem_odp->map.pfn_list[idx] & HMM_PFN_VALID)) {
+		if ((umem_odp->map.pfn_list[idx] & access) != access) {
 			need_fault = true;
 			break;
 		}
@@ -160,6 +164,7 @@ static unsigned long rxe_odp_iova_to_page_offset(struct ib_umem_odp *umem_odp, u
 static int rxe_odp_map_range_and_lock(struct rxe_mr *mr, u64 iova, int length, u32 flags)
 {
 	struct ib_umem_odp *umem_odp = to_ib_umem_odp(mr->umem);
+	bool write = !(flags & RXE_PAGEFAULT_RDONLY);
 	bool need_fault;
 	int err;
 
@@ -168,7 +173,7 @@ static int rxe_odp_map_range_and_lock(struct rxe_mr *mr, u64 iova, int length, u
 
 	mutex_lock(&umem_odp->umem_mutex);
 
-	need_fault = rxe_check_pagefault(umem_odp, iova, length);
+	need_fault = rxe_check_pagefault(umem_odp, iova, length, write);
 	if (need_fault) {
 		mutex_unlock(&umem_odp->umem_mutex);
 
@@ -178,7 +183,7 @@ static int rxe_odp_map_range_and_lock(struct rxe_mr *mr, u64 iova, int length, u
 		if (err < 0)
 			return err;
 
-		need_fault = rxe_check_pagefault(umem_odp, iova, length);
+		need_fault = rxe_check_pagefault(umem_odp, iova, length, write);
 		if (need_fault) {
 			mutex_unlock(&umem_odp->umem_mutex);
 			return -EFAULT;
@@ -340,8 +345,9 @@ int rxe_odp_flush_pmem_iova(struct rxe_mr *mr, u64 iova,
 	int err;
 	u8 *va;
 
+	/* A flush never modifies memory; read-only access suffices. */
 	err = rxe_odp_map_range_and_lock(mr, iova, length,
-					 RXE_PAGEFAULT_DEFAULT);
+					 RXE_PAGEFAULT_RDONLY);
 	if (err)
 		return err;
 
Signature · 1 line
2.53.0
author maintainer
#25 lore raw

PATCH 25/438 RDMA/rxe: insert mcg into mcg_tree only after rxe_mcast_add() succeeds

In reply to Greg Kroah-Hartman

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

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

From: Michael Bommarito <[email protected]>

[ Upstream commit 1caceeb2d74bbe88223aea55eb8626b4c5f076fd ]

rxe_get_mcg() publishes a newly allocated multicast group in rxe->mcg_tree before programming the backing Ethernet multicast address with rxe_mcast_add(), which runs outside mcg_lock. A local userspace RDMA client reaches this path with ATTACH_MCAST on a UD QP; if rxe_mcast_add() then returns an error (for example -ENODEV when the backing netdev has been removed, or a propagated dev_mc_add() error), the unwind frees the published group without removing it from the tree. A later lookup of the same MGID dereferences the freed struct rxe_mcg from __rxe_lookup_mcg().

Fix this by keeping the new mcg private until rxe_mcast_add() succeeds. Split the tree publication into __rxe_publish_mcg(), call rxe_mcast_add() before taking the tree reference, and free the still-private mcg on failure. Because the group is never visible in mcg_tree until the multicast address is programmed, no concurrent caller can look it up or attach a QP to a group that is about to be torn down, so the error path needs no conditional unwind. If another caller publishes the same MGID while the address is being programmed, the post-add re-check under mcg_lock finds the winner; this caller then drops its private object and balances its own rxe_mcast_add() with rxe_mcast_del() before returning the winner.

Reproduced by forcing the rxe_mcast_add() error return under KASAN:
without the change the next attach to the same MGID reports a slab-use-after-free in __rxe_lookup_mcg(); with it the forced failure returns cleanly. A no-injection attach/detach regression, including a two-QP shared join/leave and re-attach, stays KASAN- and leak-clean.

Fixes a926a903b7dc ("RDMA/rxe: Do not call dev_mc_add/del() under a spinlock")
---
 drivers/infiniband/sw/rxe/rxe_mcast.c | 50 +++++++++++++++++++--------
 1 file changed, 36 insertions(+), 14 deletions(-)
drivers/infiniband/sw/rxe/rxe_mcast.c +36 -14
index acd03bd87794e..5ca9211ab33bc 100644
@@ -175,7 +175,9 @@ struct rxe_mcg *rxe_lookup_mcg(struct rxe_dev *rxe, union ib_gid *mgid)
  * @mgid: multicast address as a gid
  * @mcg: new mcg object
  *
- * Context: caller should hold rxe->mcg lock
+ * Initializes the mcg fields. The mcg is private and not yet visible in
+ * mcg_tree, so this may run without rxe->mcg_lock; __rxe_publish_mcg()
+ * makes it visible under the lock once it is ready.
  */
 static void __rxe_init_mcg(struct rxe_dev *rxe, union ib_gid *mgid,
 			   struct rxe_mcg *mcg)
@@ -184,13 +186,22 @@ static void __rxe_init_mcg(struct rxe_dev *rxe, union ib_gid *mgid,
 	memcpy(&mcg->mgid, mgid, sizeof(mcg->mgid));
 	INIT_LIST_HEAD(&mcg->qp_list);
 	mcg->rxe = rxe;
+}
 
-	/* caller holds a ref on mcg but that will be
-	 * dropped when mcg goes out of scope. We need to take a ref
-	 * on the pointer that will be saved in the red-black tree
-	 * by __rxe_insert_mcg and used to lookup mcg from mgid later.
-	 * Inserting mcg makes it visible to outside so this should
-	 * be done last after the object is ready.
+/**
+ * __rxe_publish_mcg - make a fully initialized mcg visible in mcg_tree
+ * @mcg: the mcg object
+ *
+ * Context: caller must hold rxe->mcg_lock and a reference on mcg
+ */
+static void __rxe_publish_mcg(struct rxe_mcg *mcg)
+{
+	/* caller holds a ref on mcg but that will be dropped when mcg goes
+	 * out of scope. We need to take a ref on the pointer that will be
+	 * saved in the red-black tree by __rxe_insert_mcg and used to lookup
+	 * mcg from mgid later. Inserting mcg makes it visible to outside so
+	 * this is done last after the object is ready and the multicast
+	 * address has been programmed.
 	 */
 	kref_get(&mcg->ref_cnt);
 	__rxe_insert_mcg(mcg);
@@ -228,26 +239,37 @@ static struct rxe_mcg *rxe_get_mcg(struct rxe_dev *rxe, union ib_gid *mgid)
 		err = -ENOMEM;
 		goto err_dec;
 	}
+	__rxe_init_mcg(rxe, mgid, mcg);
+
+	/* program the multicast address while mcg is still private, before
+	 * it is inserted into mcg_tree. dev_mc_add() may sleep so this must
+	 * run outside mcg_lock. On failure mcg was never published, so a
+	 * plain free is correct and the tree is untouched.
+	 */
+	err = rxe_mcast_add(rxe, mgid);
+	if (err) {
+		kfree(mcg);
+		goto err_dec;
+	}
 
 	spin_lock_bh(&rxe->mcg_lock);
-	/* re-check to see if someone else just added it */
+	/* re-check to see if someone else just added it while we were adding
+	 * the multicast address; if so use theirs and drop ours
+	 */
 	tmp = __rxe_lookup_mcg(rxe, mgid);
 	if (tmp) {
 		spin_unlock_bh(&rxe->mcg_lock);
+		rxe_mcast_del(rxe, mgid);
 		atomic_dec(&rxe->mcg_num);
 		kfree(mcg);
 		return tmp;
 	}
 
-	__rxe_init_mcg(rxe, mgid, mcg);
+	__rxe_publish_mcg(mcg);
 	spin_unlock_bh(&rxe->mcg_lock);
 
-	/* add mcast address outside of lock */
-	err = rxe_mcast_add(rxe, mgid);
-	if (!err)
-		return mcg;
+	return mcg;
 
-	kfree(mcg);
 err_dec:
 	atomic_dec(&rxe->mcg_num);
 	return ERR_PTR(err);
Signature · 1 line
2.53.0
author maintainer
#26 lore raw

PATCH 26/438 RDMA/mlx5: Remove warn on missing representor in query_port_speed

In reply to Greg Kroah-Hartman

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

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

From: Or Har-Toov <[email protected]>

[ Upstream commit 2be77295316c2dff0a33c0dc3a65abdab4ccf796 ]

The representor ib_device's phys_port_cnt is set to the total vport count when the uplink vport rep loads. Individual port[i].rep entries are populated only as each VF/SF vport rep registers. A NULL .rep for a given port index is therefore expected while VF reps are still loading or haven't been enabled yet.

Tools like ibstat and ibv_devinfo iterate over all ports of all RDMA devices. Some ports may not have an eswitch representor, causing repeated dmesg warnings when these tools run without a device argument. This causes dmesg to be flooded with this message on every ibstat invocation.

Remove the warning and return -ENODEV when no representor exists for the queried port.

---
 drivers/infiniband/hw/mlx5/main.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/infiniband/hw/mlx5/main.c +2 -5
index c283a902ea7e4..05985395fca00 100644
@@ -1684,11 +1684,8 @@ static int mlx5_ib_query_port_speed_rep(struct mlx5_ib_dev *dev, u32 port_num,
 	struct mlx5_core_dev *mdev;
 	u16 op_mod;
 
-	if (!dev->port[port_num - 1].rep) {
-		mlx5_ib_warn(dev, "Representor doesn't exist for port %u\n",
-			     port_num);
-		return -EINVAL;
-	}
+	if (!dev->port[port_num - 1].rep)
+		return -ENODEV;
 
 	rep = dev->port[port_num - 1].rep;
 	mdev = mlx5_eswitch_get_core_dev(rep->esw);
Signature · 1 line
2.53.0
author maintainer
#27 lore raw

PATCH 27/438 RDMA/core: Reject unregistering netdevs in ib_get_eth_speed

In reply to Greg Kroah-Hartman

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

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

From: Krystian Kaniewski <[email protected]>

[ Upstream commit ef9fbe1b93f3b617b96e86d5cd76b3fa44514cb5 ]

ib_device_get_netdev() intentionally returns a referenced net_device even when it is unregistering, so matching and cleanup callers can still find the association. The reference keeps struct net_device allocated, but does not guarantee that the device remains operational.

ib_get_eth_speed() uses the returned device operationally by invoking its ethtool callback. Although that call is made under RTNL, the function does not verify the registration state first. An asynchronous RDMA port query can therefore call into a netdev after NETDEV_UNREGISTER and ndo_uninit have completed.

Check for NETREG_REGISTERED while holding RTNL and return -ENODEV for a device which is being unregistered. Keeping RTNL across the check and the ethtool operation prevents unregister from starting between them.

Keep the speed fallback and warning under RTNL as well, so the warning can safely read netdev->name. Drop the netdev reference before releasing RTNL once all accesses to the device are complete.

---
 drivers/infiniband/core/verbs.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/infiniband/core/verbs.c +8 -4
index f8b219bd308bd..5447d39fa89dd 100644
@@ -2056,11 +2056,13 @@ int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u16 *speed, u8 *width)
 		return -ENODEV;
 
 	rtnl_lock();
-	rc = __ethtool_get_link_ksettings(netdev, &lksettings);
-	rtnl_unlock();
-
-	dev_put(netdev);
+	if (READ_ONCE(netdev->reg_state) != NETREG_REGISTERED) {
+		dev_put(netdev);
+		rtnl_unlock();
+		return -ENODEV;
+	}
 
+	rc = __ethtool_get_link_ksettings(netdev, &lksettings);
 	if (!rc && lksettings.base.speed != (u32)SPEED_UNKNOWN) {
 		netdev_speed = lksettings.base.speed;
 	} else {
@@ -2069,6 +2071,8 @@ int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u16 *speed, u8 *width)
 			pr_warn("%s speed is unknown, defaulting to %u\n",
 				netdev->name, netdev_speed);
 	}
+	dev_put(netdev);
+	rtnl_unlock();
 
 	ib_get_width_and_speed(netdev_speed, lksettings.lanes,
 			       speed, width);
Signature · 1 line
2.53.0
author maintainer
#28 lore raw

PATCH 28/438 RDMA/uverbs: Fix mmap_lock/disassociation_lock circular dependency

In reply to Greg Kroah-Hartman

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

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

From: Or Har-Toov <[email protected]>

[ Upstream commit a44a3f175eaee7e5aeb6a8fed381c4a0d5f49236 ]

Commit 51976c6cd786 ("RDMA/core: Provide rdma_user_mmap_disassociate() to disassociate mmap pages") introduced disassociation_lock to protect new mmap registrations against uverbs_user_mmap_disassociate(), but created an ABBA deadlock:

Thread A (mmap / fork):

    mmap_lock -> disassociation_lock

Thread B (disassociate):

    disassociation_lock -> mmap_lock

Fix by removing disassociation_lock entirely and using the pre-existing hw_destroy_rwsem instead. hw_destroy_rwsem already provides the same
protection: rdma_umap_open() and ib_uverbs_mmap() both use down_read_trylock() before registering a new VMA, so holding hw_destroy_rwsem in uverbs_user_mmap_disassociate() is sufficient to block new registrations. trylock is used in both mmap paths (not blocking down_read) because mmap_lock is already held on entry, and uverbs_user_mmap_disassociate() acquires mmap_lock internally — a blocking read would recreate the same deadlock.

The only caller that was not taking hw_destroy_rwsem for write was rdma_user_mmap_disassociate(). Fix it to take the rwsem per-ufile while iterating under lists_mutex. This is safe because ib_uverbs_close() releases hw_destroy_rwsem entirely before acquiring lists_mutex, so the two locks are never held simultaneously.

lockdep warning:

 [  776.654252] ======================================================
 [  776.655214] WARNING: possible circular locking dependency detected
 [  776.656167] 6.18.0for-upstream_debug_94e244d9ccab #1 Not tainted
 [  776.657114] ------------------------------------------------------
 [  776.658087] devlink/14824 is trying to acquire lock:
 [  776.658879] ffff88811170c800 (&mm->mmap_lock){++++}-{4:4}, at: uverbs_user_mmap_disassociate+0x168/0x780 [ib_uverbs]
 [  776.660479]
 [  776.660479] but task is already holding lock:
 [  776.661460] ffff888142d92b08 (&file->disassociation_lock){+.+.}-{4:4}, at: uverbs_user_mmap_disassociate+0x39/0x780 [ib_uverbs]
 [  776.663177]
 [  776.663177] which lock already depends on the new lock.
 [  776.663177]
 [  776.664525]
 [  776.664525] the existing dependency chain (in reverse order) is:
 [  776.665724]
 [  776.665724] -> #2 (&file->disassociation_lock){+.+.}-{4:4}:
 [  776.666887]        __mutex_lock+0x16d/0x2330
 [  776.667633]        rdma_umap_open+0x129/0x280 [ib_uverbs]
 [  776.668489]        dup_mmap+0xa40/0x1790
 [  776.669170]        copy_process+0x5dd2/0x6170
 [  776.669933]        kernel_clone+0xb6/0x610
 [  776.670636]        __do_sys_clone+0xb5/0xf0
 [  776.671354]        do_syscall_64+0x70/0x12e0
 [  776.672083]        entry_SYSCALL_64_after_hwframe+0x4b/0x53
 [  776.672940]
 [  776.672940] -> #1 (&mm->mmap_lock/1){+.+.}-{4:4}:
 [  776.673985]        down_write_nested+0x90/0x1e0
 [  776.674751]        dup_mmap+0x201/0x1790
 [  776.675448]        copy_process+0x5dd2/0x6170
 [  776.676180]        kernel_clone+0xb6/0x610
 [  776.676904]        __do_sys_clone+0xb5/0xf0
 [  776.677615]        do_syscall_64+0x70/0x12e0
 [  776.678351]        entry_SYSCALL_64_after_hwframe+0x4b/0x53
 [  776.679239]
 [  776.679239] -> #0 (&mm->mmap_lock){++++}-{4:4}:
 [  776.680253]        __lock_acquire+0x18c6/0x2ec0
 [  776.681018]        lock_acquire+0x10e/0x2e0
 [  776.681742]        down_read+0x95/0x430
 [  776.682395]        uverbs_user_mmap_disassociate+0x168/0x780 [ib_uverbs]
 [  776.683436]        uverbs_destroy_ufile_hw+0x1ae/0x270 [ib_uverbs]
 [  776.684416]        ib_uverbs_remove_one+0x22b/0x420 [ib_uverbs]
 [  776.685371]        remove_client_context+0xa6/0xf0 [ib_core]
 [  776.686342]        disable_device+0x12b/0x240 [ib_core]
 [  776.687249]        __ib_unregister_device+0x269/0x460 [ib_core]
 [  776.688233]        ib_unregister_device+0x21/0x30 [ib_core]
 [  776.689140]        mlx5r_remove+0xd0/0x170 [mlx5_ib]
 [  776.689999]        device_release_driver_internal+0x3b2/0x560
 [  776.694876]        bus_remove_device+0x1f5/0x3e0
 [  776.695638]        device_del+0x3b9/0x990
 [  776.696329]        mlx5_detach_device+0x17e/0x350 [mlx5_core]
 [  776.697429]        mlx5_unload_one_devl_locked+0x3f/0xb0 [mlx5_core]
 [  776.698578]        mlx5_devlink_reload_down+0x1f9/0x550 [mlx5_core]
 [  776.699712]        devlink_reload+0x13e/0x680
 [  776.700456]        devlink_nl_reload_doit+0xc29/0x1160
 [  776.701293]        genl_family_rcv_msg_doit+0x1c9/0x2a0
 [  776.702135]        genl_rcv_msg+0x3f0/0x6b0
 [  776.702854]        netlink_rcv_skb+0x11d/0x370
 [  776.703605]        genl_rcv+0x24/0x40
 [  776.704236]        netlink_unicast+0x5b4/0x970
 [  776.704984]        netlink_sendmsg+0x730/0xbf0
 [  776.705748]        __sock_sendmsg+0xc5/0x190
 [  776.706461]        __sys_sendto+0x201/0x2f0
 [  776.707188]        __x64_sys_sendto+0xdc/0x1b0
 [  776.707931]        do_syscall_64+0x70/0x12e0
 [  776.708643]        entry_SYSCALL_64_after_hwframe+0x4b/0x53
 [  776.709546]
 [  776.709546] other info that might help us debug this:
 [  776.709546]
 [  776.710910] Chain exists of:
 [  776.710910]   &mm->mmap_lock --> &mm->mmap_lock/1 --> &file->disassociation_lock
 [  776.710910]
 [  776.712805]  Possible unsafe locking scenario:
 [  776.712805]
 [  776.713828]        CPU0                    CPU1
 [  776.714589]        ----                    ----
 [  776.715347]   lock(&file->disassociation_lock);
 [  776.716097]                                lock(&mm->mmap_lock/1);
 [  776.717067]                                lock(&file->disassociation_lock);
 [  776.718199]   rlock(&mm->mmap_lock);
 [  776.718857]
 [  776.718857]  *** DEADLOCK ***
Fixes 51976c6cd786 ("RDMA/core: Provide rdma_user_mmap_disassociate() to disassociate mmap pages")
---
 drivers/infiniband/core/rdma_core.c   |  1 -
 drivers/infiniband/core/uverbs_main.c | 25 +++++++++++--------------
 include/rdma/uverbs_types.h           |  2 --
 3 files changed, 11 insertions(+), 17 deletions(-)
drivers/infiniband/core/rdma_core.c +0 -1
index fd5651c003aed..a7cbe643e33c6 100644
@@ -69,7 +69,6 @@ void ib_uverbs_release_file(struct kref *ref)
 
 	if (file->disassociate_page)
 		__free_pages(file->disassociate_page, 0);
-	mutex_destroy(&file->disassociation_lock);
 	mutex_destroy(&file->umap_lock);
 	mutex_destroy(&file->ucontext_lock);
 	kfree(file);
drivers/infiniband/core/uverbs_main.c +11 -14
index 0d88b2ee68ffa..2a046c888dfab 100644
@@ -644,12 +644,15 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
 		goto out;
 	}
 
-	mutex_lock(&file->disassociation_lock);
+	if (!down_read_trylock(&file->hw_destroy_rwsem)) {
+		ret = -EIO;
+		goto out;
+	}
 
 	vma->vm_ops = &rdma_umap_ops;
 	ret = ucontext->device->ops.mmap(ucontext, vma);
 
-	mutex_unlock(&file->disassociation_lock);
+	up_read(&file->hw_destroy_rwsem);
 out:
 	srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
 	return ret;
@@ -671,7 +674,6 @@ static void rdma_umap_open(struct vm_area_struct *vma)
 	/* We are racing with disassociation */
 	if (!down_read_trylock(&ufile->hw_destroy_rwsem))
 		goto out_zap;
-	mutex_lock(&ufile->disassociation_lock);
 
 	/*
 	 * Disassociation already completed, the VMA should already be zapped.
@@ -684,12 +686,10 @@ static void rdma_umap_open(struct vm_area_struct *vma)
 		goto out_unlock;
 	rdma_umap_priv_init(priv, vma, opriv->entry);
 
-	mutex_unlock(&ufile->disassociation_lock);
 	up_read(&ufile->hw_destroy_rwsem);
 	return;
 
 out_unlock:
-	mutex_unlock(&ufile->disassociation_lock);
 	up_read(&ufile->hw_destroy_rwsem);
 out_zap:
 	/*
@@ -773,7 +773,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 {
 	struct rdma_umap_priv *priv, *next_priv;
 
-	mutex_lock(&ufile->disassociation_lock);
+	lockdep_assert_held_write(&ufile->hw_destroy_rwsem);
 
 	while (1) {
 		struct mm_struct *mm = NULL;
@@ -799,10 +799,8 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 			break;
 		}
 		mutex_unlock(&ufile->umap_lock);
-		if (!mm) {
-			mutex_unlock(&ufile->disassociation_lock);
+		if (!mm)
 			return;
-		}
 
 		/*
 		 * The umap_lock is nested under mmap_lock since it used within
@@ -832,8 +830,6 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 		mmap_read_unlock(mm);
 		mmput(mm);
 	}
-
-	mutex_unlock(&ufile->disassociation_lock);
 }
 
 /**
@@ -851,8 +847,11 @@ void rdma_user_mmap_disassociate(struct ib_device *device)
 
 	mutex_lock(&uverbs_dev->lists_mutex);
 	list_for_each_entry(ufile, &uverbs_dev->uverbs_file_list, list) {
-		if (ufile->ucontext)
+		if (ufile->ucontext) {
+			down_write(&ufile->hw_destroy_rwsem);
 			uverbs_user_mmap_disassociate(ufile);
+			up_write(&ufile->hw_destroy_rwsem);
+		}
 	}
 	mutex_unlock(&uverbs_dev->lists_mutex);
 }
@@ -927,8 +926,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
 	mutex_init(&file->umap_lock);
 	INIT_LIST_HEAD(&file->umaps);
 
-	mutex_init(&file->disassociation_lock);
-
 	filp->private_data = file;
 	list_add_tail(&file->list, &dev->uverbs_file_list);
 	mutex_unlock(&dev->lists_mutex);
include/rdma/uverbs_types.h +0 -2
index 5a07f9a6dcd1f..6f3622892c0cc 100644
@@ -180,8 +180,6 @@ struct ib_uverbs_file {
 	struct page *disassociate_page;
 
 	struct xarray		idr;
-
-	struct mutex disassociation_lock;
 };
 
 extern const struct uverbs_obj_type_class uverbs_idr_class;
Signature · 1 line
2.53.0
author maintainer
#29 lore raw

PATCH 29/438 power: sequencing: Fix build issue with COMPILE_TEST

In reply to Greg Kroah-Hartman

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

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

From: Biju Das <[email protected]>

[ Upstream commit 3b54dbd119805361695cb50ca6a875f4c7518b74 ]

The POWER_SEQUENCING_TH1520_GPU driver depends on (ARCH_THEAD && AUXILIARY_BUS) || COMPILE_TEST. This means when COMPILE_TEST=y and ARCH_THEAD is not set, the driver can still be built even though it requires AUXILIARY_BUS, which may not be selected in that configuration, leading to a build failure.

Fix this by dropping AUXILIARY_BUS from the dependency and instead selecting it directly, so the dependency is satisfied regardless of whether COMPILE_TEST or ARCH_THEAD is enabled.

Fixes 1a7312b93ab0 ("power: sequencing: extend build coverage with COMPILE_TEST=y")
---
 drivers/power/sequencing/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/power/sequencing/Kconfig +2 -1
index 1c5f5820f5b76..226c62704d9bb 100644
@@ -29,7 +29,8 @@ config POWER_SEQUENCING_QCOM_WCN
 
 config POWER_SEQUENCING_TH1520_GPU
 	tristate "T-HEAD TH1520 GPU power sequencing driver"
-	depends on (ARCH_THEAD && AUXILIARY_BUS) || COMPILE_TEST
+	depends on ARCH_THEAD || COMPILE_TEST
+	select AUXILIARY_BUS
 	help
 	  Say Y here to enable the power sequencing driver for the TH1520 SoC
 	  GPU. This driver handles the complex clock and reset sequence
Signature · 1 line
2.53.0
author maintainer
#30 lore raw

PATCH 30/438 arm64: dts: renesas: r9a09g057: Switch GBETH TX queue scheduling to WRR

In reply to Greg Kroah-Hartman

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

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

From: Ovidiu Panait <[email protected]>

[ Upstream commit 33da68f61d25ef8411489d06514ff627c1f88152 ]

The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.

Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:

iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.

Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.

Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.

---
 arch/arm64/boot/dts/renesas/r9a09g057.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g057.dtsi +10 -0
index 1e94366bb7eee..99d197f309d00 100644
@@ -1559,23 +1559,28 @@ queue3 {
 
 			mtl_tx_setup0: tx-queues-config {
 				snps,tx-queues-to-use = <4>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 					snps,priority = <0x1>;
 				};
 
 				queue1 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 					snps,priority = <0x2>;
 				};
 
 				queue2 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 					snps,priority = <0x4>;
 				};
 
 				queue3 {
+					snps,weight = <0x18>;
 					snps,dcb-algorithm;
 					snps,priority = <0x8>;
 				};
@@ -1660,23 +1665,28 @@ queue3 {
 
 			mtl_tx_setup1: tx-queues-config {
 				snps,tx-queues-to-use = <4>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 					snps,priority = <0x1>;
 				};
 
 				queue1 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 					snps,priority = <0x2>;
 				};
 
 				queue2 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 					snps,priority = <0x4>;
 				};
 
 				queue3 {
+					snps,weight = <0x18>;
 					snps,dcb-algorithm;
 					snps,priority = <0x8>;
 				};
Signature · 1 line
2.53.0
author maintainer
#31 lore raw

PATCH 31/438 arm64: dts: renesas: r9a09g056: Switch GBETH TX queue scheduling to WRR

In reply to Greg Kroah-Hartman

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

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

From: Ovidiu Panait <[email protected]>

[ Upstream commit 66fcbdbeca0118b8aeac218b33fa18c394513543 ]

The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.

Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:

iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.

Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.

Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.

---
 arch/arm64/boot/dts/renesas/r9a09g056.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g056.dtsi +10 -0
index 5a3a6f72029a2..6e1444b80a28f 100644
@@ -1569,23 +1569,28 @@ queue3 {
 
 			mtl_tx_setup0: tx-queues-config {
 				snps,tx-queues-to-use = <4>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 					snps,priority = <0x1>;
 				};
 
 				queue1 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 					snps,priority = <0x2>;
 				};
 
 				queue2 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 					snps,priority = <0x4>;
 				};
 
 				queue3 {
+					snps,weight = <0x18>;
 					snps,dcb-algorithm;
 					snps,priority = <0x8>;
 				};
@@ -1670,23 +1675,28 @@ queue3 {
 
 			mtl_tx_setup1: tx-queues-config {
 				snps,tx-queues-to-use = <4>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 					snps,priority = <0x1>;
 				};
 
 				queue1 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 					snps,priority = <0x2>;
 				};
 
 				queue2 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 					snps,priority = <0x4>;
 				};
 
 				queue3 {
+					snps,weight = <0x18>;
 					snps,dcb-algorithm;
 					snps,priority = <0x8>;
 				};
Signature · 1 line
2.53.0
author maintainer
#32 lore raw

PATCH 32/438 arm64: dts: renesas: r9a09g047: Switch GBETH TX queue scheduling to WRR

In reply to Greg Kroah-Hartman

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

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

From: Ovidiu Panait <[email protected]>

[ Upstream commit 63016c3a91f2c458ca75869c8c782e899591f22d ]

The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.

Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:

iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.

Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.

Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.

---
 arch/arm64/boot/dts/renesas/r9a09g047.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g047.dtsi +10 -0
index b6193c1583706..4de93fceb605a 100644
@@ -1394,23 +1394,28 @@ queue3 {
 
 			mtl_tx_setup0: tx-queues-config {
 				snps,tx-queues-to-use = <4>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 					snps,priority = <0x1>;
 				};
 
 				queue1 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 					snps,priority = <0x2>;
 				};
 
 				queue2 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 					snps,priority = <0x4>;
 				};
 
 				queue3 {
+					snps,weight = <0x18>;
 					snps,dcb-algorithm;
 					snps,priority = <0x8>;
 				};
@@ -1494,23 +1499,28 @@ queue3 {
 
 			mtl_tx_setup1: tx-queues-config {
 				snps,tx-queues-to-use = <4>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 					snps,priority = <0x1>;
 				};
 
 				queue1 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 					snps,priority = <0x2>;
 				};
 
 				queue2 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 					snps,priority = <0x4>;
 				};
 
 				queue3 {
+					snps,weight = <0x18>;
 					snps,dcb-algorithm;
 					snps,priority = <0x8>;
 				};
Signature · 1 line
2.53.0
author maintainer
#33 lore raw

PATCH 33/438 arm64: dts: renesas: r9a09g077: Switch GBETH TX queue scheduling to WRR

In reply to Greg Kroah-Hartman

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

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

From: Ovidiu Panait <[email protected]>

[ Upstream commit f9d9a1913c09366bf7b967d39575e06cb80128dc ]

The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.

Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:

iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.

Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.

Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.

---
 arch/arm64/boot/dts/renesas/r9a09g077.dtsi | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g077.dtsi +27 -0
index 40494159831d8..bac39390ead74 100644
@@ -642,36 +642,45 @@ queue7 {
 
 			mtl_tx_setup0: tx-queues-config {
 				snps,tx-queues-to-use = <8>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 				};
 
 				queue1 {
+					snps,weight = <0x11>;
 					snps,dcb-algorithm;
 				};
 
 				queue2 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 				};
 
 				queue3 {
+					snps,weight = <0x13>;
 					snps,dcb-algorithm;
 				};
 
 				queue4 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 				};
 
 				queue5 {
+					snps,weight = <0x15>;
 					snps,dcb-algorithm;
 				};
 
 				queue6 {
+					snps,weight = <0x16>;
 					snps,dcb-algorithm;
 				};
 
 				queue7 {
+					snps,weight = <0x17>;
 					snps,dcb-algorithm;
 				};
 			};
@@ -788,36 +797,45 @@ queue7 {
 
 			mtl_tx_setup1: tx-queues-config {
 				snps,tx-queues-to-use = <8>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 				};
 
 				queue1 {
+					snps,weight = <0x11>;
 					snps,dcb-algorithm;
 				};
 
 				queue2 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 				};
 
 				queue3 {
+					snps,weight = <0x13>;
 					snps,dcb-algorithm;
 				};
 
 				queue4 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 				};
 
 				queue5 {
+					snps,weight = <0x15>;
 					snps,dcb-algorithm;
 				};
 
 				queue6 {
+					snps,weight = <0x16>;
 					snps,dcb-algorithm;
 				};
 
 				queue7 {
+					snps,weight = <0x17>;
 					snps,dcb-algorithm;
 				};
 			};
@@ -934,36 +952,45 @@ queue7 {
 
 			mtl_tx_setup2: tx-queues-config {
 				snps,tx-queues-to-use = <8>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 				};
 
 				queue1 {
+					snps,weight = <0x11>;
 					snps,dcb-algorithm;
 				};
 
 				queue2 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 				};
 
 				queue3 {
+					snps,weight = <0x13>;
 					snps,dcb-algorithm;
 				};
 
 				queue4 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 				};
 
 				queue5 {
+					snps,weight = <0x15>;
 					snps,dcb-algorithm;
 				};
 
 				queue6 {
+					snps,weight = <0x16>;
 					snps,dcb-algorithm;
 				};
 
 				queue7 {
+					snps,weight = <0x17>;
 					snps,dcb-algorithm;
 				};
 			};
Signature · 1 line
2.53.0
author maintainer
#34 lore raw

PATCH 34/438 arm64: dts: renesas: r9a09g087: Switch GBETH TX queue scheduling to WRR

In reply to Greg Kroah-Hartman

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

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

From: Ovidiu Panait <[email protected]>

[ Upstream commit 2ac7bad110be6ebe478d6bd57821f7f5259a1f54 ]

The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.

Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:

iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.

Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.

Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.

---
 arch/arm64/boot/dts/renesas/r9a09g087.dtsi | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g087.dtsi +27 -0
index e8d4f76949ccb..03b976d93e105 100644
@@ -643,36 +643,45 @@ queue7 {
 
 			mtl_tx_setup0: tx-queues-config {
 				snps,tx-queues-to-use = <8>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 				};
 
 				queue1 {
+					snps,weight = <0x11>;
 					snps,dcb-algorithm;
 				};
 
 				queue2 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 				};
 
 				queue3 {
+					snps,weight = <0x13>;
 					snps,dcb-algorithm;
 				};
 
 				queue4 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 				};
 
 				queue5 {
+					snps,weight = <0x15>;
 					snps,dcb-algorithm;
 				};
 
 				queue6 {
+					snps,weight = <0x16>;
 					snps,dcb-algorithm;
 				};
 
 				queue7 {
+					snps,weight = <0x17>;
 					snps,dcb-algorithm;
 				};
 			};
@@ -790,36 +799,45 @@ queue7 {
 
 			mtl_tx_setup1: tx-queues-config {
 				snps,tx-queues-to-use = <8>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 				};
 
 				queue1 {
+					snps,weight = <0x11>;
 					snps,dcb-algorithm;
 				};
 
 				queue2 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 				};
 
 				queue3 {
+					snps,weight = <0x13>;
 					snps,dcb-algorithm;
 				};
 
 				queue4 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 				};
 
 				queue5 {
+					snps,weight = <0x15>;
 					snps,dcb-algorithm;
 				};
 
 				queue6 {
+					snps,weight = <0x16>;
 					snps,dcb-algorithm;
 				};
 
 				queue7 {
+					snps,weight = <0x17>;
 					snps,dcb-algorithm;
 				};
 			};
@@ -937,36 +955,45 @@ queue7 {
 
 			mtl_tx_setup2: tx-queues-config {
 				snps,tx-queues-to-use = <8>;
+				snps,tx-sched-wrr;
 
 				queue0 {
+					snps,weight = <0x10>;
 					snps,dcb-algorithm;
 				};
 
 				queue1 {
+					snps,weight = <0x11>;
 					snps,dcb-algorithm;
 				};
 
 				queue2 {
+					snps,weight = <0x12>;
 					snps,dcb-algorithm;
 				};
 
 				queue3 {
+					snps,weight = <0x13>;
 					snps,dcb-algorithm;
 				};
 
 				queue4 {
+					snps,weight = <0x14>;
 					snps,dcb-algorithm;
 				};
 
 				queue5 {
+					snps,weight = <0x15>;
 					snps,dcb-algorithm;
 				};
 
 				queue6 {
+					snps,weight = <0x16>;
 					snps,dcb-algorithm;
 				};
 
 				queue7 {
+					snps,weight = <0x17>;
 					snps,dcb-algorithm;
 				};
 			};
Signature · 1 line
2.53.0
author maintainer
#35 lore raw

PATCH 35/438 IB/iser: reject a remote invalidation of an unregistered direction

In reply to Greg Kroah-Hartman

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

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

From: Yehyeong Lee <[email protected]>

[ Upstream commit d85f0f0a7c85756fc992c70d869706f19dac9259 ]

A write command whose data is sent entirely as immediate data is not registered. iser_reg_mem_fastreg() takes the DMA key path and leaves rdma_reg[ISER_DIR_OUT].desc at NULL, while iser_dma_map_task_data() has already set dir[ISER_DIR_OUT].

iser_check_remote_inv() looks at dir[] alone and hands the descriptor to iser_inv_desc(), which reads desc->sig_protected. A target that answers such a command with IB_WR_SEND_WITH_INV faults the initiator. Leaving those commands unregistered is deliberate.

The same function already terminates the connection when a target sends a remote invalidation the initiator did not ask for. A target that invalidates a direction that was never registered is in the same class, so give it the same answer.

  Oops: general protection fault, probably for non-canonical address 0xdffffc0000000004: 0000 [#1] SMP KASAN NOPTI
  KASAN: null-ptr-deref in range [0x0000000000000020-0x0000000000000027]
  CPU: 0 UID: 0 PID: 40 Comm: kworker/u8:2 Not tainted 7.2.0-rc5-ISERHOST-gf5098b6bae76-dirty #3 PREEMPT(lazy)
  Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
  Workqueue: rxe_wq do_work
  RIP: 0010:iser_task_rsp+0x6d6/0xec0
  Code: 48 c1 ea 03 80 3c 02 00 0f 85 ba 06 00 00 48 8b 9b 78 01 00 00 48 b8 00 00 00 00 00 fc ff df 48 8d 7b 20 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 06 0f 8e 76 06 00 00 80 7b 20 00 0f 84 3d 04
  RSP: 0018:ffff88811b008db8 EFLAGS: 00010202
  RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000001848
  RDX: 0000000000000004 RSI: 1ffff11021587b12 RDI: 0000000000000020
  RBP: ffff88810adc1ae4 R08: ffff888109b7f860 R09: ffffffff90a922c0
  R10: ffff88810adc1a1c R11: 000000000000003c R12: ffff888109b7f800
  R13: ffff88810adc1acc R14: ffff888109b7f820 R15: 0000000000000000
  FS:  0000000000000000(0000) GS:ffff88818a676000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  CR2: 00000000005afe2b CR3: 000000010af23005 CR4: 0000000000770ef0
  PKRU: 55555554
  Call Trace:
   <IRQ>
   __ib_process_cq+0xe1/0x390
   ib_poll_handler+0x6e/0x200
   irq_poll_softirq+0x1df/0x480
   ? clockevents_program_event+0x2ba/0x860
   ? __pfx_irq_poll_softirq+0x10/0x10
   handle_softirqs+0x18e/0x590
   ? __pfx_handle_softirqs+0x10/0x10
   ? __hrtimer_rearm_deferred+0x156/0x450
   do_softirq+0x3b/0x60
   </IRQ>
   <TASK>
   __local_bh_enable_ip+0x61/0x70
   __alloc_skb+0x732/0x890
   ? _raw_spin_lock_irqsave+0x85/0xe0
   ? __pfx___alloc_skb+0x10/0x10
   ? _raw_read_unlock_irqrestore+0x16/0x50
   rxe_init_packet+0x16b/0x4f0
   prepare_ack_packet+0xb8/0x830
   rxe_receiver+0x499/0x9980
   ? __pfx_rxe_receiver+0x10/0x10
   ? rxe_completer+0x29e5/0x38c0
   ? hrtimer_start_range_ns_common+0x75f/0x1730
   ? hrtimer_start_range_ns+0xa6/0x2c0
   ? __pfx__raw_spin_lock_irqsave+0x10/0x10
   ? __pfx_rxe_receiver+0x10/0x10
   do_work+0x144/0x470
   process_one_work+0x633/0x1030
   ? assign_work+0x11d/0x370
   worker_thread+0x45b/0xd10
   ? __pfx_worker_thread+0x10/0x10
   kthread+0x2c6/0x3b0
   ? recalc_sigpending+0x15c/0x1e0
   ? __pfx_kthread+0x10/0x10
   ret_from_fork+0x36e/0x5a0
   ? __pfx_ret_from_fork+0x10/0x10
   ? __switch_to+0x572/0xdd0
   ? __pfx_kthread+0x10/0x10
   ret_from_fork_asm+0x1a/0x30
   </TASK>
  Modules linked in:
  ---[ end trace 0000000000000000 ]---
Fixes 59caaed7a72a ("IB/iser: Support the remote invalidation exception")
---
 drivers/infiniband/ulp/iser/iser_initiator.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/infiniband/ulp/iser/iser_initiator.c +11 -5
index 12a2d12fef070..7ea6888b479cf 100644
@@ -598,11 +598,8 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc,
 		iser_dbg("conn %p: remote invalidation for rkey %#x\n",
 			 iser_conn, rkey);
 
-		if (unlikely(!iser_conn->snd_w_inv)) {
-			iser_err("conn %p: unexpected remote invalidation, terminating connection\n",
-				 iser_conn);
-			return -EPROTO;
-		}
+		if (unlikely(!iser_conn->snd_w_inv))
+			goto bad_inv;
 
 		task = iscsi_itt_to_ctask(iser_conn->iscsi_conn, hdr->itt);
 		if (likely(task)) {
@@ -611,12 +608,16 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc,
 
 			if (iser_task->dir[ISER_DIR_IN]) {
 				desc = iser_task->rdma_reg[ISER_DIR_IN].desc;
+				if (unlikely(!desc))
+					goto bad_inv;
 				if (unlikely(iser_inv_desc(desc, rkey)))
 					return -EINVAL;
 			}
 
 			if (iser_task->dir[ISER_DIR_OUT]) {
 				desc = iser_task->rdma_reg[ISER_DIR_OUT].desc;
+				if (unlikely(!desc))
+					goto bad_inv;
 				if (unlikely(iser_inv_desc(desc, rkey)))
 					return -EINVAL;
 			}
@@ -627,6 +628,11 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc,
 	}
 
 	return 0;
+
+bad_inv:
+	iser_err("conn %p: unexpected remote invalidation, terminating connection\n",
+		 iser_conn);
+	return -EPROTO;
 }
 
 
Signature · 1 line
2.53.0
author maintainer
#36 lore raw

PATCH 36/438 IB/isert: wait for deferred control PDU completions before releasing the connection

In reply to Greg Kroah-Hartman

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

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

From: Yehyeong Lee <[email protected]>

[ Upstream commit a8fe3dfce8c0d8a76dc3d8486a5bff5feebe156f ]

isert_send_done() hands ISTATE_SEND_TASKMGTRSP, ISTATE_SEND_REJECT and ISTATE_SEND_TEXTRSP completions off to isert_comp_wq and returns. The work item then runs isert_completion_put() -> isert_put_cmd(), which reads isert_conn->conn and takes conn->cmd_lock.

Nothing orders that work item against teardown. isert_wait_conn() queues isert_release_work, which frees isert_conn, and iscsit_close_connection() frees the iscsit_conn right after it returns, so the queued work can run against freed memory.

Count the deferred control PDU completions per connection and let isert_wait_conn() wait for them before the release work is queued.

ISTATE_SEND_LOGOUTRSP is deliberately not counted: that branch runs iscsit_logout_post_handler(), which ends up waiting for conn->conn_wait_comp, and that completion is only sent by iscsit_close_connection() after it has called iscsit_wait_conn(). Waiting for it here would deadlock. Its wait stays the existing isert_wait4logout().

The splat below is from a kernel with tracing printk()s and an msleep(200) injected into isert_do_control_comp() to widen the window:

  BUG: KASAN: slab-use-after-free in isert_put_cmd+0x53d/0x620
  Read of size 8 at addr ffff8881054f1038 by task kworker/u17:1/182

  CPU: 0 UID: 0 PID: 182 Comm: kworker/u17:1 Tainted: G    B               7.2.0-rc5-TWIDE-gb8babf08acc7 #1 PREEMPT(lazy)
  Tainted: [B]=BAD_PAGE
  Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
  Workqueue: isert_comp_wq isert_do_control_comp
  Call Trace:
   <TASK>
   dump_stack_lvl+0x53/0x70
   print_report+0xd0/0x630
   ? __pfx__raw_spin_lock_irqsave+0x10/0x10
   ? _raw_spin_unlock_irqrestore+0x3e/0x70
   ? isert_put_cmd+0x53d/0x620
   kasan_report+0xce/0x100
   ? isert_put_cmd+0x53d/0x620
   isert_put_cmd+0x53d/0x620
   ? isert_completion_put+0x305/0x330
   ? isert_do_control_comp+0x2ef/0x310
   process_one_work+0x633/0x1030
   ? assign_work+0x11d/0x370
   worker_thread+0x45b/0xd10
   ? __pfx_worker_thread+0x10/0x10
   ? __pfx_worker_thread+0x10/0x10
   kthread+0x2c6/0x3b0
   ? recalc_sigpending+0x15c/0x1e0
   ? __pfx_kthread+0x10/0x10
   ret_from_fork+0x36e/0x5a0
   ? __pfx_ret_from_fork+0x10/0x10
   ? __switch_to+0x572/0xdd0
   ? __pfx_kthread+0x10/0x10
   ret_from_fork_asm+0x1a/0x30
   </TASK>

  Allocated by task 48:
   kasan_save_stack+0x33/0x60
   kasan_save_track+0x14/0x30
   __kasan_kmalloc+0x8f/0xa0
   __kmalloc_cache_noprof+0x158/0x370
   isert_cma_handler+0x1e3/0x2ae0
   cma_cm_event_handler+0x3e/0x240
   cma_ib_req_handler+0x17d9/0x4490
   cm_process_work+0x41/0x330
   cm_work_handler+0x5727/0xc160
   process_one_work+0x633/0x1030
   worker_thread+0x45b/0xd10
   kthread+0x2c6/0x3b0
   ret_from_fork+0x36e/0x5a0
   ret_from_fork_asm+0x1a/0x30

  Freed by task 184:
   kasan_save_stack+0x33/0x60
   kasan_save_track+0x14/0x30
   kasan_save_free_info+0x3b/0x60
   __kasan_slab_free+0x43/0x70
   kfree+0x121/0x380
   iscsit_close_connection+0x7cf/0x1e60
   iscsit_take_action_for_connection_exit+0x1b6/0x360
   iscsi_target_tx_thread+0x472/0x690
   kthread+0x2c6/0x3b0
   ret_from_fork+0x36e/0x5a0
   ret_from_fork_asm+0x1a/0x30
Fixes b8d26b3be8b3 ("iser-target: Add iSCSI Extensions for RDMA (iSER) target driver")
---
 drivers/infiniband/ulp/isert/ib_isert.c | 22 ++++++++++++++++++++++
 drivers/infiniband/ulp/isert/ib_isert.h |  2 ++
 2 files changed, 24 insertions(+)
drivers/infiniband/ulp/isert/ib_isert.c +22 -0
index df5d8295a7fc1..6a9e76d60f816 100644
@@ -21,6 +21,7 @@
 #include <target/target_core_fabric.h>
 #include <target/iscsi/iscsi_transport.h>
 #include <linux/semaphore.h>
+#include <linux/wait_bit.h>
 
 #include "ib_isert.h"
 
@@ -310,6 +311,7 @@ isert_init_conn(struct isert_conn *isert_conn)
 	init_completion(&isert_conn->login_req_comp);
 	init_waitqueue_head(&isert_conn->rem_wait);
 	kref_init(&isert_conn->kref);
+	atomic_set(&isert_conn->ctrl_comp_cnt, 0);
 	mutex_init(&isert_conn->mutex);
 	INIT_WORK(&isert_conn->release_work, isert_release_work);
 }
@@ -1695,6 +1697,8 @@ isert_do_control_comp(struct work_struct *work)
 	struct isert_conn *isert_conn = isert_cmd->conn;
 	struct ib_device *ib_dev = isert_conn->cm_id->device;
 	struct iscsit_cmd *cmd = isert_cmd->iscsit_cmd;
+	/* The switch below may free isert_cmd. */
+	bool counted = isert_cmd->ctrl_counted;
 
 	isert_dbg("Cmd %p i_state %d\n", isert_cmd, cmd->i_state);
 
@@ -1716,6 +1720,14 @@ isert_do_control_comp(struct work_struct *work)
 		dump_stack();
 		break;
 	}
+
+	/*
+	 * The count is what keeps isert_conn alive, so drop it last.  The wait
+	 * queue lives in the global hash table, not in isert_conn, so this is
+	 * safe even if the waiter has already freed the connection.
+	 */
+	if (counted && atomic_dec_and_test(&isert_conn->ctrl_comp_cnt))
+		wake_up_var(&isert_conn->ctrl_comp_cnt);
 }
 
 static void
@@ -1759,6 +1771,12 @@ isert_send_done(struct ib_cq *cq, struct ib_wc *wc)
 	case ISTATE_SEND_TEXTRSP:
 		isert_unmap_tx_desc(tx_desc, ib_dev);
 
+		/* Paired with the wait in isert_wait_conn(). */
+		isert_cmd->ctrl_counted =
+			isert_cmd->iscsit_cmd->i_state != ISTATE_SEND_LOGOUTRSP;
+		if (isert_cmd->ctrl_counted)
+			atomic_inc(&isert_conn->ctrl_comp_cnt);
+
 		INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp);
 		queue_work(isert_comp_wq, &isert_cmd->comp_work);
 		return;
@@ -2603,6 +2621,10 @@ static void isert_wait_conn(struct iscsit_conn *conn)
 	isert_wait4cmds(conn);
 	isert_wait4logout(isert_conn);
 
+	/* Paired with the count taken in isert_send_done(). */
+	wait_var_event(&isert_conn->ctrl_comp_cnt,
+		       !atomic_read(&isert_conn->ctrl_comp_cnt));
+
 	queue_work(isert_release_wq, &isert_conn->release_work);
 }
 
drivers/infiniband/ulp/isert/ib_isert.h +2 -0
index 0bac5aa66c802..519b17e54bd34 100644
@@ -153,6 +153,7 @@ struct isert_cmd {
 	struct work_struct	comp_work;
 	struct scatterlist	sg;
 	bool			ctx_init_done;
+	bool			ctrl_counted;
 };
 
 static inline struct isert_cmd *tx_desc_to_cmd(struct iser_tx_desc *desc)
@@ -187,6 +188,7 @@ struct isert_conn {
 	struct mutex		mutex;
 	struct kref		kref;
 	struct work_struct	release_work;
+	atomic_t		ctrl_comp_cnt;
 	bool                    logout_posted;
 	bool                    snd_w_inv;
 	wait_queue_head_t	rem_wait;
Signature · 1 line
2.53.0
author maintainer
#37 lore raw

PATCH 37/438 RDMA/bnxt_re: check create_singlethread_workqueue() in DCB setup

In reply to Greg Kroah-Hartman

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

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

From: Linkai Gong <[email protected]>

[ Upstream commit 6c368f7baaea63c1c7c28c6df271511f2a1562c9 ]

bnxt_re_init_dcb_wq() ignores a failed allocation. The async DCB handler later calls queue_work() on the NULL pointer.

Fixes 51dc5312dcd9 ("RDMA/bnxt_re: Add support to handle DCB_CONFIG_CHANGE event")
---
 drivers/infiniband/hw/bnxt_re/main.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/infiniband/hw/bnxt_re/main.c +8 -2
index d25fdc458120e..c2fa83eb0da59 100644
@@ -356,9 +356,13 @@ static int bnxt_re_update_qp1_tos_dscp(struct bnxt_re_dev *rdev)
 	return bnxt_qplib_modify_qp(&rdev->qplib_res, &qp->qplib_qp);
 }
 
-static void bnxt_re_init_dcb_wq(struct bnxt_re_dev *rdev)
+static int bnxt_re_init_dcb_wq(struct bnxt_re_dev *rdev)
 {
 	rdev->dcb_wq = create_singlethread_workqueue("bnxt_re_dcb_wq");
+	if (!rdev->dcb_wq)
+		return -ENOMEM;
+
+	return 0;
 }
 
 static void bnxt_re_uninit_dcb_wq(struct bnxt_re_dev *rdev)
@@ -2343,7 +2347,9 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
 
 	bnxt_re_debugfs_add_pdev(rdev);
 
-	bnxt_re_init_dcb_wq(rdev);
+	rc = bnxt_re_init_dcb_wq(rdev);
+	if (rc)
+		goto fail;
 	bnxt_re_net_register_async_event(rdev);
 
 	if (!rdev->is_virtfn)
Signature · 1 line
2.53.0
author maintainer
#38 lore raw

PATCH 38/438 RDMA/rtrs: guard against null kobj name

In reply to Greg Kroah-Hartman

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

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

From: Ryan Mehri <[email protected]>

[ Upstream commit 99c24a8968ebef0573825b5cb89d5985d51635b9 ]

In the client, if init_path() errors, the callee tries to clean up with rtrs_clt_close_conns(). However, this can lead to calling the event tracing code with clt_path->kobj->name being NULL and thus causing a null pointer dereference when trying to copy from it.

This just adds a guard to check that the name is not NULL before copying from it. The server appears to have a similar pattern.

Fixes 5a93929d9f9a1 ("RDMA/rtrs-clt: Add event tracing support")
Fixes c16762b7bf54d ("RDMA/rtrs-srv: Add event tracing support")
Reported-by [email protected]
---
 drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h | 2 +-
 drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h +1 -1
index 7738e26768557..29e23404bb7b8 100644
@@ -55,7 +55,7 @@ DECLARE_EVENT_CLASS(rtrs_clt_conn_class,
 		__entry->max_reconnect_attempts = clt->max_reconnect_attempts;
 		__entry->fail_cnt = clt_path->stats->reconnects.fail_cnt;
 		__entry->success_cnt = clt_path->stats->reconnects.successful_cnt;
-		memcpy(__entry->sessname, kobject_name(&clt_path->kobj), NAME_MAX);
+		strscpy(__entry->sessname, kobject_name(&clt_path->kobj) ?: "", NAME_MAX);
 	),
 
 	TP_printk("RTRS-CLT: sess='%s' state=%s attempts='%d' max-attempts='%d' fail='%d' success='%d'",
drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h +1 -1
index 587d3e0330812..a7d7b971e6c80 100644
@@ -61,7 +61,7 @@ TRACE_EVENT(send_io_resp_imm,
 		__entry->msg_id = id->msg_id;
 		__entry->wr_cnt = atomic_read(&con->c.wr_cnt);
 		__entry->signal_interval = s->signal_interval;
-		memcpy(__entry->sessname, kobject_name(&srv_path->kobj), NAME_MAX);
+		strscpy(__entry->sessname, kobject_name(&srv_path->kobj) ?: "", NAME_MAX);
 	),
 
 	TP_printk("sess='%s' state='%s' dir=%s err='%d' inval='%d' glob-inval='%d' msgid='%u' wrcnt='%d' sig-interval='%u'",
Signature · 1 line
2.53.0
author maintainer
#39 lore raw

PATCH 39/438 RDMA/bnxt_re: Avoid exposing umdbr to userspace

In reply to Greg Kroah-Hartman

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

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

From: Sriharsha Basavapatna <[email protected]>

[ Upstream commit 23d7e03a52ece66b992620aa9b8fa5f164077c0f ]

The umdbr field in struct bnxt_re_db_region returns the raw unmapped PCI BAR address of the doorbell region. Avoid sharing this field to the userspace. Change this to a reserved field and stop populating it, keeping the ABI layout and size unchanged for existing binaries.

---
 drivers/infiniband/hw/bnxt_re/uapi.c | 6 ++----
 include/uapi/rdma/bnxt_re-abi.h      | 2 +-
 2 files changed, 3 insertions(+), 5 deletions(-)
drivers/infiniband/hw/bnxt_re/uapi.c +2 -4
index 263238a6e4cdd..f278c4f70ff7b 100644
@@ -409,7 +409,6 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_DBR_ALLOC)(struct uverbs_attr_bundle *a
 	uobj->object = obj;
 	uverbs_finalize_uobj_create(attrs, BNXT_RE_ALLOC_DBR_HANDLE);
 
-	dbr.umdbr = dpi->umdbr;
 	dbr.dpi = dpi->dpi;
 	ret = uverbs_copy_to_struct_or_zero(attrs, BNXT_RE_ALLOC_DBR_ATTR,
 					    &dbr, sizeof(dbr));
@@ -472,7 +471,6 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_DEFAULT_DBR)(struct uverbs_attr_bun
 		return PTR_ERR(ib_uctx);
 
 	uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
-	dpi.umdbr = uctx->dpi.umdbr;
 	dpi.dpi = uctx->dpi.dpi;
 
 	ret = uverbs_copy_to_struct_or_zero(attrs, BNXT_RE_DEFAULT_DBR_ATTR,
@@ -490,7 +488,7 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_DBR_ALLOC,
 					    UA_MANDATORY),
 			    UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_DBR_ATTR,
 						UVERBS_ATTR_STRUCT(struct bnxt_re_db_region,
-								   umdbr),
+								   reserved2),
 								   UA_MANDATORY),
 			    UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_DBR_OFFSET,
 						UVERBS_ATTR_TYPE(u64),
@@ -510,7 +508,7 @@ DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_DBR,
 DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_DEFAULT_DBR,
 			    UVERBS_ATTR_PTR_OUT(BNXT_RE_DEFAULT_DBR_ATTR,
 						UVERBS_ATTR_STRUCT(struct bnxt_re_db_region,
-								   umdbr),
+								   reserved2),
 						UA_MANDATORY));
 
 DECLARE_UVERBS_GLOBAL_METHODS(BNXT_RE_OBJECT_DEFAULT_DBR,
include/uapi/rdma/bnxt_re-abi.h +1 -1
index a4599d7b736aa..0a125c2a8cc4e 100644
@@ -247,7 +247,7 @@ struct bnxt_re_query_device_ex_resp {
 struct bnxt_re_db_region {
 	__u32 dpi;
 	__u32 reserved;
-	__aligned_u64 umdbr;
+	__aligned_u64 reserved2;
 };
 
 enum bnxt_re_obj_dbr_alloc_attrs {
Signature · 1 line
2.53.0
author maintainer
#40 lore raw

PATCH 40/438 RDMA/uverbs: Fix potential leak of resources->collection in flow_resources_alloc()

In reply to Greg Kroah-Hartman

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

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

From: Li RongQing <[email protected]>

[ Upstream commit 08d4d9802d58bf032099091e6acf719f3298f28e ]

The two array allocations are done unconditionally and only checked afterwards, so if the counters allocation fails while the collection allocation succeeds, the error path frees counters and the containing struct but never frees resources->collection, losing the only pointer to it.

Fixes de7498147d00 ("RDMA/uverbs: Refactor flow_resources_alloc() function")
---
 drivers/infiniband/core/uverbs_flow.c | 1 +
 1 file changed, 1 insertion(+)
drivers/infiniband/core/uverbs_flow.c +1 -0
index 1528a294f7f85..de5a2769f0847 100644
@@ -26,6 +26,7 @@ struct ib_uflow_resources *flow_resources_alloc(size_t num_specs)
 	return resources;
 
 err:
+	kfree(resources->collection);
 	kfree(resources->counters);
 	kfree(resources);
 
Signature · 1 line
2.53.0
author maintainer
#41 lore raw

PATCH 41/438 RDMA/mad: Fix receive buffer leak when PKey enforcement fails

In reply to Greg Kroah-Hartman

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

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

From: Li RongQing <[email protected]>

[ Upstream commit 3476c28c9addfa253f505e6bd87f1f5598b961d0 ]

ib_mad_complete_recv() initializes mad_recv_wc->rmpp_list and then runs ib_mad_enforce_security() before linking recv_buf onto that list. On failure it calls ib_free_recv_mad(), which only walks rmpp_list and frees the ib_mad_private of every buffer found there. As the list is still empty at that point, nothing is freed at all.

The caller cannot clean up either: ib_mad_recv_done() sets recv to NULL right after ib_mad_complete_recv() returns, assuming the MAD layer took ownership of the buffer. Every MAD that fails the PKey check therefore leaks one ib_mad_private (about 300 bytes per IB port MAD, ~2K for OPA), and a remote node can trigger this repeatedly by sending MADs with a wrong PKey.

Link recv_buf onto rmpp_list right after the list is initialized, so the error path has something to free.

Fixes 47a2b338fe63 ("IB/core: Enforce security on management datagrams")
---
 drivers/infiniband/core/mad.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/infiniband/core/mad.c +2 -1
index e0b3b36b8b149..3c91f00d09c6b 100644
@@ -2059,6 +2059,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 	int ret;
 
 	INIT_LIST_HEAD(&mad_recv_wc->rmpp_list);
+	list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
+
 	ret = ib_mad_enforce_security(mad_agent_priv,
 				      mad_recv_wc->wc->pkey_index);
 	if (ret) {
@@ -2067,7 +2069,6 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
 		return;
 	}
 
-	list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
 	if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) {
 		spin_lock_irqsave(&mad_agent_priv->lock, flags);
 		mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
Signature · 1 line
2.53.0
author maintainer
#42 lore raw

PATCH 42/438 RDMA/erdma: Use IRQ-safe XArray helpers for QP and CQ tables

In reply to Greg Kroah-Hartman

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

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

From: Cheng Xu <[email protected]>

[ Upstream commit 00baeade709fb66da647e8327e8398bb532e30f7 ]

Locked QP and CQ lookups from EQ interrupts can deadlock with create-path XArray updates. If an interrupt arrives while the create path holds the plain xa_lock, the lookup spins forever trying to acquire the same lock.

Use IRQ-safe XArray helpers for all QP and CQ create-path updates, including the GSI QP store and error paths. Initialize both arrays with XA_FLAGS_LOCK_IRQ so sleeping allocations preserve interrupt state.

Fixes 98df2aee1459 ("RDMA/erdma: Hold CQ references when processing EQ events")
Fixes a52eeff32024 ("RDMA/erdma: Hold QP references for AE and CM processing")
---
 drivers/infiniband/hw/erdma/erdma_main.c  |  4 ++--
 drivers/infiniband/hw/erdma/erdma_verbs.c | 18 +++++++++---------
 2 files changed, 11 insertions(+), 11 deletions(-)
drivers/infiniband/hw/erdma/erdma_main.c +2 -2
index 7e87a815e853b..445182c6bc5d3 100644
@@ -572,8 +572,8 @@ static int erdma_ib_device_add(struct pci_dev *pdev)
 	INIT_LIST_HEAD(&dev->cep_list);
 
 	spin_lock_init(&dev->lock);
-	xa_init_flags(&dev->qp_xa, XA_FLAGS_ALLOC1);
-	xa_init_flags(&dev->cq_xa, XA_FLAGS_ALLOC1);
+	xa_init_flags(&dev->qp_xa, XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_IRQ);
+	xa_init_flags(&dev->cq_xa, XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_IRQ);
 	dev->next_alloc_cqn = 1;
 	dev->next_alloc_qpn = 1;
 
drivers/infiniband/hw/erdma/erdma_verbs.c +9 -9
index 20944d506da77..5efd3bfb59d65 100644
@@ -1023,15 +1023,15 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
 	init_completion(&qp->safe_free);
 
 	if (qp->ibqp.qp_type == IB_QPT_GSI) {
-		old_entry = xa_store(&dev->qp_xa, 1, qp, GFP_KERNEL);
+		old_entry = xa_store_irq(&dev->qp_xa, 1, qp, GFP_KERNEL);
 		if (xa_is_err(old_entry))
 			ret = xa_err(old_entry);
 		else
 			qp->ibqp.qp_num = 1;
 	} else {
-		ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp,
-				      XA_LIMIT(1, dev->attrs.max_qp - 1),
-				      &dev->next_alloc_qpn, GFP_KERNEL);
+		ret = xa_alloc_cyclic_irq(&dev->qp_xa, &qp->ibqp.qp_num, qp,
+					  XA_LIMIT(1, dev->attrs.max_qp - 1),
+					  &dev->next_alloc_qpn, GFP_KERNEL);
 	}
 
 	if (ret < 0) {
@@ -1091,7 +1091,7 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
 	else
 		free_kernel_qp(qp);
 err_out_xa:
-	xa_erase(&dev->qp_xa, QP_ID(qp));
+	xa_erase_irq(&dev->qp_xa, QP_ID(qp));
 err_out:
 	return ret;
 }
@@ -1995,9 +1995,9 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
 	refcount_set(&cq->refcount, 1);
 	init_completion(&cq->free);
 
-	ret = xa_alloc_cyclic(&dev->cq_xa, &cq->cqn, cq,
-			      XA_LIMIT(1, dev->attrs.max_cq - 1),
-			      &dev->next_alloc_cqn, GFP_KERNEL);
+	ret = xa_alloc_cyclic_irq(&dev->cq_xa, &cq->cqn, cq,
+				  XA_LIMIT(1, dev->attrs.max_cq - 1),
+				  &dev->next_alloc_cqn, GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
@@ -2043,7 +2043,7 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
 	}
 
 err_out_xa:
-	xa_erase(&dev->cq_xa, cq->cqn);
+	xa_erase_irq(&dev->cq_xa, cq->cqn);
 
 	return ret;
 }
Signature · 1 line
2.53.0
author maintainer
#43 lore raw

PATCH 43/438 RDMA/irdma: Enforce local fence for IB_WR_REG_MR

In reply to Greg Kroah-Hartman

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

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

From: Jacob Moroni <[email protected]>

[ Upstream commit 3fb905f07ea45b31c8f67ba6e4668de46f527e65 ]

Enforce local fence for IB_WR_REG_MR to avoid spurious FASTREG_VALID_MKEY async events during heavy invalidation and registration activity.

Commit 69e8e429bca2 ("RDMA/irdma: Enforce local fence for LOCAL_INV WRs") was very similar, but was not sufficient to prevent all occurrences of these async events.

Fixes b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
---
 drivers/infiniband/hw/irdma/verbs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/irdma/verbs.c +1 -1
index 04d5af78686b5..e926eb37982c6 100644
@@ -4244,7 +4244,7 @@ static int irdma_post_send(struct ib_qp *ibqp,
 			stag_info.total_len = iwmr->ibmr.length;
 			stag_info.reg_addr_pa = *palloc->level1.addr;
 			stag_info.first_pm_pbl_index = palloc->level1.idx;
-			stag_info.local_fence = ib_wr->send_flags & IB_SEND_FENCE;
+			stag_info.local_fence = true;
 			if (iwmr->npages > IRDMA_MIN_PAGES_PER_FMR)
 				stag_info.chunk_size = 1;
 			err = irdma_sc_mr_fast_register(&iwqp->sc_qp, &stag_info,
Signature · 1 line
2.53.0
author maintainer
#44 lore raw

PATCH 44/438 RDMA/rtrs-clt: Fix CQ pool leak when connect is interrupted

In reply to Greg Kroah-Hartman

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

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

From: Quanye Yang <[email protected]>

[ Upstream commit 2ae16aaa78b5edc6e6d0904c84fd9cdfb762bcda ]

The client borrows shared CQ credits in the ADDR_RESOLVED handler via ib_cq_pool_get(), before the peer is connected. create_cm() can return -ERESTARTSYS from wait_event_interruptible_timeout() without destroying the CM ID. The init_conns() and stop-and-destroy paths then call destroy_con_cq_qp() while cq is still NULL (no PUT) and only afterwards rdma_destroy_id().

CMA serializes the handler against rdma_destroy_id() with handler_mutex, but that does not order the GET against destroy_con_cq_qp(). If ADDR_RESOLVED has already passed the DESTROYING check, it can take con_mutex, GET credits, and then lose the con to kfree. Device unregister later hits WARN_ON(cq->cqe_used) in ib_cq_pool_cleanup().

Set a per-connection flag under con_mutex before CQ/QP teardown so a racing ADDR_RESOLVED cannot borrow credits after teardown has begun.

---
 drivers/infiniband/ulp/rtrs/rtrs-clt.c | 8 ++++++++
 drivers/infiniband/ulp/rtrs/rtrs-clt.h | 2 ++
 2 files changed, 10 insertions(+)
drivers/infiniband/ulp/rtrs/rtrs-clt.c +8 -0
index d34d7e5f34d6f..62cc93be7b877 100644
@@ -1735,6 +1735,8 @@ static void destroy_con_cq_qp(struct rtrs_clt_con *con)
 	/*
 	 * Be careful here: destroy_con_cq_qp() can be called even
 	 * create_con_cq_qp() failed, see comments there.
+	 * Caller must set con->destroyed under this lock first so a
+	 * racing ADDR_RESOLVED cannot ib_cq_pool_get() after we PUT/SKIP.
 	 */
 	lockdep_assert_held(&con->con_mutex);
 	rtrs_cq_qp_destroy(&con->c);
@@ -1769,6 +1771,10 @@ static int rtrs_rdma_addr_resolved(struct rtrs_clt_con *con)
 	int err;
 
 	mutex_lock(&con->con_mutex);
+	if (con->destroyed) {
+		mutex_unlock(&con->con_mutex);
+		return -ECONNABORTED;
+	}
 	err = create_con_cq_qp(con);
 	mutex_unlock(&con->con_mutex);
 	if (err) {
@@ -2224,6 +2230,7 @@ static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_path *clt_path)
 			break;
 		con = to_clt_con(clt_path->s.con[cid]);
 		mutex_lock(&con->con_mutex);
+		con->destroyed = true;
 		destroy_con_cq_qp(con);
 		mutex_unlock(&con->con_mutex);
 		destroy_cm(con);
@@ -2390,6 +2397,7 @@ static int init_conns(struct rtrs_clt_path *clt_path)
 		if (con->c.cm_id) {
 			stop_cm(con);
 			mutex_lock(&con->con_mutex);
+			con->destroyed = true;
 			destroy_con_cq_qp(con);
 			mutex_unlock(&con->con_mutex);
 			destroy_cm(con);
drivers/infiniband/ulp/rtrs/rtrs-clt.h +2 -0
index 1305601a6251e..ad64f4517c4b3 100644
@@ -75,6 +75,8 @@ struct rtrs_clt_con {
 	unsigned int		cpu;
 	struct mutex		con_mutex;
 	int			cm_err;
+	/* Set under con_mutex before CQ/QP teardown. */
+	bool			destroyed;
 };
 
 /**
Signature · 1 line
2.53.0
author maintainer
#45 lore raw

PATCH 45/438 dmaengine: mmp_pdma: fix wrong extended DRCMR base for SpacemiT K3

In reply to Greg Kroah-Hartman

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

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

From: Troy Mitchell <[email protected]>

[ Upstream commit d1fc569fcbc7be6de06b034cf954a95e30ca1fb2 ]

The extended DRCMR window on SpacemiT K3 starts at 0x1100. Commit 6587b8661a0b ("dmaengine: mmp_pdma: add SpacemiT K3 support") incorrectly set it to 0x1000, causing DRCMR accesses for request IDs >= 64 to target offsets 0x100 too low.

The 0x1100 base has been verified on K3 silicon using real SPI and QSPI DMA transactions. The K3 DMA documentation [1] was updated on June 24, 2026, to reflect the corrected register addresses.

Drop the bogus DRCMR_EXT_BASE_K3 macro and reuse
DRCMR_EXT_BASE_DEFAULT for the K3 ops.

---
 drivers/dma/mmp_pdma.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/dma/mmp_pdma.c +1 -2
index 386e85cd4882a..78e3e07e681df 100644
@@ -52,7 +52,6 @@
 #define DCSR_EORINTR	BIT(9)	/* The end of Receive */
 
 #define DRCMR_BASE		0x0100
-#define DRCMR_EXT_BASE_K3	0x1000
 #define DRCMR_EXT_BASE_DEFAULT	0x1100
 #define DRCMR_REQ_LIMIT		64
 #define DRCMR_MAPVLD	BIT(7)	/* Map Valid (read / write) */
@@ -1219,7 +1218,7 @@ static const struct mmp_pdma_ops spacemit_k3_pdma_ops = {
 	.get_desc_dst_addr = get_desc_dst_addr_64,
 	.run_bits = (DCSR_RUN | DCSR_LPAEEN | DCSR_EORIRQEN | DCSR_EORSTOPEN),
 	.dma_width = 64,
-	.drcmr_ext_base = DRCMR_EXT_BASE_K3,
+	.drcmr_ext_base = DRCMR_EXT_BASE_DEFAULT,
 };
 
 static const struct of_device_id mmp_pdma_dt_ids[] = {
Signature · 1 line
2.53.0
author maintainer
#46 lore raw

PATCH 46/438 dmaengine: sprd: Fix runtime PM reference leak in probe

In reply to Greg Kroah-Hartman

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

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

From: Ruoyu Wang <[email protected]>

[ Upstream commit a7df136ec529ee49a789c5029bc37b98b0d4bedd ]

pm_runtime_get_sync() increments a device's usage counter even when it fails. sprd_dma_probe() currently jumps directly to controller clock cleanup on that error, bypassing both pm_runtime_put_noidle() and pm_runtime_disable(). This can happen if the preceding unchecked pm_runtime_set_active() fails and the following runtime-resume attempt also returns an error.

Enter the existing runtime-PM unwind path instead. This drops the reference without idling the partially initialized device, disables runtime PM, and then releases the controller clocks. The success path and propagated error code are unchanged.

This issue was found by a static analysis checker and confirmed by manual source review.

---
 drivers/dma/sprd-dma.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/dma/sprd-dma.c +1 -2
index 087fea3af2e41..19b32a23c882d 100644
@@ -1212,7 +1212,7 @@ static int sprd_dma_probe(struct platform_device *pdev)
 
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0)
-		goto err_rpm;
+		goto err_register;
 
 	ret = dma_async_device_register(&sdev->dma_dev);
 	if (ret < 0) {
@@ -1234,7 +1234,6 @@ static int sprd_dma_probe(struct platform_device *pdev)
 err_register:
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-err_rpm:
 	sprd_dma_disable(sdev);
 	return ret;
 }
Signature · 1 line
2.53.0
author maintainer
#47 lore raw

PATCH 47/438 wifi: mac80211: include TIM bitmap control for buffered S1G mcast traffic

In reply to Greg Kroah-Hartman

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

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

From: Lachlan Hodges <[email protected]>

[ Upstream commit af72b5946d493cecced27d0951ea37c1d178601e ]

Currently when building the S1G TIM element, we only build the bitmap control if we have buffered unicast traffic. Since AID 0 sits within the bitmap control if we have buffered multicast traffic with no buffered unicast traffic the bitmap control won't be emitted and dozing stations will be unaware of buffered multicast.

To fix, only exclude the bitmap control byte when we don't have both buffered unicast and multicast traffic.

Fixes ee6360945483 ("wifi: mac80211: support block bitmap S1G TIM encoding")
---
 net/mac80211/tx.c | 41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)
net/mac80211/tx.c +22 -19
index fd4c379b3f201..7cb9dd1b27314 100644
@@ -5063,10 +5063,18 @@ static void ieee80211_beacon_add_tim_pvb(struct ps_data *ps,
  */
 static void ieee80211_s1g_beacon_add_tim_pvb(struct ps_data *ps,
 					     struct sk_buff *skb,
-					     bool mcast_traffic)
+					     bool mcast_traffic,
+					     bool ucast_traffic)
 {
 	int blk;
 
+	/*
+	 * if no unicast and multicast traffic don't emit a bitmap control
+	 * or pvb
+	 */
+	if (!mcast_traffic && !ucast_traffic)
+		return;
+
 	/*
 	 * Emit a bitmap control block with a page slice number of 31 and a
 	 * page index of 0 which indicates as per IEEE80211-2024 9.4.2.5.1
@@ -5075,6 +5083,10 @@ static void ieee80211_s1g_beacon_add_tim_pvb(struct ps_data *ps,
 	 */
 	skb_put_u8(skb, mcast_traffic | (31 << 1));
 
+	/* If there's no unicast traffic we don't need to include a PVB. */
+	if (!ucast_traffic)
+		return;
+
 	/* Emit an encoded block for each non-zero sub-block */
 	for (blk = 0; blk < IEEE80211_MAX_SUPPORTED_S1G_TIM_BLOCKS; blk++) {
 		u8 blk_bmap = 0;
@@ -5156,25 +5168,16 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
 
 	ps->dtim_bc_mc = mcast_traffic;
 
-	if (have_bits) {
-		if (s1g)
-			ieee80211_s1g_beacon_add_tim_pvb(ps, skb,
-							 mcast_traffic);
-		else
-			ieee80211_beacon_add_tim_pvb(ps, skb, mcast_traffic);
+	if (s1g) {
+		ieee80211_s1g_beacon_add_tim_pvb(ps, skb, mcast_traffic,
+						 have_bits);
+	} else if (have_bits) {
+		ieee80211_beacon_add_tim_pvb(ps, skb, mcast_traffic);
 	} else {
-		/*
-		 * If there is no buffered unicast traffic for an S1G
-		 * interface, we can exclude the bitmap control. This is in
-		 * contrast to other phy types as they do include the bitmap
-		 * control and pvb even when there is no buffered traffic.
-		 */
-		if (!s1g) {
-			/* Bitmap control */
-			skb_put_u8(skb, mcast_traffic);
-			/* Part Virt Bitmap */
-			skb_put_u8(skb, 0);
-		}
+		/* Bitmap control */
+		skb_put_u8(skb, mcast_traffic);
+		/* Part Virt Bitmap */
+		skb_put_u8(skb, 0);
 	}
 
 	tim->datalen = skb_tail_pointer(skb) - tim->data;
Signature · 1 line
2.53.0
author maintainer
#48 lore raw

PATCH 48/438 wifi: virt_wifi: free skb when disconnected

In reply to Greg Kroah-Hartman

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

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

From: Mariano Baragiola <[email protected]>

[ Upstream commit f9edf7cf63b96d2b776fca8d258d3c5256e40c8e ]

When the simulated link is disconnected, virt_wifi_start_xmit() returns NET_XMIT_DROP without freeing the skb. dev_hard_start_xmit() treats this return value as consumed, so every packet sent while disconnected leaks its skb.

Free the skb before returning the drop status.

Fixes c7cdba31ed8b ("mac80211-next: rtnetlink wifi simulation device")
---
 drivers/net/wireless/virtual/virt_wifi.c | 1 +
 1 file changed, 1 insertion(+)
drivers/net/wireless/virtual/virt_wifi.c +1 -0
index 2335e45db8b85..b69a4650fba85 100644
@@ -434,6 +434,7 @@ static netdev_tx_t virt_wifi_start_xmit(struct sk_buff *skb,
 	priv->tx_packets++;
 	if (!priv->is_connected) {
 		priv->tx_failed++;
+		dev_kfree_skb_any(skb);
 		return NET_XMIT_DROP;
 	}
 
Signature · 1 line
2.53.0
author maintainer
#49 lore raw

PATCH 49/438 wifi: mwifiex: fix IRQ leak using wrong index in MSI-X error path

In reply to Greg Kroah-Hartman

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

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

From: Peng Hao <[email protected]>

[ Upstream commit a3d722190cdef18da4878b5efc27c3c386dda248 ]

mwifiex_pcie_request_irq() registers each MSI-X vector with a per-index dev_id (&card->msix_ctx[i]). On a request_irq() failure the cleanup loop "for (j = 0; j < i; j++)" frees msix_entries[j].vector but passes the failed index's &card->msix_ctx[i] as the dev_id. free_irq() matches on (irq, dev_id), so it fails to find the action registered with &card->msix_ctx[j]: the already-requested IRQ j is not freed (leaked) and free_irq() warns about freeing a non-existent IRQ. Use &card->msix_ctx[j].

Fixes 99074fc1e67b ("mwifiex: enable pcie MSIx interrupt mode support")
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/marvell/mwifiex/pcie.c +1 -1
index a760de191fce7..a9425e9a94f45 100644
@@ -3068,7 +3068,7 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
 					    ret);
 				for (j = 0; j < i; j++)
 					free_irq(card->msix_entries[j].vector,
-						 &card->msix_ctx[i]);
+						 &card->msix_ctx[j]);
 				pci_disable_msix(pdev);
 			} else {
 				mwifiex_dbg(adapter, MSG, "MSIx enabled!");
Signature · 1 line
2.53.0
author maintainer
#50 lore raw

PATCH 50/438 wifi: brcmfmac: cyw: pass PMKID to firmware if present

In reply to Greg Kroah-Hartman

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

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

From: Bogdan Nicolae <[email protected]>

[ Upstream commit e2de8d5eb2984416affdd9559e55f37c7f1bbf47 ]

Zero out auth_status on initialization. Otherwise, garbage will leak from the stack to the firmware (when ssid is less than 32 bytes and/or when params->pmkid is set). Then, pass the params->pmkid to the firmware (without it, the firmware caches a garbage PMKID on successful authentication and denies a subsequent association request that includes the PMKID).

Fixes 66f909308a7c ("wifi: brcmfmac: cyw: support external SAE authentication in station mode")
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c +4 -1
index 873754be5174b..c86d0bdde8326 100644
@@ -200,7 +200,7 @@ brcmf_cyw_external_auth(struct wiphy *wiphy, struct net_device *dev,
 {
 	struct brcmf_if *ifp;
 	struct brcmf_pub *drvr;
-	struct brcmf_auth_req_status_le auth_status;
+	struct brcmf_auth_req_status_le auth_status = {};
 	int ret = 0;
 
 	brcmf_dbg(TRACE, "Enter\n");
@@ -208,6 +208,9 @@ brcmf_cyw_external_auth(struct wiphy *wiphy, struct net_device *dev,
 	ifp = netdev_priv(dev);
 	drvr = ifp->drvr;
 	if (params->status == WLAN_STATUS_SUCCESS) {
+		if (params->pmkid)
+			memcpy(auth_status.pmkid, params->pmkid,
+			       WLAN_PMKID_LEN);
 		auth_status.flags = cpu_to_le16(BRCMF_EXTAUTH_SUCCESS);
 	} else {
 		bphy_err(drvr, "External authentication failed: status=%d\n",
Signature · 1 line
2.53.0
author maintainer
#51 lore raw

PATCH 51/438 wifi: libipw: reject too-short beacon and probe responses

In reply to Greg Kroah-Hartman

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

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

From: Shmulik Cohen <[email protected]>

[ Upstream commit 5ce5721e8cbe3e80db8f43851cc2a2a92485ef4b ]

libipw_process_probe_response() and the libipw_network_init() call it makes assume the frame contains the full 36-byte beacon and probe response prefix, but the ipw2100 and ipw2200 receive paths only establish that a management frame carries the generic 24-byte three-address header.

libipw_network_init() then computes the information element length as

	stats->len - sizeof(*beacon)

stats->len is a u16 and sizeof() has type size_t, so the subtraction is evaluated as size_t and wraps instead of going negative. Truncating that to the u16 length parameter of libipw_parse_info_param() yields 65524 for a 24-byte beacon, and the parser then walks the receive buffer as if it held almost 64 KiB of information elements, reading past the allocation.

Reject the frame before any fixed field is touched.

Found by an AI-assisted review of length arithmetic in management frame parsers. Verified with a KUnit case under Generic KASAN on arm64 under QEMU; I do not have the hardware, so it is not tested on a real device.

Fixes b453872c35cf ("[NET] ieee80211 subsystem")
Assisted-by Claude:claude-opus-5
---
 drivers/net/wireless/intel/ipw2x00/libipw_rx.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/net/wireless/intel/ipw2x00/libipw_rx.c +3 -0
index c8841f9b9ad91..2661dac6985e4 100644
@@ -1421,6 +1421,9 @@ static void libipw_process_probe_response(struct libipw_device
 #endif
 	unsigned long flags;
 
+	if (stats->len < sizeof(*beacon))
+		return;
+
 	LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
 		     info_element->len, info_element->data,
 		     beacon->header.addr3,
Signature · 1 line
2.53.0
author maintainer
#52 lore raw

PATCH 52/438 wifi: libipw: reject too-short association responses

In reply to Greg Kroah-Hartman

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

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

From: Shmulik Cohen <[email protected]>

[ Upstream commit adb7118b7d2cfd7e8213c17d7d2829f353017754 ]

libipw_handle_assoc_resp() reads the capability, status and aid fields of the 30-byte association response prefix and then computes the information element length as

	stats->len - sizeof(*frame)

stats->len is a u16 and sizeof() has type size_t, so the subtraction is evaluated as size_t and wraps instead of going negative. Truncating that to the u16 length parameter of libipw_parse_info_param() turns a frame shorter than the fixed fields into a length near 64 KiB, and the parser then reads past the receive buffer.

Both the ipw2100 and ipw2200 management receive paths reach this function having established only that the frame carries the generic 24-byte three-address header.

Reject the frame before any fixed field is touched.

Found by an AI-assisted review of length arithmetic in management frame parsers. Verified with a KUnit case under Generic KASAN on arm64 under QEMU; I do not have the hardware, so it is not tested on a real device.

Fixes 9e8571affd1c ("[PATCH] ieee80211: Add QoS (WME) support to the ieee80211 subsystem")
Assisted-by Claude:claude-opus-5
---
 drivers/net/wireless/intel/ipw2x00/libipw_rx.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/net/wireless/intel/ipw2x00/libipw_rx.c +3 -0
index 2661dac6985e4..424349a6935e4 100644
@@ -1209,6 +1209,9 @@ static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_as
 	struct libipw_network *network = &network_resp;
 	struct net_device *dev = ieee->dev;
 
+	if (stats->len < sizeof(*frame))
+		return 1;
+
 	network->flags = 0;
 	network->qos_data.active = 0;
 	network->qos_data.supported = 0;
Signature · 1 line
2.53.0
author maintainer
#53 lore raw

PATCH 53/438 IB/IPoIB: Avoid restoring OPER_UP after multicast flush

In reply to Greg Kroah-Hartman

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

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

From: Carolina Jubran <[email protected]>

[ Upstream commit 9a141d3dc869d18b2eab35e999f4790a9b84e40f ]

ipoib_ib_dev_flush_light() temporarily clears IPOIB_FLAG_OPER_UP to prevent multicast joins while ipoib_mcast_dev_flush() is running, and restores the flag afterwards if it was previously set.

This restore races with ipoib_ib_dev_down(). If the interface is brought down while the flush is in progress, ipoib_ib_dev_down() clears IPOIB_FLAG_OPER_UP, but the flush path may set it again after the device has already gone down.

Since commit 894021a75291 ("IB/ipoib: Make the carrier_on_task race aware"), ipoib_mcast_carrier_on_task() relies on IPOIB_FLAG_OPER_UP being cleared to terminate its rtnl_trylock() retry loop. If the flag is left set after shutdown, the workqueue retries forever, causing teardown to deadlock when ipoib_ndo_uninit() waits in destroy_workqueue() while holding RTNL.

Instead of overloading IPOIB_FLAG_OPER_UP to block multicast joins during a light flush, introduce a dedicated IPOIB_FLAG_MCAST_FLUSH flag. Use it together with IPOIB_FLAG_OPER_UP to determine whether multicast joins are allowed, avoiding the race with device shutdown.

---
 drivers/infiniband/ulp/ipoib/ipoib.h           |  7 +++++++
 drivers/infiniband/ulp/ipoib/ipoib_ib.c        | 12 +++++++-----
 drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 16 ++++++++--------
 3 files changed, 22 insertions(+), 13 deletions(-)
drivers/infiniband/ulp/ipoib/ipoib.h +7 -0
index 91f866e3fb8bd..143e03b649021 100644
@@ -87,6 +87,7 @@ enum {
 	IPOIB_FLAG_INITIALIZED	  = 1,
 	IPOIB_FLAG_ADMIN_UP	  = 2,
 	IPOIB_PKEY_ASSIGNED	  = 3,
+	IPOIB_FLAG_MCAST_FLUSH	  = 4,
 	IPOIB_FLAG_SUBINTERFACE	  = 5,
 	IPOIB_STOP_REAPER	  = 7,
 	IPOIB_FLAG_ADMIN_CM	  = 9,
@@ -414,6 +415,12 @@ struct ipoib_dev_priv {
 	const struct net_device_ops	*rn_ops;
 };
 
+static inline bool ipoib_mcast_allowed(struct ipoib_dev_priv *priv)
+{
+	return test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) &&
+	       !test_bit(IPOIB_FLAG_MCAST_FLUSH, &priv->flags);
+}
+
 struct ipoib_ah {
 	struct net_device *dev;
 	struct ib_ah	  *ah;
drivers/infiniband/ulp/ipoib/ipoib_ib.c +7 -5
index 5061d52a7b12c..81bbb3f7c1132 100644
@@ -1227,17 +1227,19 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
 	}
 
 	if (level == IPOIB_FLUSH_LIGHT) {
-		int oper_up;
 		ipoib_mark_paths_invalid(dev);
-		/* Set IPoIB operation as down to prevent races between:
+		/* Set MCAST_FLUSH to prevent races between:
 		 * the flush flow which leaves MCG and on the fly joins
 		 * which can happen during that time. mcast restart task
 		 * should deal with join requests we missed.
+		 *
+		 * Do not clear OPER_UP for this; restoring it races with
+		 * ipoib_ib_dev_down() and can leave OPER_UP set after the
+		 * device is down.
 		 */
-		oper_up = test_and_clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
+		set_bit(IPOIB_FLAG_MCAST_FLUSH, &priv->flags);
 		ipoib_mcast_dev_flush(dev);
-		if (oper_up)
-			set_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
+		clear_bit(IPOIB_FLAG_MCAST_FLUSH, &priv->flags);
 		ipoib_reap_dead_ahs(priv);
 	}
 
drivers/infiniband/ulp/ipoib/ipoib_multicast.c +8 -8
index 6401af2fd548f..379b78374e210 100644
@@ -74,7 +74,7 @@ static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv,
 					       struct ipoib_mcast *mcast,
 					       bool delay)
 {
-	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+	if (!ipoib_mcast_allowed(priv))
 		return;
 
 	/*
@@ -469,7 +469,7 @@ static int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
 	int ret = 0;
 
 	if (!priv->broadcast ||
-	    !test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+	    !ipoib_mcast_allowed(priv))
 		return -EINVAL;
 
 	init_completion(&mcast->done);
@@ -555,7 +555,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
 	unsigned long delay_until = 0;
 	struct ipoib_mcast *mcast = NULL;
 
-	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+	if (!ipoib_mcast_allowed(priv))
 		return;
 
 	if (ib_query_port(priv->ca, priv->port, &port_attr)) {
@@ -577,7 +577,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
 	netif_addr_unlock_bh(dev);
 
 	spin_lock_irq(&priv->lock);
-	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+	if (!ipoib_mcast_allowed(priv))
 		goto out;
 
 	if (!priv->broadcast) {
@@ -749,7 +749,7 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb)
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)		||
+	if (!ipoib_mcast_allowed(priv)				||
 	    !priv->broadcast					||
 	    !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
 		++dev->stats.tx_dropped;
@@ -871,7 +871,7 @@ void ipoib_mcast_restart_task(struct work_struct *work)
 	LIST_HEAD(remove_list);
 	struct ib_sa_mcmember_rec rec;
 
-	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+	if (!ipoib_mcast_allowed(priv))
 		/*
 		 * shortcut...on shutdown flush is called next, just
 		 * let it do all the work
@@ -965,9 +965,9 @@ void ipoib_mcast_restart_task(struct work_struct *work)
 	ipoib_mcast_remove_list(&remove_list);
 
 	/*
-	 * Double check that we are still up
+	 * Double check that we are still up and not flushing
 	 */
-	if (test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) {
+	if (ipoib_mcast_allowed(priv)) {
 		spin_lock_irq(&priv->lock);
 		__ipoib_mcast_schedule_join_thread(priv, NULL, 0);
 		spin_unlock_irq(&priv->lock);
Signature · 1 line
2.53.0
author maintainer
#54 lore raw

PATCH 54/438 wifi: cfg80211: dont get the radio mask for netdev-less wdevs

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit a7783e585360ee05dfe21d3173dbbe985c94f29e ]

cfg80211_calculate_bi_data() calls rdev_get_radio_mask() with wdev->netdev, which can be NULL and then crashes in mac80211.

To avoid that, invert the order of checks since wdev->netdev is always valid for beaconing interfaces.

---
 net/wireless/util.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
net/wireless/util.c +4 -5
index 24527bf321b2a..7142b81963d27 100644
@@ -2426,16 +2426,15 @@ static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
 		if (wdev->valid_links)
 			continue;
 
+		wdev_bi = cfg80211_wdev_bi(wdev);
+		if (!wdev_bi)
+			continue;
+
 		/* skip wdevs not active on the given wiphy radio */
 		if (radio_idx >= 0 &&
 		    !(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx)))
 			continue;
 
-		wdev_bi = cfg80211_wdev_bi(wdev);
-
-		if (!wdev_bi)
-			continue;
-
 		if (!*beacon_int_gcd) {
 			*beacon_int_gcd = wdev_bi;
 			continue;
Signature · 1 line
2.53.0
author maintainer
#55 lore raw

PATCH 55/438 wifi: cfg80211: check IP header size in cfg80211_classify8021d()

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 48b2c5c628b09cf36cbeca53e0432fc2a7518be7 ]

A frame that looks like IP can be transmitted, but be too short, so the DS field is read incorrectly:

  BUG: KMSAN: uninit-value in cfg80211_classify8021d+0x99d/0x12b0 net/wireless/util.c:1027
   cfg80211_classify8021d+0x99d/0x12b0 net/wireless/util.c:1027
   ieee80211_select_queue+0x37a/0x9e0 net/mac80211/wme.c:180
   __ieee80211_subif_start_xmit+0x60f/0x1d90 net/mac80211/tx.c:4304
   ieee80211_subif_start_xmit+0xa8/0x6d0 net/mac80211/tx.c:4538
   ...
   packet_sendmsg+0x9173/0xa2a0 net/packet/af_packet.c:3108

Use skb_header_pointer() like the MPLS case.

---
 net/wireless/util.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)
net/wireless/util.c +22 -4
index 7142b81963d27..ef56fe0ac41b2 100644
@@ -988,12 +988,30 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
 	}
 
 	switch (skb->protocol) {
-	case htons(ETH_P_IP):
-		dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;
+	case htons(ETH_P_IP): {
+		const struct iphdr *iph;
+		struct iphdr _iph;
+
+		iph = skb_header_pointer(skb, sizeof(struct ethhdr),
+					 sizeof(*iph), &_iph);
+		if (!iph)
+			return 0;
+
+		dscp = ipv4_get_dsfield(iph) & 0xfc;
 		break;
-	case htons(ETH_P_IPV6):
-		dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & 0xfc;
+	}
+	case htons(ETH_P_IPV6): {
+		const struct ipv6hdr *ip6h;
+		struct ipv6hdr _ip6h;
+
+		ip6h = skb_header_pointer(skb, sizeof(struct ethhdr),
+					  sizeof(*ip6h), &_ip6h);
+		if (!ip6h)
+			return 0;
+
+		dscp = ipv6_get_dsfield(ip6h) & 0xfc;
 		break;
+	}
 	case htons(ETH_P_MPLS_UC):
 	case htons(ETH_P_MPLS_MC): {
 		struct mpls_label mpls_tmp, *mpls;
Signature · 1 line
2.53.0
author maintainer
#56 lore raw

PATCH 56/438 soundwire: cadence_master: wait and cancel cdns->work before clock stop

In reply to Greg Kroah-Hartman

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

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

From: Bard Liao <[email protected]>

[ Upstream commit aba7b41faeecb7692458095ce6fafc341fe0b80e ]

A peripheral event could happen during the clock stop process. We need to wait for the event be handled before stopping the bus clock. Otherwise, we will get the IO transfer timed out issue.

Fixes af4cc917826f ("soundwire: cadence: mask Slave interrupt before stopping clock")
---
 drivers/soundwire/cadence_master.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/soundwire/cadence_master.c +7 -0
index 98ed337fb9b01..cf456d7cf0a8f 100644
@@ -1701,6 +1701,13 @@ int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake)
 		return 0;
 	}
 
+	/*
+	 * wait for any in-flight peripheral event handling to complete before stopping the clock.
+	 * No need to disable peripheral interrupts before canceling the work, as the peripheral
+	 * interrupts are already masked before the work is scheduled.
+	 */
+	cancel_work_sync(&cdns->work);
+
 	/*
 	 * Before entering clock stop we mask the Slave
 	 * interrupts. This helps avoid having to deal with e.g. a
Signature · 1 line
2.53.0
author maintainer
#57 lore raw

PATCH 57/438 mips: econet: fix unmet dependencies for ECONET

In reply to Greg Kroah-Hartman

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

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

From: Julian Braha <[email protected]>

[ Upstream commit fb5a08026a68be0ec5f660588311fb1091bf5d58 ]

ECONET selects EARLY_PRINTK_8250, SERIAL_OF_PLATFORM, and SERIAL_8250 without ensuring their dependencies, EARLY_PRINTK and TTY are met. This causes unmet dependencies:

WARNING: unmet direct dependencies detected for SERIAL_8250
Depends on [n]: TTY [=n] && HAS_IOMEM [=y] && !S390 Selected by [y]:
- ECONET [=y]

WARNING: unmet direct dependencies detected for EARLY_PRINTK_8250
Depends on [n]: EARLY_PRINTK [=n] && USE_GENERIC_EARLY_PRINTK_8250 [=y] Selected by [y]:
- ECONET [=y]

WARNING: unmet direct dependencies detected for SERIAL_OF_PLATFORM
Depends on [n]: TTY [=n] && HAS_IOMEM [=y] && SERIAL_8250 [=y] && OF [=y] Selected by [y]:
- ECONET [=y]

However, in the discussion of v1 of this patch, Arnd pointed out that these selects don't belong here in the first place. [1]
Let's remove them to resolve the unmet dependencies.

These unmet dependencies were found by kconfirm, a static analysis tool for Kconfig.

Fixes 79ee1d20e37c ("mips: econet: Fix incorrect Kconfig dependencies")
Fixes 35fb26f94dfa ("mips: Add EcoNet MIPS platform support")
---
 arch/mips/Kconfig | 3 ---
 1 file changed, 3 deletions(-)
arch/mips/Kconfig +0 -3
index 8555bbf47c633..4a1e665bf012a 100644
@@ -397,10 +397,7 @@ config ECONET
 	select BOOT_RAW
 	select CPU_BIG_ENDIAN
 	select DEBUG_ZBOOT if DEBUG_KERNEL
-	select EARLY_PRINTK_8250
 	select ECONET_EN751221_TIMER
-	select SERIAL_8250
-	select SERIAL_OF_PLATFORM
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R2
Signature · 1 line
2.53.0
author maintainer
#58 lore raw

PATCH 58/438 MIPS: Octeon: apply USB FDT fixups also when USB is modular

In reply to Greg Kroah-Hartman

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

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

From: Orgad Shaneh <[email protected]>

[ Upstream commit 126f16e0a1b353c2ba5c7e2c8626cfa865934f9f ]

The uctl/usbn device-tree fixups in octeon_prune_device_tree() - which set the board's USB reference-clock frequency and type from __cvmx_helper_board_usb_get_clock_type() - are guarded by "#ifdef CONFIG_USB", which is false when USB is built as a module. The fixups then silently disappear and octeon-hcd sees whatever default the DTS carries (12MHz crystal in octeon_3xxx.dts), leaving the PHY dead or the bus erroring on boards with a different reference clock.

Use IS_ENABLED() so USB=m gets the same fixups as USB=y.

Fixes 7fd57ab9d9cf ("MIPS: Octeon: Fix compile error when USB is not enabled.")
Assisted-by Claude:claude-opus-5
---
 arch/mips/cavium-octeon/octeon-platform.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/mips/cavium-octeon/octeon-platform.c +2 -2
index 47677b5d7ed00..f53c98372e0be 100644
@@ -18,7 +18,7 @@
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-helper-board.h>
 
-#ifdef CONFIG_USB
+#if IS_ENABLED(CONFIG_USB)
 #include <linux/usb/ehci_def.h>
 #include <linux/usb/ehci_pdriver.h>
 #include <linux/usb/ohci_pdriver.h>
@@ -1080,7 +1080,7 @@ int __init octeon_prune_device_tree(void)
 		;
 	}
 
-#ifdef CONFIG_USB
+#if IS_ENABLED(CONFIG_USB)
 	/* OHCI/UHCI USB */
 	alias_prop = fdt_getprop(initial_boot_params, aliases,
 				 "uctl", NULL);
Signature · 1 line
2.53.0
author maintainer
#59 lore raw

PATCH 59/438 dma-coherent: report a failed reserved memory assignment

In reply to Greg Kroah-Hartman

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

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

From: Donggeun Yoo <[email protected]>

[ Upstream commit 504981db4f69bdd28054fb98c96a3a67f7248dde ]

rmem_dma_device_init() drops the return value of dma_assign_coherent_memory() and always reports success. That call fails with -EBUSY when the device already has a coherent pool, and the file allows only "*one* such region of memory" per device.

of_reserved_mem_device_init_by_idx() reads the zero as success. It logs "assigned reserved memory node" for a region that was not assigned and records the pairing, so of_reserved_mem_device_release() later runs rmem_dma_device_release() for it. That clears dev->dma_mem without looking at which region it was called for, dropping the pool the device did get and leaving it on ordinary memory.

dma_declare_coherent_memory() checks the same call and releases the memory on failure, and rmem_swiotlb_device_init() propagates its own errors. Return the error here as well, so a device tree that assigns two pools to one device fails the probe instead of half working.

Fixes 7bfa5ab6fa1b ("drivers: dma-coherent: add initialization from device tree")
---
 kernel/dma/coherent.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
kernel/dma/coherent.c +1 -2
index bcdc0f76d2e80..b6fe902c6a6db 100644
@@ -351,8 +351,7 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
 	    min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit))
 		dev_warn(dev, "reserved memory is beyond device's set DMA address range\n");
 
-	dma_assign_coherent_memory(dev, mem);
-	return 0;
+	return dma_assign_coherent_memory(dev, mem);
 }
 
 static void rmem_dma_device_release(struct reserved_mem *rmem,
Signature · 1 line
2.53.0
author maintainer
#60 lore raw

PATCH 60/438 dma-mapping: dont trace the DMA address when the allocation fails

In reply to Greg Kroah-Hartman

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

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

From: Donggeun Yoo <[email protected]>

[ Upstream commit 92c6a8d6470f7e7aa86c1f144818d8fa4fcbd5aa ]

dma_alloc_attrs() passes *dma_handle to trace_dma_alloc() without checking whether the allocation succeeded. No backend writes it on
failure: dma_direct_alloc(), iommu_dma_alloc() and the dma_map_ops instances assign it only on the path that returns a buffer. Callers usually pass an uninitialized automatic variable, so a failed allocation records whatever the stack held, next to the virt_addr=(null) that marks the record as an error:

dma_alloc: dmatrace dir=BIDIRECTIONAL dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000

The device coherent pool path reaches the same call: a non-zero return from dma_alloc_from_dev_coherent() means the request was handled, not that it succeeded, so cpu_addr is NULL and dma_handle is untouched once the pool runs out.

For an allocation event a NULL virt_addr already means the request failed, so the address field carries nothing. Report 0 for it in the event class rather than at each call site, which covers dma_alloc_pages() and dma_alloc_sgt_err() as well.

Fixes 038eb433dc14 ("dma-mapping: add tracing for dma-mapping API calls")
Fixes 68b6dbf1f441 ("dma-mapping: trace more error paths")
---
 include/trace/events/dma.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/trace/events/dma.h +1 -1
index 31c9ddf72c9d3..daef2c176ecd8 100644
@@ -133,7 +133,7 @@ DECLARE_EVENT_CLASS(dma_alloc_class,
 	TP_fast_assign(
 		__assign_str(device);
 		__entry->virt_addr = virt_addr;
-		__entry->dma_addr = dma_addr;
+		__entry->dma_addr = virt_addr ? dma_addr : 0;
 		__entry->size = size;
 		__entry->flags = flags;
 		__entry->dir = dir;
Signature · 1 line
2.53.0
author maintainer
#61 lore raw

PATCH 61/438 dmaengine: Fix device kref underflow in dma_chan_put()

In reply to Greg Kroah-Hartman

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

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

From: Shivank Garg <[email protected]>

[ Upstream commit 44dab659064eb5c10adb0306510eebe848ed592d ]

dma_chan_get() takes chan->device->ref only on the slow path:

	/* no kref on fast path */
	if (chan->client_count) {
		__module_get(owner);
		chan->client_count++;
		return 0;
	}
	if (!try_module_get(owner))
		return -ENODEV;
	if (!dma_device_get(chan->device)) { // calls kref_get_unless_zero()

dma_chan_put() drops the ref unconditionally, so every fast-path get/put pair drops one extra device reference.

The bug fires when two conditions hold together: a non-private provider has a persistent client holding chan->client_count > 0 and another client cycles dmaengine_get()/dmaengine_put(). When the kref hits zero, the subsequent dma_find_channel() returns NULL even though the provider module is still loaded.

Fix this by dropping device->ref only on the last put, matching the single slow-path get.

Fixes 8ad342a86359 ("dmaengine: Add reference counting to dma_device struct")
---
 drivers/dma/dmaengine.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/dmaengine.c +3 -1
index 9049171df8578..4d8c6655c7a15 100644
@@ -515,7 +515,9 @@ static void dma_chan_put(struct dma_chan *chan)
 		chan->route_data = NULL;
 	}
 
-	dma_device_put(chan->device);
+	/* This channel is not in use anymore, drop the device ref */
+	if (!chan->client_count)
+		dma_device_put(chan->device);
 	module_put(dma_chan_to_owner(chan));
 }
 
Signature · 1 line
2.53.0
author maintainer
#62 lore raw

PATCH 62/438 dmaengine: fix use-after-free in dma_chan_put() and dma_release_channel()

In reply to Greg Kroah-Hartman

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

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

From: Shivank Garg <[email protected]>

[ Upstream commit e873c74132f0c5f1452816cd9bb26208f0bba1e1 ]

When dma_device_put() drops the last reference on chan->device->ref, dma_device_release() runs and may free the dma_device along with its channels.

dma_chan_put() then still reads chan->device->owner via dma_chan_to_owner() for the trailing module_put(). KASAN catches it:

	slab-use-after-free in dma_chan_put+0x3e6/0x4c0
	Read of size 8 by task insmod/6319
	Freed by task 6319:
	  kfree+0x225/0x470
	  dma_chan_put+0x395/0x4c0
	  dmaengine_put+0xf8/0x160

Cache the module owner in dma_chan_put() before the put so the trailing module_put() does not need chan->device.

---
 drivers/dma/dmaengine.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/dma/dmaengine.c +4 -1
index 4d8c6655c7a15..7de33df0529a7 100644
@@ -495,10 +495,13 @@ static int dma_chan_get(struct dma_chan *chan)
  */
 static void dma_chan_put(struct dma_chan *chan)
 {
+	struct module *owner;
+
 	/* This channel is not in use, bail out */
 	if (!chan->client_count)
 		return;
 
+	owner = dma_chan_to_owner(chan);
 	chan->client_count--;
 
 	/* This channel is not in use anymore, free it */
@@ -518,7 +521,7 @@ static void dma_chan_put(struct dma_chan *chan)
 	/* This channel is not in use anymore, drop the device ref */
 	if (!chan->client_count)
 		dma_device_put(chan->device);
-	module_put(dma_chan_to_owner(chan));
+	module_put(owner);
 }
 
 enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
Signature · 1 line
2.53.0
author maintainer
#63 lore raw

PATCH 63/438 dmaengine: wait for RCU readers before releasing dma_device

In reply to Greg Kroah-Hartman

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

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

From: Shivank Garg <[email protected]>

[ Upstream commit dc750422170a563c7a81f6e49d36bb02c62ae37f ]

dma_issue_pending_all() walks the dma_device_list with list_for_each_entry_rcu() under rcu_read_lock(). dma_device_release() unlinks the device with list_del_rcu() and then calls device->device_release() (which in many drivers, such as plx_dma.c, directly calls kfree()).

Because there is no grace period between unlinking the device and freeing it, concurrent RCU readers in dma_issue_pending_all() can access the device after it has been freed.

The lockless walk originally relied on clients holding a dmaengine reference to pin the provider module, and therefore the device, for as long as they might traverse the list. Commit 8ad342a86359 ("dmaengine:
Add reference counting to dma_device struct") decoupled the dma_device lifetime from the module reference, so the device can now be released while a reader is still walking the list.

Add synchronize_rcu() before the device is freed, so RCU readers are guaranteed to have finished. Keep it unconditional: providers that do not implement device_release() free the device themselves once dma_async_device_unregister() returns. This call will delay for a grace period with dma_list_mutex held, which is safe and only teardown path is delayed.

---
 drivers/dma/dmaengine.c | 1 +
 1 file changed, 1 insertion(+)
drivers/dma/dmaengine.c +1 -0
index 7de33df0529a7..5b5673fc7344f 100644
@@ -428,6 +428,7 @@ static void dma_device_release(struct kref *ref)
 
 	list_del_rcu(&device->global_node);
 	dma_channel_rebalance();
+	synchronize_rcu();
 
 	if (device->device_release)
 		device->device_release(device);
Signature · 1 line
2.53.0
author maintainer
#64 lore raw

PATCH 64/438 wifi: cfg80211: dont free driver-owned scan requests

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit dab68a74e90b8e07f08ed9deaa5884857a3cfe89 ]

When an interface goes down while a scan is running, cfg80211 completes the scan towards userspace and frees the scan request. However, the driver can be convinced that it owns the request, since the cancellation is (intended to be) asynchronous.

The WARN_ON() in the netdev notifier was meant to catch this, but it's not actually avoidable, so it triggers and we get a UAF in scan_done().

There doesn't seem to be a great way around it, so just track that the driver is still convinced it owns the request, and then just free it on completion if it was already cancelled. Also remove the warnings since they can trigger in the intended architecture.

---
 net/wireless/core.c     | 11 +++++------
 net/wireless/core.h     | 10 ++++++++++
 net/wireless/rdev-ops.h |  3 +++
 net/wireless/scan.c     | 31 +++++++++++++++++++++++++++++--
 4 files changed, 47 insertions(+), 8 deletions(-)
net/wireless/core.c +5 -6
index d13310fef691a..8bb2cbd66b488 100644
@@ -244,9 +244,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
 	rdev->opencount--;
 
 	if (rdev->scan_req && rdev->scan_req->req.wdev == wdev) {
-		if (WARN_ON(!rdev->scan_req->notified &&
-			    (!rdev->int_scan_req ||
-			     !rdev->int_scan_req->notified)))
+		if (!rdev->scan_req->notified &&
+		    (!rdev->int_scan_req || !rdev->int_scan_req->notified))
 			rdev->scan_req->info.aborted = true;
 		___cfg80211_scan_done(rdev, false);
 	}
@@ -1758,9 +1757,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 		wiphy_lock(&rdev->wiphy);
 		cfg80211_update_iface_num(rdev, wdev->iftype, -1);
 		if (rdev->scan_req && rdev->scan_req->req.wdev == wdev) {
-			if (WARN_ON(!rdev->scan_req->notified &&
-				    (!rdev->int_scan_req ||
-				     !rdev->int_scan_req->notified)))
+			if (!rdev->scan_req->notified &&
+			    (!rdev->int_scan_req ||
+			     !rdev->int_scan_req->notified))
 				rdev->scan_req->info.aborted = true;
 			___cfg80211_scan_done(rdev, false);
 		}
net/wireless/core.h +10 -0
index ac6ce9f967ec7..979e968ff5959 100644
@@ -24,6 +24,16 @@
 struct cfg80211_scan_request_int {
 	struct cfg80211_scan_info info;
 	bool notified;
+	/*
+	 * set while the request is handed to the driver, i.e. between
+	 * rdev_scan() and cfg80211_scan_done()
+	 */
+	bool driver_owns;
+	/*
+	 * set when cfg80211 is done with the request but the driver still
+	 * owns it, so that cfg80211_scan_done() knows to just free it
+	 */
+	bool stale;
 	/* must be last - variable members */
 	struct cfg80211_scan_request req;
 };
net/wireless/rdev-ops.h +3 -0
index 63c26e8b11395..8f466e1ab1d72 100644
@@ -464,7 +464,10 @@ static inline int rdev_scan(struct cfg80211_registered_device *rdev,
 		return -EINVAL;
 
 	trace_rdev_scan(&rdev->wiphy, request);
+	request->driver_owns = true;
 	ret = rdev->ops->scan(&rdev->wiphy, &request->req);
+	if (ret)
+		request->driver_owns = false;
 	trace_rdev_return_int(&rdev->wiphy, ret);
 	return ret;
 }
net/wireless/scan.c +29 -2
index 071083cc33672..1a28f95246764 100644
@@ -1114,6 +1114,21 @@ int cfg80211_scan(struct cfg80211_registered_device *rdev)
 	return 0;
 }
 
+/*
+ * Release the scan request, but free it only if the driver is also done,
+ * e.g. mac80211 may cancel it asynchronously and still use it.
+ */
+static void cfg80211_put_scan_req(struct cfg80211_scan_request_int *req)
+{
+	if (!req)
+		return;
+
+	if (req->driver_owns)
+		req->stale = true;
+	else
+		kfree(req);
+}
+
 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
 			   bool send_message)
 {
@@ -1173,10 +1188,10 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
 
 	dev_put(wdev->netdev);
 
-	kfree(rdev->int_scan_req);
+	cfg80211_put_scan_req(rdev->int_scan_req);
 	rdev->int_scan_req = NULL;
 
-	kfree(rdev->scan_req);
+	cfg80211_put_scan_req(rdev->scan_req);
 	rdev->scan_req = NULL;
 
 	if (!send_message)
@@ -1199,6 +1214,18 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request,
 	struct cfg80211_scan_info old_info = intreq->info;
 
 	trace_cfg80211_scan_done(intreq, info);
+
+	intreq->driver_owns = false;
+
+	if (intreq->stale) {
+		/*
+		 * The scan is already completed as far as we're concerned,
+		 * it was just kept around for the driver - done now, free it.
+		 */
+		kfree(intreq);
+		return;
+	}
+
 	WARN_ON(intreq != rdev->scan_req &&
 		intreq != rdev->int_scan_req);
 
Signature · 1 line
2.53.0
author maintainer
#65 lore raw

PATCH 65/438 wifi: cfg80211: only group hidden BSSes with beacon entries

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 068843ed0902c552a13860c5ec6b2ca65b57a065 ]

When a probe response for an unknown BSS comes in, __cfg80211_bss_update() looks for an existing entry with the same BSSID and a hidden (zero-length or NUL-filled) SSID, and if it finds one it groups them, using the beacon IEs from the existing entry.

But that could find another entry without a beacon, if it was also from a probe response (with SSID), so there's a group without beacon elements.

If a beacon with a hidden SSID for that BSSID arrives later, cfg80211_combine_bsses() goes looking for the probe response entries that belong to it - i.e. entries with the same BSSID and channel that have no beacon IEs - and finds those two. They are already grouped with each other, so it hits its

WARN_ON_ONCE(bss->pub.hidden_beacon_bss)
WARN_ON_ONCE(!list_empty(&bss->hidden_list))

which are there because an entry without beacon elements is not supposed to be part of a group yet.

Only combine entries when a beacon was already received, ones that are kept separate will be combined when a beacon arrives.

---
 net/wireless/scan.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/wireless/scan.c +7 -0
index 1a28f95246764..4f7d17e7f8337 100644
@@ -2049,6 +2049,13 @@ __cfg80211_bss_update(struct cfg80211_registered_device *rdev,
 			if (!hidden)
 				hidden = rb_find_bss(rdev, tmp,
 						     BSS_CMP_HIDE_NUL);
+			/*
+			 * Only group with an entry with beacon data, otherwise
+			 * beacon data can never be filled/updated.
+			 */
+			if (hidden &&
+			    !rcu_access_pointer(hidden->pub.beacon_ies))
+				hidden = NULL;
 			if (hidden) {
 				new->pub.hidden_beacon_bss = &hidden->pub;
 				list_add(&new->hidden_list,
Signature · 1 line
2.53.0
author maintainer
#66 lore raw

PATCH 66/438 wifi: cfg80211: dont filter by BSS type when removing stale entries

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit b377e1000d963e7182a987082b4b06580bd7ac84 ]

When an assoc AP switches to a channel that already has a BSS entry, cfg80211_update_assoc_bss_entry() removes that entry before rehashing the real one, since the two would otherwise collide in the BSS rbtree.

The lookup for that entry also required it to match the connection's BSS type, so an entry advertising e.g. the IBSS capability bit was left in place, and the following cfg80211_rehash_bss() then ran into it:

WARN_ON(!cmp)

Changing the type shouldn't really happen, but can be triggered by a rogue AP/device, so drop the check and remove any entries matching the comparison.

---
 net/wireless/scan.c | 5 -----
 1 file changed, 5 deletions(-)
net/wireless/scan.c +0 -5
index 4f7d17e7f8337..4a1ec7e3547d8 100644
@@ -3477,11 +3477,6 @@ void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
 	cbss->pub.channel = chan;
 
 	list_for_each_entry(bss, &rdev->bss_list, list) {
-		if (!cfg80211_bss_type_match(bss->pub.capability,
-					     bss->pub.channel->band,
-					     wdev->conn_bss_type))
-			continue;
-
 		if (bss == cbss)
 			continue;
 
Signature · 1 line
2.53.0
author maintainer
#67 lore raw

PATCH 67/438 wifi: cfg80211: ibss: ref BSS entry for joined event

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 708f9d43d6a2eb9c6b83fe62af628de9dffd9314 ]

When the IBSS is joined, we only record the BSSID/channel in the event and look up the BSS entry when processing it. However, that's racy, e.g. a new scan with NL80211_SCAN_FLAG_FLUSH can remove it, causing a warning in the event work:

!bss

  WARNING: net/wireless/ibss.c:37 at __cfg80211_ibss_joined+0x3d3/0x440
  Workqueue: cfg80211 cfg80211_event_work
   cfg80211_process_wdev_events+0x39f/0x5b0 net/wireless/util.c:1144
   cfg80211_process_rdev_events+0xa1/0x110 net/wireless/util.c:1179
   cfg80211_event_work+0x2f/0x40 net/wireless/core.c:393

Do the lookup early (the driver is expected to only join an IBSS that has a BSS entry) and keep a reference to it.

---
 net/wireless/core.h |  6 ++----
 net/wireless/ibss.c | 36 ++++++++++++++++++++----------------
 net/wireless/util.c |  3 +--
 3 files changed, 23 insertions(+), 22 deletions(-)
net/wireless/core.h +2 -4
index 979e968ff5959..81e595247b932 100644
@@ -290,8 +290,7 @@ struct cfg80211_event {
 			bool locally_generated;
 		} dc;
 		struct {
-			u8 bssid[ETH_ALEN];
-			struct ieee80211_channel *channel;
+			struct cfg80211_bss *bss;
 		} ij;
 		struct {
 			u8 peer_addr[ETH_ALEN];
@@ -354,8 +353,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
 void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
 int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
 			struct net_device *dev, bool nowext);
-void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-			    struct ieee80211_channel *channel);
+void __cfg80211_ibss_joined(struct net_device *dev, struct cfg80211_bss *bss);
 int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
 			    struct wireless_dev *wdev);
 
net/wireless/ibss.c +20 -16
index b1d748bdb504e..7f6779d326b81 100644
@@ -16,26 +16,18 @@
 #include "rdev-ops.h"
 
 
-void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-			    struct ieee80211_channel *channel)
+void __cfg80211_ibss_joined(struct net_device *dev, struct cfg80211_bss *bss)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct cfg80211_bss *bss;
 #ifdef CONFIG_CFG80211_WEXT
 	union iwreq_data wrqu;
 #endif
 
 	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
-		return;
+		goto put_bss;
 
 	if (!wdev->u.ibss.ssid_len)
-		return;
-
-	bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
-			       IEEE80211_BSS_TYPE_IBSS, IEEE80211_PRIVACY_ANY);
-
-	if (WARN_ON(!bss))
-		return;
+		goto put_bss;
 
 	if (wdev->u.ibss.current_bss) {
 		cfg80211_unhold_bss(wdev->u.ibss.current_bss);
@@ -43,17 +35,22 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 	}
 
 	cfg80211_hold_bss(bss_from_pub(bss));
+	/* the reference from the event is transferred to current_bss */
 	wdev->u.ibss.current_bss = bss_from_pub(bss);
 
 	cfg80211_upload_connect_keys(wdev);
 
-	nl80211_send_ibss_bssid(wiphy_to_rdev(wdev->wiphy), dev, bssid,
+	nl80211_send_ibss_bssid(wiphy_to_rdev(wdev->wiphy), dev, bss->bssid,
 				GFP_KERNEL);
 #ifdef CONFIG_CFG80211_WEXT
 	memset(&wrqu, 0, sizeof(wrqu));
-	memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
+	memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN);
 	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
 #endif
+	return;
+
+put_bss:
+	cfg80211_put_bss(wdev->wiphy, bss);
 }
 
 void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
@@ -62,6 +59,7 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 	struct cfg80211_event *ev;
+	struct cfg80211_bss *bss;
 	unsigned long flags;
 
 	trace_cfg80211_ibss_joined(dev, bssid, channel);
@@ -69,13 +67,19 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 	if (WARN_ON(!channel))
 		return;
 
+	bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
+			       IEEE80211_BSS_TYPE_IBSS, IEEE80211_PRIVACY_ANY);
+	if (WARN_ON(!bss))
+		return;
+
 	ev = kzalloc_obj(*ev, gfp);
-	if (!ev)
+	if (!ev) {
+		cfg80211_put_bss(wdev->wiphy, bss);
 		return;
+	}
 
 	ev->type = EVENT_IBSS_JOINED;
-	memcpy(ev->ij.bssid, bssid, ETH_ALEN);
-	ev->ij.channel = channel;
+	ev->ij.bss = bss;
 
 	spin_lock_irqsave(&wdev->event_lock, flags);
 	list_add_tail(&ev->list, &wdev->event_list);
net/wireless/util.c +1 -2
index ef56fe0ac41b2..12285bbd29730 100644
@@ -1184,8 +1184,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
 						!ev->dc.locally_generated);
 			break;
 		case EVENT_IBSS_JOINED:
-			__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
-					       ev->ij.channel);
+			__cfg80211_ibss_joined(wdev->netdev, ev->ij.bss);
 			break;
 		case EVENT_STOPPED:
 			/*
Signature · 1 line
2.53.0
author maintainer
#68 lore raw

PATCH 68/438 wifi: cfg80211: fix NAN regulatory enforcement

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 17a5f8571d1d40c88b78cfc154a7da0d60f13f37 ]

reg_wdev_chan_valid() returns early for any wdev that has no netdev, which is fine for P2P originally (and later PD still), but NAN has no netdev and yet enforcement code was added and is needed, but is dead code right now.

Use wdev_running() instead so that netdev-less wdevs aren't skipped. P2P/PD don't do anything in the later switch, but NAN code can now be reached.

Assisted-by LLM
Fixes 0e8ec738a71e ("wifi: cfg80211: add support for NAN data interface")
---
 net/wireless/reg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/wireless/reg.c +1 -1
index 1e8214d6b6d88..3454afa038bf7 100644
@@ -2345,7 +2345,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
 	iftype = wdev->iftype;
 
 	/* make sure the interface is active */
-	if (!wdev->netdev || !netif_running(wdev->netdev))
+	if (!wdev_running(wdev))
 		return true;
 
 	/* NAN doesn't have links, handle it separately */
Signature · 1 line
2.53.0
author maintainer
#69 lore raw

PATCH 69/438 wifi: mac80211: dont start a ROC while scanning

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 733f0fde95392ed5f61a4e36aee661ea8d0e8581 ]

The ROC work can be pending when a scan starts (which requires ROC list to be empty, but that's possible), and then a new ROC can be added to the list and the work will pick it up.

Avoid starting that ROC if a scan made it between things, as otherwise we'll hit a warning later:

  WARNING: net/mac80211/offchannel.c:404 at ieee80211_start_next_roc+0x256/0x2d0
  Workqueue: events_unbound cfg80211_wiphy_work
  Call Trace:
   __ieee80211_scan_completed+0x4fd/0xe40 net/mac80211/scan.c:537
   ieee80211_scan_work+0x472/0x1ff0 net/mac80211/scan.c:1193
   cfg80211_wiphy_work+0x410/0x570 net/wireless/core.c:513
---
 net/mac80211/offchannel.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/mac80211/offchannel.c +7 -0
index 2bceb73717c66..6f8de5d4a20d3 100644
@@ -460,6 +460,13 @@ static void __ieee80211_roc_work(struct ieee80211_local *local)
 		return;
 
 	if (!roc->started) {
+		/*
+		 * The work can be started by a previous ROC work, but a scan
+		 * can get between things; scan finish will retrigger us.
+		 */
+		if (local->scanning)
+			return;
+
 		WARN_ON(!local->emulate_chanctx);
 		_ieee80211_start_next_roc(local);
 	} else {
Signature · 1 line
2.53.0
author maintainer
#70 lore raw

PATCH 70/438 wifi: mac80211: dont warn when an IBSS has no channel to scan

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit a7491b7efbd9136b120a12ed72af9c12121dd134 ]

ieee80211_request_ibss_scan() warns when regulatory leaves no allowed channel, but that can happen as the regdomain can change while IBSS is operating, and it can continue to operate briefly during the 60s grace period until it's shut down.

Just remove the warning in this case.

---
 net/mac80211/scan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/scan.c +1 -1
index eeff230bd909f..8e950ef6d1ead 100644
@@ -1242,7 +1242,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
 			}
 		}
 
-		if (WARN_ON_ONCE(n_ch == 0))
+		if (n_ch == 0)
 			return -EINVAL;
 
 		local->int_scan_req->n_channels = n_ch;
Signature · 1 line
2.53.0
author maintainer
#71 lore raw

PATCH 71/438 wifi: mac80211: dont offload TC setup on AP_VLAN interfaces

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 362bd5bce29ed0f6fd3d39a7065567777d70606e ]

AP_VLAN interfaces are purely virtual, so don't try to offload TC setup to drivers. We can't really use the AP interface either since we may not know it all the time, and it could technically even change.

Just reject the TC offload so things get done in software.

---
 net/mac80211/iface.c | 3 +++
 1 file changed, 3 insertions(+)
net/mac80211/iface.c +3 -0
index 43460a705a6bd..8c300e045fdf9 100644
@@ -935,6 +935,9 @@ static int ieee80211_netdev_setup_tc(struct net_device *dev,
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
 
+	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+		return -EOPNOTSUPP;
+
 	return drv_net_setup_tc(local, sdata, dev, type, type_data);
 }
 
Signature · 1 line
2.53.0
author maintainer
#72 lore raw

PATCH 72/438 wifi: mac80211: suppress chanctx warning for debugfs reset

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit bf29d085e0eba92388518719d044f4702a8c6644 ]

Before suspend all the channel contexts should removed, so the warning makes sense and should be there, but during reset the same code is called without first removing. Limit the check to the real suspend case.

---
 net/mac80211/cfg.c         | 2 +-
 net/mac80211/debugfs.c     | 2 +-
 net/mac80211/ieee80211_i.h | 2 +-
 net/mac80211/pm.c          | 8 +++++---
 4 files changed, 8 insertions(+), 6 deletions(-)
net/mac80211/cfg.c +1 -1
index 43f142624d33e..213f1d39f9e07 100644
@@ -3475,7 +3475,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
 static int ieee80211_suspend(struct wiphy *wiphy,
 			     struct cfg80211_wowlan *wowlan)
 {
-	return __ieee80211_suspend(wiphy_priv(wiphy), wowlan);
+	return __ieee80211_suspend(wiphy_priv(wiphy), wowlan, false);
 }
 
 static int ieee80211_resume(struct wiphy *wiphy)
net/mac80211/debugfs.c +1 -1
index a4d5461f6480f..f36cc25903050 100644
@@ -388,7 +388,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf,
 
 	rtnl_lock();
 	wiphy_lock(local->hw.wiphy);
-	__ieee80211_suspend(&local->hw, NULL);
+	__ieee80211_suspend(&local->hw, NULL, true);
 	ret = __ieee80211_resume(&local->hw);
 	wiphy_unlock(local->hw.wiphy);
 
net/mac80211/ieee80211_i.h +1 -1
index 34a9ea8b6f857..0564370419fba 100644
@@ -2433,7 +2433,7 @@ int ieee80211_reconfig(struct ieee80211_local *local);
 void ieee80211_stop_device(struct ieee80211_local *local, bool suspend);
 
 int __ieee80211_suspend(struct ieee80211_hw *hw,
-			struct cfg80211_wowlan *wowlan);
+			struct cfg80211_wowlan *wowlan, bool reset);
 
 static inline int __ieee80211_resume(struct ieee80211_hw *hw)
 {
net/mac80211/pm.c +5 -3
index 5a508d99e84f7..f63676c448536 100644
@@ -18,7 +18,8 @@ static void ieee80211_sched_scan_cancel(struct ieee80211_local *local)
 	cfg80211_sched_scan_stopped_locked(local->hw.wiphy, 0);
 }
 
-int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
+int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan,
+			bool reset)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct ieee80211_sub_if_data *sdata;
@@ -166,9 +167,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 
 	/*
 	 * We disconnected on all interfaces before suspend, all channel
-	 * contexts should be released.
+	 * contexts should be released, but on 'reset' debugfs that's
+	 * not true so don't check there.
 	 */
-	WARN_ON(!list_empty(&local->chanctx_list));
+	WARN_ON(!reset && !list_empty(&local->chanctx_list));
 
 	/* stop hardware - this must stop RX */
 	ieee80211_stop_device(local, true);
Signature · 1 line
2.53.0
author maintainer
#73 lore raw

PATCH 73/438 wifi: mac80211: abort chanswitch when leaving a mesh

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit ac7472a24bd433b81c06582835dd1d5547c10da9 ]

The code in ieee80211_stop_mesh() leaves CSA active, but leaving the mesh released the channel context, so the CSA finalize work crashes:

  Oops: general protection fault, probably for non-canonical address
        0xdffffc0000000003
  KASAN: null-ptr-deref in range [0x0000000000000018-0x000000000000001f]
  RIP: 0010:ieee80211_put_srates_elem+0x42/0x640 net/mac80211/util.c:3272
  Call Trace:
   ieee80211_mesh_build_beacon+0xa83/0x1b50 net/mac80211/mesh.c:1093
   ieee80211_mesh_rebuild_beacon+0xc7/0x170 net/mac80211/mesh.c:1147
   ieee80211_mesh_finish_csa+0x131/0x210 net/mac80211/mesh.c:1542
   ieee80211_set_after_csa_beacon net/mac80211/cfg.c:4085 [inline]
   __ieee80211_csa_finalize net/mac80211/cfg.c:4133 [inline]
   ieee80211_csa_finalize+0x633/0x1150 net/mac80211/cfg.c:4155
   cfg80211_wiphy_work+0x2ab/0x450 net/wireless/core.c:438

Abort the channel switch properly.

---
 net/mac80211/mesh.c | 4 ++++
 1 file changed, 4 insertions(+)
net/mac80211/mesh.c +4 -0
index d4507e4e6ec16..bed7ac8382505 100644
@@ -1204,6 +1204,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 
 	netif_carrier_off(sdata->dev);
 
+	/* abort any running channel switch */
+	sdata->vif.bss_conf.csa_active = false;
+	ieee80211_vif_unblock_queues_csa(sdata);
+
 	/* flush STAs and mpaths on this iface */
 	sta_info_flush(sdata, -1);
 	ieee80211_free_keys(sdata, true);
Signature · 1 line
2.53.0
author maintainer
#74 lore raw

PATCH 74/438 wifi: mac80211: reset state when starting AP fails

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 3f28551d0241254a75626d868041c6340285088b ]

ieee80211_start_ap() can set enable_beacon (and beacon_int) and fail later, leaving it set forever. Scanning can then attempt to restore beaconing on such an interface, leading to:

  Oops: divide error: 0000 [#1] SMP KASAN NOPTI
  RIP: 0010:mac80211_hwsim_link_info_changed+0xca7/0xf00
  Call Trace:
   drv_link_info_changed+0x413/0x860 net/mac80211/driver-ops.c:495
   ieee80211_link_info_change_notify+0x24b/0x3c0 net/mac80211/main.c:427
   ieee80211_offchannel_return+0x381/0x580 net/mac80211/offchannel.c:160
   __ieee80211_scan_completed+0x993/0xe30 net/mac80211/scan.c:519
   ieee80211_scan_work+0x472/0x2010 net/mac80211/scan.c:1193
   cfg80211_wiphy_work+0x2b7/0x550 net/wireless/core.c:538

in hwsim. Also, cfg80211 then allows changing the interface type, and the off-channel path getgs confused about beaconing as well, leading to another warning:

  WARNING: net/mac80211/driver-ops.c:468 at drv_link_info_changed+0x583/0x880
   ieee80211_link_info_change_notify+0x24b/0x3c0 net/mac80211/main.c:427
   ieee80211_offchannel_stop_vifs+0x328/0x5c0 net/mac80211/offchannel.c:122
   ieee80211_start_sw_scan net/mac80211/scan.c:583 [inline]
   __ieee80211_start_scan+0xfb6/0x1af0 net/mac80211/scan.c:882

Reset the state on failures to always have it correct.

---
 net/mac80211/cfg.c | 3 +++
 1 file changed, 3 insertions(+)
net/mac80211/cfg.c +3 -0
index 213f1d39f9e07..45f8e3c87884a 100644
@@ -1929,6 +1929,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	return 0;
 
 error:
+	link_conf->enable_beacon = false;
+	link_conf->beacon_int = prev_beacon_int;
+	sdata->vif.cfg.ssid_len = 0;
 	ieee80211_link_release_channel(link);
 
 	return err;
Signature · 1 line
2.53.0
author maintainer
#75 lore raw

PATCH 75/438 wifi: mac80211: reset the LED state when ifup fails

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 78183e8331958fda11cd2b6850bb424a9747c4b2 ]

When the first interface comes up, the radio LED is turned on. This can start the TPT trigger timer, which continues running.

But if bringing up the interface fails then the timer keeps running and won't be stopped by anything, eventually it can be freed:

ODEBUG: free active (active state 0) object: ffff888127e12130 object type: timer_list hint: tpt_trig_timer+0x0/0x300 net/mac80211/led.c:145

  WARNING: CPU: 0 PID: 5923 at lib/debugobjects.c:612 debug_print_object+0x1a2/0x2b0
   debug_check_no_obj_freed+0x4b7/0x600 lib/debugobjects.c:1129
   kfree+0x436/0x670 mm/slub.c:6818
   ieee80211_led_exit+0x162/0x1c0 net/mac80211/led.c:210
   ieee80211_unregister_hw+0x27e/0x3a0 net/mac80211/main.c:1706
   rt2x00lib_remove_dev+0x55b/0x670

Undo the LED state in the error path.

---
 net/mac80211/iface.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
net/mac80211/iface.c +5 -1
index 8c300e045fdf9..4c34c3287eb4a 100644
@@ -1606,8 +1606,12 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
  err_del_interface:
 	drv_remove_interface(local, sdata);
  err_stop:
-	if (!local->open_count)
+	if (!local->open_count) {
+		ieee80211_led_radio(local, false);
+		ieee80211_mod_tpt_led_trig(local, 0,
+					   IEEE80211_TPT_LEDTRIG_FL_RADIO);
 		drv_stop(local, false);
+	}
 	if (sdata->vif.type == NL80211_IFTYPE_NAN_DATA)
 		RCU_INIT_POINTER(sdata->u.nan_data.nmi, NULL);
 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
Signature · 1 line
2.53.0
author maintainer
#76 lore raw

PATCH 76/438 wifi: mac80211: only operate on TDLS peers in the TDLS code

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 6f0a100df8539ce90f37c14e1945f396ca2410bc ]

ieee80211_tdls_oper() can operate on the AP station, which then yields various warnings when the AP station is removed then or at a later point in time after being confused for a TDLS peer.

Always check that the station is a TDLS peer.

Assisted-by LLM
Fixes dfe018bf9953 ("mac80211: handle TDLS high-level commands and frames")
Fixes 17e6a59a365a ("mac80211: cleanup TDLS state during failed setup")
Reported-by [email protected]
---
 net/mac80211/tdls.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)
net/mac80211/tdls.c +9 -12
index ffd575a8d188f..5f2f89795dc99 100644
@@ -1142,6 +1142,7 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
 	struct ieee80211_local *local = sdata->local;
 	enum ieee80211_smps_mode smps_mode =
 		sdata->deflink.u.mgd.driver_smps_mode;
+	struct sta_info *sta;
 	int ret;
 
 	/* don't support setup with forced SMPS mode that's not off */
@@ -1168,14 +1169,10 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
 	 * Allow error packets to be sent - sometimes we don't even add a STA
 	 * before failing the setup.
 	 */
-	if (status_code == 0) {
-		rcu_read_lock();
-		if (!sta_info_get(sdata, peer)) {
-			rcu_read_unlock();
-			ret = -ENOLINK;
-			goto out_unlock;
-		}
-		rcu_read_unlock();
+	sta = sta_info_get(sdata, peer);
+	if ((status_code == 0 && !sta) || (sta && !sta->sta.tdls)) {
+		ret = -ENOLINK;
+		goto out_unlock;
 	}
 
 	ieee80211_flush_queues(local, sdata, false);
@@ -1442,6 +1439,10 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
 	 */
 	tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer);
 
+	sta = sta_info_get(sdata, peer);
+	if (!sta || !sta->sta.tdls)
+		return -ENOLINK;
+
 	switch (oper) {
 	case NL80211_TDLS_ENABLE_LINK:
 		if (sdata->vif.bss_conf.csa_active) {
@@ -1449,10 +1450,6 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
 			return -EBUSY;
 		}
 
-		sta = sta_info_get(sdata, peer);
-		if (!sta || !sta->sta.tdls)
-			return -ENOLINK;
-
 		iee80211_tdls_recalc_chanctx(sdata, sta);
 		iee80211_tdls_recalc_ht_protection(sdata, sta);
 
Signature · 1 line
2.53.0
author maintainer
#77 lore raw

PATCH 77/438 wifi: cfg80211: restore netns_immutable on failures

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit eeee52cfd1d639774c9812e8890631404a057dd2 ]

Switching a wiphy's netns has to clear netns_immutable before moving interfaces, but then if any of the interfaces fails to move, it gets netns_immutable cleared forever. Then userspace can move it by itself, breaking the assumption that they all move together.

Fix the order here and always reset netns_immutable after attempting the move.

---
 net/wireless/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/wireless/core.c +1 -1
index 8bb2cbd66b488..6c0c97e57ebb2 100644
@@ -167,9 +167,9 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 			continue;
 		wdev->netdev->netns_immutable = false;
 		err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
+		wdev->netdev->netns_immutable = true;
 		if (err)
 			break;
-		wdev->netdev->netns_immutable = true;
 	}
 
 	if (err) {
Signature · 1 line
2.53.0
author maintainer
#78 lore raw

PATCH 78/438 wifi: cfg80211: undo netns switch if renaming the wiphy fails

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit a41bd1938a9bfe226d444172a7e20e4bd5097960 ]

Once all the interfaces have been moved, cfg80211_switch_netns() moves the wiphy itself by setting its network namespace and then renaming it, which makes sysfs move it. The rename can fail (but only on allocation failures), leaving things mixed up and hitting the warning there.

Ignoring it isn't great, undo the move and let the change fail in this case. If undo fails then WARN, then things would again be stuck in two different network namespaces.

---
 net/wireless/core.c | 88 +++++++++++++++++++++++++--------------------
 1 file changed, 50 insertions(+), 38 deletions(-)
net/wireless/core.c +50 -38
index 6c0c97e57ebb2..59facacf1a36f 100644
@@ -153,9 +153,25 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
 	return 0;
 }
 
+static int cfg80211_switch_wdev_netns(struct wireless_dev *wdev,
+				      struct net *net)
+{
+	int err;
+
+	if (!wdev->netdev)
+		return 0;
+
+	wdev->netdev->netns_immutable = false;
+	err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
+	wdev->netdev->netns_immutable = true;
+
+	return err;
+}
+
 int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 			  struct net *net)
 {
+	struct net *old_net = wiphy_net(&rdev->wiphy);
 	struct wireless_dev *wdev;
 	int err = 0;
 
@@ -163,58 +179,54 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 		return -EOPNOTSUPP;
 
 	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
-		if (!wdev->netdev)
-			continue;
-		wdev->netdev->netns_immutable = false;
-		err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
-		wdev->netdev->netns_immutable = true;
+		err = cfg80211_switch_wdev_netns(wdev, net);
 		if (err)
-			break;
+			goto undo;
 	}
 
-	if (err) {
-		/* failed -- clean up to old netns */
-		net = wiphy_net(&rdev->wiphy);
-
-		list_for_each_entry_continue_reverse(wdev,
-						     &rdev->wiphy.wdev_list,
-						     list) {
+	scoped_guard(wiphy, &rdev->wiphy) {
+		list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
 			if (!wdev->netdev)
 				continue;
-			wdev->netdev->netns_immutable = false;
-			err = dev_change_net_namespace(wdev->netdev, net,
-							"wlan%d");
-			WARN_ON(err);
-			wdev->netdev->netns_immutable = true;
+			nl80211_notify_iface(rdev, wdev,
+					     NL80211_CMD_DEL_INTERFACE);
 		}
 
-		return err;
-	}
+		nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
 
-	guard(wiphy)(&rdev->wiphy);
+		wiphy_net_set(&rdev->wiphy, net);
 
-	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
-		if (!wdev->netdev)
-			continue;
-		nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
-	}
-
-	nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
+		/* this only fails on allocation failure */
+		err = device_rename(&rdev->wiphy.dev,
+				    dev_name(&rdev->wiphy.dev));
+		if (err)
+			wiphy_net_set(&rdev->wiphy, old_net);
 
-	wiphy_net_set(&rdev->wiphy, net);
+		nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
 
-	err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev));
-	WARN_ON(err);
+		list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+			if (!wdev->netdev)
+				continue;
+			nl80211_notify_iface(rdev, wdev,
+					     NL80211_CMD_NEW_INTERFACE);
+		}
+	}
 
-	nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
+	if (!err)
+		return 0;
 
-	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
-		if (!wdev->netdev)
-			continue;
-		nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
-	}
+	/* set to the last one to undo all of them */
+	wdev = list_entry(&rdev->wiphy.wdev_list, typeof(*wdev), list);
+undo:
+	/*
+	 * Move back everything, if this fails again (allocation failures)
+	 * then things get stuck in different network namespaces.
+	 */
+	list_for_each_entry_continue_reverse(wdev, &rdev->wiphy.wdev_list,
+					     list)
+		WARN_ON(cfg80211_switch_wdev_netns(wdev, old_net));
 
-	return 0;
+	return err;
 }
 
 static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
Signature · 1 line
2.53.0
author maintainer
#79 lore raw

PATCH 79/438 wifi: mac80211: unlist vifs when their netdev is unregistered

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit eee2efd82867b623982ac51925b5a1812a74c50d ]

mac80211 only removes vifs from the local->interfaces list when an interface is removed via ieee80211_if_remove(), before it unregisters the netdev. However, it's possible for a netdev to be unregistered without going through that: When the netns that holds the wiphy is destroyed, the wiphy is supposed to move to the init_ns, but that can run into allocation failures.

Then, mac80211 has an interface listed that doesn't exist, and will eventually hit

  BUG: failure at net/wireless/core.h:141/wiphy_to_rdev()!
  ...
  _cfg80211_unregister_wdev+0x24/0x36a [cfg80211]
  cfg80211_unregister_wdev+0x15/0x1d [cfg80211]
  ieee80211_remove_interfaces+0x1ff/0x257 [mac80211]
  ieee80211_unregister_hw+0x73/0x1d1 [mac80211]
  mac80211_hwsim_del_radio+0x114/0x166 [mac80211_hwsim]

Remove the interface from the list in ->ndo_uninit if it's still around to avoid this.

---
 net/mac80211/iface.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)
net/mac80211/iface.c +25 -1
index 4c34c3287eb4a..842bfb4a7cb68 100644
@@ -924,9 +924,33 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
 	}
 }
 
+/*
+ * The netdev can be unregistered without mac80211 doing it, e.g. by the netdev
+ * core when cfg80211 couldn't move it out of a network namespace that's being
+ * destroyed. Drop it from the interface list either way.
+ */
+static void ieee80211_unlist_sdata(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_sub_if_data *iter;
+
+	ASSERT_RTNL();
+
+	list_for_each_entry(iter, &local->interfaces, list) {
+		if (iter != sdata)
+			continue;
+		guard(mutex)(&local->iflist_mtx);
+		list_del_rcu(&sdata->list);
+		return;
+	}
+}
+
 static void ieee80211_uninit(struct net_device *dev)
 {
-	ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev));
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	ieee80211_unlist_sdata(sdata);
+	ieee80211_teardown_sdata(sdata);
 }
 
 static int ieee80211_netdev_setup_tc(struct net_device *dev,
Signature · 1 line
2.53.0
author maintainer
#80 lore raw

PATCH 80/438 wifi: cfg80211: get the wiphy out of a dying network namespace

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 4635b1a1c1d693178a537446a6e09963f0fdae52 ]

When a network namespace is destroyed, cfg80211_pernet_exit() moves any wiphy back to the initial namespace, and just warns if that fails. But moving an interface can fail (due to allocation failures), and then the wiphy is left behind with a garbage netns pointer:

Kernel mode fault at addr 0x30

  genlmsg_multicast_netns.constprop.0+0x46/0xcf [cfg80211]
  nl80211_notify_wiphy+0xcd/0xe8 [cfg80211]
  wiphy_unregister+0x169/0x3fc [cfg80211]

Note that commit debac3a20dec ("net: Remove conflicting altnames for dying netns in __dev_change_net_namespace().") fixed another path that could reach it without allocation failures.

Remove interfaces that cannot be moved instead of failing the switch, so that the wiphy always ends up in the initial namespace. In this case the netdev core will unregister the interfaces anyway.

---
 net/wireless/core.c | 37 +++++++++++++++++++++++++------------
 1 file changed, 25 insertions(+), 12 deletions(-)
net/wireless/core.c +25 -12
index 59facacf1a36f..bc7e2c50cc726 100644
@@ -168,20 +168,24 @@ static int cfg80211_switch_wdev_netns(struct wireless_dev *wdev,
 	return err;
 }
 
-int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
-			  struct net *net)
+static int __cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
+				   struct net *net, bool force)
 {
 	struct net *old_net = wiphy_net(&rdev->wiphy);
-	struct wireless_dev *wdev;
+	struct wireless_dev *wdev, *tmp;
 	int err = 0;
 
-	if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
-		return -EOPNOTSUPP;
-
-	list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+	list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
 		err = cfg80211_switch_wdev_netns(wdev, net);
-		if (err)
+		if (!err)
+			continue;
+		if (!force)
 			goto undo;
+		/* remove interfaces that fail to allow wiphy switching */
+		dev_close(wdev->netdev);
+		scoped_guard(wiphy, &rdev->wiphy)
+			cfg80211_unregister_wdev(wdev);
+		err = 0;
 	}
 
 	scoped_guard(wiphy, &rdev->wiphy) {
@@ -199,7 +203,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 		/* this only fails on allocation failure */
 		err = device_rename(&rdev->wiphy.dev,
 				    dev_name(&rdev->wiphy.dev));
-		if (err)
+		if (err && !force)
 			wiphy_net_set(&rdev->wiphy, old_net);
 
 		nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
@@ -212,8 +216,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 		}
 	}
 
-	if (!err)
-		return 0;
+	if (!err || force)
+		return err;
 
 	/* set to the last one to undo all of them */
 	wdev = list_entry(&rdev->wiphy.wdev_list, typeof(*wdev), list);
@@ -229,6 +233,15 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
 	return err;
 }
 
+int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
+			  struct net *net)
+{
+	if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
+		return -EOPNOTSUPP;
+
+	return __cfg80211_switch_netns(rdev, net, false);
+}
+
 static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
 {
 	struct cfg80211_registered_device *rdev = data;
@@ -1879,7 +1892,7 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)
 	rtnl_lock();
 	for_each_rdev(rdev) {
 		if (net_eq(wiphy_net(&rdev->wiphy), net))
-			WARN_ON(cfg80211_switch_netns(rdev, &init_net));
+			WARN_ON(__cfg80211_switch_netns(rdev, &init_net, true));
 	}
 	rtnl_unlock();
 }
Signature · 1 line
2.53.0
author maintainer
#81 lore raw

PATCH 81/438 wifi: mac80211_hwsim: dont hand frames to mac80211 while stopping

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 87840d4a3a21b1c19b867a80e16ba69dff284de2 ]

The code checks ->started for frames coming from wmediumd, but the radio can be stopped after the check and before frame delivery, causing mac80211 to hit the WARN_ON(!local->started).

Expand the mutex for this case and synchronise against it when the radio is stopped to avoid being able to hit the warning with hwsim.

Drop the error print that would've complicated the error path, it only triggers for allocation failures (already noisy) and malformed frames anyway.

---
 .../wireless/virtual/mac80211_hwsim_main.c    | 39 ++++++++++++-------
 1 file changed, 24 insertions(+), 15 deletions(-)
drivers/net/wireless/virtual/mac80211_hwsim_main.c +24 -15
index b4cabbfa9cdba..8c634cada5ddd 100644
@@ -2317,7 +2317,12 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw, bool suspend)
 	struct sk_buff *skb;
 	int i;
 
-	data->started = false;
+	/*
+	 * Serialise against wmediumd userspace, so no more frames
+	 * can be handed to mac80211 after this returns.
+	 */
+	scoped_guard(mutex, &data->mutex)
+		data->started = false;
 
 	for (i = 0; i < ARRAY_SIZE(data->link_data); i++)
 		hrtimer_cancel(&data->link_data[i].beacon_timer);
@@ -6453,12 +6458,12 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 
 	if (frame_data_len < sizeof(struct ieee80211_hdr_3addr) ||
 	    frame_data_len > IEEE80211_MAX_DATA_LEN)
-		goto err;
+		goto out;
 
 	/* Allocate new skb here */
 	skb = alloc_skb(frame_data_len, GFP_KERNEL);
 	if (skb == NULL)
-		goto err;
+		goto out;
 
 	/* Copy the data */
 	skb_put_data(skb, frame_data, frame_data_len);
@@ -6483,10 +6488,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 			goto out;
 	}
 
+	/*
+	 * Serialise against mac80211_hwsim_stop() - mac80211 doesn't allow
+	 * frames reported while the HW is down, hence the ->started check
+	 * must be under mutex.
+	 */
+	mutex_lock(&data2->mutex);
+
 	/* check if radio is configured properly */
 
 	if ((data2->idle && !data2->tmp_chan) || !data2->started)
-		goto out;
+		goto out_unlock;
 
 	/* A frame is received from user space */
 	memset(&rx_status, 0, sizeof(rx_status));
@@ -6505,22 +6517,18 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 		iter_data.channel = ieee80211_get_channel(data2->hw->wiphy,
 							  rx_status.freq);
 		if (!iter_data.channel)
-			goto out;
+			goto out_unlock;
 		rx_status.band = iter_data.channel->band;
 
-		mutex_lock(&data2->mutex);
 		if (!hwsim_chans_compat(iter_data.channel, channel)) {
 			ieee80211_iterate_active_interfaces_atomic(
 				data2->hw, IEEE80211_IFACE_ITER_NORMAL,
 				mac80211_hwsim_tx_iter, &iter_data);
-			if (!iter_data.receive) {
-				mutex_unlock(&data2->mutex);
-				goto out;
-			}
+			if (!iter_data.receive)
+				goto out_unlock;
 		}
-		mutex_unlock(&data2->mutex);
 	} else if (!channel) {
-		goto out;
+		goto out_unlock;
 	} else {
 		rx_status.freq = channel->center_freq;
 		rx_status.band = channel->band;
@@ -6528,7 +6536,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 
 	rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
 	if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates)
-		goto out;
+		goto out_unlock;
 	rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
 
 	hdr = (void *)skb->data;
@@ -6538,10 +6546,11 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
 		rx_status.boottime_ns = ktime_get_boottime_ns();
 
 	mac80211_hwsim_rx(data2, &rx_status, skb);
+	mutex_unlock(&data2->mutex);
 
 	return 0;
-err:
-	pr_debug("mac80211_hwsim: error occurred in %s\n", __func__);
+out_unlock:
+	mutex_unlock(&data2->mutex);
 out:
 	dev_kfree_skb(skb);
 	return -EINVAL;
Signature · 1 line
2.53.0
author maintainer
#82 lore raw

PATCH 82/438 wifi: mac80211: dont allow injecting frames wider than the chanctx

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit e14bf37bb2b3853012ff160131d1c6233f7a9cc9 ]

Frames injected on a monitor interface can carry a radiotap field requesting a bandwidth, which mac80211 passes down to the driver regardless of the the actual operational bandwidth.

If the bandwidth requested is too wide, that triggers a warning in hwsim:

WARN_ON(hwsim_get_chanwidth(bw) > hwsim_get_chanwidth(confbw))

Drop such frames entirely instead since they cannot be sent.

Assisted-by LLM
Fixes 646e76bb5daf ("mac80211: parse VHT info in injected frames")
Reported-by [email protected]
---
 include/net/mac80211.h |  5 ++++-
 net/mac80211/iface.c   |  2 +-
 net/mac80211/tx.c      | 28 ++++++++++++++++++++++++++--
 3 files changed, 31 insertions(+), 4 deletions(-)
include/net/mac80211.h +4 -1
index 4f95da023746f..36055d40172a1 100644
@@ -7615,11 +7615,14 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
  *
  * @skb: packet injected by userspace
  * @dev: the &struct device of this 802.11 device
+ * @chandef: the channel definition the frame will be transmitted on, or
+ *	%NULL to skip the bandwidth checks
  *
  * Return: %true if the radiotap header was parsed, %false otherwise
  */
 bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
-				 struct net_device *dev);
+				 struct net_device *dev,
+				 const struct cfg80211_chan_def *chandef);
 
 /**
  * struct ieee80211_noa_data - holds temporary data for tracking P2P NoA state
net/mac80211/iface.c +1 -1
index 842bfb4a7cb68..ca66eb493ac7d 100644
@@ -991,7 +991,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
 	/* reset flags and info before parsing radiotap header */
 	memset(info, 0, sizeof(*info));
 
-	if (!ieee80211_parse_tx_radiotap(skb, dev))
+	if (!ieee80211_parse_tx_radiotap(skb, dev, NULL))
 		return 0; /* doesn't matter, frame will be dropped */
 
 	len_rthdr = ieee80211_get_radiotap_len(skb->data);
net/mac80211/tx.c +26 -2
index 7cb9dd1b27314..a726a697c32d7 100644
@@ -2096,8 +2096,29 @@ static bool ieee80211_validate_radiotap_len(struct sk_buff *skb)
 	return true;
 }
 
+static bool ieee80211_rate_bw_usable(u16 rate_flags,
+				     const struct cfg80211_chan_def *chandef)
+{
+	int width;
+
+	if (!chandef)
+		return true;
+
+	if (rate_flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+		width = 160;
+	else if (rate_flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+		width = 80;
+	else if (rate_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		width = 40;
+	else
+		return true;
+
+	return width <= cfg80211_chandef_get_width(chandef);
+}
+
 bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
-				 struct net_device *dev)
+				 struct net_device *dev,
+				 const struct cfg80211_chan_def *chandef)
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct ieee80211_radiotap_iterator iterator;
@@ -2271,6 +2292,9 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
 		struct ieee80211_supported_band *sband =
 			local->hw.wiphy->bands[info->band];
 
+		if (!ieee80211_rate_bw_usable(rate_flags, chandef))
+			return false;
+
 		info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT;
 
 		for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
@@ -2470,7 +2494,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
 	 * selected chandef above to accurately set injection rates and
 	 * retransmissions.
 	 */
-	if (!ieee80211_parse_tx_radiotap(skb, dev))
+	if (!ieee80211_parse_tx_radiotap(skb, dev, chandef))
 		goto fail_rcu;
 
 	/* remove the injection radiotap header */
Signature · 1 line
2.53.0
author maintainer
#83 lore raw

PATCH 83/438 wifi: mac80211: reset the AP_VLAN tailroom counter on ifdown

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 4504f3960dc4501c73be9f99eabda2e26e9db41e ]

On ifup, AP_VLAN interfaces get crypto_tx_tailroom_needed_cnt from the AP interface, but it's never decremented again unless the AP is also brought down. Thus, bringing the same AP_VLAN up again will increment the counter again and eventually hit the sanity check:

WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt !=

               master->crypto_tx_tailroom_needed_cnt);

Reset it on ifdown to avoid that.

Assisted-by LLM
Fixes f9dca80b98ca ("mac80211: fix AP_VLAN crypto tailroom calculation")
Reported-by [email protected]
---
 net/mac80211/iface.c | 2 ++
 1 file changed, 2 insertions(+)
net/mac80211/iface.c +2 -0
index ca66eb493ac7d..889c32fd8de19 100644
@@ -616,6 +616,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 		RCU_INIT_POINTER(sdata->vif.bss_conf.chanctx_conf, NULL);
 		/* see comment in the default case below */
 		ieee80211_free_keys(sdata, true);
+		/* increased by AP value on ifup, so reset on ifdown */
+		sdata->crypto_tx_tailroom_needed_cnt = 0;
 		/* no need to tell driver */
 		break;
 	case NL80211_IFTYPE_MONITOR:
Signature · 1 line
2.53.0
author maintainer
#84 lore raw

PATCH 84/438 wifi: mac80211: require a peer station for TDLS setup confirm

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 038e1d126304fd25d507fd4e671232df57bd1799 ]

It's nonsense for the setup confirm to go to station that doesn't even exist, and it hits a warning when building the frame:

  WARN_ON_ONCE(!sta || !ap_sta)

Only accept WLAN_TDLS_SETUP_CONFIRM when the station is already there as a TDLS station. Need to copy the call to ieee80211_tdls_prep_mgmt_packet() since the existing WLAN_TDLS_DISCOVERY_REQUEST already falls through to it.

Assisted-by LLM
Fixes 6f7eaa47e1de ("mac80211: add TDLS QoS param IE on setup-confirm")
Reported-by [email protected]
---
 net/mac80211/tdls.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)
net/mac80211/tdls.c +18 -1
index 5f2f89795dc99..9e721d3735e7e 100644
@@ -1281,6 +1281,24 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
 						   peer_capability, initiator,
 						   extra_ies, extra_ies_len);
 		break;
+	case WLAN_TDLS_SETUP_CONFIRM: {
+		struct sta_info *sta;
+
+		sta = sta_info_get(sdata, peer);
+		if (!sta || !sta->sta.tdls) {
+			ret = -ENOLINK;
+			break;
+		}
+
+		ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
+						      link_id, action_code,
+						      dialog_token,
+						      status_code,
+						      peer_capability,
+						      initiator, extra_ies,
+						      extra_ies_len, 0, NULL);
+		break;
+	}
 	case WLAN_TDLS_DISCOVERY_REQUEST:
 		/*
 		 * Protect the discovery so we can hear the TDLS discovery
@@ -1289,7 +1307,6 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
 		 */
 		drv_mgd_protect_tdls_discover(sdata->local, sdata, link_id);
 		fallthrough;
-	case WLAN_TDLS_SETUP_CONFIRM:
 	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
 		/* no special handling */
 		ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
Signature · 1 line
2.53.0
author maintainer
#85 lore raw

PATCH 85/438 wifi: mac80211: dont allow link changes when iface is down

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 370872d30349d81dec519e15ea2949fd63511cf7 ]

ieee80211_set_active_links() only checks that the interface is running in the inner __ieee80211_set_active_links(), after drv_can_activate_links() was already called, so using active_links on an interface that's down triggers the check-sdata-in-driver warning.

Add the missing check in the debugfs file.

Assisted-by LLM
Fixes 3d9011029227 ("wifi: mac80211: implement link switching")
Reported-by [email protected]
---
 net/mac80211/debugfs_netdev.c | 3 +++
 1 file changed, 3 insertions(+)
net/mac80211/debugfs_netdev.c +3 -0
index f3c6a41e49119..8346d3eb11430 100644
@@ -729,6 +729,9 @@ static ssize_t ieee80211_if_parse_active_links(struct ieee80211_sub_if_data *sda
 	if (kstrtou16(buf, 0, &active_links) || !active_links)
 		return -EINVAL;
 
+	if (!ieee80211_sdata_running(sdata))
+		return -ENETDOWN;
+
 	return ieee80211_set_active_links(&sdata->vif, active_links) ?: buflen;
 }
 IEEE80211_IF_FILE_RW(active_links);
Signature · 1 line
2.53.0
author maintainer
#86 lore raw

PATCH 86/438 wifi: mac80211: dont RCU-dereference the mesh CSA settings we just set

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit b481e64e4498e2c053d5954f546ee02338f6ab63 ]

In the error path of ieee80211_mesh_csa_beacon() the settings that were just assigned are read back with rcu_dereference(), which lockdep then complains about.

There's no need to read the pointer at all, tmp_csa_settings still is the right value anyway.

Assisted-by LLM
Fixes b8456a14e9d2 ("{nl,cfg,mac}80211: implement mesh channel switch userspace API")
Reported-by [email protected]
---
 net/mac80211/mesh.c | 1 -
 1 file changed, 1 deletion(-)
net/mac80211/mesh.c +0 -1
index bed7ac8382505..a35e2d5870b6f 100644
@@ -1559,7 +1559,6 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
 
 	ret = ieee80211_mesh_rebuild_beacon(sdata);
 	if (ret) {
-		tmp_csa_settings = rcu_dereference(ifmsh->csa);
 		RCU_INIT_POINTER(ifmsh->csa, NULL);
 		kfree_rcu(tmp_csa_settings, rcu_head);
 		return ret;
Signature · 1 line
2.53.0
author maintainer
#87 lore raw

PATCH 87/438 wifi: mac80211: dont access the TSF of a down interface

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 0b1de9feeb8651f7a3bb53ed7c9006e3b5298c01 ]

The tsf debugfs files call the driver even if the interface isn't up, tgriggering check-sdata-in-driver warnings.

Reject the access in that case.

Assisted-by LLM
Fixes 37a41b4affa3 ("mac80211: add ieee80211_vif param to tsf functions")
Reported-by [email protected]
---
 net/mac80211/debugfs_netdev.c | 6 ++++++
 1 file changed, 6 insertions(+)
net/mac80211/debugfs_netdev.c +6 -0
index 8346d3eb11430..6aba224936708 100644
@@ -657,6 +657,9 @@ static ssize_t ieee80211_if_fmt_tsf(
 	struct ieee80211_local *local = sdata->local;
 	u64 tsf;
 
+	if (!ieee80211_sdata_running((struct ieee80211_sub_if_data *)sdata))
+		return -ENETDOWN;
+
 	tsf = drv_get_tsf(local, (struct ieee80211_sub_if_data *)sdata);
 
 	return scnprintf(buf, buflen, "0x%016llx\n", (unsigned long long) tsf);
@@ -670,6 +673,9 @@ static ssize_t ieee80211_if_parse_tsf(
 	int ret;
 	int tsf_is_delta = 0;
 
+	if (!ieee80211_sdata_running(sdata))
+		return -ENETDOWN;
+
 	if (strncmp(buf, "reset", 5) == 0) {
 		if (local->ops->reset_tsf) {
 			drv_reset_tsf(local, sdata);
Signature · 1 line
2.53.0
author maintainer
#88 lore raw

PATCH 88/438 wifi: mac80211: add HE 6 GHz capability in the scan elems len

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit cd54bf333f5631d3630bab0a832e9ae648f73515 ]

The HE 6 GHz Band Capability element is in the probe request for every band if 6 GHz is supported, so add the size to scan_ies_len.

Otherwise, building probe request elements can fail, triggering the WARN_ON in __ieee80211_start_scan().

Assisted-by LLM
Fixes 2ad2274c58ee ("mac80211: Add HE 6GHz capabilities element to probe request")
Reported-by [email protected]
---
 net/mac80211/main.c | 4 ++++
 1 file changed, 4 insertions(+)
net/mac80211/main.c +4 -0
index eb1eaaf34612e..8edfef2b57f80 100644
@@ -1454,6 +1454,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 			sizeof(struct ieee80211_he_mcs_nss_supp) +
 			IEEE80211_HE_PPE_THRES_MAX_LEN;
 
+		if (local->hw.wiphy->bands[NL80211_BAND_6GHZ])
+			local->scan_ies_len +=
+				3 + sizeof(struct ieee80211_he_6ghz_capa);
+
 		if (supp_eht)
 			local->scan_ies_len +=
 				3 + sizeof(struct ieee80211_eht_cap_elem) +
Signature · 1 line
2.53.0
author maintainer
#89 lore raw

PATCH 89/438 wifi: mac80211: mesh: reset the CSA state when leaving

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 860134b3af77970e006feab7e5decb8c84771c7f ]

ifmsh->csa is allocated in ieee80211_mesh_csa_beacon() and only freed in ieee80211_mesh_finish_csa(), i.e. when the channel switch completes. Leaving the mesh while a switch is still pending therefore leaks it.

Additionally, ifmsh->csa_role and ifmsh->chsw_ttl have their state leak in this case, so things can get mixed up in addition to the memory leak.

Refactor the reset and call it in ieee80211_stop_mesh() to fix it all.

Assisted-by LLM
Reported-by [email protected]
Fixes b8456a14e9d2 ("{nl,cfg,mac}80211: implement mesh channel switch userspace API")
---
 net/mac80211/mesh.c | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)
net/mac80211/mesh.c +18 -11
index a35e2d5870b6f..8f88141253758 100644
@@ -1196,6 +1196,21 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 	return 0;
 }
 
+static void ieee80211_mesh_reset_csa(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+	struct mesh_csa_settings *csa;
+
+	/* Reset the TTL value and Initiator flag */
+	ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
+	ifmsh->chsw_ttl = 0;
+
+	/* Remove the CSA and MCSP elements from the beacon */
+	csa = sdata_dereference(ifmsh->csa, sdata);
+	RCU_INIT_POINTER(ifmsh->csa, NULL);
+	kfree_rcu(csa, rcu_head);
+}
+
 void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
@@ -1206,6 +1221,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 
 	/* abort any running channel switch */
 	sdata->vif.bss_conf.csa_active = false;
+	ieee80211_mesh_reset_csa(sdata);
 	ieee80211_vif_unblock_queues_csa(sdata);
 
 	/* flush STAs and mpaths on this iface */
@@ -1514,19 +1530,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
 
 int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata, u64 *changed)
 {
-	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-	struct mesh_csa_settings *tmp_csa_settings;
-	int ret = 0;
+	int ret;
 
-	/* Reset the TTL value and Initiator flag */
-	ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
-	ifmsh->chsw_ttl = 0;
+	ieee80211_mesh_reset_csa(sdata);
 
-	/* Remove the CSA and MCSP elements from the beacon */
-	tmp_csa_settings = sdata_dereference(ifmsh->csa, sdata);
-	RCU_INIT_POINTER(ifmsh->csa, NULL);
-	if (tmp_csa_settings)
-		kfree_rcu(tmp_csa_settings, rcu_head);
 	ret = ieee80211_mesh_rebuild_beacon(sdata);
 	if (ret)
 		return -EINVAL;
Signature · 1 line
2.53.0
author maintainer
#90 lore raw

PATCH 90/438 wifi: mac80211: mesh: release the channel if start fails

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit ae97fff6495a8764bc0ef281cfe5444f701e527f ]

ieee80211_join_mesh() acquires a channel context and then calls ieee80211_start_mesh(), which can fail. In that case, the chanctx isn't released then interface removal will attempt to unassign it after it's removed from the driver, hitting:

wlan0: Failed check-sdata-in-driver check, flags: 0x0

  WARNING: net/mac80211/driver-ops.c:366 at drv_unassign_vif_chanctx
   ieee80211_assign_link_chanctx
   __ieee80211_link_release_channel
   ieee80211_link_release_channel
   ieee80211_teardown_sdata
   unregister_netdevice_many_notify
   _cfg80211_unregister_wdev
   ieee80211_remove_interfaces
   ieee80211_unregister_hw
   mac80211_hwsim_del_radio
   hwsim_exit_net

Correctly release the channel on start failures.

---
 net/mac80211/cfg.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
net/mac80211/cfg.c +5 -1
index 45f8e3c87884a..8e2ff624a0caa 100644
@@ -3323,7 +3323,11 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
 	if (err)
 		return err;
 
-	return ieee80211_start_mesh(sdata);
+	err = ieee80211_start_mesh(sdata);
+	if (err)
+		ieee80211_link_release_channel(&sdata->deflink);
+
+	return err;
 }
 
 static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
Signature · 1 line
2.53.0
author maintainer
#91 lore raw

PATCH 91/438 wifi: mac80211: set up the TX info early to fix failure paths

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 50d3d79dc0743b616afb00d01a626c76758721f7 ]

The previous commit 2c51457d930f ("wifi: mac80211: free ack status frame on TX header build failure") cleaned up the leak, but still left the code a bit messy and the failed SKB didn't get reported to userspace.

Fix this up by initialising skb->cb[] earlier, which allows using ieee80211_free_txskb() and therefore reports it for the failure in ieee80211_build_hdr(), and unifies the ieee80211_skb_resize() failure path with it.

Assisted-by LLM
Fixes c3e7724b6bc2 ("mac80211: use ieee80211_free_txskb to fix possible skb leaks")
---
 net/mac80211/tx.c | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)
net/mac80211/tx.c +20 -18
index a726a697c32d7..e264121208736 100644
@@ -2974,10 +2974,23 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 	 */
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (unlikely(!skb)) {
-		ret = -ENOMEM;
-		goto free;
+		/* skb_share_check() already freed the skb */
+		if (info_id)
+			ieee80211_remove_ack_skb(local, info_id);
+		return ERR_PTR(-ENOMEM);
 	}
 
+	/* set this up so failure paths can clean up ack skb */
+	info = IEEE80211_SKB_CB(skb);
+	memset(info, 0, sizeof(*info));
+
+	info->flags = info_flags;
+	if (info_id) {
+		info->status_data = info_id;
+		info->status_data_idr = 1;
+	}
+	info->band = band;
+
 	hdr.frame_control = fc;
 	hdr.duration_id = 0;
 	hdr.seq_ctrl = 0;
@@ -3016,10 +3029,8 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 		head_need += local->tx_headroom;
 		head_need = max_t(int, 0, head_need);
 		if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) {
-			ieee80211_free_txskb(&local->hw, skb);
-			skb = NULL;
 			ret = -ENOMEM;
-			goto free;
+			goto free_txskb;
 		}
 	}
 
@@ -3046,16 +3057,6 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 
 	skb_reset_mac_header(skb);
 
-	info = IEEE80211_SKB_CB(skb);
-	memset(info, 0, sizeof(*info));
-
-	info->flags = info_flags;
-	if (info_id) {
-		info->status_data = info_id;
-		info->status_data_idr = 1;
-	}
-	info->band = band;
-
 	if (likely(!cookie)) {
 		ctrl_flags |= u32_encode_bits(link_id,
 					      IEEE80211_TX_CTRL_MLO_LINK);
@@ -3079,16 +3080,17 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 					     pre_conf_link_id, link_id);
 #endif
 			ret = -EINVAL;
-			goto free;
+			goto free_txskb;
 		}
 	}
 
 	info->control.flags = ctrl_flags;
 
 	return skb;
+ free_txskb:
+	ieee80211_free_txskb(&local->hw, skb);
+	return ERR_PTR(ret);
  free:
-	if (info_id)
-		ieee80211_remove_ack_skb(local, info_id);
 	kfree_skb(skb);
 	return ERR_PTR(ret);
 }
Signature · 1 line
2.53.0
author maintainer
#92 lore raw

PATCH 92/438 mm: memblock: show all region flags in debugfs

In reply to Greg Kroah-Hartman

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

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

From: Meijing Zhao <[email protected]>

[ Upstream commit e2d5b01f878d76bd1142e512a0b979a1d3cd0abf ]

Commit 493f349e38d0 ("memblock: Add flags and nid info in memblock debugfs") made memblock_debug_show() stop after finding the first set flag. A memblock region can carry multiple flags, so the remaining flags are hidden from debugfs.

Walk all bits in the region flags and print every set flag separated by "|". Keep walking beyond flagname[] so that a set flag without a known name is reported as UNKNOWN rather than silently ignored.

Fixes 493f349e38d0 ("memblock: Add flags and nid info in memblock debugfs")
---
 mm/memblock.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
mm/memblock.c +11 -7
index 6349c48154f4b..a8d1992ba7a13 100644
@@ -2823,14 +2823,18 @@ static int memblock_debug_show(struct seq_file *m, void *private)
 		else
 			seq_printf(m, "%4c ", 'x');
 		if (reg->flags) {
-			for (j = 0; j < count; j++) {
-				if (reg->flags & (1U << j)) {
-					seq_printf(m, "%s\n", flagname[j]);
-					break;
-				}
+			unsigned int flags = reg->flags;
+			bool first = true;
+
+			for (j = 0; flags; j++, flags >>= 1) {
+				if (!(flags & 1))
+					continue;
+				if (!first)
+					seq_putc(m, '|');
+				seq_puts(m, j < count ? flagname[j] : "UNKNOWN");
+				first = false;
 			}
-			if (j == count)
-				seq_printf(m, "%s\n", "UNKNOWN");
+			seq_putc(m, '\n');
 		} else {
 			seq_printf(m, "%s\n", "NONE");
 		}
Signature · 1 line
2.53.0
author maintainer
#93 lore raw

PATCH 93/438 scsi: pm80xx: Fix the use_msix, use_tasklet and read_wwn parameter descriptions

In reply to Greg Kroah-Hartman

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

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

From: Karl Mehltretter <[email protected]>

[ Upstream commit 264bf9655c3d067d775a46f05eb8c871c488a864 ]

The MODULE_PARM_DESC() lines of use_msix, use_tasklet and read_wwn all name a parameter zoned, which does not exist, and the use_tasklet one repeats the use_msix text. modinfo shows three "zoned" entries and no description for the real parameters.

Name the right parameters and describe use_tasklet.

Fixes efa1fca45082 ("scsi: pm8001: Remove PM8001_USE_MSIX")
Fixes 205430290ad0 ("scsi: pm8001: Remove PM8001_USE_TASKLET")
Fixes 80975adc79dd ("scsi: pm8001: Remove PM8001_READ_VPD")
Assisted-by LLM
---
 drivers/scsi/pm8001/pm8001_init.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/scsi/pm8001/pm8001_init.c +3 -3
index 54b35893261a6..5af81c73a8f87 100644
@@ -58,15 +58,15 @@ MODULE_PARM_DESC(link_rate, "Enable link rate.\n"
 
 bool pm8001_use_msix = true;
 module_param_named(use_msix, pm8001_use_msix, bool, 0444);
-MODULE_PARM_DESC(zoned, "Use MSIX interrupts. Default: true");
+MODULE_PARM_DESC(use_msix, "Use MSIX interrupts. Default: true");
 
 static bool pm8001_use_tasklet = true;
 module_param_named(use_tasklet, pm8001_use_tasklet, bool, 0444);
-MODULE_PARM_DESC(zoned, "Use MSIX interrupts. Default: true");
+MODULE_PARM_DESC(use_tasklet, "Use tasklets for interrupt handling. Default: true");
 
 static bool pm8001_read_wwn = true;
 module_param_named(read_wwn, pm8001_read_wwn, bool, 0444);
-MODULE_PARM_DESC(zoned, "Get WWN from the controller. Default: true");
+MODULE_PARM_DESC(read_wwn, "Get WWN from the controller. Default: true");
 
 uint pcs_event_log_severity = 0x03;
 module_param(pcs_event_log_severity, int, 0644);
Signature · 1 line
2.53.0
author maintainer
#94 lore raw

PATCH 94/438 scsi: qla2xxx: Fix the ql2xfc2target parameter description

In reply to Greg Kroah-Hartman

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

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

From: Karl Mehltretter <[email protected]>

[ Upstream commit 779f202a92ef10a426efc07d0f4267918cb07ca3 ]

The module parameter is ql2xfc2target, but its MODULE_PARM_DESC() names qla2xfc2target, so modinfo describes a parameter that does not exist and shows no description for the real one.

Use the parameter name in the description.

Fixes 877b03795fcf ("scsi: qla2xxx: Add option to disable FC2 Target support")
Assisted-by LLM
---
 drivers/scsi/qla2xxx/qla_os.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_os.c +1 -1
index e0c5732037adf..f2114b386fa0f 100644
@@ -352,7 +352,7 @@ MODULE_PARM_DESC(ql2xnvme_queues,
 
 int ql2xfc2target = 1;
 module_param(ql2xfc2target, int, 0444);
-MODULE_PARM_DESC(qla2xfc2target,
+MODULE_PARM_DESC(ql2xfc2target,
 		  "Enables FC2 Target support. "
 		  "0 - FC2 Target support is disabled. "
 		  "1 - FC2 Target support is enabled (default).");
Signature · 1 line
2.53.0
author maintainer
#95 lore raw

PATCH 95/438 dmaengine: xilinx_dma: Fix hardware buffer descriptor reuse order

In reply to Greg Kroah-Hartman

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

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

From: Alex Bereza <[email protected]>

[ Upstream commit cee9c863ee68cb27d66745eb03f60e357f4f8ad2 ]

xilinx_dma_alloc_chan_resources() builds a static ring of hardware buffer descriptors once and the driver uses this ring throughout the lifetime of a channel. This requires the allocation order of hardware buffer descriptors from chan->free_seg_list to stay in sync with the hardware buffer descriptor ring built at channel allocation time by returning oldest descriptors to chan->free_seg_list first.

When chan->pending_list is not empty e.g. during xilinx_dma_terminate_all() the chan->free_seg_list and the order of the static hardware buffer descriptor ring get out of sync. Descriptors age in this order: pending -> active -> done. So freeing pending_list first returns the newest buffer descriptors to the chan->free_seg_list first and thus breaks the order required by the static hardware buffer descriptor ring. Then when the channel is reused, after a wrap around of the free_seg_list the DMA will find a hardware buffer descriptor with a length field that is still zeroed and stop with something like this:

xilinx-vdma 86000000.dma: Channel 000000003a21d7b8 has errors 10, cdr 6de4c000 tdr 6de4c000

After this no more descriptors are completed and a consumer potentially blocks and waits forever. The only way to get out of this error state is to rebuild the static hardware buffer descriptor ring and the free_seg_list by releasing and re-acquiring the channel.

Fix the order in which hardware buffer descriptors are returned to free_seg_list to ensure the mentioned requirement holds.

Fixes 23059408b6a3 ("dmaengine: xilinx_dma: Fix race condition in the driver for multiple descriptor scenario")
---
 drivers/dma/xilinx/xilinx_dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/xilinx/xilinx_dma.c +1 -1
index 74ad80d6c5a5f..0e62e523d0ccd 100644
@@ -920,9 +920,9 @@ static void xilinx_dma_free_descriptors(struct xilinx_dma_chan *chan)
 
 	spin_lock_irqsave(&chan->lock, flags);
 
-	xilinx_dma_free_desc_list(chan, &chan->pending_list);
 	xilinx_dma_free_desc_list(chan, &chan->done_list);
 	xilinx_dma_free_desc_list(chan, &chan->active_list);
+	xilinx_dma_free_desc_list(chan, &chan->pending_list);
 
 	spin_unlock_irqrestore(&chan->lock, flags);
 }
Signature · 1 line
2.53.0
author maintainer
#96 lore raw

PATCH 96/438 dmaengine: pxa: fix double counting of the hw descriptors

In reply to Greg Kroah-Hartman

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

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

From: Sascha Hauer <[email protected]>

[ Upstream commit f6504be006aa4bb4bd26285f410a885c17920d65 ]

pxad_alloc_desc() was converted from

kzalloc(struct_size(sw_desc, hw_desc, nb_hw_desc), GFP_NOWAIT)

to kzalloc_flex(), which sets the __counted_by() counter sw_desc->nb_desc itself - but only where the compiler has __builtin_counted_by_ref(), so from gcc 15.1 or clang 22.1 on. The loop below it still increments nb_desc, which makes it come out doubled there and correct elsewhere.

nb_desc is what pxad_free_desc() iterates over and what set_updater_desc() indexes from, so set it explicitly and drop the increment. The error path has to lower it to the number of descriptors allocated so far, otherwise pxad_free_desc() would free entries that were never allocated.

Fixes 69050f8d6d075 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")
Assisted-by Claude:claude-opus-5
---
 drivers/dma/pxa_dma.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/dma/pxa_dma.c +2 -1
index fa2ee0b3e09f8..fc43124fefa89 100644
@@ -744,6 +744,7 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
 	sw_desc = kzalloc_flex(*sw_desc, hw_desc, nb_hw_desc, GFP_NOWAIT);
 	if (!sw_desc)
 		return NULL;
+	sw_desc->nb_desc = nb_hw_desc;
 	sw_desc->desc_pool = chan->desc_pool;
 
 	for (i = 0; i < nb_hw_desc; i++) {
@@ -752,10 +753,10 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
 			dev_err(&chan->vc.chan.dev->device,
 				"%s(): Couldn't allocate the %dth hw_desc from dma_pool %p\n",
 				__func__, i, sw_desc->desc_pool);
+			sw_desc->nb_desc = i;
 			goto err;
 		}
 
-		sw_desc->nb_desc++;
 		sw_desc->hw_desc[i] = desc;
 
 		if (i == 0)
Signature · 1 line
2.53.0
author maintainer
#97 lore raw

PATCH 97/438 dmaengine: xilinx_dma: Fix hardware buffer descriptor chain after cyclic DMA

In reply to Greg Kroah-Hartman

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

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

From: Alex Bereza <[email protected]>

[ Upstream commit 7ed1e3070c9b4bbd67d5519e14711038dd53ab13 ]

Using the DMA in cyclic mode modifies the hardware buffer descriptor chain in xilinx_dma_prep_dma_cyclic so that the last descriptor used by the cyclic transfer points back to the first descriptor, but it never restores the original descriptor ring. This breaks using non-cyclic mode after cyclic mode with an error like:

xilinx-vdma 86000000.dma: Channel 00000000354d5c8d has errors 100, cdr 6de40000 tdr 6de40400

The only way to get out of this error state is to rebuild the hardware buffer descriptor ring by releasing and re-acquiring the channel.

Fix using non-cyclic mode after cyclic mode by always restoring the original buffer descriptor ring in the same manner as it is set up by xilinx_dma_alloc_chan_resources().

---
 drivers/dma/xilinx/xilinx_dma.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)
drivers/dma/xilinx/xilinx_dma.c +17 -7
index 0e62e523d0ccd..12cf1ca3a98a1 100644
@@ -756,15 +756,25 @@ xilinx_aximcdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
 	return segment;
 }
 
-static void xilinx_dma_clean_hw_desc(struct xilinx_axidma_desc_hw *hw)
+static void xilinx_dma_clean_hw_desc(struct xilinx_dma_chan *chan,
+				     struct xilinx_axidma_tx_segment *segment)
 {
-	u32 next_desc = hw->next_desc;
-	u32 next_desc_msb = hw->next_desc_msb;
+	dma_addr_t next;
+	u32 i;
 
-	memset(hw, 0, sizeof(struct xilinx_axidma_desc_hw));
+	/*
+	 * Restore the buffer descriptor's next descriptor pointer to the value
+	 * set up in xilinx_dma_alloc_chan_resources(). Otherwise using the DMA
+	 * in cyclic mode leaves the next descriptor pointer altered and
+	 * prevents subsequent non-cyclic transfers.
+	 */
+	i = segment - chan->seg_v;
+	next = chan->seg_p +
+	       sizeof(*chan->seg_v) * ((i + 1) % XILINX_DMA_NUM_DESCS);
 
-	hw->next_desc = next_desc;
-	hw->next_desc_msb = next_desc_msb;
+	memset(&segment->hw, 0, sizeof(segment->hw));
+	segment->hw.next_desc = lower_32_bits(next);
+	segment->hw.next_desc_msb = upper_32_bits(next);
 }
 
 static void xilinx_mcdma_clean_hw_desc(struct xilinx_aximcdma_desc_hw *hw)
@@ -786,7 +796,7 @@ static void xilinx_mcdma_clean_hw_desc(struct xilinx_aximcdma_desc_hw *hw)
 static void xilinx_dma_free_tx_segment(struct xilinx_dma_chan *chan,
 				struct xilinx_axidma_tx_segment *segment)
 {
-	xilinx_dma_clean_hw_desc(&segment->hw);
+	xilinx_dma_clean_hw_desc(chan, segment);
 
 	list_add_tail(&segment->node, &chan->free_seg_list);
 }
Signature · 1 line
2.53.0
author maintainer
#98 lore raw

PATCH 98/438 RDMA/efa: Keep admin queues alive while IRQ is registered

In reply to Greg Kroah-Hartman

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

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

From: Leon Romanovsky <[email protected]>

[ Upstream commit e08aca85c02ff290f785f07acae758f0daf5f49e ]

The management IRQ handler accesses both the admin completion queue and the async event queue. The driver registered the IRQ before constructing these queues and destroyed them before freeing the IRQ, so the handler's lifetime was not contained by the resources it accesses.

Initialize the queues with interrupts masked, request the IRQ, and then switch to interrupt mode. On removal, reset the device and free the IRQ before destroying the queues. Also reset the device before destroying the queues if IRQ registration fails, because the device already has their DMA addresses.

---
 drivers/infiniband/hw/efa/efa_com.c  |  4 +---
 drivers/infiniband/hw/efa/efa_main.c | 15 +++++++++------
 2 files changed, 10 insertions(+), 9 deletions(-)
drivers/infiniband/hw/efa/efa_com.c +1 -3
index 7cc3f4af0bb9d..12ccb6441d13d 100644
@@ -786,7 +786,7 @@ int efa_com_admin_init(struct efa_com_dev *edev,
 
 	aq->dmadev = edev->dmadev;
 	aq->efa_dev = edev->efa_dev;
-	set_bit(EFA_AQ_STATE_POLLING_BIT, &aq->state);
+	efa_com_set_admin_polling_mode(edev, true);
 
 	sema_init(&aq->avail_cmds, aq->depth);
 
@@ -804,8 +804,6 @@ int efa_com_admin_init(struct efa_com_dev *edev,
 	if (err)
 		goto err_destroy_sq;
 
-	efa_com_set_admin_polling_mode(edev, false);
-
 	err = efa_com_admin_init_aenq(edev, aenq_handlers);
 	if (err)
 		goto err_destroy_cq;
drivers/infiniband/hw/efa/efa_main.c +9 -6
index 97da8e828e340..25af30c441929 100644
@@ -611,18 +611,21 @@ static struct efa_dev *efa_probe_device(struct pci_dev *pdev)
 	edev->aq.msix_vector_idx = dev->admin_msix_vector_idx;
 	edev->aenq.msix_vector_idx = dev->admin_msix_vector_idx;
 
-	err = efa_set_mgmnt_irq(dev);
+	err = efa_com_admin_init(edev, &aenq_handlers);
 	if (err)
 		goto err_disable_msix;
 
-	err = efa_com_admin_init(edev, &aenq_handlers);
+	err = efa_set_mgmnt_irq(dev);
 	if (err)
-		goto err_free_mgmnt_irq;
+		goto err_destroy_admin;
+
+	efa_com_set_admin_polling_mode(edev, false);
 
 	return dev;
 
-err_free_mgmnt_irq:
-	efa_free_irq(dev, &dev->admin_irq);
+err_destroy_admin:
+	efa_com_dev_reset(edev, EFA_REGS_RESET_INIT_ERR);
+	efa_com_admin_destroy(edev);
 err_disable_msix:
 	efa_disable_msix(dev);
 err_reg_read_destroy:
@@ -646,8 +649,8 @@ static void efa_remove_device(struct pci_dev *pdev,
 
 	edev = &dev->edev;
 	efa_com_dev_reset(edev, reset_reason);
-	efa_com_admin_destroy(edev);
 	efa_free_irq(dev, &dev->admin_irq);
+	efa_com_admin_destroy(edev);
 	efa_disable_msix(dev);
 	efa_com_mmio_reg_read_destroy(edev);
 	devm_iounmap(&pdev->dev, edev->reg_bar);
Signature · 1 line
2.53.0
author maintainer
#99 lore raw

PATCH 99/438 RDMA/efa: Keep EQ resources alive while IRQ is registered

In reply to Greg Kroah-Hartman

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

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

From: Leon Romanovsky <[email protected]>

[ Upstream commit e22a3627b7151754f07f90ea3d1ab6e85f5d93f4 ]

The completion IRQ handler accesses the EQ state and DMA buffer. Its IRQ was registered before that state was initialized, while teardown released the buffer before free_irq() synchronized the handler.

Initialize the EQ without arming it, register the IRQ, and then arm it. Reverse the resource order during teardown by freeing the IRQ before destroying the EQ.

---
 drivers/infiniband/hw/efa/efa_com.c  |  3 +--
 drivers/infiniband/hw/efa/efa_com.h  |  1 +
 drivers/infiniband/hw/efa/efa_main.c | 18 ++++++++++--------
 3 files changed, 12 insertions(+), 10 deletions(-)
drivers/infiniband/hw/efa/efa_com.c +1 -2
index 12ccb6441d13d..eed6000fc62df 100644
@@ -1192,7 +1192,7 @@ static void efa_com_destroy_eq(struct efa_com_dev *edev,
 				      err);
 }
 
-static void efa_com_arm_eq(struct efa_com_dev *edev, struct efa_com_eq *eeq)
+void efa_com_arm_eq(struct efa_com_dev *edev, struct efa_com_eq *eeq)
 {
 	u32 val = 0;
 
@@ -1281,7 +1281,6 @@ int efa_com_eq_init(struct efa_com_dev *edev, struct efa_com_eq *eeq,
 	eeq->phase = 1;
 	eeq->depth = params.depth;
 	eeq->cb = cb;
-	efa_com_arm_eq(edev, eeq);
 
 	return 0;
 
drivers/infiniband/hw/efa/efa_com.h +1 -0
index f8c692b0e092e..d9b3eb0cdf37c 100644
@@ -159,6 +159,7 @@ int efa_com_admin_init(struct efa_com_dev *edev,
 void efa_com_admin_destroy(struct efa_com_dev *edev);
 int efa_com_eq_init(struct efa_com_dev *edev, struct efa_com_eq *eeq,
 		    efa_eqe_handler cb, u16 depth, u8 msix_vec);
+void efa_com_arm_eq(struct efa_com_dev *edev, struct efa_com_eq *eeq);
 void efa_com_eq_destroy(struct efa_com_dev *edev, struct efa_com_eq *eeq);
 int efa_com_dev_reset(struct efa_com_dev *edev,
 		      enum efa_regs_reset_reason_types reset_reason);
drivers/infiniband/hw/efa/efa_main.c +10 -8
index 25af30c441929..c2ecd44476d4f 100644
@@ -300,28 +300,30 @@ static void efa_set_host_info(struct efa_dev *dev)
 
 static void efa_destroy_eq(struct efa_dev *dev, struct efa_eq *eq)
 {
-	efa_com_eq_destroy(&dev->edev, &eq->eeq);
 	efa_free_irq(dev, &eq->irq);
+	efa_com_eq_destroy(&dev->edev, &eq->eeq);
 }
 
 static int efa_create_eq(struct efa_dev *dev, struct efa_eq *eq, u32 msix_vec)
 {
 	int err;
 
-	efa_setup_comp_irq(dev, eq, msix_vec);
-	err = efa_request_irq(dev, &eq->irq);
+	err = efa_com_eq_init(&dev->edev, &eq->eeq, efa_process_eqe,
+			      dev->dev_attr.max_eq_depth, msix_vec);
 	if (err)
 		return err;
 
-	err = efa_com_eq_init(&dev->edev, &eq->eeq, efa_process_eqe,
-			      dev->dev_attr.max_eq_depth, msix_vec);
+	efa_setup_comp_irq(dev, eq, msix_vec);
+	err = efa_request_irq(dev, &eq->irq);
 	if (err)
-		goto err_free_comp_irq;
+		goto err_destroy_eq;
+
+	efa_com_arm_eq(&dev->edev, &eq->eeq);
 
 	return 0;
 
-err_free_comp_irq:
-	efa_free_irq(dev, &eq->irq);
+err_destroy_eq:
+	efa_com_eq_destroy(&dev->edev, &eq->eeq);
 	return err;
 }
 
Signature · 1 line
2.53.0
author maintainer
#100 lore raw

PATCH 100/438 RDMA/siw: Bound fragmented header copies by the remaining length

In reply to Greg Kroah-Hartman

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

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

From: Jérémy Jean <[email protected]>

[ Upstream commit 9ff797e516dbc1ecb73701ec4c24055712d44411 ]

siw_get_hdr() can receive an extended DDP/RDMAP header across more than one TCP callback. The first callback may receive most of the header, while the next one still limits the copy to hdrlen - MIN_DDP_HDR instead of the number of missing bytes. This makes the destination move past the end of the header and overwrite the receive state, including fpdu_part_rcvd. A later callback can then use a negative fpdu_part_rcvd value as a copy offset, which creates an OOB write.

Use the number of header bytes already received when calculating the next copy length.

Fixes 754209850df8 ("RDMA/siw: Always consume all skbuf data in sk_data_ready() upcall.")
Assisted-by Codex:gpt-6
---
 drivers/infiniband/sw/siw/siw_qp_rx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/sw/siw/siw_qp_rx.c +1 -1
index b566d163c5aab..e5b641c8d694a 100644
@@ -1079,7 +1079,7 @@ static int siw_get_hdr(struct siw_rx_stream *srx)
 	if (iwarp_pktinfo[opcode].hdr_len > sizeof(struct iwarp_ctrl_tagged)) {
 		int hdrlen = iwarp_pktinfo[opcode].hdr_len;
 
-		bytes = min_t(int, hdrlen - MIN_DDP_HDR, srx->skb_new);
+		bytes = min_t(int, hdrlen - srx->fpdu_part_rcvd, srx->skb_new);
 
 		skb_copy_bits(skb, srx->skb_offset,
 			      (char *)c_hdr + srx->fpdu_part_rcvd, bytes);
Signature · 1 line
2.53.0
author maintainer
#101 lore raw

PATCH 101/438 x86/div64: Fix addition of large constants in mul_u64_add_u64_div_u64()

In reply to Greg Kroah-Hartman

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

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

From: David Laight <[email protected]>

[ Upstream commit f65d38155aef069c897a64643a03db237dd1e0c8 ]

Adding constants over 2^31 fails to compile because the ADD instruction only supports 32bit signed immediates.

Replace the "irm" constraint with "erm" so that the compiler loads large constants into a register.

Found by a patch to drivers/iio/frequency/ad9910.c

[ bp: Massage commit message. ]

Fixes 6480241f31f5 ("lib: add mul_u64_add_u64_div_u64() and mul_u64_u64_div_u64_roundup()")
---
 arch/x86/include/asm/div64.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/div64.h +1 -1
index 30fd06ede751c..8a2d343f977ec 100644
@@ -111,7 +111,7 @@ static inline u64 mul_u64_add_u64_div_u64(u64 rax, u64 mul, u64 add, u64 div)
 
 	if (!statically_true(!add))
 		asm ("addq %[add], %[lo]; adcq $0, %[hi]" :
-			[lo] "+r" (rax), [hi] "+r" (rdx) : [add] "irm" (add));
+			[lo] "+r" (rax), [hi] "+r" (rdx) : [add] "erm" (add));
 
 	asm ("divq %[div]" : "+a" (rax), "+d" (rdx) : [div] "rm" (div));
 
Signature · 1 line
2.53.0
author maintainer
#102 lore raw

PATCH 102/438 drm/msm: Fix the separate_gpu_kms parameter description

In reply to Greg Kroah-Hartman

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

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

From: Karl Mehltretter <[email protected]>

[ Upstream commit adf5967331318bcb436fc80069915231ec039352 ]

The module parameter is separate_gpu_kms, but its MODULE_PARM_DESC() names separate_gpu_drm, so modinfo describes a parameter that does not exist and shows no description for the real one.

Use the parameter name in the description.

Fixes 217ed15bd399 ("drm/msm: enable separate binding of GPU and display devices")
Assisted-by LLM

Patchwork: https://patchwork.freedesktop.org/patch/751407/
Message-ID: <[email protected]>

---
 drivers/gpu/drm/msm/msm_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/msm_drv.c +1 -1
index 32d5ebea2596f..fa46ab3063e6f 100644
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disab
 module_param(modeset, bool, 0600);
 
 static bool separate_gpu_kms;
-MODULE_PARM_DESC(separate_gpu_drm, "Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)");
+MODULE_PARM_DESC(separate_gpu_kms, "Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)");
 module_param(separate_gpu_kms, bool, 0400);
 
 DECLARE_FAULT_ATTR(fail_gem_alloc);
Signature · 1 line
2.53.0
author maintainer
#103 lore raw

PATCH 103/438 drm/msm/adreno: Fix the skip_gpu parameter description

In reply to Greg Kroah-Hartman

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

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

From: Karl Mehltretter <[email protected]>

[ Upstream commit 8061ee61b9426fe38350fa9eead2d9c50b03deb6 ]

The module parameter is skip_gpu, but its MODULE_PARM_DESC() names no_gpu, so modinfo describes a parameter that does not exist and shows no description for the real one.

Use the parameter name in the description.

Fixes 3f17991488af ("drm/msm/adreno: Add a modparam to skip GPU")
Assisted-by LLM

Patchwork: https://patchwork.freedesktop.org/patch/751406/
Message-ID: <[email protected]>

---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/adreno/adreno_device.c +1 -1
index 7f20320ef66af..05c77fe27e620 100644
@@ -25,7 +25,7 @@ MODULE_PARM_DESC(disable_acd, "Forcefully disable GPU ACD");
 module_param_unsafe(disable_acd, bool, 0400);
 
 static bool skip_gpu;
-MODULE_PARM_DESC(no_gpu, "Disable GPU driver register (0=enable GPU driver register (default), 1=skip GPU driver register");
+MODULE_PARM_DESC(skip_gpu, "Disable GPU driver register (0=enable GPU driver register (default), 1=skip GPU driver register");
 module_param(skip_gpu, bool, 0400);
 
 extern const struct adreno_gpulist a2xx_gpulist;
Signature · 1 line
2.53.0
author maintainer
#104 lore raw

PATCH 104/438 dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels

In reply to Greg Kroah-Hartman

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

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

From: Karl Mehltretter <[email protected]>

[ Upstream commit 143755bdabaa96776c24f878014608e9cb44f930 ]

Commit 646013f513f3 ("dma-buf: enable DMABUF_DEBUG by default on DEBUG kernels") changed the default of DMABUF_DEBUG to "y if DEBUG", but no Kconfig symbol DEBUG exists, so the option has had no default since.

Use DEBUG_KERNEL, the Kconfig symbol for a debug kernel.

Fixes 646013f513f3 ("dma-buf: enable DMABUF_DEBUG by default on DEBUG kernels")
Assisted-by LLM
---
 drivers/dma-buf/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma-buf/Kconfig +1 -1
index 7efc0f0d07126..e4f078a326a41 100644
@@ -43,7 +43,7 @@ config UDMABUF
 config DMABUF_DEBUG
 	bool "DMA-BUF debug checks"
 	depends on DMA_SHARED_BUFFER
-	default y if DEBUG
+	default y if DEBUG_KERNEL
 	help
 	  This option enables additional checks for DMA-BUF importers and
 	  exporters. Specifically it validates that importers do not peek at the
Signature · 1 line
2.53.0
#105 lore raw

Re: [PATCH 7.2 104/438] dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels

I object to including this patch in 7.2.8. I authored the upstream patch, but did not tag it for stable. It corrects a Kconfig default and thereby enables the DMA-BUF importer checks in configurations that take the DEBUG_KERNEL default.

Jianfeng has now reported a drm/msm hardware video decode regression from the upstream change:

https://lore.kernel.org/r/[email protected]/

The impact of enabling this by default for stable needs further discussion.

Thanks,
Karl

maintainer
#106 lore raw

Re: [PATCH 7.2 104/438] dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels

Quoted 4 lines · Karl Mehltretter

I object to including this patch in 7.2.8. I authored the upstream patch, but did not tag it for stable. It corrects a Kconfig default and thereby enables the DMA-BUF importer checks in configurations that take the DEBUG_KERNEL default.

Dropped from the 7.2 queue, so it won't be in 7.2.8.

Signature · 2 lines
Thanks,
Sasha
#107 lore raw

Re: [PATCH 7.2 104/438] dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels

Quoted 8 lines · Sasha Levin
Quoted 4 lines · Karl Mehltretter

I object to including this patch in 7.2.8. I authored the upstream patch, but did not tag it for stable. It corrects a Kconfig default and thereby enables the DMA-BUF importer checks in configurations that take the DEBUG_KERNEL default.

Dropped from the 7.2 queue, so it won't be in 7.2.8.

Thanks for catching this Karl and I agree completely.

That config option is for phasing out a broken approach in some DRM drivers, but not meant to be added to any stable kernel.

Regards,
Christian.

author maintainer
#108 lore raw

PATCH 105/438 netfilter: nft_nat: fully initialise new_addr in netmap setup

In reply to Greg Kroah-Hartman

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

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

From: Theodor Arsenij Larionov Trichkine <[email protected]>

[ Upstream commit d313499df66159b4b7971d760d16729598ab7e5a ]

nft_nat_setup_netmap() builds the mapped address in an on-stack union nf_inet_addr. For an IPv4 mapping it writes only the 4-byte .ip member and the loop runs a single 32-bit iteration, but it then copies the whole 16-byte union into range->min_addr and range->max_addr, so the upper 12 bytes reach nf_nat_setup_info() uninitialised.

KMSAN reports an uninit-value in nf_nat_setup_info() reached from nft_nat_eval(). The IPv6 path fills all 16 bytes and is not affected.

Zero-initialise new_addr.

Fixes 3ff7ddb1353d ("netfilter: nft_nat: add netmap support")
---
 net/netfilter/nft_nat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nft_nat.c +1 -1
index e32cd9fbc7c2e..cdbd800cac969 100644
@@ -64,8 +64,8 @@ static void nft_nat_setup_netmap(struct nf_nat_range2 *range,
 				 const struct nft_pktinfo *pkt,
 				 const struct nft_nat *priv)
 {
+	union nf_inet_addr new_addr = {};
 	struct sk_buff *skb = pkt->skb;
-	union nf_inet_addr new_addr;
 	__be32 netmask;
 	int i, len = 0;
 
Signature · 1 line
2.53.0
author maintainer
#109 lore raw

PATCH 106/438 netfilter: nf_tables: fix device name and prefix match in hook lookup

In reply to Greg Kroah-Hartman

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

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

From: Fernando Fernandez Mancera <[email protected]>

[ Upstream commit 444e4c88c9c62a3d823069006563513fe7d5aa66 ]

Currently, a netdev chain or flowtable hooked to a device prefix can be unintentionally deleted by a control-plane request targeting an exact device name or even a shorter one due to the usage of min() to calculate the length to match.

Fix this by making sure an exact device match never matches a prefix and that both the target and the candidate have the same length during delete operation. The add and update paths retain the existing overlap matching to prevent a single device from matching multiple hooks.

---
 net/netfilter/nf_tables_api.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)
net/netfilter/nf_tables_api.c +13 -9
index 63003a3b8babe..245fe7b2f6734 100644
@@ -2435,11 +2435,14 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
 }
 
 static struct nft_hook *nft_hook_list_find(struct list_head *hook_list,
-					   const struct nft_hook *this)
+					   const struct nft_hook *this,
+					   bool strict)
 {
 	struct nft_hook *hook;
 
 	list_for_each_entry(hook, hook_list, list) {
+		if (strict && hook->ifnamelen != this->ifnamelen)
+			continue;
 		if (!strncmp(hook->ifname, this->ifname,
 			     min(hook->ifnamelen, this->ifnamelen))) {
 			if (hook->flags & NFT_HOOK_REMOVE)
@@ -2481,7 +2484,7 @@ static int nf_tables_parse_netdev_hooks(struct net *net,
 			err = PTR_ERR(hook);
 			goto err_hook;
 		}
-		if (nft_hook_list_find(hook_list, hook)) {
+		if (nft_hook_list_find(hook_list, hook, false)) {
 			NL_SET_BAD_ATTR(extack, tmp);
 			nft_netdev_hook_free(hook);
 			err = -EEXIST;
@@ -2938,7 +2941,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
 					ops->hook	= basechain->ops.hook;
 				}
 
-				if (nft_hook_list_find(&basechain->hook_list, h)) {
+				if (nft_hook_list_find(&basechain->hook_list, h, false)) {
 					list_del(&h->list);
 					nft_netdev_hook_free(h);
 					continue;
@@ -2951,7 +2954,8 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
 					    !nft_trans_chain_update(trans))
 						continue;
 
-					if (nft_hook_list_find(&nft_trans_chain_hooks(trans), h)) {
+					if (nft_hook_list_find(&nft_trans_chain_hooks(trans),
+							       h, false)) {
 						nft_chain_release_hook(&hook);
 						return -EEXIST;
 					}
@@ -3252,7 +3256,7 @@ static int nft_delchain_hook(struct nft_ctx *ctx,
 		return err;
 
 	list_for_each_entry(this, &chain_hook.list, list) {
-		hook = nft_hook_list_find(&basechain->hook_list, this);
+		hook = nft_hook_list_find(&basechain->hook_list, this, true);
 		if (!hook) {
 			err = -ENOENT;
 			goto err_chain_del_hook;
@@ -9031,7 +9035,7 @@ static int nft_register_flowtable_net_hooks(struct net *net,
 			if (!nft_is_active_next(net, ft))
 				continue;
 
-			if (nft_hook_list_find(&ft->hook_list, hook)) {
+			if (nft_hook_list_find(&ft->hook_list, hook, false)) {
 				err = -EEXIST;
 				goto err_unregister_net_hooks;
 			}
@@ -9108,7 +9112,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
 		return err;
 
 	list_for_each_entry_safe(hook, next, &flowtable_hook.list, list) {
-		if (nft_hook_list_find(&flowtable->hook_list, hook)) {
+		if (nft_hook_list_find(&flowtable->hook_list, hook, false)) {
 			list_del(&hook->list);
 			nft_netdev_hook_free(hook);
 			continue;
@@ -9121,7 +9125,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
 			    !nft_trans_flowtable_update(trans))
 				continue;
 
-			if (nft_hook_list_find(&nft_trans_flowtable_hooks(trans), hook)) {
+			if (nft_hook_list_find(&nft_trans_flowtable_hooks(trans), hook, false)) {
 				err = -EEXIST;
 				goto err_flowtable_update_hook;
 			}
@@ -9341,7 +9345,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
 		return err;
 
 	list_for_each_entry(this, &flowtable_hook.list, list) {
-		hook = nft_hook_list_find(&flowtable->hook_list, this);
+		hook = nft_hook_list_find(&flowtable->hook_list, this, true);
 		if (!hook) {
 			err = -ENOENT;
 			goto err_flowtable_del_hook;
Signature · 1 line
2.53.0
author maintainer
#110 lore raw

PATCH 107/438 netfilter: nf_nat: unregister and release hooks on error

In reply to Greg Kroah-Hartman

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

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

From: Pablo Neira Ayuso <[email protected]>

[ Upstream commit cbdd39ce42530a193c56beb206a3356cb6d01016 ]

If nf_hook_entries_insert_raw() fails, the NAT hooks get never released, resulting in a memleak.

Postpone setting nat_proto_net->nat_hook_ops when the hooks are registered to simplify the error path to decide whether the nat hooks need unwinding.

Fixes 1cd472bf036c ("netfilter: nf_nat: add nat hook register functions to nf_nat")
---
 net/netfilter/nf_nat_core.c | 46 ++++++++++++++++++++++++-------------
 1 file changed, 30 insertions(+), 16 deletions(-)
net/netfilter/nf_nat_core.c +30 -16
index 63ff6b4d5d214..be021d8ecc41a 100644
@@ -1230,31 +1230,45 @@ int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops,
 		}
 
 		ret = nf_register_net_hooks(net, nat_ops, ops_count);
-		if (ret < 0) {
-			mutex_unlock(&nf_nat_proto_mutex);
-			for (i = 0; i < ops_count; i++) {
-				priv = nat_ops[i].priv;
-				kfree_rcu(priv, rcu_head);
-			}
-			kfree_rcu(nat_ops, rcu);
-			return ret;
-		}
-
-		nat_proto_net->nat_hook_ops = nat_ops;
+		if (ret < 0)
+			goto err_free_hooks;
+	} else {
+		nat_ops = nat_proto_net->nat_hook_ops;
 	}
 
-	nat_ops = nat_proto_net->nat_hook_ops;
 	priv = nat_ops[hooknum].priv;
 	if (WARN_ON_ONCE(!priv)) {
-		mutex_unlock(&nf_nat_proto_mutex);
-		return -EOPNOTSUPP;
+		ret = -EOPNOTSUPP;
+		goto err_unregister_hooks;
 	}
 
 	ret = nf_hook_entries_insert_raw(&priv->entries, ops);
-	if (ret == 0)
-		nat_proto_net->users++;
+	if (ret)
+		goto err_unregister_hooks;
+
+	if (!nat_proto_net->nat_hook_ops)
+		nat_proto_net->nat_hook_ops = nat_ops;
+
+	nat_proto_net->users++;
 
 	mutex_unlock(&nf_nat_proto_mutex);
+
+	return 0;
+
+err_unregister_hooks:
+	if (nat_proto_net->nat_hook_ops) {
+		mutex_unlock(&nf_nat_proto_mutex);
+		return ret;
+	}
+	nf_unregister_net_hooks(net, nat_ops, ops_count);
+err_free_hooks:
+	mutex_unlock(&nf_nat_proto_mutex);
+	for (i = 0; i < ops_count; i++) {
+		priv = nat_ops[i].priv;
+		kfree_rcu(priv, rcu_head);
+	}
+	kfree_rcu(nat_ops, rcu);
+
 	return ret;
 }
 
Signature · 1 line
2.53.0
author maintainer
#111 lore raw

PATCH 108/438 netfilter: flowtable: hold reference on ct until flow is released

In reply to Greg Kroah-Hartman

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

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

From: Pablo Neira Ayuso <[email protected]>

[ Upstream commit e75a9fa1d44bcbd66ea02e8781bcca6ea4076e0d ]

nf_ct_put() releases the ct->ext area inmediately, the rcu typesafe semantics also allow to refer to the wrong conntrack from the flowtable datapath. Hold reference on ct until flow is released after rcu grace period.

Add rcu_barrier() on module exit path, to ensure pending flow entries are release before module goes away.

Fixes 0ff90b6c2034 ("netfilter: nf_flow_offload: fix use-after-free and a resource leak")
---
 net/netfilter/nf_flow_table_core.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
net/netfilter/nf_flow_table_core.c +10 -2
index 8b1165f2b5a49..254063fca0780 100644
@@ -258,6 +258,14 @@ static void flow_offload_route_release(struct flow_offload *flow)
 	nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_REPLY);
 }
 
+static void flow_offload_free_rcu(struct rcu_head *rcu_head)
+{
+	struct flow_offload *flow = container_of(rcu_head, struct flow_offload, rcu_head);
+
+	nf_ct_put(flow->ct);
+	kfree(flow);
+}
+
 void flow_offload_free(struct flow_offload *flow)
 {
 	switch (flow->type) {
@@ -267,8 +275,7 @@ void flow_offload_free(struct flow_offload *flow)
 	default:
 		break;
 	}
-	nf_ct_put(flow->ct);
-	kfree_rcu(flow, rcu_head);
+	call_rcu(&flow->rcu_head, flow_offload_free_rcu);
 }
 EXPORT_SYMBOL_GPL(flow_offload_free);
 
@@ -852,6 +859,7 @@ static int __init nf_flow_table_module_init(void)
 
 static void __exit nf_flow_table_module_exit(void)
 {
+	rcu_barrier();
 	nf_flow_table_offload_exit();
 	unregister_pernet_subsys(&nf_flow_table_net_ops);
 	kmem_cache_destroy(flow_offload_cachep);
Signature · 1 line
2.53.0
author maintainer
#112 lore raw

PATCH 109/438 perf/arm-cmn: Fix wp_dev_sel2 setting for multi-DTM configurations

In reply to Greg Kroah-Hartman

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

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

From: Shouping Wang <[email protected]>

[ Upstream commit 49daa3d668b69a5454b5aba0078848a479f79f1c ]

When MXP_MULTIPLE_DTM_EN is TRUE, each DTM will monitor at most two device ports. In this case, {wp_dev_sel2, wp_dev_sel} will only use values 2'b00 and 2'b01 per DTM.

Previously the setting allowed values beyond the supported range per DTM, which could cause each DTM to select invalid ports when MXP_MULTIPLE_DTM_EN is TRUE.

Fix this by only setting CMN_DTM_WPn_CONFIG_WP_DEV_SEL2 when !multi_dtm.

Fixes 60d1504070c2 ("perf/arm-cmn: Support new IP features")
---
 drivers/perf/arm-cmn.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/perf/arm-cmn.c +7 -3
index 6e5cc4086a9e2..7e75903811710 100644
@@ -1393,13 +1393,14 @@ static void arm_cmn_claim_wp_idx(struct arm_cmn_dtm *dtm,
 
 static u32 arm_cmn_wp_config(struct perf_event *event, int wp_idx)
 {
+	struct arm_cmn *cmn = to_cmn(event->pmu);
 	u32 config;
 	u32 dev = CMN_EVENT_WP_DEV_SEL(event);
 	u32 chn = CMN_EVENT_WP_CHN_SEL(event);
 	u32 grp = CMN_EVENT_WP_GRP(event);
 	u32 exc = CMN_EVENT_WP_EXCLUSIVE(event);
 	u32 combine = CMN_EVENT_WP_COMBINE(event);
-	bool is_cmn600 = to_cmn(event->pmu)->part == PART_CMN600;
+	bool is_cmn600 = cmn->part == PART_CMN600;
 
 	/* CMN-600 supports only primary and secondary matching groups */
 	if (is_cmn600)
@@ -1407,8 +1408,11 @@ static u32 arm_cmn_wp_config(struct perf_event *event, int wp_idx)
 
 	config = FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) |
 		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) |
-		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_GRP, grp) |
-		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL2, dev >> 1);
+		 FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_GRP, grp);
+
+	if (!cmn->multi_dtm)
+		config |= FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL2, dev >> 1);
+
 	if (exc)
 		config |= is_cmn600 ? CMN600_WPn_CONFIG_WP_EXCLUSIVE :
 				      CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE;
Signature · 1 line
2.53.0
author maintainer
#113 lore raw

PATCH 110/438 arm64: hibernate: clone only the linear map that exists at runtime

In reply to Greg Kroah-Hartman

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

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

From: Breno Leitao <[email protected]>

[ Upstream commit e4a6f57d22e079e23fafac51057fad534160b269 ]

This is similar to commit 1537e55728ec2 ("arm64: trans_pgd: clone only the linear map that exists at runtime"), but in a different place.

swsusp_arch_resume() clones the kernel linear map with trans_pgd_create_copy(..., PAGE_OFFSET, PAGE_END). PAGE_OFFSET comes from the compile-time VA_BITS, so a CONFIG_ARM64_VA_BITS_52 kernel booting on hardware without LPA2 -- vabits_actual is 48 and the fifth level is folded -- hands the walk a 3.9PB window while its linear map only spans the top 128TB.

On a VA_BITS_52 4k kernel with CONFIG_KASAN_GENERIC in a 4GB VM, I see:

swapper/0: page allocation failure: order:0, mode:0x920(GFP_ATOMIC|__GFP_ZERO)

   hibernate_page_alloc+0x10/0x1c
   swsusp_arch_resume+0x70/0x320
   hibernation_restore+0xa4/0x138
   software_resume+0x15c/0x270
  PM: hibernation: Failed to load image, recovering.
  PM: hibernation: resume failed (-12)

Fix it by copying the linear map that is the actual one, not the compiled one.

Fixes a6bbf5d4d9d1 ("arm64: mm: Add definitions to support 5 levels of paging")
---
 arch/arm64/kernel/hibernate.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/kernel/hibernate.c +2 -2
index 7bf1174277772..424291c547f02 100644
@@ -423,8 +423,8 @@ int __nocfi swsusp_arch_resume(void)
 	 * Create a second copy of just the linear map, and use this when
 	 * restoring.
 	 */
-	rc = trans_pgd_create_copy(&trans_info, &tmp_pg_dir, PAGE_OFFSET,
-				   PAGE_END);
+	rc = trans_pgd_create_copy(&trans_info, &tmp_pg_dir,
+				   _PAGE_OFFSET(vabits_actual), PAGE_END);
 	if (rc)
 		return rc;
 
Signature · 1 line
2.53.0
author maintainer
#114 lore raw

PATCH 111/438 arm64: mte: Fix PTRACE_{PEEK,POKE}MTETAGS error documentation

In reply to Greg Kroah-Hartman

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

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

From: Catalin Marinas <[email protected]>

[ Upstream commit fdb9ebc7fb7788b8371fbef6c17dc5c8291e1429 ]

PTRACE_{PEEK,POKE}MTETAGS return -EIO rather than -EOPNOTSUPP (as documented) when no tags are copied from/to a mapping without PROT_MTE. This has been the behaviour since the interface was introduced, though the original intent was to distinguish between address not being accessible and mapped as untagged.

Update the documentation to match the implementation (de-facto ABI). Since -EOPNOTSUPP was never returned, change the error assignment to -EIO as well to avoid confusion.

Fixes df9d7a22dd21 ("arm64: mte: Add Memory Tagging Extension documentation")
Fixes 18ddbaa02b7a ("arm64: mte: ptrace: Add PTRACE_{PEEK,POKE}MTETAGS support")
Cc Will Deacon <[email protected]>
Cc Mark Rutland <[email protected]>
---
 Documentation/arch/arm64/memory-tagging-extension.rst | 5 ++---
 arch/arm64/kernel/mte.c                               | 2 +-
 2 files changed, 3 insertions(+), 4 deletions(-)
Documentation/arch/arm64/memory-tagging-extension.rst +2 -3
index e6fe428f0e2a4..1d32fc5df1838 100644
@@ -208,11 +208,10 @@ will use the corresponding aligned address.
   tracer's space cannot be accessed or does not have valid tags.
 - ``-EPERM`` - the specified process cannot be traced.
 - ``-EIO`` - the tracee's address range cannot be accessed (e.g. invalid
-  address) and no tags copied. ``iov_len`` not updated.
+  address) or does not have valid tags (not mapped with the ``PROT_MTE``
+  flag) and no tags copied. ``iov_len`` not updated.
 - ``-EFAULT`` - fault on accessing the tracer's memory (``struct iovec``
   or ``iov_base`` buffer) and no tags copied. ``iov_len`` not updated.
-- ``-EOPNOTSUPP`` - the tracee's address does not have valid tags (never
-  mapped with the ``PROT_MTE`` flag). ``iov_len`` not updated.
 
 **Note**: There are no transient errors for the requests above, so user
 programs should not retry in case of a non-zero system call return.
arch/arm64/kernel/mte.c +1 -1
index 1a9aad6ef22a0..31f5c6b0510e7 100644
@@ -476,7 +476,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
 		 * was never mapped with PROT_MTE.
 		 */
 		if (!(vma->vm_flags & VM_MTE)) {
-			err = -EOPNOTSUPP;
+			err = -EIO;
 			put_page(page);
 			break;
 		}
Signature · 1 line
2.53.0
author maintainer
#115 lore raw

PATCH 112/438 drm: Fix drm_pending_vblank_event leak in error path for out_fence_ptr

In reply to Greg Kroah-Hartman

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

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

From: Thadeu Lima de Souza Cascardo <[email protected]>

[ Upstream commit 9eb1a393c89a79c4210230d23e7d88d239c61d7b ]

When an out_fence_ptr is provided but DRM_MODE_PAGE_FLIP_EVENT is not set, a drm_pending_vblank_event will be allocated. If later, there is an allocation failure or another failure at setup_out_fence(), that event will not have base.fence set and it will not be released at complete_signaling().

Release the event and set crtc_state->event to NULL just like in the DRM_MODE_PAGE_FLIP_EVENT case when there is a failure at drm_event_reserve_init(). That is, prepare_signaling() releases the event and there is nothing to be done at complete_signaling(). Use drm_event_cancel_free() as that will also undo drm_event_reserve_init() in case it has been called.

---
 drivers/gpu/drm/drm_atomic_uapi.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_atomic_uapi.c +10 -3
index 7b951af5ab320..66b591b39a513 100644
@@ -1461,10 +1461,12 @@ static int prepare_signaling(struct drm_device *dev,
 			struct dma_fence *fence;
 			struct drm_out_fence_state *f;
 
+			ret = -ENOMEM;
+
 			f = krealloc(*fence_state, sizeof(**fence_state) *
 				     (*num_fences + 1), GFP_KERNEL);
 			if (!f)
-				return -ENOMEM;
+				goto err_free_event;
 
 			memset(&f[*num_fences], 0, sizeof(*f));
 
@@ -1473,12 +1475,12 @@ static int prepare_signaling(struct drm_device *dev,
 
 			fence = drm_crtc_create_fence(crtc);
 			if (!fence)
-				return -ENOMEM;
+				goto err_free_event;
 
 			ret = setup_out_fence(&f[(*num_fences)++], fence);
 			if (ret) {
 				dma_fence_put(fence);
-				return ret;
+				goto err_free_event;
 			}
 
 			crtc_state->event->base.fence = fence;
@@ -1534,6 +1536,11 @@ static int prepare_signaling(struct drm_device *dev,
 	}
 
 	return 0;
+
+err_free_event:
+	drm_event_cancel_free(dev, &crtc_state->event->base);
+	crtc_state->event = NULL;
+	return ret;
 }
 
 static void complete_signaling(struct drm_device *dev,
Signature · 1 line
2.53.0
author maintainer
#116 lore raw

PATCH 113/438 smb: client: validate absolute native symlink targets before NT fixups

In reply to Greg Kroah-Hartman

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

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

From: Jérémy Jean <[email protected]>

[ Upstream commit 23c240d9509e15f72e4112fc95f0160ab32ec430 ]

With symlinkroot unset, an absolute target is copied without conversion to an NT drive path. Later code still assumes an NT prefix is present when modifying the target and calculating the print name length.

For "/ab", this causes two failures: sym[5] and path[5] are written past their allocations, and plen -= 2 * poff subtracts an assumed 8-byte prefix from a 6-byte UTF-16 target, wrapping u16 plen to 65534. That underflow causes another overflow: memcpy() copies 65534 bytes into a 24-byte buffer. A user with write access to a mounted share can trigger these bugs with default settings.

Validate the NT drive prefix, including an ASCII drive letter, before accessing fixed offsets or subtracting the prefix length.

Fixes 3363da82e02f ("smb: client: fix native SMB symlink traversal")
Assisted-by Codex:gpt-5
---
 fs/smb/client/reparse.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)
fs/smb/client/reparse.c +17 -7
index 8a1b9e8be5ba7..9e31fce7e0a52 100644
@@ -3,6 +3,7 @@
  * Copyright (c) 2024 Paulo Alcantara <[email protected]>
  */
 
+#include <linux/ctype.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/slab.h>
@@ -159,15 +160,24 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
 		convert_delimiter(sym, sep);
 
 	/*
-	 * For absolute NT symlinks it is required to pass also leading
-	 * backslash and to not mangle NT object prefix "\\??\\" and not to
-	 * mangle colon in drive letter. But cifs_convert_path_to_utf16()
-	 * removes leading backslash and replaces '?' and ':'. So temporary
-	 * mask these characters in NT object prefix by '_' and then change
-	 * them back.
+	 * Absolute NT symlinks must retain the leading backslash, "\\??\\"
+	 * prefix and drive-letter colon. cifs_convert_path_to_utf16() strips
+	 * the leading backslash and maps '?' and ':', so temporarily mask
+	 * these characters with '_' and restore them after conversion.
+	 *
+	 * When symlinkroot is unset, sym comes directly from the caller.
+	 * Validate the complete "\\??\\X:" prefix before using fixed offsets
+	 * or subtracting the NT prefix length below. Require an ASCII drive
+	 * letter so the prefix occupies six characters in UTF-16 too.
 	 */
-	if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/')
+	if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
+		if (!strstarts(sym, "\\??\\") || !isascii(sym[4]) ||
+		    !isalpha(sym[4]) || sym[5] != ':') {
+			rc = -EINVAL;
+			goto out;
+		}
 		sym[0] = sym[1] = sym[2] = sym[5] = '_';
+	}
 
 	/*
 	 * On a POSIX paths mount the symlink target is stored verbatim, so
Signature · 1 line
2.53.0
author maintainer
#117 lore raw

PATCH 114/438 keys: fix lost wakeup when reaping a dead key type

In reply to Greg Kroah-Hartman

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

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

From: Karl Mehltretter <[email protected]>

[ Upstream commit 2725ab3f5ad1c5f375c7c9fee4af02a9b138f701 ]

clear_bit() is atomic with respect to the word it modifies, but it is an unordered operation: it implies no memory barrier on either side (Documentation/atomic_bitops.txt).

key_garbage_collector() clears KEY_GC_REAPING_KEYTYPE with clear_bit() and calls wake_up_bit() after reaping a dead key type. wake_up_bit() uses a lockless waitqueue check and requires a full barrier after the clear.

The existing smp_mb() is before clear_bit(), so nothing orders the clear against that check. The GC can see an empty waitqueue while unregister_key_type() still sees the bit set. The final wakeup is then lost, leaving module unload stuck in wait_on_bit().

Use clear_and_wake_up_bit(). Its clear_bit_unlock() has RELEASE semantics, so the completed GC work stays ordered before the clear, and its smp_mb__after_atomic() orders the clear before the waitqueue check.

Fixes 0c061b5707ab ("KEYS: Correctly destroy key payloads when their keytype is removed")
Assisted-by Claude:claude-fable-5
---
 security/keys/gc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
security/keys/gc.c +1 -3
index 748e83818a760..eda445f815d47 100644
@@ -318,9 +318,7 @@ static void key_garbage_collector(struct work_struct *work)
 
 	if (unlikely(gc_state & KEY_GC_REAPING_DEAD_3)) {
 		kdebug("dead wake");
-		smp_mb();
-		clear_bit(KEY_GC_REAPING_KEYTYPE, &key_gc_flags);
-		wake_up_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE);
+		clear_and_wake_up_bit(KEY_GC_REAPING_KEYTYPE, &key_gc_flags);
 	}
 
 	if (gc_state & KEY_GC_REAP_AGAIN)
Signature · 1 line
2.53.0
author maintainer
#118 lore raw

PATCH 115/438 neighbour: Add missing RCU annotation for neightbl_dump_info().

In reply to Greg Kroah-Hartman

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

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

From: Kuniyuki Iwashima <[email protected]>

[ Upstream commit 764dcebb033764633700a036c7351a7c6350eec6 ]

neightbl_dump_info() fetches the first non-default neigh_parms with list_next_entry(&tbl->parms, ...) and iterates through the list with list_for_each_entry_from_rcu().

However, list_next_entry() does not use RCU helper.

Let's use list_for_each_entry_rcu() and skip the default parms.

---
 net/core/neighbour.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
net/core/neighbour.c +5 -2
index 1349c0eedb642..49dd7df149ef3 100644
@@ -2611,11 +2611,14 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 			break;
 
 		nidx = 0;
-		p = list_next_entry(&tbl->parms, list);
-		list_for_each_entry_from_rcu(p, &tbl->parms_list, list) {
+
+		list_for_each_entry_rcu(p, &tbl->parms_list, list) {
 			if (!net_eq(neigh_parms_net(p), net))
 				continue;
 
+			if (!p->dev)
+				continue;
+
 			if (nidx < neigh_skip)
 				goto next;
 
Signature · 1 line
2.53.0
author maintainer
#119 lore raw

PATCH 116/438 neighbour: Enforce min/max to NDTPA_INTERVAL_PROBE_TIME_MS.

In reply to Greg Kroah-Hartman

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

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

From: Kuniyuki Iwashima <[email protected]>

[ Upstream commit 6d79b223ec44ada58ad37db42f539b60985a7722 ]

NDTPA_INTERVAL_PROBE_TIME_MS sets .type and .min but misses .validation_type, so no validation is applied:

  # ynl --family rt-neigh --do setneightbl \
  --json '{"name": "arp_cache", "parms": {"interval-probe-time-ms": 0}}'
  # ynl --family rt-neigh --dump getneightbl --output-json | \
  jq '.[] | select(.name == "arp_cache" and has("config"))
          | .parms["interval-probe-time-ms"]'
  0

Moreover, nla_get_msecs() uses msecs_to_jiffies(), and u64 is silently cast to u32, so a larger value can bypass the min check:

e.g. 4294967296 == 0x100000000

  # ynl --family rt-neigh --do setneightbl \
  --json '{"name": "arp_cache", "parms": {"interval-probe-time-ms": 4294967296}}'
  # ynl --family rt-neigh --dump getneightbl --output-json | \
  jq '.[] | select(.name == "arp_cache" and has("config"))
          | .parms["interval-probe-time-ms"]'
  0

msecs_to_jiffies() returns MAX_JIFFY_OFFSET if the value is larger than INT_MAX. Also, INT_MAX ms overflows int NEIGH_VAR() when HZ > 1000 (Alpha, MIPS), and passing a negative integer to queue_delayed_work(unsigned long delay) causes sign extension, which wraps around the expiry time to the past, resulting in it being handled as 0 delay in the timer wheel.

Let's use NLA_POLICY_FULL_RANGE() and limit the max to 1 day.

The same max check is applied to sysctl as well.

Note that this controls the probe interval for NTF_MANAGED entries, so the max of 1 day is unlikely to break any deployments.

Fixes 211da42eaa45 ("net, neigh: introduce interval_probe_time_ms for periodic probe")
---
 Documentation/netlink/specs/rt-neigh.yaml |  3 +++
 Documentation/networking/ip-sysctl.rst    |  2 +-
 net/core/neighbour.c                      | 17 +++++++++++++----
 3 files changed, 17 insertions(+), 5 deletions(-)
Documentation/netlink/specs/rt-neigh.yaml +3 -0
index 0f46ef3135905..c8e55c98d5649 100644
@@ -341,6 +341,9 @@ attribute-sets:
       -
         name: interval-probe-time-ms
         type: u64
+        checks:
+          min: 1
+          max: 86400000
 
 operations:
   enum-model: directional
Documentation/networking/ip-sysctl.rst +1 -1
index 208f46967ee59..b05829e44d8fc 100644
@@ -248,7 +248,7 @@ neigh/default/unres_qlen - INTEGER
 
 neigh/default/interval_probe_time_ms - INTEGER
 	The probe interval for neighbor entries with NTF_MANAGED flag,
-	the min value is 1.
+	the min value is 1, and the max value is 86400000 (1 day).
 
 	Default: 5000
 
net/core/neighbour.c +13 -4
index 49dd7df149ef3..0db78a0dfb516 100644
@@ -2359,6 +2359,13 @@ static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
 	[NDTA_PARMS]		= { .type = NLA_NESTED },
 };
 
+#define NTBL_PARM_MS_MAX	(24 * 60 * 60 * MSEC_PER_SEC)
+
+static const struct netlink_range_validation nl_ntbl_parm_ms_range = {
+	.min = 1,
+	.max = NTBL_PARM_MS_MAX,
+};
+
 static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
 	[NDTPA_IFINDEX]			= { .type = NLA_U32 },
 	[NDTPA_QUEUE_LEN]		= { .type = NLA_U32 },
@@ -2375,7 +2382,8 @@ static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
 	[NDTPA_ANYCAST_DELAY]		= { .type = NLA_U64 },
 	[NDTPA_PROXY_DELAY]		= { .type = NLA_U64 },
 	[NDTPA_LOCKTIME]		= { .type = NLA_U64 },
-	[NDTPA_INTERVAL_PROBE_TIME_MS]	= { .type = NLA_U64, .min = 1 },
+	[NDTPA_INTERVAL_PROBE_TIME_MS]	= NLA_POLICY_FULL_RANGE(NLA_U64,
+								&nl_ntbl_parm_ms_range),
 };
 
 static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -3672,12 +3680,13 @@ static int neigh_proc_dointvec_ms_jiffies_positive(const struct ctl_table *ctl,
 						   void *buffer, size_t *lenp, loff_t *ppos)
 {
 	struct ctl_table tmp = *ctl;
-	int ret;
+	int ret, min, max;
 
-	int min = msecs_to_jiffies(1);
+	min = msecs_to_jiffies(1);
+	max = msecs_to_jiffies(NTBL_PARM_MS_MAX);
 
 	tmp.extra1 = &min;
-	tmp.extra2 = NULL;
+	tmp.extra2 = &max;
 
 	ret = proc_dointvec_ms_jiffies_minmax(&tmp, write, buffer, lenp, ppos);
 	neigh_proc_update(ctl, write);
Signature · 1 line
2.53.0
author maintainer
#120 lore raw

PATCH 117/438 neighbour: Dont render blackhole_netdev via RTM_GETNEIGHTBL.

In reply to Greg Kroah-Hartman

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

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

From: Kuniyuki Iwashima <[email protected]>

[ Upstream commit 7b430fcfc972f61b09cc19ca95997586af4a147d ]

The cited commits started to initialise blackhole_netdev with neigh_parms_alloc().

This is visible in init_net as the ifindex==0 entries via RTM_GETNEIGHTBL:

  # ynl --family rt-neigh --dump getneightbl --output-json \
    | jq '.[] | select(.parms.ifindex == 0)
              | {name: .name, ifindex: .parms.ifindex}'
  {
    "name": "arp_cache",
    "ifindex": 0
  }
  {
    "name": "ndisc_cache",
    "ifindex": 0
  }

For RTM_SETNEIGHTBL, ifindex being 0 means wildcard.

Let's skip blackhole_netdev's parms in neightbl_dump_info().

Note that lookup_neigh_parms() does not need the same change because the default parms is always the first entry and matches with ifindex == 0.

Fixes e5f80fcf869a ("ipv6: give an IPv6 dev to blackhole_netdev")
Fixes 22600596b675 ("ipv4: give an IPv4 dev to blackhole_netdev")
---
 net/core/neighbour.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/neighbour.c +1 -1
index 0db78a0dfb516..02bf940ce00af 100644
@@ -2624,7 +2624,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 			if (!net_eq(neigh_parms_net(p), net))
 				continue;
 
-			if (!p->dev)
+			if (!p->dev || p->dev == blackhole_netdev)
 				continue;
 
 			if (nidx < neigh_skip)
Signature · 1 line
2.53.0
author maintainer
#121 lore raw

PATCH 118/438 neighbour: Skip default parms when resumed in neightbl_dump_info().

In reply to Greg Kroah-Hartman

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

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

From: Kuniyuki Iwashima <[email protected]>

[ Upstream commit 979aabdad8dd03394467ee484a1a70f3d40b19ba ]

neightbl_dump_info() calls neightbl_fill_info() in each loop to render the default parms.

If there are many devices and neightbl_fill_param_info() failed, neightbl_fill_info() is called again when the dump resumes:

  # ynl --family rt-neigh --dump getneightbl --output-json |
    jq '.[] | {name: .name, ifindex: .parms.ifindex}'
  ...
  {
    "name": "ndisc_cache",
    "ifindex": null
  }
  ...
  {
    "name": "ndisc_cache",
    "ifindex": 6
  }
  {
    "name": "ndisc_cache",
    "ifindex": null
  }
  {
    "name": "ndisc_cache",
    "ifindex": 5
  }

Let's skip neightbl_fill_info() if it is already called in neightbl_dump_info().

Note that we cannot use !neigh_skip instead of !default_skip because default_skip == 1 && neigh_skip == 0 could be true if the first neightbl_fill_param_info() fails.

Also, nidx must be cleared at the end of each table loop; otherwise, if neightbl_fill_info() for a subsequent table fails, the leftover nidx from the previous table would be saved in cb->args[1], resulting in erroneously skipping parms of the subsequent table in the next dump.

Fixes c7fb64db001f ("[NETLINK]: Neighbour table configuration and statistics via rtnetlink")
---
 net/core/neighbour.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
net/core/neighbour.c +8 -3
index 02bf940ce00af..7448320f7ad52 100644
@@ -2587,9 +2587,10 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	const struct nlmsghdr *nlh = cb->nlh;
 	struct net *net = sock_net(skb->sk);
+	int default_skip = cb->args[2];
+	int neigh_skip = cb->args[1];
 	int family, tidx, nidx = 0;
 	int tbl_skip = cb->args[0];
-	int neigh_skip = cb->args[1];
 	struct neigh_table *tbl;
 
 	if (cb->strict_check) {
@@ -2613,12 +2614,13 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 		if (tidx < tbl_skip || (family && tbl->family != family))
 			continue;
 
-		if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
+		if (!default_skip &&
+		    neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
 				       nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
 				       NLM_F_MULTI) < 0)
 			break;
 
-		nidx = 0;
+		default_skip = 1;
 
 		list_for_each_entry_rcu(p, &tbl->parms_list, list) {
 			if (!net_eq(neigh_parms_net(p), net))
@@ -2641,12 +2643,15 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 		}
 
 		neigh_skip = 0;
+		nidx = 0;
+		default_skip = 0;
 	}
 out:
 	rcu_read_unlock();
 
 	cb->args[0] = tidx;
 	cb->args[1] = nidx;
+	cb->args[2] = default_skip;
 
 	return skb->len;
 }
Signature · 1 line
2.53.0
author maintainer
#122 lore raw

PATCH 119/438 ALSA: bcd2000: Fix race between rawmidi and disconnect

In reply to Greg Kroah-Hartman

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

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

From: Takashi Iwai <[email protected]>

[ Upstream commit 221253723dc58bb901c3f27a7659823e63fc598c ]

Although we tried to fix the potential UAF issues at USB disconnect on bcd2000 driver, there is still an overlooked case -- namely, when a rawmidi trigger callback has been already running at USB disconnect handling, the in-flight function (e.g. bcd2000_midi_send()) could still access the URB, because the previous URB NULL-check & clearance was considered only for the URB complete callbacks, but not about the parallel rawmidi operations.

For addressing the race, this patch introduced a new spinlock that covers each rawmidi operation as well as the rawmidi handling in the complete callback. The URB is cleared with the lock, so it guarantees that the pending rawmidi task already finished or a NULL check is effective.

Fixes 459d3a64766f ("ALSA: bcd2000: clear the URB pointers on disconnect")
---
 sound/usb/bcd2000/bcd2000.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)
sound/usb/bcd2000/bcd2000.c +26 -7
index c5c542d17ccc1..2bd49bf827489 100644
@@ -43,6 +43,7 @@ struct bcd2000 {
 	struct usb_interface *intf;
 	int card_index;
 
+	spinlock_t midi_lock;
 	int midi_out_active;
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi_substream *midi_receive_substream;
@@ -90,6 +91,8 @@ static void bcd2000_midi_input_trigger(struct snd_rawmidi_substream *substream,
 						int up)
 {
 	struct bcd2000 *bcd2k = substream->rmidi->private_data;
+
+	guard(spinlock_irqsave)(&bcd2k->midi_lock);
 	bcd2k->midi_receive_substream = up ? substream : NULL;
 }
 
@@ -195,6 +198,8 @@ static void bcd2000_midi_output_trigger(struct snd_rawmidi_substream *substream,
 {
 	struct bcd2000 *bcd2k = substream->rmidi->private_data;
 
+	guard(spinlock_irqsave)(&bcd2k->midi_lock);
+
 	if (up) {
 		bcd2k->midi_out_substream = substream;
 		/* check if there is data userspace wants to send */
@@ -219,6 +224,7 @@ static void bcd2000_output_complete(struct urb *urb)
 		return;
 
 	/* check if there is more data userspace wants to send */
+	guard(spinlock_irqsave)(&bcd2k->midi_lock);
 	bcd2000_midi_send(bcd2k);
 }
 
@@ -234,6 +240,8 @@ static void bcd2000_input_complete(struct urb *urb)
 	if (!bcd2k || urb->status == -ESHUTDOWN)
 		return;
 
+	guard(spinlock_irqsave)(&bcd2k->midi_lock);
+
 	if (urb->actual_length > 0)
 		bcd2000_midi_handle_input(bcd2k, urb->transfer_buffer,
 					urb->actual_length);
@@ -348,16 +356,26 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k)
 	return 0;
 }
 
+static void bcd2000_midi_free(struct bcd2000 *bcd2k,
+			      struct urb **urb_p)
+{
+	struct urb *urb = *urb_p;
+
+	if (!urb)
+		return;
+
+	usb_poison_urb(urb);
+	scoped_guard(spinlock_irq, &bcd2k->midi_lock)
+		*urb_p = NULL;
+
+	usb_free_urb(urb);
+}
+
 static void bcd2000_free_usb_related_resources(struct bcd2000 *bcd2k,
 						struct usb_interface *interface)
 {
-	usb_poison_urb(bcd2k->midi_out_urb);
-	usb_poison_urb(bcd2k->midi_in_urb);
-
-	usb_free_urb(bcd2k->midi_out_urb);
-	usb_free_urb(bcd2k->midi_in_urb);
-	bcd2k->midi_out_urb = NULL;
-	bcd2k->midi_in_urb = NULL;
+	bcd2000_midi_free(bcd2k, &bcd2k->midi_out_urb);
+	bcd2000_midi_free(bcd2k, &bcd2k->midi_in_urb);
 
 	if (bcd2k->intf) {
 		usb_set_intfdata(bcd2k->intf, NULL);
@@ -393,6 +411,7 @@ static int bcd2000_probe(struct usb_interface *interface,
 	bcd2k->card = card;
 	bcd2k->card_index = card_index;
 	bcd2k->intf = interface;
+	spin_lock_init(&bcd2k->midi_lock);
 
 	snd_card_set_dev(card, &interface->dev);
 
Signature · 1 line
2.53.0
author maintainer
#123 lore raw

PATCH 120/438 ntfs: use dynamic MFT tail reservation

In reply to Greg Kroah-Hartman

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

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

From: Namjae Jeon <[email protected]>

[ Upstream commit 6d8c197c9992659a65525a07de4368c8401fdda7 ]

The ntfs MFT allocator historically treated records below 64 as a permanent extension area and stopped searching for $MFT extent records after record 400. Windows and ntfs3 do not maintain that on-disk layout, so an NTFS volume can have free MFT records while ntfs returns -ENOSPC when $MFT:$DATA needs another mapping-pairs extent.

Use record 24 as the first normal record and maintain an in-memory tail reserve of up to four initialized records. Normal allocations skip the reserve, while $MFT metadata extent allocations consume it. When a new tail is initialized, allocate at least two records and reserve the following records to avoid recursive allocation during MFT extension. Existing free runs can seed the reserve on volumes mounted without one.

For $MFT/$DATA, constrain an extent record to a record whose byte offset is below the new extent lowest VCN byte offset. This preserves bootstrap reachability without an arbitrary record 400 limit. If no safe record is available, validate and use reserved records 15, 12, 13, and 14 as bootstrap candidates while keeping their MFT bitmap entries in use.

This allows existing Windows volumes to extend $MFT using their actual free records and prevents normal file allocation from consuming the metadata reserve.

Fixes 115380f9a2f9 ("ntfs: update mft operations")
---
 fs/ntfs/attrib.c |  11 +-
 fs/ntfs/mft.c    | 420 +++++++++++++++++++++++++++++++++++++----------
 fs/ntfs/mft.h    |   2 +-
 fs/ntfs/namei.c  |   2 +-
 fs/ntfs/volume.h |   6 +
 5 files changed, 349 insertions(+), 92 deletions(-)
fs/ntfs/attrib.c +7 -4
index 918ff4db75f73..f50685ec2fb34 100644
@@ -2912,7 +2912,7 @@ int ntfs_attr_add(struct ntfs_inode *ni, __le32 type,
 
 	attr_ni = NULL;
 	/* Allocate new extent. */
-	err = ntfs_mft_record_alloc(ni->vol, 0, &attr_ni, ni, NULL);
+	err = ntfs_mft_record_alloc(ni->vol, 0, &attr_ni, ni, NULL, -1);
 	if (err) {
 		ntfs_error(sb, "Failed to allocate extent record");
 		goto err_out;
@@ -3545,7 +3545,7 @@ int ntfs_attr_record_move_away(struct ntfs_attr_search_ctx *ctx, int extra)
 	 * new extent and move attribute to it.
 	 */
 	ni = NULL;
-	err = ntfs_mft_record_alloc(base_ni->vol, 0, &ni, base_ni, NULL);
+	err = ntfs_mft_record_alloc(base_ni->vol, 0, &ni, base_ni, NULL, -1);
 	if (err) {
 		ntfs_error(sb, "Couldn't allocate MFT record, err : %d", err);
 		return err;
@@ -3971,7 +3971,10 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
 		unsigned int de_cnt = 0;
 
 		/* Allocate new mft record. */
-		err = ntfs_mft_record_alloc(ni->vol, 0, &ext_ni, base_ni, NULL);
+		err = ntfs_mft_record_alloc(ni->vol, 0, &ext_ni, base_ni, NULL,
+					    base_ni->mft_no == FILE_MFT &&
+					    ni->type == AT_DATA &&
+					    ni->name == AT_UNNAMED ? stop_vcn : -1);
 		if (err) {
 			ntfs_error(sb, "Failed to allocate extent record");
 			goto put_err_out;
@@ -4831,7 +4834,7 @@ static int ntfs_resident_attr_resize(struct ntfs_inode *attr_ni, const s64 newsi
 	}
 
 	/* Allocate new mft record. */
-	err = ntfs_mft_record_alloc(base_ni->vol, 0, &ext_ni, base_ni, NULL);
+	err = ntfs_mft_record_alloc(base_ni->vol, 0, &ext_ni, base_ni, NULL, -1);
 	if (err) {
 		ntfs_error(sb, "Couldn't allocate MFT record");
 		goto put_err_out;
fs/ntfs/mft.c +334 -86

631 lines not on this page · raw message

fs/ntfs/mft.h +1 -1
index 75a51a98d0f6e..ed5c1d595c0d3 100644
@@ -78,7 +78,7 @@ static inline int write_mft_record(struct ntfs_inode *ni, struct mft_record *m,
 
 int ntfs_mft_record_alloc(struct ntfs_volume *vol, const int mode,
 		struct ntfs_inode **ni, struct ntfs_inode *base_ni,
-		struct mft_record **ni_mrec);
+		struct mft_record **ni_mrec, const s64 mft_data_vcn);
 int ntfs_mft_record_free(struct ntfs_volume *vol, struct ntfs_inode *ni);
 int ntfs_mft_records_write(const struct ntfs_volume *vol, const u64 mref,
 		const s64 count, struct mft_record *b);
fs/ntfs/namei.c +1 -1
index 96045face63f9..dfd05e604f9c1 100644
@@ -480,7 +480,7 @@ static struct ntfs_inode *__ntfs_create(struct mnt_idmap *idmap, struct inode *d
 	mark_inode_dirty(dir);
 
 	err = ntfs_mft_record_alloc(dir_ni->vol, mode, &ni, NULL,
-				    &ni_mrec);
+			&ni_mrec, -1);
 	if (err) {
 		iput(vi);
 		return ERR_PTR(err);
fs/ntfs/volume.h +6 -0
index 65fd3908af261..2b60d14fc7ef5 100644
@@ -55,6 +55,10 @@
  * @attrdef_size: Size of the attribute definition table in bytes.
  * @attrdef: Table of attribute definitions. Obtained from FILE_AttrDef.
  * @mft_data_pos: Mft record number at which to allocate the next mft record.
+ * @mft_record_reserve_pos: First record in the in-memory MFT metadata reserve
+ *                         (protected by mftbmp_lock).
+ * @mft_record_reserve_end: First record beyond the MFT metadata reserve
+ *                         (protected by mftbmp_lock).
  * @mft_zone_start: First cluster of the mft zone.
  * @mft_zone_end: First cluster beyond the mft zone.
  * @mft_zone_pos: Current position in the mft zone.
@@ -119,6 +123,8 @@ struct ntfs_volume {
 	s32 attrdef_size;
 	struct attr_def *attrdef;
 	s64 mft_data_pos;
+	s64 mft_record_reserve_pos;
+	s64 mft_record_reserve_end;
 	s64 mft_zone_start;
 	s64 mft_zone_end;
 	s64 mft_zone_pos;
Signature · 1 line
2.53.0
author maintainer
#124 lore raw

PATCH 121/438 ntfs: repack $MFT/$ATTRIBUTE LIST

In reply to Greg Kroah-Hartman

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

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

From: Namjae Jeon <[email protected]>

[ Upstream commit b1d732e62a5b3942546e4edaab8976258e779287 ]

Repack the non-resident $MFT/$ATTRIBUTE_LIST into a contiguous run when its mapping pairs no longer fit in the base MFT record. Propagate allocation and writeback errors, and check synchronous replacement writes.

Fixes 495e90fa3348 ("ntfs: update attrib operations")
---
 fs/ntfs/attrib.c   |  47 ++++++++---
 fs/ntfs/attrlist.c | 202 ++++++++++++++++++++++++++++++++++++++++++---
 fs/ntfs/inode.c    |  10 ++-
 3 files changed, 236 insertions(+), 23 deletions(-)
fs/ntfs/attrib.c +37 -10
index f50685ec2fb34..34c4044b59af2 100644
@@ -3839,13 +3839,13 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
 			 */
 			if (ni->type == AT_ATTRIBUTE_LIST) {
 				ntfs_attr_put_search_ctx(ctx);
-				if (ntfs_inode_free_space(base_ni, mp_size -
-							cur_max_mp_size)) {
-					ntfs_debug("Attribute list is too big. Defragment the volume\n");
-					return -ENOSPC;
-				}
-				if (ntfs_attrlist_update(base_ni))
-					return -EIO;
+				err = ntfs_inode_free_space(base_ni, mp_size -
+							cur_max_mp_size);
+				if (err)
+					return err;
+				err = ntfs_attrlist_update(base_ni);
+				if (err)
+					return err;
 				goto retry;
 			}
 
@@ -4517,13 +4517,39 @@ static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsiz
 					ntfs_bytes_to_cluster(vol, ni->allocated_size),
 					first_free_vcn -
 					ntfs_bytes_to_cluster(vol, ni->allocated_size),
-					lcn_seek_from, DATA_ZONE, false, false, false);
+					lcn_seek_from, DATA_ZONE, false,
+					ni->type == AT_ATTRIBUTE_LIST, false);
 			if (IS_ERR(rl)) {
 				ntfs_debug("Cluster allocation failed (%lld)",
 						(long long)first_free_vcn -
 						ntfs_bytes_to_cluster(vol, ni->allocated_size));
 				return PTR_ERR(rl);
 			}
+			/*
+			 * A contiguous ATTRIBUTE_LIST allocation keeps its mapping
+			 * pairs small enough to fit in the base MFT record. The
+			 * allocator can return a short run when contiguity was
+			 * requested, so discard it and retry normally if necessary.
+			 */
+			if (ni->type == AT_ATTRIBUTE_LIST &&
+				(rl->vcn != ntfs_bytes_to_cluster(vol,
+						ni->allocated_size) ||
+				 rl->length != first_free_vcn -
+					ntfs_bytes_to_cluster(vol, ni->allocated_size) ||
+				 rl[1].length)) {
+				ntfs_cluster_free_from_rl(vol, rl);
+				kvfree(rl);
+				rl = ntfs_cluster_alloc(vol,
+						ntfs_bytes_to_cluster(vol,
+								ni->allocated_size),
+						first_free_vcn -
+						ntfs_bytes_to_cluster(vol,
+								ni->allocated_size),
+						lcn_seek_from, DATA_ZONE, false,
+						false, false);
+				if (IS_ERR(rl))
+					return PTR_ERR(rl);
+			}
 		}
 
 		if (!NInoCompressed(ni)) {
@@ -4916,7 +4942,8 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 preallo
 	ntfs_debug("Entering for inode 0x%llx, attr 0x%x, size %lld\n",
 			(unsigned long long)ni->mft_no, ni->type, newsize);
 
-	if (ni->data_size == newsize) {
+	if (ni->data_size == newsize &&
+		(!prealloc_size || prealloc_size <= ni->allocated_size)) {
 		ntfs_debug("Size is already ok\n");
 		return 0;
 	}
@@ -4931,7 +4958,7 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 preallo
 	}
 
 	if (NInoNonResident(ni)) {
-		if (newsize > ni->data_size)
+		if (newsize > ni->data_size || prealloc_size > ni->allocated_size)
 			err = ntfs_non_resident_attr_expand(ni, newsize, prealloc_size,
 							    NVolDisableSparse(ni->vol) ?
 							    HOLES_NO : HOLES_OK, true);
fs/ntfs/attrlist.c +190 -12

242 lines not on this page · raw message

fs/ntfs/inode.c +9 -1
index f40f35afcda9a..cc5818d50e3e8 100644
@@ -3745,6 +3745,7 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,
 			u64 rl_length = 0;
 			s64 vcn;
 			struct runlist_element *rl;
+			int bio_err;
 
 			lcn_count = max_t(s64, 1, ntfs_bytes_to_cluster(vol, attr_len));
 			vcn = ntfs_pidx_to_cluster(vol, folio->index);
@@ -3788,8 +3789,15 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,
 					goto err_unlock_folio;
 				}
 
-				submit_bio_wait(bio);
+				bio_err = submit_bio_wait(bio);
 				bio_put(bio);
+				if (bio_err) {
+					ntfs_error(vi->i_sb,
+						   "Synchronous attribute write failed (%d)",
+						   bio_err);
+					ret = bio_err;
+					goto err_unlock_folio;
+				}
 				vcn += rl_length;
 				offset += length;
 			} while (lcn_count != 0);
Signature · 1 line
2.53.0
author maintainer
#125 lore raw

PATCH 122/438 ntfs: account for MFT records added during allocation

In reply to Greg Kroah-Hartman

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

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

From: Namjae Jeon <[email protected]>

[ Upstream commit 631946431ddc66a472c5cc629cd654e62dfa1f88 ]

When no free MFT record is available in the initialized $MFT/$BITMAP, ntfs_mft_record_alloc() extends $MFT/$DATA and formats the requested record together with a dynamically sized tail reserve. Those records become visible through the $MFT file size before charging the requested record to the free-record counter.

Account for all newly visible records before releasing the MFT allocation lock, then subtract the one record being allocated. Keep MFT counter updates independent of the asynchronous free-cluster scan and update the counter when a record is successfully cleared in the MFT bitmap.

Store the clamped result of the MFT bitmap scan and keep statfs from exposing an invalid cached count if an accounting error occurs.

Fixes 115380f9a2f9 ("ntfs: update mft operations")
---
 fs/ntfs/mft.c    | 11 ++++++++---
 fs/ntfs/super.c  | 12 +++++++++---
 fs/ntfs/volume.h |  6 ------
 3 files changed, 17 insertions(+), 12 deletions(-)
fs/ntfs/mft.c +8 -3
index 5fae9ad03858e..ed3aa4c423e81 100644
@@ -1539,7 +1539,6 @@ static int ntfs_mft_bitmap_extend_initialized_nolock(struct ntfs_volume *vol)
 	ret = ntfs_attr_set(mftbmp_ni, old_initialized_size, 8, 0);
 	if (likely(!ret)) {
 		ntfs_debug("Done.  (Wrote eight initialized bytes to mft bitmap.");
-		ntfs_inc_free_mft_records(vol, 8 * 8);
 		return 0;
 	}
 	ntfs_error(vol->sb, "Failed to write to mft bitmap.");
@@ -2135,6 +2134,7 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, const int mode,
 			  struct mft_record **ni_mrec, const s64 mft_data_vcn)
 {
 	s64 ll, bit, old_data_initialized, old_data_size;
+	s64 nr_new_mft_records = 0;
 	s64 max_mft_no = -1, reserve_start = -1, reserve_end = -1;
 	s64 candidate_reserve_end = -1;
 	s64 *reserve_endp;
@@ -2501,8 +2501,13 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, const int mode,
 			mft_ni->initialized_size);
 	WARN_ON(i_size_read(vol->mft_ino) > mft_ni->allocated_size);
 	WARN_ON(mft_ni->initialized_size > i_size_read(vol->mft_ino));
+	nr_new_mft_records = (i_size_read(vol->mft_ino) - old_data_size) >>
+			     vol->mft_record_size_bits;
 	read_unlock_irqrestore(&mft_ni->size_lock, flags);
 mft_rec_already_initialized:
+	/* Account for newly visible MFT records before dropping the lock. */
+	if (nr_new_mft_records > 0)
+		ntfs_inc_free_mft_records(vol, nr_new_mft_records);
 	/*
 	 * We can finally drop the mft bitmap lock as the mft data attribute
 	 * has been fully updated.  The only disparity left is that the
@@ -2814,6 +2819,8 @@ int ntfs_mft_record_free(struct ntfs_volume *vol, struct ntfs_inode *ni)
 	if (base_ni->mft_no != FILE_MFT)
 		down_write(&vol->mftbmp_lock);
 	err = ntfs_bitmap_clear_bit(vol->mftbmp_ino, mft_no);
+	if (!err)
+		ntfs_inc_free_mft_records(vol, 1);
 	if (!err && base_ni->mft_no == FILE_MFT &&
 	    mft_no + 1 == vol->mft_record_reserve_pos &&
 	    mft_no < vol->mft_record_reserve_end)
@@ -2823,9 +2830,7 @@ int ntfs_mft_record_free(struct ntfs_volume *vol, struct ntfs_inode *ni)
 	memalloc_nofs_restore(memalloc_flags);
 	if (err)
 		goto bitmap_rollback;
-
 	unmap_mft_record(ni);
-	ntfs_inc_free_mft_records(vol, 1);
 	return 0;
 
 	/* Rollback what we did... */
fs/ntfs/super.c +9 -3
index 63aa83ff77f5d..b5371d269f747 100644
@@ -2064,8 +2064,7 @@ static unsigned long __get_nr_free_mft_records(struct ntfs_volume *vol,
 	/* If errors occurred we may well have gone below zero, fix this. */
 	if (nr_free < 0)
 		nr_free = 0;
-	else
-		atomic64_set(&vol->free_mft_records, nr_free);
+	atomic64_set(&vol->free_mft_records, nr_free);
 
 	ntfs_debug("Exiting.");
 	return nr_free;
@@ -2131,7 +2130,14 @@ static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs)
 	read_unlock_irqrestore(&mft_ni->size_lock, flags);
 
 	/* Free inodes in fs (based on current total count). */
-	sfs->f_ffree = atomic64_read(&vol->free_mft_records);
+	size = atomic64_read(&vol->free_mft_records);
+	if (unlikely(size < 0 || size > (s64)sfs->f_files))
+		ntfs_warning(vol->sb, "Invalid free MFT record count %lld.", size);
+	if (size < 0)
+		size = 0;
+	else if (size > (s64)sfs->f_files)
+		size = sfs->f_files;
+	sfs->f_ffree = size;
 
 	/*
 	 * File system id. This is extremely *nix flavour dependent and even
fs/ntfs/volume.h +0 -6
index 2b60d14fc7ef5..bc85a95922458 100644
@@ -258,17 +258,11 @@ static inline void ntfs_dec_free_clusters(struct ntfs_volume *vol, s64 nr)
 
 static inline void ntfs_inc_free_mft_records(struct ntfs_volume *vol, s64 nr)
 {
-	if (!NVolFreeClusterKnown(vol))
-		return;
-
 	atomic64_add(nr, &vol->free_mft_records);
 }
 
 static inline void ntfs_dec_free_mft_records(struct ntfs_volume *vol, s64 nr)
 {
-	if (!NVolFreeClusterKnown(vol))
-		return;
-
 	atomic64_sub(nr, &vol->free_mft_records);
 }
 
Signature · 1 line
2.53.0
author maintainer
#126 lore raw

PATCH 123/438 ntfs: protect runlist updates with the runlist lock

In reply to Greg Kroah-Hartman

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

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

From: Namjae Jeon <[email protected]>

[ Upstream commit 91709ba5d6d709b2b663287b7e871e2c6b480502 ]

ntfs_non_resident_attr_shrink() calls runlist helpers that require the runlist write lock, but did not hold it while freeing clusters and truncating the runlist. Serialize those operations and the resident conversion with the runlist lock.

ntfs_attr_map_cluster() can merge a newly allocated run before updating mapping pairs. If the update fails, free the clusters and restore both the in-memory runlist and on-disk mapping pairs from a saved runlist. Mark the volume in error if either rollback step fails.

Fixes 495e90fa3348 ("ntfs: update attrib operations")
---
 fs/ntfs/attrib.c   | 205 +++++++++++++++++++++++++++++++++++----------
 fs/ntfs/attrib.h   |   9 ++
 fs/ntfs/attrlist.c |  46 ++++++----
 fs/ntfs/attrlist.h |   2 +
 fs/ntfs/compress.c |   2 +-
 fs/ntfs/file.c     |   3 +-
 fs/ntfs/inode.c    |   2 +-
 fs/ntfs/mft.c      |  13 +--
 8 files changed, 216 insertions(+), 66 deletions(-)
fs/ntfs/attrib.c +161 -44
index 34c4044b59af2..b10ef76c98f33 100644
@@ -3569,7 +3569,8 @@ int ntfs_attr_record_move_away(struct ntfs_attr_search_ctx *ctx, int extra)
  * update allocated and compressed size.
  */
 static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni,
-		struct mft_record *m, struct ntfs_attr_search_ctx *ctx)
+		struct mft_record *m, struct ntfs_attr_search_ctx *ctx,
+		struct ntfs_inode *locked_ni, bool defer_attrlist)
 {
 	int sparse, err = 0;
 	struct ntfs_inode *base_ni;
@@ -3605,6 +3606,8 @@ static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni,
 		     le16_to_cpu(a->data.non_resident.mapping_pairs_offset) == 8) &&
 		    !(le32_to_cpu(m->bytes_allocated) - le32_to_cpu(m->bytes_in_use))) {
 
+			if (defer_attrlist)
+				return -ENOSPC;
 			if (!NInoAttrList(base_ni)) {
 				err = ntfs_inode_add_attrlist(base_ni);
 				if (err)
@@ -3618,7 +3621,7 @@ static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni,
 				goto out;
 			}
 
-			err = ntfs_attrlist_update(base_ni);
+			err = ntfs_attrlist_update_locked(base_ni, locked_ni);
 			if (err)
 				goto out;
 			err = -EAGAIN;
@@ -3698,6 +3701,8 @@ static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni,
  * ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute
  * @ni:		non-resident ntfs inode for which we need update
  * @from_vcn:	update runlist starting this VCN
+ * @locked_ni:	inode whose runlist write lock is already held
+ * @defer_attrlist: return -ENOSPC instead of updating an attribute list
  *
  * Build mapping pairs from @na->rl and write them to the disk. Also, this
  * function updates sparse bit, allocated and compressed size (allocates/frees
@@ -3707,7 +3712,10 @@ static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni,
  * call to this function. Vice-versa @na->compressed_size will be calculated and
  * set to correct value during this function.
  */
-int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
+static int __ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni,
+					    s64 from_vcn,
+					    struct ntfs_inode *locked_ni,
+					    bool defer_attrlist)
 {
 	struct ntfs_attr_search_ctx *ctx;
 	struct ntfs_inode *base_ni;
@@ -3799,7 +3807,8 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
 			continue;
 		}
 
-		err = ntfs_attr_update_meta(a, ni, m, ctx);
+		err = ntfs_attr_update_meta(a, ni, m, ctx, locked_ni,
+					    defer_attrlist);
 		if (err < 0) {
 			if (err == -EAGAIN) {
 				ntfs_attr_put_search_ctx(ctx);
@@ -3839,11 +3848,17 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
 			 */
 			if (ni->type == AT_ATTRIBUTE_LIST) {
 				ntfs_attr_put_search_ctx(ctx);
+				ctx = NULL;
+				if (locked_ni == ni || defer_attrlist) {
+					err = -ENOSPC;
+					goto put_err_out;
+				}
 				err = ntfs_inode_free_space(base_ni, mp_size -
 							cur_max_mp_size);
 				if (err)
 					return err;
-				err = ntfs_attrlist_update(base_ni);
+				err = ntfs_attrlist_update_locked(
+					base_ni, locked_ni);
 				if (err)
 					return err;
 				goto retry;
@@ -3851,6 +3866,10 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
 
 			/* Add attribute list if it isn't present, and retry. */
 			if (!NInoAttrList(base_ni)) {
+				if (defer_attrlist) {
+					err = -ENOSPC;
+					goto put_err_out;
+				}
 				ntfs_attr_put_search_ctx(ctx);
 				if (ntfs_inode_add_attrlist(base_ni)) {
 					ntfs_error(sb, "Can not add attrlist");
@@ -3878,13 +3897,21 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
 			}
 		}
 
+		if (defer_attrlist &&
+		    (ctx->ntfs_ino->nr_extents == -1 ||
+		     NInoAttrList(ctx->ntfs_ino)) &&
+		    ctx->attr->type != AT_ATTRIBUTE_LIST) {
+			err = -ENOSPC;
+			goto put_err_out;
+		}
+
 		/* Update lowest vcn. */
 		a->data.non_resident.lowest_vcn = cpu_to_le64(stop_vcn);
 		mark_mft_record_dirty(ctx->ntfs_ino);
 		if ((ctx->ntfs_ino->nr_extents == -1 || NInoAttrList(ctx->ntfs_ino)) &&
 		    ctx->attr->type != AT_ATTRIBUTE_LIST) {
 			ctx->al_entry->lowest_vcn = cpu_to_le64(stop_vcn);
-			err = ntfs_attrlist_update(base_ni);
+			err = ntfs_attrlist_update_locked(base_ni, locked_ni);
 			if (err)
 				goto put_err_out;
 		}
@@ -4059,6 +4086,19 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
 	return err;
 }
 
+int ntfs_attr_update_mapping_pairs_locked(struct ntfs_inode *ni,
+					  s64 from_vcn,
+					 struct ntfs_inode *locked_ni)
+{
+	return __ntfs_attr_update_mapping_pairs(ni, from_vcn, locked_ni,
+						false);
+}
+
+int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)
+{
+	return ntfs_attr_update_mapping_pairs_locked(ni, from_vcn, NULL);
+}
+
 /*
  * ntfs_attr_make_resident - convert a non-resident to a resident attribute
  * @ni:		open ntfs attribute to make resident
@@ -4192,7 +4232,9 @@ static int ntfs_attr_make_resident(struct ntfs_inode *ni, struct ntfs_attr_searc
  *
  * Reduce the size of a non-resident, open ntfs attribute @na to @newsize bytes.
  */
-static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsize)
+static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni,
+					 const s64 newsize,
+					struct ntfs_inode *locked_ni)
 {
 	struct ntfs_volume *vol;
 	struct ntfs_attr_search_ctx *ctx;
@@ -4200,6 +4242,7 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
 	s64 nr_freed_clusters;
 	int err;
 	struct ntfs_inode *base_ni;
+	bool runlist_locked = locked_ni == ni;
 
 	ntfs_debug("Inode 0x%llx attr 0x%x new size %lld\n",
 		(unsigned long long)ni->mft_no, ni->type, (long long)newsize);
@@ -4245,18 +4288,24 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
 	 * clusters if there is a change.
 	 */
 	if (ntfs_bytes_to_cluster(vol, ni->allocated_size) != first_free_vcn) {
-		struct ntfs_attr_search_ctx *ctx;
+		/*
+		 * ntfs_cluster_free() and ntfs_rl_truncate_nolock()
+		 * both require this lock.
+		 */
+		if (!runlist_locked)
+			down_write(&ni->runlist.lock);
 
 		err = ntfs_attr_map_whole_runlist(ni);
 		if (err) {
 			ntfs_debug("Eeek! ntfs_attr_map_whole_runlist failed.\n");
-			return err;
+			goto unlock_runlist;
 		}
 
 		ctx = ntfs_attr_get_search_ctx(ni, NULL);
 		if (!ctx) {
 			ntfs_error(vol->sb, "%s: Failed to get search context", __func__);
-			return -ENOMEM;
+			err = -ENOMEM;
+			goto unlock_runlist;
 		}
 
 		/* Deallocate all clusters starting with the first free one. */
@@ -4264,7 +4313,8 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
 		if (nr_freed_clusters < 0) {
 			ntfs_debug("Eeek! Freeing of clusters failed. Aborting...\n");
 			ntfs_attr_put_search_ctx(ctx);
-			return (int)nr_freed_clusters;
+			err = (int)nr_freed_clusters;
+			goto unlock_runlist;
 		}
 		ntfs_attr_put_search_ctx(ctx);
 
@@ -4277,7 +4327,8 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
 			kvfree(ni->runlist.rl);
 			ni->runlist.rl = NULL;
 			ntfs_error(vol->sb, "Eeek! Run list truncation failed.\n");
-			return -EIO;
+			err = -EIO;
+			goto unlock_runlist;
 		}
 
 		/* Prepare to mapping pairs update. */
@@ -4293,11 +4344,13 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
 			VFS_I(base_ni)->i_blocks = ni->allocated_size >> 9;
 
 		/* Write mapping pairs for new runlist. */
-		err = ntfs_attr_update_mapping_pairs(ni, 0 /*first_free_vcn*/);
+		err = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
 		if (err) {
 			ntfs_debug("Eeek! Mapping pairs update failed. Leaving inconstant metadata. Run chkdsk.\n");
-			return err;
+			goto unlock_runlist;
 		}
+		if (!runlist_locked)
+			up_write(&ni->runlist.lock);
 	}
 
 	/* Get the first attribute record. */
@@ -4339,7 +4392,11 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
 
 	/* If the attribute now has zero size, make it resident. */
 	if (!newsize && !NInoEncrypted(ni) && !NInoCompressed(ni)) {
+		if (!runlist_locked)
+			down_write(&ni->runlist.lock);
 		err = ntfs_attr_make_resident(ni, ctx);
+		if (!runlist_locked)
+			up_write(&ni->runlist.lock);
 		if (err) {
 			/* If couldn't make resident, just continue. */
 			if (err != -EPERM)
@@ -4356,6 +4413,11 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
 put_err_out:
 	ntfs_attr_put_search_ctx(ctx);
 	return err;
+
+unlock_runlist:
+	if (!runlist_locked)
+		up_write(&ni->runlist.lock);
+	return err;
 }
 
 /*
@@ -4364,13 +4426,14 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz
  * @prealloc_size:	preallocation size (in bytes) to which to expand the attribute
  * @newsize:		new size (in bytes) to which to expand the attribute
  * @holes:		how to create a hole if expanding
- * @need_lock:		whether mrec lock is needed or not
+ * @locked_ni:		inode whose runlist lock is already held
  *
  * Expand the size of a non-resident, open ntfs attribute @na to @newsize bytes,
  * by allocating new clusters.
  */
 static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsize,
-		const s64 prealloc_size, unsigned int holes, bool need_lock)
+		const s64 prealloc_size, unsigned int holes,
+		struct ntfs_inode *locked_ni)
 {
 	s64 lcn_seek_from;
 	s64 first_free_vcn;
@@ -4568,7 +4631,8 @@ static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsiz
 
 		/* Prepare to mapping pairs update. */
 		ni->allocated_size = ntfs_cluster_to_bytes(vol, first_free_vcn);
-		err = ntfs_attr_update_mapping_pairs(ni, 0);
+		err = ntfs_attr_update_mapping_pairs_locked(
+				ni, 0, locked_ni);
 		if (err) {
 			ntfs_debug("Mapping pairs update failed");
 			goto rollback;
@@ -4612,11 +4676,11 @@ static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsiz
 		ntfs_debug("Leaking clusters");
 
 	/* Now, truncate the runlist itself. */
-	if (need_lock)
+	if (ni != locked_ni)
 		down_write(&ni->runlist.lock);
 	err2 = ntfs_rl_truncate_nolock(vol, &ni->runlist,
 			ntfs_bytes_to_cluster(vol, org_alloc_size));
-	if (need_lock)
+	if (ni != locked_ni)
 		up_write(&ni->runlist.lock);
 	if (err2) {
 		/*
@@ -4630,11 +4694,11 @@ static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsiz
 		/* Prepare to mapping pairs update. */
 		ni->allocated_size = org_alloc_size;
 		/* Restore mapping pairs. */
-		if (need_lock)
+		if (ni != locked_ni)
 			down_read(&ni->runlist.lock);
-		if (ntfs_attr_update_mapping_pairs(ni, 0))
+		if (__ntfs_attr_update_mapping_pairs(ni, 0, locked_ni, true))
 			ntfs_error(sb, "Failed to restore old mapping pairs");
-		if (need_lock)
+		if (ni != locked_ni)
 			up_read(&ni->runlist.lock);
 
 		if (NInoSparse(ni) || NInoCompressed(ni)) {
@@ -4739,7 +4803,8 @@ static int ntfs_resident_attr_resize(struct ntfs_inode *attr_ni, const s64 newsi
 		mark_mft_record_dirty(ctx->ntfs_ino);
 		ntfs_attr_put_search_ctx(ctx);
 		/* Resize non-resident attribute */
-		return ntfs_non_resident_attr_expand(attr_ni, newsize, prealloc_size, holes, true);
+		return ntfs_non_resident_attr_expand(
+				attr_ni, newsize, prealloc_size, holes, NULL);
 	} else if (err != -ENOSPC && err != -EPERM) {
 		ntfs_error(sb, "Failed to make attribute non-resident");
 		goto put_err_out;
@@ -4914,13 +4979,14 @@ int __ntfs_attr_truncate_vfs(struct ntfs_inode *ni, const s64 newsize,
 	if (NInoNonResident(ni)) {
 		if (newsize > i_size) {
 			down_write(&ni->runlist.lock);
-			err = ntfs_non_resident_attr_expand(ni, newsize, 0,
-							    NVolDisableSparse(ni->vol) ?
-							    HOLES_NO : HOLES_OK,
-							    false);
+			err = ntfs_non_resident_attr_expand(
+					ni, newsize, 0,
+					NVolDisableSparse(ni->vol) ?
+					HOLES_NO : HOLES_OK, ni);
 			up_write(&ni->runlist.lock);
 		} else
-			err = ntfs_non_resident_attr_shrink(ni, newsize);
+			err = ntfs_non_resident_attr_shrink(
+					ni, newsize, NULL);
 	} else
 		err = ntfs_resident_attr_resize(ni, newsize, 0,
 						NVolDisableSparse(ni->vol) ?
@@ -4929,7 +4995,9 @@ int __ntfs_attr_truncate_vfs(struct ntfs_inode *ni, const s64 newsize,
 	return err;
 }
 
-int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 prealloc_size)
+int ntfs_attr_expand_locked(struct ntfs_inode *ni, const s64 newsize,
+			    const s64 prealloc_size,
+			   struct ntfs_inode *locked_ni)
 {
 	int err = 0;
 
@@ -4959,9 +5027,10 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 preallo
 
 	if (NInoNonResident(ni)) {
 		if (newsize > ni->data_size || prealloc_size > ni->allocated_size)
-			err = ntfs_non_resident_attr_expand(ni, newsize, prealloc_size,
-							    NVolDisableSparse(ni->vol) ?
-							    HOLES_NO : HOLES_OK, true);
+			err = ntfs_non_resident_attr_expand(
+					ni, newsize, prealloc_size,
+					NVolDisableSparse(ni->vol) ?
+					HOLES_NO : HOLES_OK, locked_ni);
 	} else
 		err = ntfs_resident_attr_resize(ni, newsize, prealloc_size,
 						NVolDisableSparse(ni->vol) ?
@@ -4972,6 +5041,12 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 preallo
 	return err;
 }
 
+int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize,
+		     const s64 prealloc_size)
+{
+	return ntfs_attr_expand_locked(ni, newsize, prealloc_size, NULL);
+}
+
 /*
  * ntfs_attr_truncate_i - resize an ntfs attribute
  * @ni:		open ntfs inode to resize
@@ -4984,7 +5059,9 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 preallo
  * newly allocated space is marked as not initialised and no real allocation
  * on disk is performed.
  */
-int ntfs_attr_truncate_i(struct ntfs_inode *ni, const s64 newsize, unsigned int holes)
+int ntfs_attr_truncate_i_locked(struct ntfs_inode *ni, const s64 newsize,
+				unsigned int holes,
+			       struct ntfs_inode *locked_ni)
 {
 	int err;
 
@@ -5018,15 +5095,23 @@ int ntfs_attr_truncate_i(struct ntfs_inode *ni, const s64 newsize, unsigned int
 
 	if (NInoNonResident(ni)) {
 		if (newsize > ni->data_size)
-			err = ntfs_non_resident_attr_expand(ni, newsize, 0, holes, true);
+			err = ntfs_non_resident_attr_expand(
+					ni, newsize, 0, holes, locked_ni);
 		else
-			err = ntfs_non_resident_attr_shrink(ni, newsize);
+			err = ntfs_non_resident_attr_shrink(
+					ni, newsize, locked_ni);
 	} else
 		err = ntfs_resident_attr_resize(ni, newsize, 0, holes);
 	ntfs_debug("Return status %d\n", err);
 	return err;
 }
 
+int ntfs_attr_truncate_i(struct ntfs_inode *ni, const s64 newsize,
+			 unsigned int holes)
+{
+	return ntfs_attr_truncate_i_locked(ni, newsize, holes, NULL);
+}
+
 /*
  * Resize an attribute, creating a hole if relevant
  */
@@ -5044,10 +5129,11 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,
 	struct ntfs_volume *vol = ni->vol;
 	struct ntfs_attr_search_ctx *ctx;
 	struct runlist_element *rl, *rlc;
+	struct runlist_element *old_rl = NULL;
 	s64 vcn = vcn_start, lcn, clu_count;
 	s64 lcn_seek_from = -1;
 	int err = 0;
-	size_t new_rl_count;
+	size_t new_rl_count, old_rl_count;
 
 	err = ntfs_attr_map_whole_runlist(ni);
 	if (err)
@@ -5140,6 +5226,19 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,
 	WARN_ON(rlc->vcn != vcn);
 	lcn = rlc->lcn;
 	clu_count = rlc->length;
+	old_rl_count = ni->runlist.count;
+	old_rl = kmemdup(ni->runlist.rl,
+			 old_rl_count * sizeof(*old_rl), GFP_NOFS);
+	if (!old_rl) {
+		err = -ENOMEM;
+		if (ntfs_cluster_free_from_rl(vol, rlc)) {
+			ntfs_error(vol->sb,
+				   "Failed to free cluster allocation after runlist backup failure.");
+			NVolSetErrors(vol);
+		}
+		kvfree(rlc);
+		goto out;
+	}
 
 	rl = ntfs_runlists_merge(&ni->runlist, rlc, 0, &new_rl_count);
 	if (IS_ERR(rl)) {
@@ -5163,15 +5262,32 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,
 
 	if (update_mp) {
 		ntfs_attr_reinit_search_ctx(ctx);
-		err = ntfs_attr_update_mapping_pairs(ni, 0);
+		err = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
 		if (err) {
 			int err2;
 
 			err2 = ntfs_cluster_free(ni, vcn, clu_count, ctx);
-			if (err2 < 0)
+			if (err2 < 0 || err2 != clu_count) {
 				ntfs_error(vol->sb,
-					   "Failed to free cluster allocation. Leaving inconstant metadata.\n");
-			goto out;
+					   "Failed to free cluster allocation. Leaving inconsistent metadata.\n");
+				NVolSetErrors(vol);
+				goto out;
+			}
+
+			/*
+			 * Restore the runlist before repairing the on-disk
+			 * mapping pairs.
+			 */
+			kvfree(ni->runlist.rl);
+			ni->runlist.rl = old_rl;
+			ni->runlist.count = old_rl_count;
+			old_rl = NULL;
+			if (ntfs_attr_update_mapping_pairs_locked(
+					ni, 0, ni)) {
+				ntfs_error(vol->sb,
+					   "Failed to restore mapping pairs after allocation rollback.\n");
+				NVolSetErrors(vol);
+			}
 		}
 	} else {
 		VFS_I(ni)->i_blocks += clu_count << (vol->cluster_size_bits - 9);
@@ -5183,6 +5299,7 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,
 	*lcn_count = clu_count;
 	*balloc = true;
 out:
+	kvfree(old_rl);
 	ntfs_attr_put_search_ctx(ctx);
 	return err;
 }
@@ -5420,7 +5537,7 @@ int ntfs_non_resident_attr_insert_range(struct ntfs_inode *ni, s64 start_vcn, s6
 	ni->data_size += ntfs_cluster_to_bytes(vol, len);
 	if (ntfs_cluster_to_bytes(vol, start_vcn) < ni->initialized_size)
 		ni->initialized_size += ntfs_cluster_to_bytes(vol, len);
-	ret = ntfs_attr_update_mapping_pairs(ni, 0);
+	ret = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
 	up_write(&ni->runlist.lock);
 	if (ret)
 		return ret;
@@ -5505,7 +5622,7 @@ int ntfs_non_resident_attr_collapse_range(struct ntfs_inode *ni, s64 start_vcn,
 	}
 
 	if (ni->allocated_size > 0) {
-		ret = ntfs_attr_update_mapping_pairs(ni, 0);
+		ret = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
 		if (ret) {
 			up_write(&ni->runlist.lock);
 			goto out_rl;
@@ -5583,7 +5700,7 @@ int ntfs_non_resident_attr_punch_hole(struct ntfs_inode *ni, s64 start_vcn, s64
 	ni->runlist.rl = rl;
 	ni->runlist.count = new_rl_count;
 
-	ret = ntfs_attr_update_mapping_pairs(ni, 0);
+	ret = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
 	up_write(&ni->runlist.lock);
 	if (ret) {
 		kvfree(punch_rl);
@@ -5759,7 +5876,7 @@ int ntfs_attr_fallocate(struct ntfs_inode *ni, loff_t start, loff_t byte_len, bo
 	if (NInoRunlistDirty(ni)) {
 		mutex_lock_nested(&ni->mrec_lock, NTFS_INODE_MUTEX_NORMAL);
 		down_write(&ni->runlist.lock);
-		err = ntfs_attr_update_mapping_pairs(ni, 0);
+		err = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
 		if (err)
 			ntfs_error(ni->vol->sb, "Updating mapping pairs failed");
 		else
fs/ntfs/attrib.h +9 -0
index e2224fbfaabe9..6b4fa9f576401 100644
@@ -112,7 +112,13 @@ int ntfs_non_resident_attr_punch_hole(struct ntfs_inode *ni, s64 start_vcn, s64
 int __ntfs_attr_truncate_vfs(struct ntfs_inode *ni, const s64 newsize,
 		const s64 i_size);
 int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 prealloc_size);
+int ntfs_attr_expand_locked(struct ntfs_inode *ni, const s64 newsize,
+			    const s64 prealloc_size,
+			   struct ntfs_inode *locked_ni);
 int ntfs_attr_truncate_i(struct ntfs_inode *ni, const s64 newsize, unsigned int holes);
+int ntfs_attr_truncate_i_locked(struct ntfs_inode *ni, const s64 newsize,
+				unsigned int holes,
+			       struct ntfs_inode *locked_ni);
 int ntfs_attr_truncate(struct ntfs_inode *ni, const s64 newsize);
 int ntfs_attr_rm(struct ntfs_inode *ni);
 int ntfs_attr_exist(struct ntfs_inode *ni, const __le32 type, __le16 *name,
@@ -133,6 +139,9 @@ int ntfs_resident_attr_record_add(struct ntfs_inode *ni, __le32 type,
 		__le16 *name, u8 name_len, u8 *val, u32 size,
 		__le16 flags);
 int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn);
+int ntfs_attr_update_mapping_pairs_locked(struct ntfs_inode *ni,
+					  s64 from_vcn,
+					 struct ntfs_inode *locked_ni);
 struct runlist_element *ntfs_attr_vcn_to_rl(struct ntfs_inode *ni, s64 vcn, s64 *lcn);
 
 /*
fs/ntfs/attrlist.c +32 -14

114 lines not on this page · raw message

fs/ntfs/attrlist.h +2 -0
index 1892a3934d3ab..10cc2cc8e2081 100644
@@ -16,5 +16,7 @@ int ntfs_attrlist_need(struct ntfs_inode *ni);
 int ntfs_attrlist_entry_add(struct ntfs_inode *ni, struct attr_record *attr);
 int ntfs_attrlist_entry_rm(struct ntfs_attr_search_ctx *ctx);
 int ntfs_attrlist_update(struct ntfs_inode *base_ni);
+int ntfs_attrlist_update_locked(struct ntfs_inode *base_ni,
+				struct ntfs_inode *locked_ni);
 
 #endif /* defined _NTFS_ATTRLIST_H */
fs/ntfs/compress.c +1 -1
index 4ea1a6bfb3eb7..89a151901b9de 100644
@@ -1390,7 +1390,7 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages,
 	ni->runlist.count = new_rl_count;
 	ni->runlist.rl = rl;
 
-	err = ntfs_attr_update_mapping_pairs(ni, 0);
+	err = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
 	up_write(&ni->runlist.lock);
 	if (err) {
 		err = -EIO;
fs/ntfs/file.c +2 -1
index 7c1cf27bcaad8..8f682dbe51eaf 100644
@@ -111,7 +111,8 @@ static int ntfs_trim_prealloc(struct inode *vi)
 			ntfs_error(vol->sb, "Preallocated block rollback failed");
 		} else {
 			ni->allocated_size = ntfs_cluster_to_bytes(vol, vcn_tr);
-			err = ntfs_attr_update_mapping_pairs(ni, 0);
+			err = ntfs_attr_update_mapping_pairs_locked(
+					ni, 0, ni);
 			if (err)
 				ntfs_error(vol->sb,
 					   "Failed to rollback mapping pairs for prealloc");
fs/ntfs/inode.c +1 -1
index cc5818d50e3e8..560f1dd1fba39 100644
@@ -2772,7 +2772,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)
 
 	if (NInoNonResident(ni) && NInoRunlistDirty(ni)) {
 		down_write(&ni->runlist.lock);
-		err = ntfs_attr_update_mapping_pairs(ni, 0);
+		err = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
 		if (!err)
 			NInoClearRunlistDirty(ni);
 		up_write(&ni->runlist.lock);
fs/ntfs/mft.c +8 -5
index ed3aa4c423e81..60f10bb0004fd 100644
@@ -1131,7 +1131,8 @@ static s64 mft_bitmap_alloc_free_rec(struct ntfs_volume *vol,
 	return ll;
 }
 
-static int ntfs_mft_attr_extend(struct ntfs_inode *ni)
+static int ntfs_mft_attr_extend(struct ntfs_inode *ni,
+				struct ntfs_inode *locked_ni)
 {
 	int ret = 0;
 	struct ntfs_inode *base_ni;
@@ -1152,7 +1153,7 @@ static int ntfs_mft_attr_extend(struct ntfs_inode *ni)
 		}
 	}
 
-	ret = ntfs_attr_update_mapping_pairs(ni, 0);
+	ret = ntfs_attr_update_mapping_pairs_locked(ni, 0, locked_ni);
 	if (ret)
 		pr_err("MP update failed\n");
 
@@ -1340,7 +1341,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(struct ntfs_volume *vol)
 	ret = ntfs_attr_record_resize(ctx->mrec, a, mp_size +
 			le16_to_cpu(a->data.non_resident.mapping_pairs_offset));
 	if (unlikely(ret)) {
-		ret = ntfs_mft_attr_extend(mftbmp_ni);
+		ret = ntfs_mft_attr_extend(mftbmp_ni, mftbmp_ni);
 		if (!ret)
 			goto extended_ok;
 		if (ret != -EAGAIN)
@@ -1451,7 +1452,9 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(struct ntfs_volume *vol)
 			NVolSetErrors(vol);
 		}
 		mark_mft_record_dirty(ctx->ntfs_ino);
-	} else if (status.mp_extended && ntfs_attr_update_mapping_pairs(mftbmp_ni, 0)) {
+	} else if (status.mp_extended &&
+		   ntfs_attr_update_mapping_pairs_locked(mftbmp_ni, 0,
+							  mftbmp_ni)) {
 		ntfs_error(vol->sb, "Failed to restore mapping pairs.%s", es);
 		NVolSetErrors(vol);
 	}
@@ -1776,7 +1779,7 @@ static int ntfs_mft_data_extend_allocation_nolock(struct ntfs_volume *vol)
 	ret = ntfs_attr_record_resize(ctx->mrec, a, mp_size +
 			le16_to_cpu(a->data.non_resident.mapping_pairs_offset));
 	if (unlikely(ret)) {
-		ret = ntfs_mft_attr_extend(mft_ni);
+		ret = ntfs_mft_attr_extend(mft_ni, NULL);
 		if (!ret)
 			goto extended_ok;
 		if (ret != -EAGAIN)
Signature · 1 line
2.53.0
author maintainer
#127 lore raw

PATCH 124/438 ntfs: propagate folio errors

In reply to Greg Kroah-Hartman

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

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

From: Namjae Jeon <[email protected]>

[ Upstream commit 1923eeffa63edeff427d76fc302bc5eb835771ce ]

Return the error from __filemap_get_folio() instead of replacing it with -ENOMEM.

Fixes af0db57d4293 ("ntfs: update inode operations")
---
 fs/ntfs/inode.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ntfs/inode.c +1 -1
index 560f1dd1fba39..b6e161d51dce2 100644
@@ -3713,7 +3713,7 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,
 					FGP_CREAT | FGP_LOCK,
 					mapping_gfp_mask(mapping));
 			if (IS_ERR(folio)) {
-				ret = -ENOMEM;
+				ret = PTR_ERR(folio);
 				break;
 			}
 		} else {
Signature · 1 line
2.53.0