Skip to contentSkip to conversation

7.2.7-rc1 review

PATCH Applied Greg Kroah-Hartman 15 participants 748 messages Sep 17 – Sep 19 Page 1 of 6

Subsystems (5)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 7.2.7-rc1 review

This is the start of the stable review cycle for the 7.2.7 release. There are 733 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.

Responses should be made by Sat, 19 Sep 2026 15:12:28 +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.7-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.7-rc1

Peter Zijlstra <[email protected]>
x86/mm: Fix and document DEBUG_PAGEALLOC

Griffin Kroah-Hartman <[email protected]>
misc: amd-sbi: Add null check for devm_kasprintf()

Lorenzo Stoakes (ARM) <[email protected]>
x86/mm/pat: Allocate split page tables as kernel page tables

Thomas Richter <[email protected]>
s390/pai: Support CPU hotplug for PMU PAI

Thomas Richter <[email protected]>
s390/pai: Move locking to event init and delete

Thomas Richter <[email protected]>
s390/pai: Use PAI PMU index as parameter replacing event

Satyajit Roy <[email protected]>
drm/amd/display: Honor Broadcast RGB for BT.2020 RGB output

Satyajit Roy <[email protected]>
drm/amd/display: Propagate HDMI RGB quantization selectability

Nilesh Javali <[email protected]>
scsi: qla2xxx: Serialize NVMe unsol ctx list with a per-fcport lock

Nilesh Javali <[email protected]>
scsi: qla2xxx: Unlink NVMe unsol ctx before freeing on LS reject error

Nilesh Javali <[email protected]>

    scsi: qla2xxx: Validate BSG request_len before reading vendor_cmd[]

Nilesh Javali <[email protected]>
scsi: qla2xxx: Clamp max_npiv_vports to VP_CTRL bitmap capacity

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix soft lockup polling continuation IOCB signature

Nilesh Javali <[email protected]>
scsi: qla2xxx: Skip vport under deletion in report ID acquisition

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix 64G link speed reporting in get_data_rate

Nilesh Javali <[email protected]>
scsi: qla2xxx: Null out freed pointers in qla2x00_mem_alloc() error path

Dinh Nguyen <[email protected]>
EDAC/altera: Use parent device for devres in altr_portb_setup()

Lorenzo Stoakes (ARM) <[email protected]>
x86/mm/pat: Acquire init_mm read lock on attribute changes to avoid UAF

Mike Rapoport (Microsoft) <[email protected]>
x86/mm/pat: Don't gate cpa_lock on debug_pagealloc_enabled()

Arda Doğu Ari <[email protected]>
platform/x86: hp-wmi: Fix board_params typo for 8DD6 board

Radhey Kalra <[email protected]>
platform/x86: hp-wmi: Introduce board-specific feature data

Heikki Krogerus <[email protected]>
drm/xe/i2c: Fix the interrupt handling

Heikki Krogerus <[email protected]>
i2c: designware: Global register definitions

Lizhi Hou <[email protected]>
accel/amdxdna: Disable device buffer exporting

Ville Syrjälä <[email protected]>
drm/i915/cdclk: Avoid spurious cdclk sanitization on PTL+

Chao Yu <[email protected]>
f2fs: fix to reset all pinned status during fggc

Chao Yu <[email protected]>
f2fs: fix to shrink gc_lock coverage in f2fs_gc_range()

Daeho Jeong <[email protected]>
f2fs: accurately adjust free_sections during free_segment_range

Nilesh Javali <[email protected]>
scsi: qla2xxx: Use memset_io() to clear QLAFX00 request ring slot

Nilesh Javali <[email protected]>
scsi: qla2xxx: Use ring-slot helpers in __qla2x00_alloc_iocbs

Nilesh Javali <[email protected]>
scsi: qla2xxx: Bound VP index against VP_CTRL IOCB bitmap size

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix use-after-free of qpair work on queue teardown

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix queue teardown NULL dma_free and bitmap locking

Hungyu Lin <[email protected]>
media: qcom: iris: fix runtime PM reference leaks

Sang-Heon Jeon <[email protected]>
media: remove conditional return with no effect

Arie Miller <[email protected]>
hwmon: (asus_rog_ryujin) Synchronize HID command and report handling

Arie Miller <[email protected]>
hwmon: (asus_rog_ryujin) Validate HID report lengths

Arie Miller <[email protected]>
hwmon: (asus_rog_ryujin) Add per-device configuration

Gary Guo <[email protected]>
usb: usbtmc: don't store usb_device_id

Gary Guo <[email protected]>
usb: xusbatm: don't rely on id table pointer arithmetic

Gary Guo <[email protected]>
net: usb: pegasus: don't rely on id table pointer arithmetic

Gary Guo <[email protected]>
usb: serial: spcp8x5: don't store usb_device_id

Gary Guo <[email protected]>
media: as102: do not rely on id table address comparison

Gary Guo <[email protected]>
wifi: ath9k_htc: don't store usb_device_id

Richard Fitzgerald <[email protected]>
ASoC: cs35l56: Fix race between kexec and snd_soc_register_component()

Darrick J. Wong <[email protected]>
xfs: actually check internal-rtdev fields in the superblock

Darrick J. Wong <[email protected]>
xfs: actually recover intended file sizes in xfs_xmi_item_recover_intent

Darrick J. Wong <[email protected]>
xfs: advance the findparent inode scan cursor while holding ILOCK

Darrick J. Wong <[email protected]>
xfs: always set xfs_healthmon::first_event when inserting at front of list

Darrick J. Wong <[email protected]>
xfs: bail out on bitmap errors in xrep_agfl_fill

Darrick J. Wong <[email protected]>
xfs: bump lost_prev_errors if we lose even the healthmon lost event

Darrick J. Wong <[email protected]>
xfs: check healthmon outbuffer space correctly

Darrick J. Wong <[email protected]>
xfs: compute dquot checksum after resetting dd_lsn in repair

Darrick J. Wong <[email protected]>
xfs: count escaped corruption errors in scrub stats

Darrick J. Wong <[email protected]>
xfs: cross-reference the rtgroup superblock extent, not block

Darrick J. Wong <[email protected]>
xfs: destroy seen inode bitmap when we fail to add a dirpath

Darrick J. Wong <[email protected]>
xfs: don't leak dqacct if rhashtable insertion fails

Darrick J. Wong <[email protected]>
xfs: don't leak new_bp if xfs_btree_bload_drop_buf fails

Darrick J. Wong <[email protected]>
xfs: don't modify file attributes or poke fsnotify for dry runs

Darrick J. Wong <[email protected]>
xfs: don't spin forever on zero-length dirents when salvaging them

Darrick J. Wong <[email protected]>
xfs: don't stash removename operations with unknown ftype

Darrick J. Wong <[email protected]>
xfs: fix backwards mergeability logic in refcount scrubber

Darrick J. Wong <[email protected]>
xfs: fix backwards skipping logic in xrep_quota_block

Darrick J. Wong <[email protected]>
xfs: fix bnobt repair space reservation disposal failure

Lin Jiapeng <[email protected]>
xfs: fix exchange-range reflink flag clearing issue with INO1_WRITTEN

Darrick J. Wong <[email protected]>
xfs: fix media verification ioctl for internal rt volumes

Darrick J. Wong <[email protected]>
xfs: fix name string recording in slowpath pptr tracepoints

Darrick J. Wong <[email protected]>
xfs: fix parent rec lookup initialization in xrep_metapath_unlink

Eric Sandeen <[email protected]>
xfs: fix reclaimed page accounting in xfs_buf_free

Darrick J. Wong <[email protected]>
xfs: fix replaying dirent removals into the temporary directory

Darrick J. Wong <[email protected]>
xfs: fix rtrefcount btree block counting in scrub

Darrick J. Wong <[email protected]>
xfs: fix rtrmap cross-referencing elision logic

Darrick J. Wong <[email protected]>
xfs: fix short ifork reaping computation in xreap_bmapi_binval

Darrick J. Wong <[email protected]>
xfs: fix the rtrmap and rtrefcount _maxlevels_ondisk functions

Darrick J. Wong <[email protected]>
xfs: fix under-reservation of blocks when repairing sf directories

Darrick J. Wong <[email protected]>
xfs: fix unit conversions in per_binval computation

Darrick J. Wong <[email protected]>
xfs: fix xfs_rtrmapbt_mem_cursor for non-rmap filesystems

Javier Tia <[email protected]>

    xfs: initialise args->total for parent pointer updates

Javier Tia <[email protected]>
xfs: initialise error in xfs_defer_finish_one()

Darrick J. Wong <[email protected]>
xfs: lock the healthmon when inserting unmount event

Darrick J. Wong <[email protected]>
xfs: log the tempip after we convert it to extents format

Darrick J. Wong <[email protected]>
xfs: make the rtsummary repair fix the file size too

Darrick J. Wong <[email protected]>
xfs: preserve owner on in-memory btree creation

Anuj Gupta <[email protected]>
xfs: release alleged child inode on metapath unlink error

Darrick J. Wong <[email protected]>
xfs: report healthy filesystem events in scrub stats

Darrick J. Wong <[email protected]>
xfs: report nonexistent parents as a filesystem corruption

Darrick J. Wong <[email protected]>
xfs: reset parent pointer args before each dir tree unlink repair

Darrick J. Wong <[email protected]>
xfs: signal inode btree xref error if get_rec returns an error

Darrick J. Wong <[email protected]>
xfs: snapshot old AGFL before rewriting it

Darrick J. Wong <[email protected]>
xfs: snapshot scrub stats when rendering them

Darrick J. Wong <[email protected]>
xfs: strengthen the "is cow staging" helpers in scrub

Darrick J. Wong <[email protected]>
xfs: truncate quota file correctly when repairing quota file

Darrick J. Wong <[email protected]>
xfs: use the rtgroup extent count to find rtrefcount gaps

Paulo Alcantara <[email protected]>
smb: client: avoid using uninitialized SIDs in cifs_posix_to_fattr()

Bjoern Doebel <[email protected]>
smb: client: fix heap overflow in DACL owner/group rewrite

Bjoern Doebel <[email protected]>
smb: client: avoid leaking refcount when cifs_sb_tlink() fails

Bjoern Doebel <[email protected]>
smb: client: avoid leaking refcount in cifs_queue_oplock_break()

Paulo Alcantara <[email protected]>
smb: client: fix file type corruption in wsl_to_fattr()

Paulo Alcantara <[email protected]>
smb: client: fix file type corruption in posix_reparse_to_fattr()

Paulo Alcantara <[email protected]>
smb: client: fix file type corruption in cifs_reparse_point_to_fattr()

Fan Wu <[email protected]>
smb: client: fix cifsFileInfo reference leak in deferred close

Bjoern Doebel <[email protected]>
smb: client: fail DACL rewrite when the new DACL exceeds 64K

Paulo Alcantara <[email protected]>
smb: client: fix one-byte OOB read in smb2_parse_native_symlink()

Paulo Alcantara <[email protected]>
smb: client: fix uid/gid override in getattr with posix extensions

Paulo Alcantara <[email protected]>
smb: client: fix WSL reparse point uid/gid override

Paulo Alcantara <[email protected]>
smb: client: honor forceuid/forcegid when mapping SIDs to uid/gid

Karl Mehltretter <[email protected]>
smb: client: pin DFS superblock in iterator callback

Diego Oliva <[email protected]>
smb: client: reject out-of-bounds DataOffset in CIFSSMBRead()

Aohan Mei <[email protected]>
smb: client: reject userspace cifs.idmap descriptions

Diego Oliva <[email protected]>
smb: client: reject short READ responses in CIFSSMBRead()

Qing Luo <[email protected]>
mptcp: pm: userspace: fix address ID overflow

Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: reset retrans_time when ADD_ADDR entry is reused

Kalpan Jani <[email protected]>
mptcp: pm: kernel: drop pending ADD_ADDR when removing ID0

Paolo Abeni <[email protected]>
mptcp: prevent race between disconnect() and rtx

Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: lib: get counters for the right test

Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: lib: dump nstat for the right test

Gang Yan <[email protected]>
selftests: mptcp: fix an UAF in mptcp_connect.c

Matthieu Baerts (NGI0) <[email protected]>
mptcp: options: fix uninit-value in mptcp_write_data_fin

Matthieu Baerts (NGI0) <[email protected]>
mptcp: syncookies: remember the request backup flag

Matthieu Baerts (NGI0) <[email protected]>
mptcp: subflow: no need to copy thmac during ulp_clone

Matthieu Baerts (NGI0) <[email protected]>
mptcp: options: handle MPC data + csum reqd + no csum

Paolo Abeni <[email protected]>
mptcp: do not reschedule the RTX timer for fallback sockets

Joe Damato <[email protected]>
bnxt_en: Prevent queue stop with deferred completions

Joe Damato <[email protected]>
bnxt_en: Bound SW TPA IDs to prevent crashes

Joe Damato <[email protected]>
bnxt_en: Propagate TPA buffer allocation failures in bnxt_queue_mem_alloc()

Joe Damato <[email protected]>
bnxt_en: Propagate RX ring init failures in bnxt_init_nic()

Joe Damato <[email protected]>
bnxt_en: Handle buffer allocation failure in bnxt_rx_ring_reset()

Joe Damato <[email protected]>
bnxt_en: Don't free the live ring's TPA state on queue restart failure

Joe Damato <[email protected]>
bnxt_en: Only restore LRO if the device supports TPA

Michael Bommarito <[email protected]>
media: v4l2-ctrls: validate AV1 tile counts

Michael Bommarito <[email protected]>
media: v4l2-ctrls: validate HEVC tile counts

Michael Bommarito <[email protected]>
media: verisilicon: rockchip: reject AV1 frames exceeding the tile capacity

Michael Bommarito <[email protected]>
media: verisilicon: rockchip: guard VPU981 AV1 divisor and tile buffer

Haotian Zhang <[email protected]>
media: v4l2-h264: Fix memcmp() size in B1 reference list comparison

Michael Bommarito <[email protected]>
media: mediatek: vcodec: bound AV1 tile-start copy to the array capacity

Michael Bommarito <[email protected]>
media: rkvdec: bound HEVC tile loops and PPS id to the array capacity

Michael Bommarito <[email protected]>
media: verisilicon: hantro: bound G2 HEVC tile loop to the buffer capacity

Sergey Zagursky <[email protected]>
media: ipu-bridge: do not use the CVS device lookup for IVSC

Michael Bommarito <[email protected]>
media: hevc: add bounded tile-count helpers

Vishnu Razdan <[email protected]>
hwmon: (pmbus) Clear generic status alarms with CLEAR_FAULTS

Nikhil Gurudasani <[email protected]>
hwmon: (mcp9982) Propagate one-shot polling errors

Fan Wu <[email protected]>
hwmon: (gpio-fan) Fix use-after-free in alarm work

Javier Carrasco <[email protected]>
hwmon: (chipcap2) fix channels in humidity alarm notifications

Cong Nguyen <[email protected]>
hwmon: (applesmc) fix key backlight workqueue leak on register failure

Chengfeng Ye <[email protected]>
afs: Clear stale peer app data after address list changes

David Howells <[email protected]>
afs: Fix incorrect free in candidate cleanup in afs_lookup_server()

David Howells <[email protected]>
afs: Fix double-unmap of directory block

David Howells <[email protected]>
afs: Fix missing kunmap in afs_dir_search_bucket()

Xixin Liu <[email protected]>
perf: RISC-V: use BIT_ULL for u64 overflow masks

Xixin Liu <[email protected]>
perf: RISC-V: store available counter mask as bitmap

Mahmoud Nagy Adam <[email protected]>
selftests: ublk: install test_common.sh and trace/ scripts

Harald Freudenberger <[email protected]>
s390/crypto: Map EBUSY to EIO when key conversion fails repeatedly

Harald Freudenberger <[email protected]>
s390/crypto: Fix wrong return code to engine in asynch callbacks

Harald Freudenberger <[email protected]>
s390/crypto: Fix missing scrub of temp buffers with PAES algorithm

Harald Freudenberger <[email protected]>
s390/crypto: Fix handling of EBUSY in PHMAC when req is pushed to crypto engine

Harald Freudenberger <[email protected]>
s390/crypto: Fix missing cra_flags in paes_s390

Harald Freudenberger <[email protected]>
s390/crypto: Fix missing scrub of temp buffers with AES ctr and gcm algorithm

Harald Freudenberger <[email protected]>
s390/crypto: Fix use of mutex in atomic context

Harald Freudenberger <[email protected]>
s390/crypto: Fix skcipher_walk return code handling in aes_s390

Nagamani PV <[email protected]>
s390/qeth: allow bridgeport queries despite OS_MISMATCH

Niklas Schnelle <[email protected]>
iommu/s390: Fix NULL dereference in iova_to_phys() with ZPCI_TABLE_TYPE_RFX

Norbert Szetei <[email protected]>
landlock: Fix use-after-free of the source's parent directory

leixiang <[email protected]>

    KVM: PPC: Book3S HV: Set irqfd->producer only on success

Ibrahim Hashimov <[email protected]>
mac802154: fix use-after-free of sdata via queued RX frames

Kyle Zeng <[email protected]>
ipvs: reject invalid states in connection template sync records

Zhiling Zou <[email protected]>
ipv6: flowlabel: cap duplicate leases per socket

Zihan Xi <[email protected]>
ipv4: fib: bound automatic table ID allocation

David Carlier <[email protected]>
ieee802154: hwsim: serialize pib updates to fix double-free

Fan Wu <[email protected]>

    ieee802154: cc2520: fix FIFOP work use-after-free

Zhiling Zou <[email protected]>
ieee802154: 6lowpan: fix NULL dereference in lowpan_newlink

Yilin Zhang <[email protected]>
inet: frags: invalidate queues before flushing them

Myeonghun Pak <[email protected]>
idpf: disable DIM work before freeing q_vectors

Weiming Shi <[email protected]>
fbdev: vfb: defer cleanup until the last reference

Nikhil Gurudasani <[email protected]>
erofs: preserve LZMA decoders on resize failure

Jingbo Xu <[email protected]>
erofs: add sysfs feature entry for xattr prefixes

Jeffin Philip <[email protected]>
fs: autofs: fix memory leak in autofs_fill_super()

Nathan Chancellor <[email protected]>
scripts/sorttable: Mark long_size as __maybe_unused

Xiong Weimin <[email protected]>
vdpa: solidrun: Free IRQs after request failure

Xiong Weimin <[email protected]>
vdpa: ifcvf: Put device on unsupported feature error

Ilya Maximets <[email protected]>
netfilter: report NLM_F_DUMP_FILTERED when all is filtered out

Chengfeng Ye <[email protected]>
netfilter: nf_log: unregister loggers before per-net teardown

Chengfeng Ye <[email protected]>
netfilter: cttimeout: prevent UAF during module unload

Karl Mehltretter <[email protected]>
netfs: Fix uninitialized return value in netfs_unbuffered_write()

Donggeun Yoo <[email protected]>
net: phy: dp83td510: handle the active-high LED polarity mode

Norbert Szetei <[email protected]>
net: openvswitch: fix use-after-free of the flow table mask array

Fourie Zhang <[email protected]>
net: mpls: clear inner_protocol when the last label is popped

Sahil Chandna <[email protected]>
net: mana: Reserve extra CQ slot for the fence completion CQE

Runyu Xiao <[email protected]>
net: macb: initialize PTP state before registering clock

Johan Hovold <[email protected]>
net: hso: fix TIOCMIWAIT race

Weiming Shi <[email protected]>
net: dsa: tag_brcm: legacy FCS: request needed tailroom

Zhiling Zou <[email protected]>
net: bridge: use option bits for CFM/MRP frame handlers

Xuanqiang Luo <[email protected]>
net/sched: act_api: release all action references on NEWACTION failure

David Carlier <[email protected]>
ring-buffer: Check resize_disabled before publishing the new subbuf order

Sebastian Andrzej Siewior <[email protected]>
ring-buffer: Acquire the lock with irqsave in rb_wake_up_waiters()

Gabriel Krisman Bertazi <[email protected]>
io_uring/net: don't overconsume buffers when using MSG_TRUNC

Gabriel Krisman Bertazi <[email protected]>
io_uring/net: let io_recv_buf_select return the length of the buffer region

Jens Axboe <[email protected]>

    io_uring/rw: end write accounting from ->ki_complete

Satyajit Roy <[email protected]>
drm/amd/display: Rebuild InfoFrames on output color space changes

Fangzhi Zuo <[email protected]>
drm/amd/display: Exit IPS before connector detection on resume

Thomas Hellström <[email protected]>
drm/xe: Flush LSC untyped L1 dataport cache after rcs/ccs batches

Shixiong Ou <[email protected]>
drm/sched: Create a fake device for KUnit tests

Yudi Yang <[email protected]>
drm/rockchip: analogix_dp: fix unchecked bound endpoint name length

Thorsten Blum <[email protected]>
drm/i915: Fix memory leak in query_perf_config_list()

Sunil Khatri <[email protected]>
drm/drm_exec: fix up contended obj when num_objects is 0

Esben Haabendal <[email protected]>
drm/bridge: ti-sn65dsi83: Fix error handling in sn65dsi83_reset_work()

Leonardo Costa <[email protected]>
drm/bridge: tc358768: Enforce input bus flags via atomic_check

Kevin Wang <[email protected]>
drm/amd/pm: fix gpu metrics energy accumulator for smu 13.0.0/13.0.7

Andrea Parri <[email protected]>
hrtimer: Use hard expiry when updating timers on the same base

XingWang Xiang <[email protected]>
genetlink: pin family module during policy dump

Donggeun Yoo <[email protected]>
function_graph: Use the saved entry's size when reprinting it

Moritz Tanner <[email protected]>
fs: don't return -EINVAL for successful nested thaw

Daehyeon Ko <[email protected]>
exit: hold a reference to thread_pid across proc_flush_pid

Jann Horn <[email protected]>
exec: do_close_on_exec() before taking exec_update_lock

Runyu Xiao <[email protected]>
cpufreq: initialize policy rwsem before sysfs publication

Zhongqiu Han <[email protected]>
cpufreq: zero-initialize policy cpumask before sysfs publication

Masami Hiramatsu (Google) <[email protected]>
bootconfig: Fix integer overflow in initrd size check

Rong Zhang <[email protected]>
Bluetooth: btrtl: Don't leak return code when parsing firmware format v2

Xu Rao <[email protected]>
Bluetooth: btqcomsmd: destroy RPMsg endpoints before freeing hci_dev

Runyu Xiao <[email protected]>
ASoC: sti: initialize IRQ lock before requesting IRQ

Tianchu Chen <[email protected]>
ASoC: sprd: validate compress buffer sizes against fixed allocations

Yorick Rommers <[email protected]>
ASoC: amd: acp-da7219-max98357a: don't bind on Raven/Picasso boards

Ethan Nelson-Moore <[email protected]>
ata: pata_legacy: remove documentation for removed module parameters

Rob Herring (Arm) <[email protected]>
accel: ethosu: Ensure SRAM region size matches job

Rob Herring (Arm) <[email protected]>
accel: ethosu: Ensure SRAM size is 0 on mapping failure

Rob Herring (Arm) <[email protected]>
accel: ethosu: Ensure cmd stream ends with a stop op

Rob Herring (Arm) <[email protected]>
accel: ethosu: Drop IRQF_SHARED flag

Rob Herring (Arm) <[email protected]>
accel: ethosu: Fix ethosu_job_open() return value

Dawid Osuchowski <[email protected]>
accel/ivpu: Limit firmware log name prints to field size

Magdalena Schulfer <[email protected]>
accel/ivpu: Validate firmware log buffer metadata

Magdalena Schulfer <[email protected]>
accel/ivpu: Validate full buffer range in ivpu_to_cpu_addr

Donggeun Yoo <[email protected]>
tracing: Undo the registration when enabling the histogram trigger fails

Donggeun Yoo <[email protected]>
tracing: Take the reference before publishing the named histogram trigger

Donggeun Yoo <[email protected]>
tracing: Keep the entry count when the histogram stats allocation fails

Donggeun Yoo <[email protected]>
tracing: Let histogram values keep the percent and graph modifiers

Donggeun Yoo <[email protected]>
tracing: Free histogram the field rejected for a bad modifier

Donggeun Yoo <[email protected]>
tracing: Free histogram var refs regardless of how often they are referenced

Donggeun Yoo <[email protected]>
tracing: Free histogram the var ref when its initialization fails

Henry Martin <[email protected]>
tracing/user_events: Don't destroy fields when event removal fails

Masami Hiramatsu (Google) <[email protected]>
tools/bootconfig: Fix integer overflow and truncation in size checks

Thomas Gleixner <[email protected]>
tick/broadcast: Plug clockevents replacement race

Ido Schimmel <[email protected]>
tunnels: Drop stale dst when building an ICMP error for PMTUD

Ali Ahmet Memis <[email protected]>
ufs: validate cylinder group metadata before caching it

Ali Ahmet Memis <[email protected]>
ufs: create the root dentry after loading cylinder metadata

Xiong Weimin <[email protected]>
virtio_mmio: disable IRQ wake before free_irq

James Hilliard <[email protected]>
watchdog: sunxi_wdt: preserve boot-enabled watchdog

Arunpravin Paneer Selvam <[email protected]>
drm/amdgpu: skip the VMID 0 flush for VRAM

Prike Liang <[email protected]>
drm/amdgpu: skip gfx switch_power_profile during GPU reset

Harry Wentland <[email protected]>
dm/amdgpu: fix malformed link_settings debugfs output

Andy Chiu <[email protected]>

    riscv: hwprobe: initialize pair->value in hwprobe_one_pair()

Samuel Holland <[email protected]>
Revert "riscv: Reset pmm when PR_TAGGED_ADDR_ENABLE is not set"

Tristan Madani <[email protected]>
ALSA: usbusx2y: validate URB actual_length in interrupt callback

Tristan Madani <[email protected]>
ALSA: usbusx2y: fix in04_last array size mismatch with in04_buf

Kazuki Hanai <[email protected]>
ALSA: us122l: Prevent write upgrades for read mappings

Roman Prucha <[email protected]>
ALSA: ctxfi: Fix CA20K2 S/PDIF passthrough

Miguel Ojeda <[email protected]>
drm/panic: clean new clippy::needless_range_loop lint for Rust 1.100.0

Miguel Ojeda <[email protected]>
rust: allow unknown_lints in generated bindings for Rust < 1.88

John Hubbard <[email protected]>
rust: allow clippy::as_underscore in the generated bindings

Gary Guo <[email protected]>
rust: pin-init: use irrefutable pattern for stack_pin_init

Younes Akhouayri <[email protected]>
rust: num: seal Integer

Ali Ahmet Memiş <[email protected]>
tracing: Don't dereference trace_event_file in deferred trigger free

Steven Rostedt <[email protected]>
tracing: Take trace_array reference when opening a tracer options file

Donggeun Yoo <[email protected]>
tracing: Fix memory corruption from a "STACKTRACE" histogram key

Donggeun Yoo <[email protected]>
tracing: Set the trace clock before registering the histogram trigger

Thomas Weißschuh <[email protected]>
tracing: Restore :mod: trailer after parsing in ftrace_set_clr_event()

Donggeun Yoo <[email protected]>
tracing: Fix memory corruption from the histogram stacktrace modifier

Jérémy Jean <[email protected]>
ftrace: fork: Initialize function graph state before copy_exec_state()

Leon Hwang <[email protected]>
ftrace: Use rcu_assign_pointer() for tmp_ops filter hash

Cen Zhang (Microsoft) <[email protected]>
reboot: fix cad_pid use-after-free race

Zihan Xi <[email protected]>
ipmr: account multicast table and route memory

Zihan Xi <[email protected]>
ipv6: fix fib6 walker UAF on seq stop

Harry Yoo (Meta) <[email protected]>

    mm/slab: take n->list_lock in __slab_try_return_freelist() to avoid race

Pedro Falcato <[email protected]>
x86/alternatives: Exclude text poking against change_page_attr()

Lorenzo Stoakes (ARM) <[email protected]>
x86/mm/pat: Acquire init_mm write lock on collapse to avoid UAF

Soheil Hassas Yeganeh <[email protected]>
x86/cfi: Fix FineIBT hash offset in cfi_get_func_hash()

Vernon Yang <[email protected]>
x86/mm: Fix user-space data loss with MADV_FREE and THP

Yazen Ghannam <[email protected]>
x86/amd_node: Fix PCI device reference counting in amd_smn_init()

Eric Biggers <[email protected]>
crypto: x86/aria - add missing vzeroupper in AVX-512 code

Eric Biggers <[email protected]>
crypto: x86/aria - add missing vzeroupper in AVX2 code

Jason Andryuk <[email protected]>
x86/amd_node: Fix potential NULL pointer dereference

Jasjeet Rangi <[email protected]>
x86/MCE/AMD: Fix inverted interrupt enablement during storm handling

Jason Andryuk <[email protected]>
x86/amd_node: Avoid divide by zero on virtualized systems

Shivaprasad G Bhat <[email protected]>
powerpc: pci-ioda: Fix the stale irq chip reference

Shivaprasad G Bhat <[email protected]>
powerpc/eeh: Fix recursive locking on devices without EEH sensitive driver

Thorsten Blum <[email protected]>
powerpc/ps3: Fix repository.c build failure

Vasileios Almpanis <[email protected]>
configfs: unhash the dentry before dropping the item in rmdir

Vasileios Almpanis <[email protected]>

    configfs: pin the symlink target's dirent instead of chasing ->ci_dentry

Maurizio Lombardi <[email protected]>
scsi: target: iscsi: Fix hang for aborted WRITE_PENDING commands

Vincent Donnefort <[email protected]>
tracing/remotes: Catch nr_page_va overflow in ring_buffer_desc sizing

Vincent Donnefort <[email protected]>
tracing/remotes: Account for ring buffer page header in size calculation

Lorenzo Stoakes (ARM) <[email protected]>
scripts/mksysmap: fix escape of '$' in the __pi_ pattern

Lorenzo Stoakes (ARM) <[email protected]>
scripts/mksysmap: drop the MODULE_INFO() symbols from kallsyms

Karl Mehltretter <[email protected]>
tracing: Fix ring_buffer_read_page_size() kernel-doc

Binglei Wang <[email protected]>

    erofs: add missing buf->off in erofs_bread()

Yang Xiuwei <[email protected]>
ublk: clear force_abort in ublk_queue_reset_io_flags()

Stian Halseth <[email protected]>
sunvdc: unmap LDC cookies when the descriptor send fails

David Howells <[email protected]>
block: Fix start and length check added to iov_iter_extract_bvecs()

Eelco Chaudron <[email protected]>
openvswitch: fix wrong flag value in get_ipv6_ext_hdrs()

MD Danish Anwar <[email protected]>
net: hsr: enable promiscuous mode on interlink port with fwd offload

Lorenzo Bianconi <[email protected]>
net: stmmac: fix TX descriptor availability check for TSO traffic

Greg Marsden <[email protected]>
net/rds: fix tcp stream corruption with large pages

Long Li <[email protected]>
net: mana: restore the XDP program pointer when pre-allocation fails

Donggeun Yoo <[email protected]>
net: phy: dp83867: handle the active-high LED polarity mode

Ratheesh Kannoth <[email protected]>
octeontx2-af: fix PF/CGX debugfs PCI bus lookup

Faicker Mo <[email protected]>
net: net_failover: Fix the deadlock in net_failover_slave_name_change()

Vladislav Karmanov <[email protected]>
net: phy: mediatek-ge: disable EEE on the MT7530 PHY

Aleksei Sviridkin <[email protected]>
net: ethernet: mtk_eth_soc: populate lpi_interfaces to fix EEE support

Aleksei Sviridkin <[email protected]>
net: dsa: mt7530: populate lpi_interfaces to fix EEE support

Ahmed Naseef <[email protected]>

    net: dsa: mt7530: add EN7528 support

Aamir Ahmed <[email protected]>
net: hinic: fix mailbox segment buffer overflow

Li Youhong <[email protected]>
net: sun4i-emac: fix missing of_node_put() for phy_node

Kuniyuki Iwashima <[email protected]>
net/sched: cls_api: Don't replay RTM_GETCHAIN in tc_ctl_chain().

Victor Nogueira <[email protected]>
net/sched: cls_route: Fix in-place replace

Victor Nogueira <[email protected]>
net/sched: cls_route: Reject handle aliasing

Victor Nogueira <[email protected]>
net/sched: cls_route: free emptied bucket on filter move

Hui Su <[email protected]>
sched/core: Call wq_worker_tick() for the execution context

Hui Su <[email protected]>
sched: Account cgroup CPU time to the execution context

Vincent Guittot <[email protected]>
sched/eevdf: Fix rb augmented with multi fields

Vincent Guittot <[email protected]>
sched/eevdf: Fix augmented max_slice

Dapeng Mi <[email protected]>
perf/x86/intel: Prevent drain_pebs() reentry

Dapeng Mi <[email protected]>

    perf/x86/intel: Correct pt_regs->flags update for PEBS path

Thomas Richter <[email protected]>
perf/core: Allow list_del during perf_event_overflow()

Mitul Golani <[email protected]>
drm/i915/dp: Gate UHBR SST SDP splitting on sink capability

Thibault Ferrante <[email protected]>
selftests/powerpc/tm: Fix tcheck() reading uninitialised CR value

Aboorva Devarajan <[email protected]>
powerpc/entry: Fix double accounting of user time on interrupt entry

Carolina Jubran <[email protected]>
net/mlx5e: Move representor vnic reporter to eswitch devlink port

Lorenzo Bianconi <[email protected]>
net: stmmac: initialize ptp_lock at probe time

Aleksei Sviridkin <[email protected]>
net: phylink: initialise link_state before a forced major config

Qingfang Deng <[email protected]>
ppp_synctty: ensure a writeable skb header

Eric Dumazet <[email protected]>
vxlan: initialize _md in vxlan_xmit_one()

Ratheesh Kannoth <[email protected]>
octeontx2-pf: reset HTB scheduler topology before freeing queues

Ali Ahmet Memis <[email protected]>
hwmon: (nct6694) do not expose enable on DTIN temperature channels

Linmao Li <[email protected]>
hwmon: (corsair-cpro) Remove debugfs entries when probe fails

Pengpeng Hou <[email protected]>
hwmon: (aspeed-pwm-tacho) Propagate reset deassert errors

Cong Nguyen <[email protected]>

    hwmon: (gpio-fan) take fan_data->lock in gpio_fan_shutdown()

Linmao Li <[email protected]>
hwmon: (corsair-cpro) Create debugfs entries after hwmon registration

Marek Vasut <[email protected]>
net: ks8851: Fix receiver error in 100BASE-TX mode following software power-down

Jan Havran (Advantech Czech) <[email protected]>
net: dsa: lantiq_gswip: fix GSWIP_MDIO_PHY_FCONTX_EN value

Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Sync timeout value if WDT was running at boot

Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Fix undefined behavior

Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Fix spurious reset on suspend

Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Enable clock before accessing hardware registers

Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Fix clock leak and spurious timer in settimeout()

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

David Arcari <[email protected]>
watchdog: fix hrtimer start when pretimeout is zero

Paolo Abeni <[email protected]>
mptcp: remove unneeded READ_ONCE() annotation

Varun Gupta <[email protected]>
drm/xe: Guard page-fault worker with runtime PM check

Norbert Szetei <[email protected]>
nstree: check listing permission before taking a namespace reference

Nicolai Buchwitz <[email protected]>
net: macb: put the "mdio" child node reference on success

Nicolai Buchwitz <[email protected]>
net: macb: destroy the phylink instance on the probe error path

Naman Gulati <[email protected]>
ipv6: null-check fib6_node before accessing in __ip6_del_rt_siblings()

Long Li <[email protected]>
net: mana: Clear RDMA teardown and suspend state in mana_rdma_probe()

Jiajia Liu <[email protected]>
Bluetooth: btusb: Fix leaked runtime PM reference in btusb_reset

Jiajia Liu <[email protected]>
Bluetooth: btusb: mediatek: Fix leaked runtime PM reference in reset

Krystian Kaniewski <[email protected]>
Bluetooth: hci_sysfs: Fix NULL pointer dereference in device_del()

Ivan Hu <[email protected]>
Bluetooth: btmtk: Declare MT7920 (MT7961 1a) Bluetooth firmware

Kiran K <[email protected]>
Bluetooth: btintel_pcie: fix tx_handle bounds off-by-one

Kiran K <[email protected]>
Bluetooth: btintel_pcie: validate packet_len before skb_put_data

Luiz Augusto von Dentz <[email protected]>
Bluetooth: btusb: Fix UAF of btusb_data by rx_work

Rong Zhang <[email protected]>
Bluetooth: Properly disable remote wakeup for MT7922/MT7925 on Ryzen platform

Jakub Kicinski <[email protected]>
eth: ice: don't dereference pointers from TP_printk()

Jacob Keller <[email protected]>
ice: add missing xa_destroy for sched_node_ids

Joshua Hay <[email protected]>
idpf: account for VLAN header when parsing RSC packet header

Hans de Goede <[email protected]>
platform/x86: x86-android-tablets: fix gpio_secondary_fwnode_init() not working

HyeongJun An <[email protected]>
ALSA: hda: Report a change when only the channel status bytes move

Mikhail Zaslonko <[email protected]>
s390/debug: Fix NULL pointer dereference in debug_set_level()

Karl Mehltretter <[email protected]>
drm/logicvc: Drop the select of the nonexistent CONFIG_DRM_KMS_DMA_HELPER

Karl Mehltretter <[email protected]>
drm/adp: Drop the select of the nonexistent CONFIG_DRM_KMS_DMA_HELPER

Linus Walleij <[email protected]>
net: ethernet: cortina: Count RX descriptors for freeq refill

Linus Walleij <[email protected]>
net: ethernet: cortina: Count RX drops once per frame

Linus Walleij <[email protected]>
net: ethernet: cortina: Count dropped frames as NAPI work

Linus Walleij <[email protected]>
net: ethernet: cortina: Finish RX updates before NAPI completion

Linus Walleij <[email protected]>
net: ethernet: cortina: Fix budget accounting

Aleksei Sviridkin <[email protected]>
net: macb: reject an unknown link speed in the taprio setup

Aleksei Sviridkin <[email protected]>
net: macb: zero the link settings taprio reads back

Linfeng Sun <[email protected]>
vduse: return compat ioctl results directly

Alice Mikityanska <[email protected]>
net: ipv6: Clamp to IP6_MAX_MTU in ip6_dst_mtu_maybe_forward

Alice Mikityanska <[email protected]>
net: ipv6: Fix UDP length overflow with PMTU discover and big MTU

Alice Mikityanska <[email protected]>
net: ipv4: Fix UDP length overflow with PMTU discover and big MTU

Kuniyuki Iwashima <[email protected]>
af_unix: Return immediately when manage_oob() returns NULL for 0-length buffer.

Kuniyuki Iwashima <[email protected]>
af_unix: Update last skb marker in manage_oob().

Karl Mehltretter <[email protected]>
virtio_input: stop callbacks before unregistering input device

Xiong Weimin <[email protected]>
virtio_input: reset device if input_register_device() fails

Jia Jia <[email protected]>
vhost: invalidate vring access on IOTLB transitions

Jia Jia <[email protected]>
vduse: validate virtqueue alignment

Andrew Stellman <[email protected]>
virtio-pci: return IRQ_HANDLED after non-zero ISR

Linfeng Sun <[email protected]>
vdpa_sim_net: check TX pull result before RX copy

Linfeng Sun <[email protected]>
vdpa_sim_blk: reject out-of-range sector starts

Yu Zhang <[email protected]>
vhost-vdpa: protect config_ctx from being freed under the config callback

Yu Zhang <[email protected]>
vhost-vdpa: don't install the eventfd_ctx_fdget() error in config_ctx

Jia Jia <[email protected]>
vhost/vdpa: reject VRING_NUM larger than device max

Jia Jia <[email protected]>
virtio_console: do not free control-out buffers on remove

Karl Mehltretter <[email protected]>
virtio: fix use-after-free in unregister_virtio_device()

Alexander Graf <[email protected]>
virtio_ring: fix stale descriptor flags after a failed packed add

Sascha Bischoff <[email protected]>
irqchip/gic-v5: Preserve ICC_CR0_EL1 state

hpp.iscas <[email protected]>
ASoC: mt6351: Publish the OF module alias

Donggeun Yoo <[email protected]>
regulator: pf1550: fix which regulator is notified

Florian Westphal <[email protected]>
netfilter: ip6_tables: set F_PROTO when proto value is nonzero

Florian Westphal <[email protected]>
netfilter: nfnetlink_log: cope with concurrent instance destruction

Filipe Manana <[email protected]>
btrfs: fix unnecessary transaction commit fallback from btrfs_log_all_parents()

hpp.iscas <[email protected]>
ASoC: Intel: SST: Publish the PCI module aliases

hpp.iscas <[email protected]>
ASoC: bcm: bcm63xx: Publish the OF module aliases

Guenter Roeck <[email protected]>
hwmon: (sht4x) Fix return value from heater_enable_store()

Guenter Roeck <[email protected]>
hwmon: (sht4x) Add missing locks

hanzhijian <[email protected]>
hwmon: (yogafan) fix non-kernel-doc comment

Antonin Godard <[email protected]>
Documentation: hwmon: replace full-width colon by a standard ASCII colon

Jared Kangas <[email protected]>
hwmon: (ina2xx) Decouple in0 and curr1 alarms

Jared Kangas <[email protected]>
hwmon: (ina2xx) Replace masks with enum in alert functions

Jared Kangas <[email protected]>
hwmon: (ina2xx) Parameterize ina2xx_data in ina226_alert_read()

Jared Kangas <[email protected]>
hwmon: (ina2xx) Acquire hwmon_lock in shunt_resistor_show()

Guenter Roeck <[email protected]>
hwmon: Fix potential UAF in pec_store

Guenter Roeck <[email protected]>
Documentation/hwmon: Document hwmon_notify_event()

Geert Uytterhoeven <[email protected]>
hwmon: (ltc4282) Make sure clk_init_data is fully initialized

Hemanth Selam <[email protected]>
iommu/amd: Fix ineffective error check in nested domain allocation

Vasant Hegde <[email protected]>
iommu/amd: Fix premature break in init_iommu_one() again

Karl Mehltretter <[email protected]>
iommu/amd: Do not reallocate GA log buffers on resume

Fangyu Yu <[email protected]>
iommu/riscv: Avoid waiting on failed command enqueue

Fangyu Yu <[email protected]>
iommu/riscv: Serialize command queue publishing

Fangyu Yu <[email protected]>
iommu/riscv: Add command queue lock

Chengyu Zhu <[email protected]>
erofs: delimit inode_share cache key components

Edward Adam Davis <[email protected]>
ALSA: caiaq: Decoupling ep1_in_urb in caiaq dev

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Reject non-scalar bpf_loop iteration counts

Vineeth Karumanchi <[email protected]>
net: macb: fix NULL pointer dereference on unbind with fixed-link

Jamal Hadi Salim <[email protected]>
net/sched: ets: clamp quantum in parse and fallback paths

Jamal Hadi Salim <[email protected]>
net/sched: drr: clamp quantum in change class

Jamal Hadi Salim <[email protected]>
net/sched: pie: clamp psched_mtu in pie_drop_early

Jamal Hadi Salim <[email protected]>
net/sched: dualpi2: clamp psched_mtu at all call sites

Jamal Hadi Salim <[email protected]>
net/sched: hhf: clamp quantum in change and init paths

Jamal Hadi Salim <[email protected]>
net/sched: sfq: clamp quantum in change path

Jamal Hadi Salim <[email protected]>
net/sched: fq_pie: clamp quantum in change path

Carolina Jubran <[email protected]>
net/mlx5e: Keep HW timestamp stats monotonic across reconfiguration

Lama Kayal <[email protected]>
net/mlx5: E-Switch, prevent mc_list repopulation during vport disable

Yael Chemla <[email protected]>
net/mlx5: E-Switch: fix use-after-free in mlx5_eswitch_termtbl_put

Carolina Jubran <[email protected]>
net/mlx5e: Fix use-after-free race in sample_restore_put()

Carolina Jubran <[email protected]>
net/mlx5e: Fix ETS zero BW reporting when one TC holds 100%

Akiva Goldberger <[email protected]>
net/mlx5: LAG, use local tracker to update active ports

Shahar Shitrit <[email protected]>
net/mlx5e: Fix reporting support for all RS FEC variants

Shahar Shitrit <[email protected]>
net/mlx5e: Fix setting RS FEC after remapping

Shahar Shitrit <[email protected]>
net/mlx5e: Fix missing FEC mode mapping for RS_544_514_INTERLEAVED_QUAD

Weiming Shi <[email protected]>
net/sched: defer qdisc freeing after failed creation

Mukesh Kumar Chaurasiya (IBM) <[email protected]>
powerpc/entry: Fix irq_soft_mask corruption on replayed interrupt exit

XingWang Xiang <[email protected]>
net: mctp: i3c: serialize probe with bus removal

Thorsten Blum <[email protected]>
powerpc/kexec_file: Use inclusive range checks for excluded memory

Thorsten Blum <[email protected]>
powerpc/kexec_file: Use inclusive range checks in add_usable_mem()

Eduard Zingerman <[email protected]>
bpf: propagate mark_chain_precision() errors out of loop_flag_is_zero()

Eduard Zingerman <[email protected]>
bpf: mark a NULL call argument precise

Nikhil P. Rao <[email protected]>
pds_core: don't release PCI regions for VFs on reset

Nikhil P. Rao <[email protected]>
pds_core: fix cmd_regs access racing BAR unmap on reset

Jamal Hadi Salim <[email protected]>
net: reject oversized tx_queue_len at netlink parse time

Jamal Hadi Salim <[email protected]>
net: cap tx_queue_len at S16_MAX to prevent oversized ring allocations

Seungwon Bae <[email protected]>
vxlan: reject dynamic fdb entries that reference a nexthop id

Alexandra Winter <[email protected]>
s390/ism: folio_put() after error

Alexandra Winter <[email protected]>
dibs: Unregister dibs_class after error

Jason Winter <[email protected]>

    net: usb: cx82310_eth: drop URB after 0xffff reboot sentinel to prevent partial_data heap overflow

Nikhil P. Rao <[email protected]>
ionic: use netif_txq_maybe_stop() in ionic_tx()

Viswajith Murali <[email protected]>
octeontx2-af: mcs: Clear stale X2P calibration state before calibration

Nikolay Aleksandrov <[email protected]>
net: bridge: mcast: properly convert mglist to rcu

Jakub Kicinski <[email protected]>
net: dsa: mv88e6xxx: bound the policy rule dump by the caller's buffer size

Jakub Kicinski <[email protected]>
eth: nfp: drop the replaced rule from the list when reprogramming fails

Jakub Kicinski <[email protected]>
eth: nfp: bound the ntuple rule dump by the caller's buffer size

Jakub Kicinski <[email protected]>
net: dsa: bcm_sf2: bound the CFP rule dump by the caller's buffer size

Eric Dumazet <[email protected]>
bonding: use skb_cow_head() in bond_do_alb_xmit() and rlb_arp_xmit()

Ido Schimmel <[email protected]>
nexthop: Initialize extack in remove_nh_grp_entry()

Steven Rostedt <[email protected]>
tracing: Fix comment in tracing_buffers_splice_read()

Vincent Donnefort <[email protected]>
ring-buffer: Cap static ring buffer nr_pages

Vincent Donnefort <[email protected]>
tracing: Fix subbuf resize races with trace_pipe_raw readers

Vincent Donnefort <[email protected]>
ring-buffer: Remove ring_buffer_per_cpu::mapped

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Preserve inner map identity in callback frames

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Mark NULL kptr stores precise

Nuoqi Gui <[email protected]>
bpf: Cancel special fields when recycling rhtab elements

Yuan Chen <[email protected]>
bpf: Preserve special fields in recycled rhtab elements

Jiayuan Chen <[email protected]>
selftests/bpf: Fix flaky bpf_nf test when random NAT port is 0

Masami Hiramatsu (Google) <[email protected]>
tracing: Fix to avoid creating trace instances with duplicate names

Ning Ding <[email protected]>
bpf: Reject untrusted allocated-object pointers

Ning Ding <[email protected]>
bpf: Keep refcount_acquire nullable for borrowed RCU kptrs

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Require MEM_PERCPU for percpu kptr stores

Andy Shevchenko <[email protected]>
thermal: sysfs: switch to use scnprintf() to suppress truncation warning

Eduard Zingerman <[email protected]>
bpf: Mark the zero register precise for a register-form NULL check

Eduard Zingerman <[email protected]>
bpf: Don't predict JMP32 pointer vs zero comparisons

Eduard Zingerman <[email protected]>
bpf: Don't resurrect a scalar id dropped by collect_linked_regs()

Eduard Zingerman <[email protected]>
bpf: Don't infer non-NULL from a pointer with an unbounded offset

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Reject legacy packet loads from callbacks

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Mark faultable stack helpers as sleepable

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Mark bpf_btf_find_by_name_kind() as sleepable

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Check ancestor frames for rbtree callbacks

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Track verifier instruction stats for each subprogram

Eduard Zingerman <[email protected]>
bpf: don't rewrite bpf_fastcall patterns entered by a jump

Eduard Zingerman <[email protected]>
bpf: zero extend the result of an arena 32-bit cmpxchg

Taylor Bates <[email protected]>
mlxsw: spectrum_ptp: Fix napi_gro_receive() call from GC workqueue context

Justin Chen <[email protected]>
net: bcmasp: fix tx_spb_ring_full() checking same slot cnt times

Justin Chen <[email protected]>

    net: bcmasp: clear txcb->last before writing each descriptor

Cezary Rojewski <[email protected]>
ASoC: Intel: avs: Refactor and fix init_config access

Cezary Rojewski <[email protected]>
ASoC: Intel: avs: Fix unbalanced module reference count

Cezary Rojewski <[email protected]>
ASoC: Intel: avs: Do not ignore -ENOENT when loading a topology

Cezary Rojewski <[email protected]>
ASoC: Intel: avs: Clean up streams if their initialization fails

Cezary Rojewski <[email protected]>
ASoC: Intel: avs: Clean up the bus when fetching ML caps fails

Xixin Liu <[email protected]>
nvme-tcp: defer TLS inline send to io_work

Mohamed Khalfella <[email protected]>
nvmet: print namespace IDs as unsigned 32bit value

Mohamed Khalfella <[email protected]>
nvme: print namespace IDs as unsigned 32bit value

Mohamed Khalfella <[email protected]>
nvme: remove stale namespaces by NSID range during scan

Steven Rostedt <[email protected]>
ring-buffer: Add checking nr_subbufs to persistent ring buffer validation

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Mark syscall helpers as sleepable

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Mark sched_process_wait argument as nullable

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Reject resilient lock operations in rbtree callbacks

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Reject tail calls directly from callback frames

Kumar Kartikeya Dwivedi <[email protected]>
bpf: Mark signal tracepoint siginfo arguments as scalar

Jiayuan Chen <[email protected]>
bpf: Fix NULL-ptr-deref in btf_var_show()

Jiayuan Chen <[email protected]>
bpf: Fix NULL-ptr-deref when showing a void BTF type

Jiayuan Chen <[email protected]>
bpf: Reject key-less BTF for hash maps

Igor Paunovic <[email protected]>
drm/rockchip: rk3066_hdmi: Add missing Kconfig selects

Igor Paunovic <[email protected]>
drm/rockchip: dw_dp: Select DRM_BRIDGE_CONNECTOR

Takashi Iwai <[email protected]>
ALSA: caiaq: Fix potential double-free at error path

HyeongJun An <[email protected]>
selftests/alsa: Fix the step check for INTEGER controls

Gao Xiang <[email protected]>
erofs: disable LZ4 rolling decompression for now

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

HW He <[email protected]>
net: gro: Fix nesting of TCP GSO SKBs in skb_gro_receive_list()

Lorenzo Bianconi <[email protected]>
net: stmmac: reconfigure RX packet parser table in stmmac_hw_setup() after reset

Lorenzo Bianconi <[email protected]>
net: airoha: enable RX_DONE interrupt for RX queue 31

Ritesh Harjani (IBM) <[email protected]>
powerpc: Do not restore KUAP in arch_exit_to_user_mode_prepare()

Ritesh Harjani (IBM) <[email protected]>
powerpc: Don't drop _TIF_RESTOREALL on syscall restart

Allison Henderson <[email protected]>
net/rds: don't let rds_conn_shutdown() consume a concurrent drop

Håkon Bugge <[email protected]>
net/rds: acquire the fastpath locks in rds_conn_shutdown()

Allison Henderson <[email protected]>
net/rds: acquire RDS_IN_XMIT in rds_tcp_reset_callbacks()

Gerd Rausch <[email protected]>
net/rds: tcp: don't force RDS_CONN_RESETTING over a concurrent shutdown

Allison Henderson <[email protected]>
net/rds: clear cp_flags bits individually in rds_conn_path_reset()

Allison Henderson <[email protected]>
net/rds: use clear_bit_unlock() in release_refill()

Allison Henderson <[email protected]>
net/rds: use wq_has_sleeper() in release_in_xmit()

Nicolai Buchwitz <[email protected]>
net: macb: exclude software FCS from TX byte statistics

Théo Lebrun <[email protected]>
net: macb: unify device pointer naming convention

Kuniyuki Iwashima <[email protected]>
net: Remove conflicting altnames for dying netns in __dev_change_net_namespace().

Eric Dumazet <[email protected]>
bonding: do not clear curr_active_slave prematurely when releasing all slaves

Eduard Zingerman <[email protected]>
bpf: reject BPF_PSEUDO_FUNC reference to the main program

Henry Martin <[email protected]>
tracing/probes: Fix use-after-free on field name/type of events with multiple probes

Joas Antonio dos Santos <[email protected]>
netfilter: nf_conntrack_sip: fix OOB read in sip_skip_whitespace()

Kyle Zeng <[email protected]>
ipvs: fix reversed sequence option serialization

Yogesh Mohan Marimuthu <[email protected]>
drm/amdgpu/userq: fix struct drm_amdgpu_info_device padding for 32bit compile

FAN YE <[email protected]>
btrfs: zstd: fix lost wakeup when waiting for a workspace

Qu Wenruo <[email protected]>
btrfs: do not force reloc root creation during qgroup_account_snapshot()

Avi Weiss <[email protected]>
btrfs: send: fix lost error return value in will_overwrite_ref()

Johannes Thumshirn <[email protected]>
btrfs: zoned: finish active block group cleanup if call_zone_finish() fails

Qu Wenruo <[email protected]>
btrfs: return proper negative error code for update_raid_extent_item()

Qu Wenruo <[email protected]>
btrfs: fix the possible bioc_list memory leak during error

Shuangpeng Bai <[email protected]>
btrfs: fix transaction use-after-free in raid stripe insertion

James C. Owens <[email protected]>
btrfs: scrub: report the failing sector's address, not the stripe base

Eduard Zingerman <[email protected]>
bpf: backtracking shouldn't clear outer frame R1-R5 for callbacks

Eduard Zingerman <[email protected]>
bpf: backtrack_insn(): Handle ld_{abs,ind} subprog exit edge

Linus Walleij <[email protected]>
ASoC: ux500: Program the MSP FIFO watermarks

Linus Walleij <[email protected]>
ASoC: ux500: Allow repeated MSP prepare calls

Linus Walleij <[email protected]>
ASoC: ux500: Remove obsolete PRCMU QoS calls

Linus Walleij <[email protected]>
ASoC: ux500: Request the MSP MMIO resource

Linus Walleij <[email protected]>
ASoC: ux500: Deassert the MSP reset during probe

Linus Walleij <[email protected]>

    mfd: db8500-prcmu: Fold dbx500 header into db8500

Linus Walleij <[email protected]>
ASoC: ux500: Validate MSP DAI configuration

Linus Walleij <[email protected]>
ASoC: ux500: Correct MSP frame and bit clock setup

Linus Walleij <[email protected]>
ASoC: ux500: Propagate MSP setup errors

Linus Walleij <[email protected]>
ASoC: ux500: Fix MSP stream lifecycle handling

Dmitry Torokhov <[email protected]>
platform/x86: x86-android-tablets: hold device reference for secondary fwnode teardown

John Ogness <[email protected]>
printk/nbcon: Change nbcon_irq_work to IRQ_WORK_LAZY

Qingyu Zhang <[email protected]>
ALSA: ump: do not touch legacy_rmidi before it exists

Namjae Jeon <[email protected]>
ksmbd: fix sparc build with atomic work state

Sunil Goutham <[email protected]>
octeontx2-af: Fix limiting SRIOV VF count logic

Eric Dumazet <[email protected]>
locking/lockdep: Invalidate stale class_cache entries for zapped classes

Leo Yan <[email protected]>
perf/core: Skip empty AUX records with only format flags

Mario Limonciello <[email protected]>
x86/itmt: Don't make ITMT enablement depend on debugfs

Shubhang Kaushik (Ampere) <[email protected]>

    sched/core: Skip rq->avg_idle update without a valid idle_stamp

Seiji Nishikawa <[email protected]>
sched/rt,dl: Skip migrate-disabled tasks when picking a push candidate

Ivy Lopez <[email protected]>
scsi: mpt3sas: Avoid out-of-bounds cpumask_of_node() call in _base_assign_reply_queues()

Xixin Liu <[email protected]>
perf: RISC-V: check cpu_hw_evt before dereference in overflow IRQ

Eric Dumazet <[email protected]>
bonding: alb: fix uninitialized transport header access in alb_determine_nd()

Guanghui Yang <[email protected]>
btrfs: restore active device pointers after failed sprout

Guanghui Yang <[email protected]>
btrfs: detach failed sprout device from transaction update list

Taimuraz Kaitmazov <[email protected]>
accel/amdxdna: refuse to flush an imported BO

HyeongJun An <[email protected]>
ALSA: dummy: Report a change when one capture switch channel moves

Lu Yao <[email protected]>
drm/xe/oa: Remove sysfs entry on idr_alloc failure in xe_oa_add_config_ioctl()

Richard Fitzgerald <[email protected]>
ASoC: cs35l56: Fix probe deadlock waiting for SoundWire enumeration

Richard Fitzgerald <[email protected]>

    ASoC: cs35l56: Request IRQ in cs35l56_common_probe()

Keith Busch <[email protected]>
block: save page offset gaps in cloned bio

wangdicheng <[email protected]>
ASoC: amd: yc: fix memory leak in acp6x_pdm_dma_close()

wangdicheng <[email protected]>
ASoC: amd: renoir: fix disable_pdm_interrupts() to clear mask bits

Ștefan Ghețu <[email protected]>
ASoC: fsl_micfil: balance mclk enable/disable

Vasily Gorbik <[email protected]>
s390/boot: Avoid IPL parameter append past command line

Vasily Gorbik <[email protected]>
s390/boot: Fix physical memory search range

Xu Rao <[email protected]>
ALSA: hda: restore MFG widget enumeration after core split

Eric Dumazet <[email protected]>
net: bonding: annotate lockless writes with WRITE_ONCE()

Hui Su <[email protected]>
staging: fbtft: make dirty_lock IRQ-safe

Kuniyuki Iwashima <[email protected]>
af_packet: Don't cast tpacket_hdr.tp_len to int in tpacket_parse_header().

Eric Dumazet <[email protected]>
ipv6: sr: restore network header before routing and forwarding

David Laight <[email protected]>
tipc: Dont send random pad bytes in RESET/ACTIVATE messages

Tung Nguyen <[email protected]>
tipc: fix NULL deref in tipc_named_node_up() on empty publication list

Eric Dumazet <[email protected]>
ip6_gre: check tunnel info before xmit in ip6gre_tunnel_xmit

Eric Dumazet <[email protected]>
ipv6: mcast: use jiffies_delta_to_clock_t() in igmp6_mc_seq_show()

Eric Dumazet <[email protected]>
ipv6: mcast: use rcu_assign_pointer() for __rcu list updates

Eric Dumazet <[email protected]>
ipv6: mcast: fix delay calculation in igmp6_join_group()

Eric Dumazet <[email protected]>
ipv6: mcast: use copy-on-write RCU updates in ip6_mc_source()

Eric Dumazet <[email protected]>
ipv6: mcast: fix RCU list diversion in ip6_mc_del1_src()

Josh Poimboeuf <[email protected]>
objtool/klp: Fix checksums for constant pool references

Yafang Shao <[email protected]>
klp-build: Fix wrong index in funcs cleanup error path

Qingfang Deng <[email protected]>
ppp: ppp_synctty: simplify tty disc_data access

Qingfang Deng <[email protected]>
ppp: ppp_async: simplify tty disc_data access

Eric Dumazet <[email protected]>
igmp: convert struct ip_sf_list to RCU

Mehmet Koseoglu <[email protected]>
rust: samples: add missing newlines in rust_print_main

Jamal Hadi Salim <[email protected]>
net/sched: cls_u32: fix duplicate handle when node ID pool is exhausted

Selvamani Rajagopal <[email protected]>
net: ethernet: oa_tc6: Fix for the wrong data type

Selvamani Rajagopal <[email protected]>
net: ethernet: oa_tc6: Disable tx queues on fatal error

Selvamani Rajagopal <[email protected]>
net: ethernet: oa_tc6: Improve the error recovery

Selvamani Rajagopal <[email protected]>
net: ethernet: oa_tc6: Protect skb pointer used by two different kernel instances

Ciprian Regus <[email protected]>
net: ethernet: oa_tc6: Add the OA_TC6_ prefix to standard registers

Ciprian Regus <[email protected]>
net: ethernet: oa_tc6: Export standard defined registers

Ciprian Regus <[email protected]>
net: ethernet: oa_tc6: Handle the OA TC6 SPI protected mode

Arvind Yadav <[email protected]>
drm/pagemap: Reset migration page count on eviction retry

Arvind Yadav <[email protected]>
drm/pagemap: Prevent double migration of device pages

Linus Walleij <[email protected]>
ASoC: ab8500: Skip missing DMIC GPIOs on AB8505

Linus Walleij <[email protected]>
ASoC: ab8500: Remove the nonfunctional sidetone apply control

bui duc phuc <[email protected]>
ASoC: codecs: ab8500: Use guard() for mutex locks

Linus Walleij <[email protected]>
ASoC: ab8500: Validate and program TDM slots correctly

Linus Walleij <[email protected]>
ASoC: ab8500: Correct digital interface format setup

Linus Walleij <[email protected]>
ASoC: ab8500: Repair the DAPM capture graph

Linus Walleij <[email protected]>
ASoC: ab8500: Reset the audio block before configuring it

Armin Wolf <[email protected]>
platform/x86: asus-laptop: Fix ACPI event handling

Gongwei Li <[email protected]>
Bluetooth: hci_mrvl: Fix wrong return value check of wait_on_bit_timeout()

Pauli Virtanen <[email protected]>
Bluetooth: L2CAP: clear FLAG_DEFER_SETUP only for same PID/PSM

Pauli Virtanen <[email protected]>
Bluetooth: L2CAP: fix out-of-bounds write in l2cap_ecred_connect

Pauli Virtanen <[email protected]>
Bluetooth: L2CAP: fix chan mode for LE_CONN_REQ + EXT_FLOWCTL pchan

Aleksandr Nogikh <[email protected]>
Bluetooth: hci_core: Fix race condition during device registration

Laxman Acharya Padhya <[email protected]>
Bluetooth: btintel: bound firmware ID by TLV length

Laxman Acharya Padhya <[email protected]>
Bluetooth: btintel: validate version TLV value lengths

Jiacheng Xu <[email protected]>
workqueue: reject watchdog thresholds that overflow jiffies

Kiran K <[email protected]>
Bluetooth: btintel_pcie: Clear automask on spurious interrupts

Wanwu Li <[email protected]>
sched_ext: Fix vtime delta loss in scx_flatcg cgroup migration

Wanwu Li <[email protected]>
sched_ext: Fix timer pinning and return value in scx_central

Heiko Carstens <[email protected]>
s390/pai: Reduce excessive debug feature size

Sumanth Korikkar <[email protected]>
s390/diag324: Preserve -EBUSY return code

Vasily Gorbik <[email protected]>
s390/ipl: Fix NULL deref in dump_reipl without re-IPL parm block

Vasily Gorbik <[email protected]>
s390/ipl: Fix NULL deref in kdump without re-IPL parm block

Heiko Carstens <[email protected]>
s390/time: Use jiffies instead of jiffies_64

Namjae Jeon <[email protected]>
ksmbd: fix listener task lifetime on netdev events

Namjae Jeon <[email protected]>
ksmbd: rate limit unmapped SID errors

Namjae Jeon <[email protected]>
ksmbd: propagate DACL parsing errors

Namjae Jeon <[email protected]>
ksmbd: safely drain sessions during logoff

ChenXiaoSong <[email protected]>
smb/server: cancel async requests when closing connection

Miklos Szeredi <[email protected]>
ovl: return EINVAL instead of EIO in case of mismatched user_ns

Ville Syrjälä <[email protected]>
drm/i915/cdclk: Fix dg2_power_well_count() return type

Chaitanya Kumar Borah <[email protected]>
drm/i915/dp_mst: Remove duplicate intel_pfit_compute_config() call

Kiran Kumar K <[email protected]>
octeontx2-af: fix CN20K default MCAM rule removal on port cleanup

Randy Dunlap <[email protected]>
dma-buf: fix some kernel-doc warnings

Yilin Zhang <[email protected]>
ALSA: pcm: Serialize PCM mmap with buffer reallocation to fix page UAF

David Howells <[email protected]>
cachefiles: Fix potential UAF/KASAN warning

David Howells <[email protected]>
netfs: Fix read progress reporting

David Howells <[email protected]>
netfs: Mark folios with COPY_TO_CACHE whilst issuing subreqs

David Howells <[email protected]>
netfs: Fix readahead synchronisation issues by loading all folios upfront

Edward Adam Davis <[email protected]>
netfs: break unbuffered write when netfs_alloc_subrequest() fails

David Howells <[email protected]>
netfs: Fix subreq ref leak

David Howells <[email protected]>
netfs: Fix i_size update for partial transfer

David Howells <[email protected]>

    netfs: Fix error vs transferred passed to ->ki_complete()

David Howells <[email protected]>
netfs: Fix unbuffered/DIO write partial transfer error return

Wang Yan <[email protected]>
perf powerpc-vpadtl: Fix raw_size of DTL samples

Colin Ian King <[email protected]>
OPP: of: Fix potential multiplication overflow when calculating freq

Adrian Hunter <[email protected]>
perf symbol: Do not use debug file as the binary type

Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Fix NULL pointer dereference in PM callbacks

Baul Lee <[email protected]>
vxlan: mdb: Fix use-after-free in vxlan_mdb_remote_src_del()

James Nugraha <[email protected]>
net: amd-xgbe: discard rx packets with bad FCS

Xuanqiang Luo <[email protected]>

    raw: annotate disconnect-side IPv4 match writers

Henry Martin <[email protected]>
sctp: fix soft lockup from unpadded ASCONF-ACK parameter iteration

Andy Shevchenko <[email protected]>
smb: client: transport: Fix debug printing in __release_mid()

Huiwen He <[email protected]>
smb/client: invalidate fscache for fallocate range operations

Huiwen He <[email protected]>
smb/client: fix stale page cache in insert/collapse range

Huiwen He <[email protected]>
smb/client: fix integer truncation in collapse range

Huiwen He <[email protected]>
smb/client: fix data corruption in emulated insert range

Huiwen He <[email protected]>
smb/client: mark file sparse before emulating insert range

Huiwen He <[email protected]>
smb/client: validate new EOF for zero range

Huiwen He <[email protected]>
smb/client: validate new EOF for insert range

sangram kumar yerra <[email protected]>
scsi: ufs: ufs-pci: Add MCQ support for Intel UFS 4.0 controllers

sangram kumar yerra <[email protected]>
scsi: ufs: ufs-pci: Add support for Intel UFS 4.0 HS-Gear5

Milan P. Gandhi <[email protected]>
scsi: mpi3mr: Fix target device refcount leak in mpi3mr_sas_port_add()

Milan P. Gandhi <[email protected]>
scsi: mpi3mr: Fix NULL pointer dereference in mpi3mr_sas_port_add()

Xin Long <[email protected]>
sctp: fix a TOCTOU race in SCTP_CMD_TIMER_START

Victor Nogueira <[email protected]>
net/sched: act_api: fix skb sizing and action leak on reoffload delete

Victor Nogueira <[email protected]>
net/sched: act_api: size the RTM_GETACTION reply from the actions

Victor Nogueira <[email protected]>
net/sched: act_api: budget all shared attributes in notify skbs

Dong Chenchen <[email protected]>
net: iptunnel: fix stale transport header during tunnel decapsulation

Lorenzo Bianconi <[email protected]>
net: stmmac: fix dma mapping leak in stmmac_tso_xmit()

Eric Dumazet <[email protected]>
tcp: use GFP_ATOMIC in tcp_send_active_reset()

Eric Dumazet <[email protected]>
net: icmp: avoid invalid transport header access in icmp_send tracepoint

Eduard Zingerman <[email protected]>
bpf: don't downgrade half-dead scalar zero spills to STACK_ZERO

Baolin Liu <[email protected]>
ntfs: leave HasEA flag untouched on setxattr failure

Eduard Zingerman <[email protected]>
bpf: check_cond_jmp_op(): properly infer if register is null

Dennis Tighe <[email protected]>
ntfs: reject invalid sectors_per_cluster in the boot sector

Dennis Tighe <[email protected]>
ntfs: bound $AttrDef table walk to the loaded table size

Wentao Guan <[email protected]>
ntfs: treat any nonzero dio zero-range return as an error

Dennis Tighe <[email protected]>
ntfs: do not mark the volume clean in sync_fs when errors were recorded

Baolin Liu <[email protected]>
ntfs: skip free cluster decrement when rollback fails

Baolin Liu <[email protected]>
ntfs: only count successfully cleared runs when freeing clusters

Baolin Liu <[email protected]>
ntfs: fix kmap_local leak in write_mft_record_nolock() error paths

Baolin Liu <[email protected]>
ntfs: return real error from ntfs_non_resident_attr_record_add()

Baolin Liu <[email protected]>
ntfs: preserve error code in ntfs_resident_attr_record_add()

Baolin Liu <[email protected]>
ntfs: return -ERANGE for undersized xattr buffer

Baolin Liu <[email protected]>
ntfs: propagate reparse index insertion failure

Baolin Liu <[email protected]>
ntfs: return DT_UNKNOWN on inode lookup failure in readdir

Slawomir Stepien <[email protected]>
drm/cirrus-qemu: Validate BAR0 size during probe

Ali Ahmet Memis <[email protected]>
ufs: do not treat unreadable directory blocks as empty

Tomeu Vizoso <[email protected]>
accel: ethosu: Don't read the U65 rounding mode as a storage mode

Guopeng Zhang <[email protected]>
cgroup/cpuset: Preserve boot-isolated CPUs on partition release

Guopeng Zhang <[email protected]>
selftests/cgroup: Drop invalid boot isolation comparison

Taimuraz Kaitmazov <[email protected]>
accel/amdxdna: put the chained BO when its mapping fails

Taimuraz Kaitmazov <[email protected]>
accel/amdxdna: reject a command chain that carries no commands

Lizhi Hou <[email protected]>
accel/amdxdna: Remove __counted_by from struct amdxdna_cmd_chain

Tetsuo Handa <[email protected]>
printk: Don't WARN on kthread_run failure.

Sajal Gupta <[email protected]>
drm/gud: validate GUD_ROTATION_0 is present in supported rotations

Tejun Heo <[email protected]>
sched_ext: Fix spurious aborts in scx_bpf_dsq_move() on ownership change races

Hui Su <[email protected]>
bpf: Fix percpu map update indexing with sparse CPU IDs

Hui Su <[email protected]>
bpf: Fix BPF_F_CPU validation for sparse CPU IDs

Jiayuan Chen <[email protected]>
bpf: Fix REG INVARIANTS VIOLATION on speculative pointer arithmetic

Hongfu Li <[email protected]>
selftests/cgroup: Fix cg_run_in_subcgroups ignoring arg parameter

Hemanth Selam <[email protected]>
selftests/cgroup: set the test plan after the setup checks

Liang Luo <[email protected]>
sched_ext: Fix nonexistent field in sched-ext.rst example

Xixin Liu <[email protected]>
nvmet-rdma: fix queue leak when connect backlog is exceeded

Kanchan Joshi <[email protected]>
nvme: fix racy access to FDP placement id array

Kanchan Joshi <[email protected]>

    nvme: set ns->head in nvme_alloc_ns_head

Nilay Shroff <[email protected]>
nvme: add context annotations for nvme_subsystem::lock

Xixin Liu <[email protected]>
nvme-rdma: fix -EIO cleanup order in queue_rq

Youssef Samir <[email protected]>
accel/qaic: Address potential out-of-bounds read in resp_worker()

Benjamin Leggett <[email protected]>
drm/virtio: use the DMA API for resource backing on Xen

Dan Carpenter <[email protected]>
drm/virtio: Fix a NULL vs ERR_PTR() bug in virtio_gpu_user_framebuffer_create()

Jad Keskes <[email protected]>
EDAC/device_sysfs: Use kstrtouint() for poll_msec to prevent truncation

Qiuxu Zhuo <[email protected]>
EDAC/igen6: Fix Raptor Lake-P logged error address

Qiuxu Zhuo <[email protected]>
EDAC/igen6: Fix channel address decode for non-hash mode

Qiuxu Zhuo <[email protected]>
EDAC/igen6: Fix channel selection hash

Qiuxu Zhuo <[email protected]>
EDAC/igen6: Fix interleave boundary condition

Yazen Ghannam <[email protected]>
RAS/AMD/ATL, EDAC/amd64: Only load ATL when needed

Vlatko Kosturjak <[email protected]>
ppp_async: drop the errored frame instead of resetting its headroom

Manuel Fombuena <[email protected]>
leds: st1202: Validate pattern input before stopping the sequence

Laxman Acharya Padhya <[email protected]>
wifi: mt76: mt7921: skip unknown CLC firmware records

Laxman Acharya Padhya <[email protected]>
wifi: mt76: mt7921: validate CLC firmware records

Wentao Guan <[email protected]>
iommu/arm-smmu-v3: Disable implementations during devm teardown

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

Diffstat:

 Documentation/ABI/testing/sysfs-fs-erofs           |   2 +-
 Documentation/admin-guide/kernel-parameters.txt    |  37 --
 Documentation/hwmon/gpd-fan.rst                    |   2 +-
 Documentation/hwmon/hwmon-kernel-api.rst           |  15 +
 Documentation/netlink/specs/rt-link.yaml           |   2 +
 Documentation/scheduler/sched-ext.rst              |   2 +-
 MAINTAINERS                                        |   1 +
 Makefile                                           |   4 +-
 arch/arm/mach-ux500/cpu-db8500.c                   |   6 +-
 arch/arm64/kernel/machine_kexec.c                  |   3 +-
 arch/arm64/tools/sysreg                            |   4 +-
 arch/powerpc/include/asm/entry-common.h            |  14 +-
 arch/powerpc/kernel/eeh_driver.c                   |   2 -
 arch/powerpc/kernel/interrupt.c                    |   2 +-
 arch/powerpc/kexec/file_load_64.c                  |   4 +-
 arch/powerpc/kvm/book3s_hv.c                       |   4 +-
 arch/powerpc/platforms/powernv/pci-ioda.c          |   6 +-
 arch/powerpc/platforms/ps3/repository.c            |   5 +-
 arch/riscv/kernel/process.c                        |   4 +-
 arch/riscv/kernel/sys_hwprobe.c                    |   5 +-
 arch/s390/boot/ipl_parm.c                          |  26 +-
 arch/s390/boot/physmem_info.c                      |   2 +-
 arch/s390/crypto/aes_s390.c                        |  87 ++-
 arch/s390/crypto/paes_s390.c                       |  19 +-
 arch/s390/crypto/phmac_s390.c                      |  36 +-
 arch/s390/include/asm/pai.h                        |   1 -
 arch/s390/kernel/debug.c                           |   6 +-
 arch/s390/kernel/diag/diag324.c                    |   3 +-
 arch/s390/kernel/ipl.c                             |  12 +-
 arch/s390/kernel/perf_pai.c                        | 198 ++++--
 arch/s390/kernel/vtime.c                           |   6 +-
 arch/x86/crypto/aria-aesni-avx2-asm_64.S           |   6 +
 arch/x86/crypto/aria-gfni-avx512-asm_64.S          |   3 +
 arch/x86/events/intel/core.c                       |  33 +-
 arch/x86/events/intel/ds.c                         |  18 +-
 arch/x86/events/perf_event.h                       |   3 +
 arch/x86/include/asm/pgtable.h                     |   2 +-
 arch/x86/kernel/alternative.c                      | 111 ++--
 arch/x86/kernel/amd_node.c                         |  25 +-
 arch/x86/kernel/cpu/mce/amd.c                      |   2 +-
 arch/x86/kernel/itmt.c                             |   8 +-
 arch/x86/mm/pat/set_memory.c                       | 148 +++--
 block/bio.c                                        |   9 +
 drivers/accel/amdxdna/aie2_message.c               |   2 +-
 drivers/accel/amdxdna/amdxdna_ctx.c                |   4 +-
 drivers/accel/amdxdna/amdxdna_ctx.h                |   2 +-
 drivers/accel/amdxdna/amdxdna_gem.c                |  13 +-
 drivers/accel/ethosu/ethosu_device.h               |   1 +
 drivers/accel/ethosu/ethosu_drv.c                  |   3 +-
 drivers/accel/ethosu/ethosu_gem.c                  |  11 +-
 drivers/accel/ethosu/ethosu_job.c                  |  16 +-
 drivers/accel/ivpu/ivpu_fw_log.c                   |  87 +--
 drivers/accel/ivpu/ivpu_gem.h                      |  14 +-
 drivers/accel/ivpu/ivpu_ipc.c                      |   7 +-
 drivers/accel/qaic/qaic_control.c                  |  46 +-
 drivers/block/sunvdc.c                             |  17 +
 drivers/block/ublk_drv.c                           |   1 +
 drivers/bluetooth/btintel.c                        |  39 +-
 drivers/bluetooth/btintel_pcie.c                   |   9 +-
 drivers/bluetooth/btmtk.c                          |  11 +-
 drivers/bluetooth/btmtk.h                          |   1 +
 drivers/bluetooth/btqcomsmd.c                      |   6 +-
 drivers/bluetooth/btrtl.c                          |   5 +-
 drivers/bluetooth/btusb.c                          | 105 +++-
 drivers/bluetooth/hci_mrvl.c                       |   3 +-
 drivers/char/virtio_console.c                      |  21 +-
 drivers/clk/ux500/clk-prcmu.c                      |  20 +-
 drivers/clk/ux500/u8500_of_clk.c                   |   2 +-
 drivers/cpufreq/cpufreq.c                          |   6 +-
 drivers/cpuidle/cpuidle-ux500.c                    |   6 +-
 drivers/dibs/dibs_main.c                           |  10 +-
 drivers/edac/altera_edac.c                         |  10 +-
 drivers/edac/amd64_edac.c                          |   2 +
 drivers/edac/edac_device_sysfs.c                   |  11 +-
 drivers/edac/igen6_edac.c                          |  66 +-
 drivers/gpu/drm/adp/Kconfig                        |   1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c            |  20 +-
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  14 +-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c  |  20 +-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c  |   1 +
 drivers/gpu/drm/amd/display/dc/core/dc.c           |   3 +
 drivers/gpu/drm/amd/pm/amdgpu_dpm.c                |   6 +-
 .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c   |   2 -
 .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c   |   4 +-
 drivers/gpu/drm/bridge/tc358768.c                  |  15 +-
 drivers/gpu/drm/bridge/ti-sn65dsi83.c              |   6 +-
 drivers/gpu/drm/drm_exec.c                         |  13 +
 drivers/gpu/drm/drm_pagemap.c                      | 130 +++-
 drivers/gpu/drm/drm_panic_qr.rs                    |   4 +-
 drivers/gpu/drm/gud/gud_drv.c                      |   2 +
 drivers/gpu/drm/i915/display/intel_cdclk.c         |  10 +-
 drivers/gpu/drm/i915/display/intel_display_types.h |   2 +
 drivers/gpu/drm/i915/display/intel_dp.c            |  44 +-
 drivers/gpu/drm/i915/display/intel_dp_mst.c        |   4 -
 drivers/gpu/drm/i915/i915_query.c                  |   4 +-
 drivers/gpu/drm/logicvc/Kconfig                    |   1 -
 drivers/gpu/drm/rockchip/Kconfig                   |   3 +
 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c    |   7 +-
 drivers/gpu/drm/scheduler/tests/mock_scheduler.c   |  11 +
 drivers/gpu/drm/tiny/cirrus-qemu.c                 |   3 +
 drivers/gpu/drm/virtio/virtgpu_display.c           |   2 +-
 drivers/gpu/drm/virtio/virtgpu_drv.h               |  20 +
 drivers/gpu/drm/virtio/virtgpu_object.c            |   2 +-
 drivers/gpu/drm/virtio/virtgpu_vq.c                |   6 +-
 drivers/gpu/drm/xe/Makefile                        |   4 +-
 drivers/gpu/drm/xe/instructions/xe_gpu_commands.h  |   1 +
 drivers/gpu/drm/xe/regs/xe_i2c_regs.h              |   2 +
 drivers/gpu/drm/xe/xe_amc.c                        | 197 ++++++
 drivers/gpu/drm/xe/xe_amc.h                        |  25 +
 drivers/gpu/drm/xe/xe_i2c.c                        | 128 ++--
 drivers/gpu/drm/xe/xe_i2c.h                        |  13 +-
 drivers/gpu/drm/xe/xe_oa.c                         |   6 +-
 drivers/gpu/drm/xe/xe_pagefault.c                  |  10 +
 drivers/gpu/drm/xe/xe_pagefault_types.h            |   3 +
 drivers/gpu/drm/xe/xe_ring_ops.c                   |  11 +
 drivers/hwmon/applesmc.c                           |   7 +-
 drivers/hwmon/aspeed-pwm-tacho.c                   |   4 +-
 drivers/hwmon/asus_rog_ryujin.c                    | 105 +++-
 drivers/hwmon/chipcap2.c                           |   9 +-
 drivers/hwmon/corsair-cpro.c                       |  24 +-
 drivers/hwmon/gpio-fan.c                           |  13 +-
 drivers/hwmon/hwmon.c                              |  21 +-
 drivers/hwmon/ina2xx.c                             | 163 ++++-
 drivers/hwmon/ltc4282.c                            |   2 +-
 drivers/hwmon/mcp9982.c                            |   2 +
 drivers/hwmon/nct6694-hwmon.c                      |  35 +-
 drivers/hwmon/pmbus/pmbus_core.c                   |   4 +-
 drivers/hwmon/sht4x.c                              |   8 +-
 drivers/hwmon/yogafan.c                            |   2 +-
 drivers/i2c/busses/i2c-designware-common.c         |   2 +
 drivers/i2c/busses/i2c-designware-core.h           |  85 +--
 drivers/i2c/busses/i2c-designware-master.c         |   2 +
 drivers/i2c/busses/i2c-designware-slave.c          |   2 +
 drivers/iommu/amd/init.c                           |  22 +-
 drivers/iommu/amd/nested.c                         |   7 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c        |   4 +-
 drivers/iommu/riscv/iommu.c                        | 121 ++--
 drivers/iommu/riscv/iommu.h                        |   2 +
 drivers/iommu/s390-iommu.c                         |   2 +
 drivers/irqchip/irq-gic-v5.c                       |   6 +-
 drivers/leds/leds-st1202.c                         |  10 +-
 drivers/media/i2c/mt9p031.c                        |   6 +-
 drivers/media/pci/intel/ipu-bridge.c               |  24 +
 .../vcodec/decoder/vdec/vdec_av1_req_lat_if.c      |   5 +-
 .../platform/microchip/microchip-sama7g5-isc.c     |   7 +-
 drivers/media/platform/qcom/iris/iris_resources.c  |  15 +-
 drivers/media/platform/qcom/venus/pm_helpers.c     |   7 +-
 drivers/media/platform/renesas/rcar-csi2.c         |   6 +-
 .../platform/rockchip/rkvdec/rkvdec-hevc-common.c  |  14 +-
 .../media/platform/rockchip/rkvdec/rkvdec-hevc.c   |   7 +-
 .../platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c |   2 +
 .../media/platform/samsung/s3c-camif/camif-core.c  |   7 +-
 .../platform/verisilicon/hantro_g2_hevc_dec.c      |   6 +-
 .../verisilicon/rockchip_vpu981_hw_av1_dec.c       |  57 +-
 drivers/media/usb/as102/as102_usb_drv.c            |  75 +--
 drivers/media/usb/dvb-usb-v2/mxl111sf.c            |  12 +-
 drivers/media/usb/gspca/jl2005bcd.c                |   7 +-
 drivers/media/v4l2-core/v4l2-ctrls-core.c          |  32 +
 drivers/media/v4l2-core/v4l2-h264.c                |   3 +-
 drivers/mfd/ab8500-core.c                          |   2 +-
 drivers/mfd/db8500-prcmu.c                         |   6 +-
 drivers/misc/amd-sbi/rmi-core.c                    |   4 +
 drivers/net/bonding/bond_alb.c                     |  34 +-
 drivers/net/bonding/bond_main.c                    |  18 +-
 drivers/net/bonding/bond_options.c                 |   4 +-
 drivers/net/dsa/bcm_sf2_cfp.c                      |   2 +
 drivers/net/dsa/lantiq/lantiq_gswip.h              |   2 +-
 drivers/net/dsa/mt7530-mmio.c                      |   1 +
 drivers/net/dsa/mt7530.c                           |  70 ++-
 drivers/net/dsa/mt7530.h                           |   1 +
 drivers/net/dsa/mv88e6xxx/chip.c                   |  16 +-
 drivers/net/ethernet/airoha/airoha_eth.h           |   2 +-
 drivers/net/ethernet/allwinner/sun4i-emac.c        |   2 +
 drivers/net/ethernet/amd/pds_core/fw.c             |  10 +-
 drivers/net/ethernet/amd/pds_core/main.c           |  10 +-
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c           |   3 +-
 drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c   |   4 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c          |  99 ++-
 drivers/net/ethernet/broadcom/bnxt/bnxt.h          |   3 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_gso.c      |  21 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_gso.h      |   6 +-
 drivers/net/ethernet/cadence/macb.h                |  23 +-
 drivers/net/ethernet/cadence/macb_main.c           | 677 ++++++++++----------
 drivers/net/ethernet/cadence/macb_pci.c            |  46 +-
 drivers/net/ethernet/cadence/macb_ptp.c            |  23 +-
 drivers/net/ethernet/cortina/gemini.c              |  77 ++-
 drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c  |   4 +-
 drivers/net/ethernet/intel/ice/ice_common.c        |   9 +-
 drivers/net/ethernet/intel/ice/ice_sched.c         |   4 +-
 drivers/net/ethernet/intel/ice/ice_trace.h         |  64 +-
 drivers/net/ethernet/intel/ice/ice_type.h          |   2 +-
 drivers/net/ethernet/intel/idpf/idpf_txrx.c        |  34 +-
 drivers/net/ethernet/marvell/octeontx2/af/mcs.c    |  10 +
 drivers/net/ethernet/marvell/octeontx2/af/rvu.c    |  33 +-
 .../ethernet/marvell/octeontx2/af/rvu_debugfs.c    |  10 +-
 .../net/ethernet/marvell/octeontx2/af/rvu_npc.c    |   5 +-
 drivers/net/ethernet/marvell/octeontx2/nic/qos.c   |  60 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c        |  18 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h        |   4 +-
 drivers/net/ethernet/mellanox/mlx5/core/en/port.c  |  15 +-
 drivers/net/ethernet/mellanox/mlx5/core/en/port.h  |   4 +
 .../net/ethernet/mellanox/mlx5/core/en/tc/sample.c |   7 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c |   2 +-
 .../net/ethernet/mellanox/mlx5/core/en_ethtool.c   |  13 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_rep.c   |  52 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_rep.h   |   1 -
 drivers/net/ethernet/mellanox/mlx5/core/en_stats.c |  51 +-
 .../ethernet/mellanox/mlx5/core/esw/devlink_port.c |  37 ++
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |   8 +-
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.h  |   1 +
 .../mellanox/mlx5/core/eswitch_offloads_termtbl.c  |   7 +-
 drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c  |  19 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c |  34 +-
 drivers/net/ethernet/micrel/ks8851_common.c        |   8 +-
 drivers/net/ethernet/microsoft/mana/mana_bpf.c     |   1 +
 drivers/net/ethernet/microsoft/mana/mana_en.c      |  24 +-
 .../net/ethernet/netronome/nfp/nfp_net_ethtool.c   |  19 +-
 drivers/net/ethernet/oa_tc6.c                      | 436 ++++++++-----
 drivers/net/ethernet/pensando/ionic/ionic_txrx.c   |  13 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  93 ++-
 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c   |   1 -
 drivers/net/gtp.c                                  |   5 +
 drivers/net/ieee802154/cc2520.c                    |   5 +-
 drivers/net/ieee802154/mac802154_hwsim.c           |  10 +-
 drivers/net/mctp/mctp-i3c.c                        |   9 +-
 drivers/net/net_failover.c                         |   2 +-
 drivers/net/phy/dp83867.c                          |   3 +
 drivers/net/phy/dp83td510.c                        |   3 +
 drivers/net/phy/mediatek/mtk-ge.c                  |  29 +
 drivers/net/phy/phylink.c                          |   2 +
 drivers/net/ppp/ppp_async.c                        |  89 +--
 drivers/net/ppp/ppp_synctty.c                      |  97 +--
 drivers/net/usb/cx82310_eth.c                      |   1 +
 drivers/net/usb/hso.c                              |   2 +-
 drivers/net/usb/pegasus.c                          |  54 +-
 drivers/net/usb/pegasus.h                          |   3 -
 drivers/net/vxlan/vxlan_core.c                     |  13 +-
 drivers/net/vxlan/vxlan_mdb.c                      |   8 +
 drivers/net/wireless/ath/ath9k/hif_usb.c           |  12 +-
 drivers/net/wireless/ath/ath9k/hif_usb.h           |   2 +-
 drivers/net/wireless/mediatek/mt76/mt7921/mcu.c    |  33 +-
 drivers/nvme/host/core.c                           |  77 ++-
 drivers/nvme/host/nvme.h                           |  16 +-
 drivers/nvme/host/rdma.c                           |  18 +-
 drivers/nvme/host/sysfs.c                          |   2 +-
 drivers/nvme/host/tcp.c                            |   5 +
 drivers/nvme/host/zns.c                            |   4 +-
 drivers/nvme/target/configfs.c                     |   4 +-
 drivers/nvme/target/core.c                         |   2 +-
 drivers/nvme/target/pr.c                           |   2 +-
 drivers/nvme/target/rdma.c                         |  15 +-
 drivers/opp/of.c                                   |   2 +-
 drivers/perf/riscv_pmu_legacy.c                    |   5 +-
 drivers/perf/riscv_pmu_sbi.c                       |  98 ++-
 drivers/platform/x86/asus-laptop.c                 |   4 +-
 drivers/platform/x86/hp/hp-wmi.c                   | 129 ++--
 drivers/platform/x86/x86-android-tablets/core.c    |  12 +-
 drivers/ras/amd/atl/core.c                         |   1 -
 drivers/regulator/db8500-prcmu.c                   |  12 +-
 drivers/regulator/pf1550-regulator.c               |  82 ++-
 drivers/s390/net/ism_drv.c                         |   4 +-
 drivers/s390/net/qeth_l2.h                         |   3 +-
 drivers/s390/net/qeth_l2_main.c                    |  26 +-
 drivers/s390/net/qeth_l2_sys.c                     |   7 +-
 drivers/scsi/mpi3mr/mpi3mr_transport.c             |   8 +
 drivers/scsi/mpt3sas/mpt3sas_base.c                |   5 +-
 drivers/scsi/qla2xxx/qla_bsg.c                     |  49 +-
 drivers/scsi/qla2xxx/qla_def.h                     |   2 +
 drivers/scsi/qla2xxx/qla_fw.h                      |   4 +
 drivers/scsi/qla2xxx/qla_init.c                    |  14 +
 drivers/scsi/qla2xxx/qla_iocb.c                    |  23 +-
 drivers/scsi/qla2xxx/qla_isr.c                     |  33 +-
 drivers/scsi/qla2xxx/qla_mbx.c                     |   6 +-
 drivers/scsi/qla2xxx/qla_mid.c                     |  49 +-
 drivers/scsi/qla2xxx/qla_nvme.c                    |  10 +
 drivers/scsi/qla2xxx/qla_os.c                      |  15 +
 drivers/staging/fbtft/fbtft-core.c                 |   9 +-
 drivers/target/iscsi/iscsi_target.c                |   4 +-
 drivers/thermal/db8500_thermal.c                   |  10 +-
 drivers/thermal/thermal_sysfs.c                    |  12 +-
 drivers/ufs/host/ufshcd-pci.c                      |  59 ++
 drivers/usb/atm/xusbatm.c                          |   6 +-
 drivers/usb/class/usbtmc.c                         |   2 -
 drivers/usb/serial/spcp8x5.c                       |   6 +-
 drivers/vdpa/ifcvf/ifcvf_main.c                    |   3 +-
 drivers/vdpa/solidrun/snet_main.c                  |   6 +-
 drivers/vdpa/vdpa_sim/vdpa_sim_blk.c               |   3 +-
 drivers/vdpa/vdpa_sim/vdpa_sim_net.c               |   7 +-
 drivers/vdpa/vdpa_user/vduse_dev.c                 |  10 +-
 drivers/vhost/net.c                                |   2 +
 drivers/vhost/vdpa.c                               |  88 ++-
 drivers/vhost/vhost.c                              |  57 +-
 drivers/vhost/vhost.h                              |   1 +
 drivers/vhost/vsock.c                              |   2 +
 drivers/video/fbdev/vfb.c                          |  11 +-
 drivers/virtio/virtio.c                            |   2 +-
 drivers/virtio/virtio_input.c                      |   9 +-
 drivers/virtio/virtio_mmio.c                       |  16 +-
 drivers/virtio/virtio_pci_common.c                 |   4 +-
 drivers/virtio/virtio_ring.c                       |  38 +-
 drivers/watchdog/db8500_wdt.c                      |  22 +-
 drivers/watchdog/msc313e_wdt.c                     |  74 ++-
 drivers/watchdog/sunxi_wdt.c                       |  45 +-
 drivers/watchdog/watchdog_hrtimer_pretimeout.c     |   1 +
 fs/afs/addr_list.c                                 |   5 +-
 fs/afs/dir_edit.c                                  |   9 +-
 fs/afs/dir_search.c                                |  11 +-
 fs/afs/fs_probe.c                                  |   1 +
 fs/afs/internal.h                                  |   8 +
 fs/afs/server.c                                    |   1 -
 fs/autofs/inode.c                                  |   4 +-
 fs/btrfs/inode.c                                   |   3 +
 fs/btrfs/raid-stripe-tree.c                        |  25 +-
 fs/btrfs/raid-stripe-tree.h                        |   1 +
 fs/btrfs/scrub.c                                   |  24 +-
 fs/btrfs/send.c                                    |   2 +-
 fs/btrfs/transaction.c                             |  13 +-
 fs/btrfs/tree-log.c                                |  16 +
 fs/btrfs/volumes.c                                 |   4 +
 fs/btrfs/zoned.c                                   |  11 +-
 fs/btrfs/zstd.c                                    |  11 +-
 fs/cachefiles/xattr.c                              |  16 +-
 fs/configfs/dir.c                                  |   9 +
 fs/configfs/symlink.c                              |  24 +-
 fs/erofs/data.c                                    |   2 +-
 fs/erofs/decompressor.c                            |  55 +-
 fs/erofs/decompressor_lzma.c                       |  18 +-
 fs/erofs/internal.h                                |   6 +-
 fs/erofs/sysfs.c                                   |   2 +
 fs/erofs/xattr.c                                   |   9 +-
 fs/erofs/zdata.c                                   |  18 +-
 fs/exec.c                                          |  22 +-
 fs/f2fs/f2fs.h                                     |   2 +-
 fs/f2fs/gc.c                                       |  52 +-
 fs/f2fs/segment.c                                  |   4 +-
 fs/netfs/buffered_read.c                           | 164 +++--
 fs/netfs/direct_write.c                            |  31 +-
 fs/netfs/internal.h                                |   3 +
 fs/netfs/misc.c                                    |  19 +
 fs/netfs/objects.c                                 |  32 +-
 fs/netfs/read_collect.c                            | 128 ++--
 fs/netfs/read_pgpriv2.c                            |  15 +-
 fs/netfs/read_retry.c                              |  13 +-
 fs/netfs/read_single.c                             |   2 +
 fs/netfs/rolling_buffer.c                          |  79 ++-
 fs/netfs/write_issue.c                             |   2 +
 fs/ntfs/attrib.c                                   |  10 +-
 fs/ntfs/ea.c                                       |  14 +-
 fs/ntfs/lcnalloc.c                                 |   9 +-
 fs/ntfs/mft.c                                      |   4 +-
 fs/ntfs/reparse.c                                  |   7 +-
 fs/ntfs/super.c                                    |  11 +-
 fs/overlayfs/super.c                               |   2 +-
 fs/smb/client/cifsacl.c                            |  95 ++-
 fs/smb/client/cifssmb.c                            |  26 +-
 fs/smb/client/file.c                               |  22 +-
 fs/smb/client/inode.c                              |  17 +-
 fs/smb/client/misc.c                               |  24 +-
 fs/smb/client/readdir.c                            |  17 +-
 fs/smb/client/reparse.c                            |  33 +-
 fs/smb/client/smb2ops.c                            | 188 +++++-
 fs/smb/client/trace.h                              |   1 +
 fs/smb/client/transport.c                          |  11 +-
 fs/smb/server/connection.c                         |  25 +
 fs/smb/server/ksmbd_work.h                         |   2 +-
 fs/smb/server/mgmt/user_session.c                  |  13 +-
 fs/smb/server/mgmt/user_session.h                  |   1 +
 fs/smb/server/smb2pdu.c                            |  47 +-
 fs/smb/server/smbacl.c                             |  67 +-
 fs/smb/server/transport_tcp.c                      |  36 +-
 fs/smb/server/vfs_cache.c                          |  17 +-
 fs/smb/server/vfs_cache.h                          |   1 +
 fs/super.c                                         |   9 +-
 fs/ufs/cylinder.c                                  |  10 +
 fs/ufs/dir.c                                       |   2 +-
 fs/ufs/super.c                                     |  17 +-
 fs/xfs/libxfs/xfs_btree_mem.c                      |   2 +
 fs/xfs/libxfs/xfs_btree_staging.c                  |   4 +-
 fs/xfs/libxfs/xfs_da_btree.c                       |   2 +-
 fs/xfs/libxfs/xfs_da_btree.h                       |   2 +
 fs/xfs/libxfs/xfs_defer.c                          |   2 +-
 fs/xfs/libxfs/xfs_exchmaps.c                       |  10 +
 fs/xfs/libxfs/xfs_parent.c                         |  12 +-
 fs/xfs/libxfs/xfs_rtrefcount_btree.c               |   7 +-
 fs/xfs/libxfs/xfs_rtrmap_btree.c                   |   6 +-
 fs/xfs/scrub/agheader.c                            |   7 +
 fs/xfs/scrub/agheader_repair.c                     |  39 +-
 fs/xfs/scrub/alloc_repair.c                        |  18 +-
 fs/xfs/scrub/attr_repair.c                         |   2 +-
 fs/xfs/scrub/bmap.c                                |   2 +-
 fs/xfs/scrub/dir_repair.c                          |  31 +-
 fs/xfs/scrub/dirtree.c                             |  31 +-
 fs/xfs/scrub/dirtree_repair.c                      |   2 +
 fs/xfs/scrub/findparent.c                          |  56 +-
 fs/xfs/scrub/ialloc.c                              |   4 +
 fs/xfs/scrub/metapath.c                            |   4 +-
 fs/xfs/scrub/quota_repair.c                        |  14 +-
 fs/xfs/scrub/quotacheck.c                          |   4 +-
 fs/xfs/scrub/reap.c                                |   6 +-
 fs/xfs/scrub/refcount.c                            |   8 +-
 fs/xfs/scrub/rgsuper.c                             |   6 +-
 fs/xfs/scrub/rtrefcount.c                          |  82 ++-
 fs/xfs/scrub/rtsummary_repair.c                    |   3 +-
 fs/xfs/scrub/scrub.c                               |   3 +-
 fs/xfs/scrub/stats.c                               |  61 +-
 fs/xfs/scrub/stats.h                               |   4 +-
 fs/xfs/scrub/symlink_repair.c                      |   2 +-
 fs/xfs/scrub/tempfile.c                            |  29 +-
 fs/xfs/scrub/trace.h                               |  35 +-
 fs/xfs/xfs_buf.c                                   |   2 +-
 fs/xfs/xfs_exchmaps_item.c                         |  19 +-
 fs/xfs/xfs_exchrange.c                             |  12 +-
 fs/xfs/xfs_healthmon.c                             |  30 +-
 fs/xfs/xfs_verify_media.c                          |  24 +-
 include/drm/drm_pagemap.h                          |   8 +-
 include/linux/bpf.h                                |   3 +-
 include/linux/bpf_verifier.h                       |  21 +-
 include/linux/designware_i2c.h                     | 107 ++++
 include/linux/dma-fence-array.h                    |   1 -
 include/linux/dma-fence-chain.h                    |   9 +-
 include/linux/igmp.h                               |   7 +-
 include/linux/mfd/db8500-prcmu.h                   | 252 +++++++-
 include/linux/mfd/dbx500-prcmu.h                   | 575 -----------------
 include/linux/mmap_lock.h                          |   2 +
 include/linux/netfs.h                              |   5 +-
 include/linux/oa_tc6.h                             |  50 ++
 include/linux/perf/riscv_pmu.h                     |   2 +-
 include/linux/rbtree_augmented.h                   |  35 +-
 include/linux/ring_buffer.h                        |  24 +-
 include/linux/rolling_buffer.h                     |   6 +-
 include/linux/sched.h                              |   2 +-
 include/linux/sched/signal.h                       |   5 +-
 include/linux/skbuff.h                             |   5 +
 include/media/v4l2-hevc.h                          |  41 ++
 include/net/cfg802154.h                            |   1 +
 include/net/if_inet6.h                             |   2 -
 include/net/ip.h                                   |   3 +-
 include/net/ip6_route.h                            |   2 +
 include/net/sch_generic.h                          |   2 +-
 include/net/tcp.h                                  |   3 +-
 include/trace/events/cachefiles.h                  |  19 +-
 include/trace/events/icmp.h                        |  13 +-
 include/trace/events/netfs.h                       |  30 +-
 include/uapi/drm/amdgpu_drm.h                      |   2 +-
 init/main.c                                        |  27 +-
 io_uring/net.c                                     |  51 +-
 io_uring/rw.c                                      |  29 +-
 kernel/bpf/arraymap.c                              |   5 +-
 kernel/bpf/backtrack.c                             |  64 +-
 kernel/bpf/bpf_iter.c                              |   2 +-
 kernel/bpf/btf.c                                   |  27 +-
 kernel/bpf/cfg.c                                   |   3 +
 kernel/bpf/fixups.c                                |   7 +-
 kernel/bpf/hashtab.c                               |  29 +-
 kernel/bpf/local_storage.c                         |   5 +-
 kernel/bpf/stackmap.c                              |   2 +
 kernel/bpf/states.c                                |  11 +-
 kernel/bpf/syscall.c                               |   2 +
 kernel/bpf/verifier.c                              | 263 ++++++--
 kernel/cgroup/cpuset.c                             |  39 +-
 kernel/events/core.c                               |   4 +-
 kernel/events/ring_buffer.c                        |   9 +-
 kernel/exit.c                                      |   9 +-
 kernel/fork.c                                      |   7 +-
 kernel/locking/lockdep.c                           |  50 +-
 kernel/nstree.c                                    |  10 +-
 kernel/printk/nbcon.c                              |   4 +-
 kernel/printk/printk.c                             |   2 +-
 kernel/reboot.c                                    |  19 +-
 kernel/sched/core.c                                |  19 +-
 kernel/sched/deadline.c                            |   4 +-
 kernel/sched/ext/ext.c                             |  21 +-
 kernel/sched/fair.c                                |  18 +-
 kernel/sched/rt.c                                  |   4 +-
 kernel/signal.c                                    |  12 +
 kernel/time/clockevents.c                          |  35 +-
 kernel/time/hrtimer.c                              |  15 +-
 kernel/time/tick-broadcast.c                       |  36 +-
 kernel/time/tick-internal.h                        |   2 +
 kernel/trace/ftrace.c                              |   2 +-
 kernel/trace/ring_buffer.c                         | 226 ++++---
 kernel/trace/ring_buffer_benchmark.c               |   6 +-
 kernel/trace/trace.c                               | 152 +++--
 kernel/trace/trace.h                               |  11 +-
 kernel/trace/trace_events.c                        |   2 +
 kernel/trace/trace_events_hist.c                   |  86 +--
 kernel/trace/trace_events_trigger.c                |   4 +-
 kernel/trace/trace_events_user.c                   |  26 +-
 kernel/trace/trace_functions_graph.c               |   3 +
 kernel/trace/trace_probe.c                         |  48 +-
 kernel/trace/trace_probe.h                         |   2 +
 kernel/trace/trace_remote.c                        |   6 +-
 kernel/workqueue.c                                 |   3 +
 lib/iov_iter.c                                     |  18 +-
 mm/slub.c                                          |  22 +-
 net/bluetooth/hci_core.c                           |   4 +-
 net/bluetooth/hci_sysfs.c                          |  17 +-
 net/bluetooth/l2cap_core.c                         |  33 +-
 net/bluetooth/msft.c                               |   2 +-
 net/bridge/br_cfm.c                                |  11 +-
 net/bridge/br_device.c                             |   1 -
 net/bridge/br_input.c                              |  35 +-
 net/bridge/br_mrp.c                                |  13 +-
 net/bridge/br_multicast.c                          |   9 +-
 net/bridge/br_private.h                            |  26 +-
 net/core/dev.c                                     |  27 +-
 net/core/gro_cells.c                               |   2 +
 net/core/rtnetlink.c                               |   7 +-
 net/core/skbuff.c                                  |   7 +
 net/dsa/tag_brcm.c                                 |   1 +
 net/hsr/hsr_slave.c                                |  11 +-
 net/ieee802154/6lowpan/core.c                      |   2 +-
 net/ipv4/fib_rules.c                               |   4 +-
 net/ipv4/igmp.c                                    | 210 ++++---
 net/ipv4/inet_fragment.c                           |   6 +
 net/ipv4/ip_output.c                               |   1 +
 net/ipv4/ip_tunnel_core.c                          |   6 +
 net/ipv4/ipmr.c                                    |   3 +-
 net/ipv4/ipmr_base.c                               |   2 +-
 net/ipv4/nexthop.c                                 |   2 +-
 net/ipv4/tcp.c                                     |  14 +-
 net/ipv4/tcp_offload.c                             |  22 +-
 net/ipv4/tcp_output.c                              |   4 +-
 net/ipv4/tcp_timer.c                               |   6 +-
 net/ipv4/udp.c                                     |   4 +-
 net/ipv6/exthdrs.c                                 |   4 +-
 net/ipv6/ip6_fib.c                                 |   4 +-
 net/ipv6/ip6_flowlabel.c                           |  19 +
 net/ipv6/ip6_gre.c                                 |   6 +-
 net/ipv6/ip6_output.c                              |   2 +
 net/ipv6/ip6mr.c                                   |   2 +-
 net/ipv6/mcast.c                                   | 148 +++--
 net/ipv6/netfilter/ip6_tables.c                    |   5 +
 net/ipv6/route.c                                   |   9 +-
 net/ipv6/tcpv6_offload.c                           |  15 +-
 net/mac802154/ieee802154_i.h                       |   8 +
 net/mac802154/iface.c                              |   6 +
 net/mac802154/main.c                               |   1 +
 net/mac802154/rx.c                                 | 120 +++-
 net/mac802154/scan.c                               |  10 +-
 net/mptcp/options.c                                |   8 +-
 net/mptcp/pm.c                                     |   2 +-
 net/mptcp/pm_kernel.c                              |   8 +
 net/mptcp/pm_userspace.c                           |  18 +-
 net/mptcp/protocol.c                               |  28 +-
 net/mptcp/protocol.h                               |   3 +-
 net/mptcp/subflow.c                                |   1 -
 net/mptcp/syncookies.c                             |   5 +-
 net/netfilter/ipvs/ip_vs_sync.c                    |  20 +-
 net/netfilter/nf_conntrack_netlink.c               |   2 +
 net/netfilter/nf_conntrack_sip.c                   |   2 +-
 net/netfilter/nf_log_syslog.c                      |   2 +-
 net/netfilter/nfnetlink_cttimeout.c                |   2 +-
 net/netfilter/nfnetlink_log.c                      |  15 +-
 net/netlink/genetlink.c                            |  21 +-
 net/openvswitch/flow.c                             |   4 +-
 net/openvswitch/flow_table.c                       |   4 +-
 net/packet/af_packet.c                             |   5 +-
 net/rds/connection.c                               |  89 ++-
 net/rds/ib_recv.c                                  |   9 +-
 net/rds/message.c                                  |   4 +-
 net/rds/send.c                                     |  14 +-
 net/rds/tcp.c                                      | 101 ++-
 net/rds/tcp_listen.c                               |   6 +-
 net/sched/act_api.c                                |  46 +-
 net/sched/cls_api.c                                |   2 +-
 net/sched/cls_route.c                              |  76 +--
 net/sched/cls_u32.c                                |  32 +-
 net/sched/sch_api.c                                |   2 +-
 net/sched/sch_drr.c                                |   3 +-
 net/sched/sch_dualpi2.c                            |  10 +-
 net/sched/sch_ets.c                                |  12 +-
 net/sched/sch_fq_pie.c                             |   3 +-
 net/sched/sch_generic.c                            |  24 +-
 net/sched/sch_hhf.c                                |   8 +-
 net/sched/sch_pie.c                                |   2 +-
 net/sched/sch_sfq.c                                |   7 +-
 net/sctp/sm_make_chunk.c                           |  14 +-
 net/sctp/sm_sideeffect.c                           |  11 +-
 net/tipc/link.c                                    |   6 +-
 net/tipc/name_table.c                              |  32 +-
 net/unix/af_unix.c                                 |  12 +-
 rust/bindings/lib.rs                               |   4 +-
 rust/kernel/num.rs                                 |   9 +-
 rust/pin-init/src/lib.rs                           |   8 +-
 rust/uapi/lib.rs                                   |   4 +-
 samples/rust/rust_print_main.rs                    |   8 +-
 scripts/livepatch/init.c                           |   2 +-
 scripts/mksysmap                                   |   4 +-
 scripts/sorttable.c                                |   2 +-
 security/landlock/fs.c                             |  18 +-
 sound/core/pcm_native.c                            |  35 +-
 sound/core/ump.c                                   |   4 +
 sound/drivers/dummy.c                              |   2 +-
 sound/hda/common/codec.c                           |   4 +-
 sound/hda/core/device.c                            |   5 +-
 sound/pci/ctxfi/cthw20k2.c                         |   1 +
 sound/soc/amd/acp-da7219-max98357a.c               |  23 +
 sound/soc/amd/renoir/acp3x-pdm-dma.c               |   2 +-
 sound/soc/amd/yc/acp6x-pdm-dma.c                   |   2 +
 sound/soc/bcm/bcm63xx-i2s-whistler.c               |   1 +
 sound/soc/codecs/ab8500-codec.c                    | 690 +++++++++------------
 sound/soc/codecs/cs35l56-i2c.c                     |  10 +-
 sound/soc/codecs/cs35l56-sdw.c                     |   6 +-
 sound/soc/codecs/cs35l56-spi.c                     |  10 +-
 sound/soc/codecs/cs35l56.c                         | 124 +++-
 sound/soc/codecs/cs35l56.h                         |   4 +-
 sound/soc/codecs/mt6351.c                          |   1 +
 sound/soc/fsl/fsl_micfil.c                         |  21 +-
 sound/soc/intel/atom/sst/sst_pci.c                 |   1 +
 sound/soc/intel/avs/core.c                         |  29 +-
 sound/soc/intel/avs/debugfs.c                      |  12 +-
 sound/soc/intel/avs/path.c                         |  11 +-
 sound/soc/intel/avs/pcm.c                          |  34 +-
 sound/soc/intel/avs/topology.c                     |  49 +-
 sound/soc/intel/avs/topology.h                     |   5 +-
 sound/soc/sprd/sprd-pcm-compress.c                 |  15 +-
 sound/soc/sti/uniperif_reader.c                    |   4 +-
 sound/soc/ux500/ux500_msp_dai.c                    | 189 +++---
 sound/soc/ux500/ux500_msp_dai.h                    |  14 +-
 sound/soc/ux500/ux500_msp_i2s.c                    | 260 +++++---
 sound/soc/ux500/ux500_msp_i2s.h                    |  12 +-
 sound/usb/caiaq/audio.c                            |  10 +-
 sound/usb/caiaq/device.c                           |  36 +-
 sound/usb/caiaq/device.h                           |   4 +-
 sound/usb/caiaq/midi.c                             |   6 +-
 sound/usb/usx2y/us122l.c                           |   7 +-
 sound/usb/usx2y/usbusx2y.c                         |  10 +-
 sound/usb/usx2y/usbusx2y.h                         |   4 +-
 tools/bootconfig/main.c                            |  13 +-
 tools/objtool/klp-checksum.c                       |  21 +
 tools/perf/util/powerpc-vpadtl.c                   |   2 +-
 tools/perf/util/symbol.c                           |  11 +-
 tools/sched_ext/scx_central.bpf.c                  |   6 +-
 tools/sched_ext/scx_flatcg.bpf.c                   |   2 +-
 tools/testing/selftests/alsa/mixer-test.c          |   4 +-
 tools/testing/selftests/bpf/progs/test_bpf_nf.c    |   8 +-
 .../bpf/progs/verifier_subprog_precision.c         |  12 +-
 tools/testing/selftests/cgroup/test_core.c         |   2 +-
 tools/testing/selftests/cgroup/test_cpu.c          |   2 +-
 tools/testing/selftests/cgroup/test_cpuset.c       |   2 +-
 tools/testing/selftests/cgroup/test_cpuset_prs.sh  |   6 -
 tools/testing/selftests/cgroup/test_freezer.c      |   2 +-
 tools/testing/selftests/cgroup/test_kill.c         |   2 +-
 tools/testing/selftests/cgroup/test_kmem.c         |   4 +-
 tools/testing/selftests/cgroup/test_memcontrol.c   |   2 +-
 tools/testing/selftests/cgroup/test_pids.c         |   2 +-
 tools/testing/selftests/cgroup/test_zswap.c        |   2 +-
 tools/testing/selftests/net/fib_nexthops.sh        |  28 +
 tools/testing/selftests/net/mptcp/mptcp_connect.c  |   4 +-
 tools/testing/selftests/net/mptcp/mptcp_lib.sh     |  26 +-
 tools/testing/selftests/net/pmtu.sh                |   2 +-
 tools/testing/selftests/net/test_vxlan_mdb.sh      |   6 +
 tools/testing/selftests/powerpc/tm/tm.h            |   8 +-
 tools/testing/selftests/ublk/Makefile              |   2 +
 655 files changed, 9896 insertions(+), 5497 deletions(-)
author maintainer
#1 lore raw

PATCH 1/733 iommu/arm-smmu-v3: Disable implementations during devm teardown

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

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

From: Wentao Guan <[email protected]>

The Tegra241 CMDQV teardown fix moved VINTF hardware deinitialization into the implementation device_disable() callback. However, its stable backport preceded the conversion to devm teardown and could only invoke the callback from the shutdown path.

Now that arm_smmu_disable_action() manages normal teardown, invoke the implementation callback there while the command queue is still alive. This prevents the subsequent implementation remove action from releasing resources while the CMDQV hardware remains active.

After ("iommu/arm-smmu-v3: Manage teardown with devm") merged in stable, now keep the shutdown path consistent with mainline, where disabling the base SMMU is sufficient.

It is a fix for stable tree commit to aligned with mainline, so no upstream commit id here.

Fixes 5994617e09ee ("iommu/tegra241-cmdqv: Fix CMD_SYNC use-after-free on teardown")
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +2 -2
index 35b7b2fd4a122..b52dae11fbbef 100644
@@ -4741,6 +4741,8 @@ static void arm_smmu_disable_action(void *data)
 {
 	struct arm_smmu_device *smmu = data;
 
+	if (smmu->impl_ops && smmu->impl_ops->device_disable)
+		smmu->impl_ops->device_disable(smmu);
 	arm_smmu_device_disable(smmu);
 }
 
@@ -5555,8 +5557,6 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev)
 {
 	struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
 
-	if (smmu->impl_ops && smmu->impl_ops->device_disable)
-		smmu->impl_ops->device_disable(smmu);
 	arm_smmu_device_disable(smmu);
 }
 
Signature · 1 line
2.53.0
author maintainer
#2 lore raw

PATCH 2/733 wifi: mt76: mt7921: validate CLC firmware records

In reply to Greg Kroah-Hartman

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

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

From: Laxman Acharya Padhya <[email protected]>

[ Upstream commit 9417c5818a0146980c2608fda94c908e604eb033 ]

The CLC region is supplied by firmware, but the loader trusts the region count and each record length. A malformed image can make the region table pointer precede the firmware buffer, make the record loop fail to advance, or index phy->clc past its end. Validate the table and record bounds before dereferencing or copying.

---
 .../net/wireless/mediatek/mt76/mt7921/mcu.c   | 28 ++++++++++++++++---
 1 file changed, 24 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +24 -4
index 25b9437250f7b..564dd836e0b38 100644
@@ -415,7 +415,8 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
 	struct mt76_dev *mdev = &dev->mt76;
 	struct mt792x_phy *phy = &dev->phy;
 	const struct firmware *fw;
-	int ret, i, len, offset = 0;
+	size_t clc_len, fw_data_len, len, offset = 0;
+	int ret, i;
 	u8 *clc_base = NULL, hw_encap = 0;
 
 	dev->phy.clc_chan_conf = 0xff;
@@ -441,13 +442,21 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
 	}
 
 	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));
+	if (hdr->n_region > (fw->size - sizeof(*hdr)) / sizeof(*region)) {
+		dev_err(mdev->dev, "Invalid firmware region table\n");
+		ret = -EINVAL;
+		goto out;
+	}
+	fw_data_len = fw->size - sizeof(*hdr) -
+		      hdr->n_region * sizeof(*region);
+
 	for (i = 0; i < hdr->n_region; i++) {
 		region = (const void *)((const u8 *)hdr -
 					(hdr->n_region - i) * sizeof(*region));
 		len = le32_to_cpu(region->len);
 
 		/* check if we have valid buffer size */
-		if (offset + len > fw->size) {
+		if (len > fw_data_len - offset) {
 			dev_err(mdev->dev, "Invalid firmware region\n");
 			ret = -EINVAL;
 			goto out;
@@ -464,8 +473,19 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
 	if (!clc_base)
 		goto out;
 
-	for (offset = 0; offset < len; offset += le32_to_cpu(clc->len)) {
+	for (offset = 0; offset < len; offset += clc_len) {
+		if (len - offset < sizeof(*clc)) {
+			ret = -EINVAL;
+			goto out;
+		}
+
 		clc = (const struct mt7921_clc *)(clc_base + offset);
+		clc_len = le32_to_cpu(clc->len);
+		if (clc_len < sizeof(*clc) || clc_len > len - offset ||
+		    clc->idx >= ARRAY_SIZE(phy->clc)) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		/* do not init buf again if chip reset triggered */
 		if (phy->clc[clc->idx])
@@ -477,7 +497,7 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
 			continue;
 
 		phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc,
-						  le32_to_cpu(clc->len),
+						  clc_len,
 						  GFP_KERNEL);
 
 		if (!phy->clc[clc->idx]) {
Signature · 1 line
2.53.0
author maintainer
#3 lore raw

PATCH 3/733 wifi: mt76: mt7921: skip unknown CLC firmware records

In reply to Greg Kroah-Hartman

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

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

From: Laxman Acharya Padhya <[email protected]>

[ Upstream commit 1a296bfd3e775e515233f746218824fc7dd5ff16 ]

Treat an out-of-range CLC index as newer firmware rather than a malformed image. linux-firmware 20260810 ships MT7922 records with idx 3, and rejecting them made mt7921e fail to probe.

Keep the record-length checks, and report those as errors so a truncated table is visible instead of a silent retry loop.

Fixes 9417c5818a01 ("wifi: mt76: mt7921: validate CLC firmware records")
---
 drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +7 -2
index 564dd836e0b38..45439652c847b 100644
@@ -475,18 +475,23 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name)
 
 	for (offset = 0; offset < len; offset += clc_len) {
 		if (len - offset < sizeof(*clc)) {
+			dev_err(mdev->dev, "Invalid CLC record\n");
 			ret = -EINVAL;
 			goto out;
 		}
 
 		clc = (const struct mt7921_clc *)(clc_base + offset);
 		clc_len = le32_to_cpu(clc->len);
-		if (clc_len < sizeof(*clc) || clc_len > len - offset ||
-		    clc->idx >= ARRAY_SIZE(phy->clc)) {
+		if (clc_len < sizeof(*clc) || clc_len > len - offset) {
+			dev_err(mdev->dev, "Invalid CLC record\n");
 			ret = -EINVAL;
 			goto out;
 		}
 
+		/* Newer firmware may add records this driver does not use yet */
+		if (clc->idx >= ARRAY_SIZE(phy->clc))
+			continue;
+
 		/* do not init buf again if chip reset triggered */
 		if (phy->clc[clc->idx])
 			continue;
Signature · 1 line
2.53.0
author maintainer
#4 lore raw

PATCH 4/733 leds: st1202: Validate pattern input before stopping the sequence

In reply to Greg Kroah-Hartman

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

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

From: Manuel Fombuena <[email protected]>

[ Upstream commit fd2529ba8fb44cd4b56f1069363b949644b42cec ]

Input validation for pattern duration is performed inside the write loop, after the pattern sequence has already been stopped. If validation fails mid-loop the chip is left with the sequence stopped and partially written pattern data, with no recovery.

Move all input validation before the mutex and before any hardware interaction, so an invalid input leaves the chip state unchanged.

---
 drivers/leds/leds-st1202.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/leds/leds-st1202.c +6 -4
index 2593ff39f22a6..168df5ecf27b7 100644
@@ -237,6 +237,12 @@ static int st1202_led_pattern_set(struct led_classdev *ldev,
 	if (len > ST1202_MAX_PATTERNS)
 		return -EINVAL;
 
+	for (int patt = 0; patt < len; patt++) {
+		if (pattern[patt].delta_t < ST1202_MILLIS_PATTERN_DUR_MIN ||
+				pattern[patt].delta_t > ST1202_MILLIS_PATTERN_DUR_MAX)
+			return -EINVAL;
+	}
+
 	guard(mutex)(&chip->lock);
 
 	ret = st1202_write_reg(chip, ST1202_CONFIG_REG, ST1202_CONFIG_REG_SHFT);
@@ -244,10 +250,6 @@ static int st1202_led_pattern_set(struct led_classdev *ldev,
 		return ret;
 
 	for (int patt = 0; patt < len; patt++) {
-		if (pattern[patt].delta_t < ST1202_MILLIS_PATTERN_DUR_MIN ||
-				pattern[patt].delta_t > ST1202_MILLIS_PATTERN_DUR_MAX)
-			return -EINVAL;
-
 		ret = st1202_pwm_pattern_write(chip, led->led_num, patt, pattern[patt].brightness);
 		if (ret != 0)
 			return ret;
Signature · 1 line
2.53.0
author maintainer
#5 lore raw

PATCH 5/733 ppp_async: drop the errored frame instead of resetting its headroom

In reply to Greg Kroah-Hartman

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

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

From: Vlatko Kosturjak <[email protected]>

[ Upstream commit 8dc5d98a16fa23c00999aecf10018c9f69fa5bf4 ]

ppp_receive_nonmp_frame() prepends a two-byte direction tag before running the pass/active BPF filters:

	*(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG);

Nothing on the receive path guarantees those two bytes of headroom. The frame-error path in ppp_async's process_input_packet() resets a reused skb's headroom to zero while claiming to restore it to a freshly allocated state - but a fresh skb from dev_alloc_skb() carries NET_SKB_PAD:

	err:
		if (skb) {
			/* make skb appear as freshly allocated */
			skb_trim(skb, 0);
			skb_reserve(skb, - skb_headroom(skb));
		}

ap->rpkt still points at that skb, so the next frame is reassembled into it with no headroom at all. A peer that sends a bad-FCS frame followed by one beginning ff 03 then leaves a single byte of headroom by the time the filter tag is pushed, which lands one byte below skb->head:

skbuff: skb_under_panic: len:49 put:2 head:ffff888003c10000

          data:ffff888003c0ffff tail:0x30 end:0x640 dev:<NULL>
  kernel BUG at net/core/skbuff.c:214!
  RIP: 0010:skb_panic+0x13e/0x230
  Call Trace:
   skb_push+0xbd/0x100
   ppp_receive_nonmp_frame+0x48a/0x1d10
   ppp_input+0x4e9/0x2f80
   ppp_async_process+0x2a/0xe0
   tasklet_action_common+0x20f/0x8a0
   handle_softirqs+0x18e/0x590
  Kernel panic - not syncing: Fatal exception in interrupt

Zeroing the headroom violates the NET_SKB_PAD guarantee that dev_alloc_skb() gives the rest of the receive path. Besides the filter panic above, when CCP compression is enabled ppp_decompress_frame() hands skb->data - 2 to ->decompress()/->incomp(), which then reads out of bounds before skb->head for the same reason.

Rather than restore the headroom, drop the errored frame - as ppp_synctty already does on its error path - and clear ap->rpkt so the next frame is reassembled into a fresh skb with proper headroom. This is simpler and fixes both the filter under-panic and the CCP out-of-bounds read.

The original V1 of this patch made room in ppp_receive_nonmp_frame() with skb_cow_head(); Eric pointed out that fixing the root cause in the transport is the right approach.

Found by fuzzing the PPP receive path with a mutating peer on a pty; it is an interesting (remote) DoS: root configures PPP, the peer supplies two crashing frames. The reproducer (repro-ppp-skb.c, unchanged from v1) panics in about a second, and returns cleanly with this applied.

---
 drivers/net/ppp/ppp_async.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/net/ppp/ppp_async.c +2 -5
index 93a7b0f6c4e7e..a5db4f78b5fc8 100644
@@ -812,11 +812,8 @@ process_input_packet(struct asyncppp *ap)
  err:
 	/* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */
 	ap->state = SC_PREV_ERROR;
-	if (skb) {
-		/* make skb appear as freshly allocated */
-		skb_trim(skb, 0);
-		skb_reserve(skb, - skb_headroom(skb));
-	}
+	kfree_skb(skb);
+	ap->rpkt = NULL;
 }
 
 /* Called when the tty driver has data for us. Runs parallel with the
Signature · 1 line
2.53.0
author maintainer
#6 lore raw

PATCH 6/733 RAS/AMD/ATL, EDAC/amd64: Only load ATL when needed

In reply to Greg Kroah-Hartman

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

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

From: Yazen Ghannam <[email protected]>

[ Upstream commit 4c3da04827dc01dc1cfc3d03654b7de656c42d80 ]

The AMD Address Translation Library (ATL) will attempt to load on all AMD Zen/SMCA systems.

However, only systems with DRAM ECC enabled will use the library. Other systems will fail to load the library and produce an unnecessary message to the user. More importantly, that thing is dead code loaded and unused.

Remove the ATL module dependency table to prevent autoloading. Request ATL to load from EDAC once all system checks are complete.

[ bp: Massage commit message. ]

---
 drivers/edac/amd64_edac.c  | 2 ++
 drivers/ras/amd/atl/core.c | 1 -
 2 files changed, 2 insertions(+), 1 deletion(-)
drivers/edac/amd64_edac.c +2 -0
index c6aa69dbd9fb1..475235c402e88 100644
@@ -4173,6 +4173,8 @@ static int __init amd64_edac_init(void)
 		goto err_pci;
 	}
 
+	request_module_nowait("amd_atl");
+
 	/* register stuff with EDAC MCE */
 	if (boot_cpu_data.x86 >= 0x17) {
 		amd_register_ecc_decoder(decode_umc_error);
drivers/ras/amd/atl/core.c +0 -1
index 0f7cd6dab0b0e..d77dacdd4f569 100644
@@ -190,7 +190,6 @@ static const struct x86_cpu_id amd_atl_cpuids[] = {
 	X86_MATCH_FEATURE(X86_FEATURE_ZEN, NULL),
 	{ }
 };
-MODULE_DEVICE_TABLE(x86cpu, amd_atl_cpuids);
 
 static int __init amd_atl_init(void)
 {
Signature · 1 line
2.53.0
author maintainer
#7 lore raw

PATCH 7/733 EDAC/igen6: Fix interleave boundary condition

In reply to Greg Kroah-Hartman

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

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

From: Qiuxu Zhuo <[email protected]>

[ Upstream commit f4008169bd320eedb9ddf2b39eeb21370ddac278 ]

The address translation logic splits the memory space into interleaved and non-interleaved regions using a boundary at 2 * s_size.

The current check uses '>' and incorrectly classifies the boundary address (2 * s_size) as part of the interleaved region. This leads to incorrect channel/sub-channel selection at the region boundary.

Fix the classification by using '>=' so that the boundary address is handled in the non-interleaved region, matching the hardware layout.

Fixes 10590a9d4f23 ("EDAC/igen6: Add EDAC driver for Intel client SoCs using IBECC")
---
 drivers/edac/igen6_edac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/edac/igen6_edac.c +1 -1
index f1fc20d4ebf61..43b56a2eb5479 100644
@@ -1035,7 +1035,7 @@ static void decode_addr(u64 addr, u32 hash, u64 s_size, int l_map,
 {
 	int intlv_bit = CHANNEL_HASH_LSB_MASK_BIT(hash) + 6;
 
-	if (addr > 2 * s_size) {
+	if (addr >= 2 * s_size) {
 		*sub_addr = addr - s_size;
 		*idx = l_map;
 		return;
Signature · 1 line
2.53.0
author maintainer
#8 lore raw

PATCH 8/733 EDAC/igen6: Fix channel selection hash

In reply to Greg Kroah-Hartman

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

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

From: Qiuxu Zhuo <[email protected]>

[ Upstream commit 540b79536f3a89a66c5b6c490110298d43025618 ]

In channel selection hash mode, the hardware decoding logic always includes the channel interleave bit in XOR operations. However, the hash mask may or may not include this channel interleave bit. When the mask does include this bit, the current igen6_edac code performs XOR on the interleave bit twice, effectively ignoring it - which is incorrect.

Fix this issue by ensuring the hash mask always includes the interleave bit, so XOR is performed on the interleave bit exactly once.

Fixes 10590a9d4f23 ("EDAC/igen6: Add EDAC driver for Intel client SoCs using IBECC")
---
 drivers/edac/igen6_edac.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/edac/igen6_edac.c +11 -3
index 43b56a2eb5479..f1fb644154ae3 100644
@@ -1009,14 +1009,22 @@ static void set_dimm_params(struct igen6_imc *imc, int chan)
 
 static int decode_chan_idx(u64 addr, u64 mask, int intlv_bit)
 {
-	u64 hash_addr = addr & mask, hash = 0;
-	u64 intlv = (addr >> intlv_bit) & 1;
+	u64 hash_addr, hash = 0;
 	int i;
 
+	/*
+	 * In hash mode, the @intlv_bit is the lowest selected bit of @addr
+	 * to be XORed. While @mask may or may not include this @intlv_bit,
+	 * we enforce that @mask includes @intlv_bit to ensure @intlv_bit is
+	 * XORed exactly once.
+	 */
+	mask |= 1 << intlv_bit;
+	hash_addr = addr & mask;
+
 	for (i = 6; i < 20; i++)
 		hash ^= (hash_addr >> i) & 1;
 
-	return (int)hash ^ intlv;
+	return (int)hash;
 }
 
 static u64 decode_channel_addr(u64 addr, int intlv_bit)
Signature · 1 line
2.53.0
author maintainer
#9 lore raw

PATCH 9/733 EDAC/igen6: Fix channel address decode for non-hash mode

In reply to Greg Kroah-Hartman

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

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

From: Qiuxu Zhuo <[email protected]>

[ Upstream commit 7b348d0d401d478f1923ba20a34a61681d1f7971 ]

In non-hash mode, decode_channel_addr() and channel index extraction used a hardcoded interleave bit position 6 instead of the actual intlv_bit parameter, causing incorrect channel address decoding.

Fix this by using intlv_bit consistently in both hash and non-hash modes.

Fixes 10590a9d4f23 ("EDAC/igen6: Add EDAC driver for Intel client SoCs using IBECC")
---
 drivers/edac/igen6_edac.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/edac/igen6_edac.c +5 -6
index f1fb644154ae3..ea5628d780eba 100644
@@ -1049,13 +1049,12 @@ static void decode_addr(u64 addr, u32 hash, u64 s_size, int l_map,
 		return;
 	}
 
-	if (CHANNEL_HASH_MODE(hash)) {
-		*sub_addr = decode_channel_addr(addr, intlv_bit);
+	*sub_addr = decode_channel_addr(addr, intlv_bit);
+
+	if (CHANNEL_HASH_MODE(hash))
 		*idx = decode_chan_idx(addr, CHANNEL_HASH_MASK(hash), intlv_bit);
-	} else {
-		*sub_addr = decode_channel_addr(addr, 6);
-		*idx = GET_BITFIELD(addr, 6, 6);
-	}
+	else
+		*idx = GET_BITFIELD(addr, intlv_bit, intlv_bit);
 }
 
 static int igen6_decode(struct decoded_addr *res)
Signature · 1 line
2.53.0
author maintainer
#10 lore raw

PATCH 10/733 EDAC/igen6: Fix Raptor Lake-P logged error address

In reply to Greg Kroah-Hartman

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

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

From: Qiuxu Zhuo <[email protected]>

[ Upstream commit 0361f576ec0dffca13edc94580c8666146a91e02 ]

Raptor Lake-P was treated as using a different IBECC (In-Band ECC) error address format and therefore had a dedicated extraction path that shifted the logged address.

However, Raptor Lake-P uses the same cache-line-granularity error address format as other IBECC platforms. The special handling causes the logged address to be decoded incorrectly.

Fix the issue by removing Raptor Lake-P specific extraction logic and using the common path instead. This also allows reusing Alder Lake resource configuration data.

Fixes d23627a7688f ("EDAC/igen6: Add Intel Raptor Lake-P SoCs support")
---
 drivers/edac/igen6_edac.c | 39 ++++++---------------------------------
 1 file changed, 6 insertions(+), 33 deletions(-)
drivers/edac/igen6_edac.c +6 -33
index ea5628d780eba..12d718a50e1c9 100644
@@ -175,8 +175,6 @@ static struct res_config {
 	/* Set imc->dimm_{l_size,s_size,l_map}[chan]. */
 	void (*set_dimm_params)(struct igen6_imc *imc, int chan);
 	bool (*ibecc_available)(struct pci_dev *pdev);
-	/* Extract error address logged in IBECC */
-	u64 (*err_addr)(u64 ecclog);
 	/* Convert error address logged in IBECC to system physical address */
 	u64 (*err_addr_to_sys_addr)(u64 eaddr, int mc);
 	/* Convert error address logged in IBECC to integrated memory controller address */
@@ -522,11 +520,6 @@ static u64 adl_err_addr_to_imc_addr(u64 eaddr, int mc)
 	return imc_addr;
 }
 
-static u64 rpl_p_err_addr(u64 ecclog)
-{
-	return field_get(res_cfg->reg_eccerrlog_addr_mask, ecclog);
-}
-
 static enum mem_type ptl_h_get_mem_type(struct igen6_imc *imc)
 {
 	u32 mtype, val;
@@ -716,22 +709,6 @@ static struct res_config adl_n_cfg = {
 	.err_addr_to_imc_addr	= adl_err_addr_to_imc_addr,
 };
 
-static struct res_config rpl_p_cfg = {
-	.machine_check		= true,
-	.num_imc		= 2,
-	.reg_mchbar_mask	= GENMASK_ULL(41, 17),
-	.reg_tom_mask		= GENMASK_ULL(41, 20),
-	.reg_touud_mask		= GENMASK_ULL(41, 20),
-	.reg_eccerrlog_addr_mask = GENMASK_ULL(45, 5),
-	.imc_base		= 0xd800,
-	.ibecc_base		= 0xd400,
-	.ibecc_error_log_offset	= 0x68,
-	.ibecc_available	= tgl_ibecc_available,
-	.err_addr		= rpl_p_err_addr,
-	.err_addr_to_sys_addr	= adl_err_addr_to_sys_addr,
-	.err_addr_to_imc_addr	= adl_err_addr_to_imc_addr,
-};
-
 static struct res_config mtl_ps_cfg = {
 	.machine_check				= true,
 	.num_imc				= 2,
@@ -877,11 +854,11 @@ static struct pci_device_id igen6_pci_tbl[] = {
 	{ PCI_VDEVICE(INTEL, DID_ASL_SKU1), .driver_data = (kernel_ulong_t)&adl_n_cfg },
 	{ PCI_VDEVICE(INTEL, DID_ASL_SKU2), .driver_data = (kernel_ulong_t)&adl_n_cfg },
 	{ PCI_VDEVICE(INTEL, DID_ASL_SKU3), .driver_data = (kernel_ulong_t)&adl_n_cfg },
-	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU1), .driver_data = (kernel_ulong_t)&rpl_p_cfg },
-	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU2), .driver_data = (kernel_ulong_t)&rpl_p_cfg },
-	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU3), .driver_data = (kernel_ulong_t)&rpl_p_cfg },
-	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU4), .driver_data = (kernel_ulong_t)&rpl_p_cfg },
-	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU5), .driver_data = (kernel_ulong_t)&rpl_p_cfg },
+	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU1), .driver_data = (kernel_ulong_t)&adl_cfg },
+	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU2), .driver_data = (kernel_ulong_t)&adl_cfg },
+	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU3), .driver_data = (kernel_ulong_t)&adl_cfg },
+	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU4), .driver_data = (kernel_ulong_t)&adl_cfg },
+	{ PCI_VDEVICE(INTEL, DID_RPL_P_SKU5), .driver_data = (kernel_ulong_t)&adl_cfg },
 	{ PCI_VDEVICE(INTEL, DID_MTL_PS_SKU1), .driver_data = (kernel_ulong_t)&mtl_ps_cfg },
 	{ PCI_VDEVICE(INTEL, DID_MTL_PS_SKU2), .driver_data = (kernel_ulong_t)&mtl_ps_cfg },
 	{ PCI_VDEVICE(INTEL, DID_MTL_PS_SKU3), .driver_data = (kernel_ulong_t)&mtl_ps_cfg },
@@ -1237,11 +1214,7 @@ static void ecclog_work_cb(struct work_struct *work)
 
 	llist_for_each_entry_safe(node, tmp, head, llnode) {
 		memset(&res, 0, sizeof(res));
-		if (res_cfg->err_addr)
-			eaddr = res_cfg->err_addr(node->ecclog);
-		else
-			eaddr = node->ecclog & res_cfg->reg_eccerrlog_addr_mask;
-
+		eaddr	     = node->ecclog & res_cfg->reg_eccerrlog_addr_mask;
 		res.mc	     = node->mc;
 		res.sys_addr = res_cfg->err_addr_to_sys_addr(eaddr, res.mc);
 		res.imc_addr = res_cfg->err_addr_to_imc_addr(eaddr, res.mc);
Signature · 1 line
2.53.0
author maintainer
#11 lore raw

PATCH 11/733 EDAC/device_sysfs: Use kstrtouint() for poll_msec to prevent truncation

In reply to Greg Kroah-Hartman

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

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

From: Jad Keskes <[email protected]>

[ Upstream commit 66cc9dec919dd63d8e4b3d386f7aed3ae684e645 ]

The poll_msec sysfs store file uses simple_strtoul() which accepts an unsigned long, but the target field (poll_msec) is unsigned int. On 64-bit systems, a value > UINT_MAX is silently truncated when stored.

Fix the mismatch by using kstrtouint() instead. This rejects values larger than UINT_MAX at parse time, making truncation impossible. Also add a check for value < 1 to reject the 0-delay case, which would cause the poll work to spin without delay and consume 100% CPU.

Fixes e27e3dac6517 ("drivers/edac: add edac_device class")
---
 drivers/edac/edac_device_sysfs.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/edac/edac_device_sysfs.c +9 -2
index b1c2717cd0237..6995ce039db97 100644
@@ -88,14 +88,21 @@ static ssize_t edac_device_ctl_poll_msec_store(struct edac_device_ctl_info
 					*ctl_info, const char *data,
 					size_t count)
 {
-	unsigned long value;
+	unsigned int value;
+	int ret;
 
 	/* get the value and enforce that it is non-zero, must be at least
 	 * one millisecond for the delay period, between scans
 	 * Then cancel last outstanding delay for the work request
 	 * and set a new one.
 	 */
-	value = simple_strtoul(data, NULL, 0);
+	ret = kstrtouint(data, 0, &value);
+	if (ret < 0)
+		return ret;
+
+	if (value < 1)
+		return -EINVAL;
+
 	edac_device_reset_delay_period(ctl_info, value);
 
 	return count;
Signature · 1 line
2.53.0
author maintainer
#12 lore raw

PATCH 12/733 drm/virtio: Fix a NULL vs ERR_PTR() bug in virtio_gpu_user_framebuffer_create()

In reply to Greg Kroah-Hartman

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

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

From: Dan Carpenter <[email protected]>

[ Upstream commit 94579f24e2b526a04eb41050af0ba018c6f528e7 ]

Smatch complains that returning a NULL here will lead to a NULL pointer dereference in drm_mode_addfb2(). Return an error pointer instead.

---
 drivers/gpu/drm/virtio/virtgpu_display.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/virtio/virtgpu_display.c +1 -1
index 44ffffec550fd..85ea252c658e3 100644
@@ -344,7 +344,7 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev,
 	if (ret) {
 		kfree(virtio_gpu_fb);
 		drm_gem_object_put(obj);
-		return NULL;
+		return ERR_PTR(ret);
 	}
 
 	return &virtio_gpu_fb->base;
Signature · 1 line
2.53.0
author maintainer
#13 lore raw

PATCH 13/733 drm/virtio: use the DMA API for resource backing on Xen

In reply to Greg Kroah-Hartman

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

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

From: Benjamin Leggett <[email protected]>

[ Upstream commit 6a736d2f9d0c6e6217fe7532bc4c50ceca71db78 ]

On a Xen PV domain page addresses bear no relation to the real machine addresses the host would have to use to reach it. virtio_ring.c handles this correctly, vring_use_map_api() returns true for any xen_domain() regardless of VIRTIO_F_ACCESS_PLATFORM.

virtio-gpu makes the same decision independently, but its copy looks only at the feature bit:

	bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);

QEMU does not set iommu_platform on virtio-vga by default, so VIRTIO_F_ACCESS_PLATFORM is not negotiated, use_dma_api is false, and virtio_gpu_object_shmem_init() describes the framebuffer's backing pages to the host with sg_phys(). Those are guest-physical addresses. In a PV domain they resolve, on the host side, to pages belonging to some other domain, so the host scans out unrelated memory.

Move the decision into virtio_gpu_use_dma_api() and give it the xen_domain() check, like vring_use_map_api() has. This additionally enables the dma_sync_sgtable_for_device() calls in virtgpu_vq.c, which are required for correctness whenever swiotlb is in play.

Reproduced with a Xen 4.21 PV dom0 nested inside QEMU 8.2 with virtio-vga, on both a distro 6.8 kernel and 6.18 LTS. A PVH dom0 works fine and doesn't need this fix because it is identity-mapped, only PV dom0s are affected.

---
 drivers/gpu/drm/virtio/virtgpu_drv.h    | 20 ++++++++++++++++++++
 drivers/gpu/drm/virtio/virtgpu_object.c |  2 +-
 drivers/gpu/drm/virtio/virtgpu_vq.c     |  6 +++---
 3 files changed, 24 insertions(+), 4 deletions(-)
drivers/gpu/drm/virtio/virtgpu_drv.h +20 -0
index 7449907754a43..88fb4be92cf3e 100644
@@ -43,6 +43,8 @@
 #include <drm/drm_probe_helper.h>
 #include <drm/virtgpu_drm.h>
 
+#include <xen/xen.h>
+
 #define DRIVER_NAME "virtio_gpu"
 #define DRIVER_DESC "virtio GPU"
 
@@ -60,6 +62,24 @@
 /* See virtio_gpu_ctx_create. One additional character for NULL terminator. */
 #define DEBUG_NAME_MAX_LEN 65
 
+/*
+ * Whether the host must be told about resource backing pages by DMA address
+ * rather than guest-physical address.
+ *
+ * This mirrors vring_use_map_api() in drivers/virtio/virtio_ring.c, including
+ * its xen_domain() case.
+ */
+static inline bool virtio_gpu_use_dma_api(const struct virtio_device *vdev)
+{
+	if (!virtio_has_dma_quirk(vdev))
+		return true;
+
+	if (xen_domain())
+		return true;
+
+	return false;
+}
+
 struct virtio_gpu_object_params {
 	unsigned long size;
 	bool dumb;
drivers/gpu/drm/virtio/virtgpu_object.c +1 -1
index ec9efacc69195..1527c62be88ba 100644
@@ -163,7 +163,7 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
 					struct virtio_gpu_mem_entry **ents,
 					unsigned int *nents)
 {
-	bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
+	bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
 	struct scatterlist *sg;
 	struct sg_table *pages;
 	int si;
drivers/gpu/drm/virtio/virtgpu_vq.c +3 -3
index e5e1af8b8e8a0..2b7af8e4e9e61 100644
@@ -724,7 +724,7 @@ int virtio_gpu_panic_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
 	struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
 	struct virtio_gpu_transfer_to_host_2d *cmd_p;
 	struct virtio_gpu_vbuffer *vbuf;
-	bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
+	bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
 
 	if (virtio_gpu_is_shmem(bo) && use_dma_api)
 		dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
@@ -755,7 +755,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
 	struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
 	struct virtio_gpu_transfer_to_host_2d *cmd_p;
 	struct virtio_gpu_vbuffer *vbuf;
-	bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
+	bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
 
 	if (virtio_gpu_is_shmem(bo) && use_dma_api)
 		dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
@@ -1188,7 +1188,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
 	struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]);
 	struct virtio_gpu_transfer_host_3d *cmd_p;
 	struct virtio_gpu_vbuffer *vbuf;
-	bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
+	bool use_dma_api = virtio_gpu_use_dma_api(vgdev->vdev);
 
 	if (virtio_gpu_is_shmem(bo) && use_dma_api)
 		dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
Signature · 1 line
2.53.0
author maintainer
#14 lore raw

PATCH 14/733 accel/qaic: Address potential out-of-bounds read in resp_worker()

In reply to Greg Kroah-Hartman

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

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

From: Youssef Samir <[email protected]>

[ Upstream commit ab243f74ab4084ca5c8dec608cb5b0deb27db067 ]

Although 'commit 2feec5ae5df7 ("accel/qaic: Handle DBC deactivation if the owner went away")' fixes the scenario it was intended for by walking the message and only decoding QAIC_TRANS_DEACTIVATE_FROM_DEV, if present, it skipped over the bounds checking code that is included in decode_message(). This could lead to issues such as reading past the slab allocation's end, infinite loops or kernel panics. For those issues to happen, a malformed wire message is needed to be sent from the device.

Instead of duplicating the bounds checking code already present in decode_message(), use the function inside resp_worker().

Fixes 2feec5ae5df7 ("accel/qaic: Handle DBC deactivation if the owner went away")
---
 drivers/accel/qaic/qaic_control.c | 46 ++++++++++++++++---------------
 1 file changed, 24 insertions(+), 22 deletions(-)
drivers/accel/qaic/qaic_control.c +24 -22
index 50bf3340e49ce..2ccc55486aac0 100644
@@ -963,11 +963,13 @@ static int decode_status(struct qaic_device *qdev, void *trans, struct manage_ms
 
 static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
 			  struct wire_msg *msg, struct ioctl_resources *resources,
-			  struct qaic_user *usr)
+			  struct qaic_user *usr, bool orphaned_deactivate)
 {
+	u32 msg_hdr_count = le32_to_cpu(msg->hdr.count);
 	u32 msg_hdr_len = le32_to_cpu(msg->hdr.len);
 	struct wire_trans_hdr *trans_hdr;
 	u32 msg_len = 0;
+	int trans_type;
 	int ret;
 	int i;
 
@@ -975,10 +977,12 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
 	    msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
 		return -EINVAL;
 
-	user_msg->len = 0;
-	user_msg->count = le32_to_cpu(msg->hdr.count);
+	if (user_msg) {
+		user_msg->len = 0;
+		user_msg->count = msg_hdr_count;
+	}
 
-	for (i = 0; i < user_msg->count; ++i) {
+	for (i = 0; i < msg_hdr_count; ++i) {
 		u32 hdr_len;
 
 		if (msg_len > msg_hdr_len - sizeof(*trans_hdr))
@@ -990,7 +994,20 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
 		    size_add(msg_len, hdr_len) > msg_hdr_len)
 			return -EINVAL;
 
-		switch (le32_to_cpu(trans_hdr->type)) {
+		trans_type = le32_to_cpu(trans_hdr->type);
+		/*
+		 * orphaned_deactivate is the case where a deactivate response
+		 * is received from the device after the user owning the DBC,
+		 * and the message requesting deactivation, has gone away.
+		 * In this case, only process QAIC_TRANS_DEACTIVATE_FROM_DEV
+		 * transaction and skip the others.
+		 */
+		if (orphaned_deactivate && trans_type != QAIC_TRANS_DEACTIVATE_FROM_DEV) {
+			msg_len += hdr_len;
+			continue;
+		}
+
+		switch (trans_type) {
 		case QAIC_TRANS_PASSTHROUGH_FROM_DEV:
 			ret = decode_passthrough(qdev, trans_hdr, user_msg, &msg_len);
 			break;
@@ -1281,7 +1298,7 @@ static int qaic_manage(struct qaic_device *qdev, struct qaic_user *usr, struct m
 		goto dma_cont_failed;
 	}
 
-	ret = decode_message(qdev, user_msg, rsp, &resources, usr);
+	ret = decode_message(qdev, user_msg, rsp, &resources, usr, false);
 
 dma_cont_failed:
 	free_dbc_buf(qdev, &resources);
@@ -1446,22 +1463,7 @@ static void resp_worker(struct work_struct *work)
 		 * response to the QAIC_TRANS_TERMINATE_TO_DEV transaction,
 		 * otherwise, the user can issue an soc_reset to the device.
 		 */
-		u32 msg_count = le32_to_cpu(msg->hdr.count);
-		u32 msg_len = le32_to_cpu(msg->hdr.len);
-		u32 len = 0;
-		int j;
-
-		for (j = 0; j < msg_count && len < msg_len; ++j) {
-			struct wire_trans_hdr *trans_hdr;
-
-			trans_hdr = (struct wire_trans_hdr *)(msg->data + len);
-			if (le32_to_cpu(trans_hdr->type) == QAIC_TRANS_DEACTIVATE_FROM_DEV) {
-				if (decode_deactivate(qdev, trans_hdr, &len, NULL))
-					len += le32_to_cpu(trans_hdr->len);
-			} else {
-				len += le32_to_cpu(trans_hdr->len);
-			}
-		}
+		decode_message(qdev, NULL, msg, NULL, NULL, true);
 		/* request must have timed out, drop packet */
 		kfree(msg);
 	}
Signature · 1 line
2.53.0
author maintainer
#15 lore raw

PATCH 15/733 nvme-rdma: fix -EIO cleanup order in queue_rq

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 d61828199c6cb4b76d48403c77023cd4bb9d09fc ]

On -EIO, the RDMA queue_rq path reports a host path error and then still cleans up the command and unmaps the SQE DMA. The path error helper completes the request, so that is double cleanup and DMA unmap after the request is already complete.

Unmap the SQE first, then report the host path error. Skip the outer command cleanup on that path.

Fixes 62eca39722fd ("nvme-rdma: handle nvme_rdma_post_send failures better")
---
 drivers/nvme/host/rdma.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/nvme/host/rdma.c +10 -8
index 6909e35427942..618ee95444263 100644
@@ -2003,7 +2003,7 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
 	struct ib_device *dev;
 	bool queue_ready = test_bit(NVME_RDMA_Q_LIVE, &queue->flags);
 	blk_status_t ret;
-	int err;
+	int err = 0;
 
 	WARN_ON_ONCE(rq->tag < 0);
 
@@ -2059,16 +2059,18 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
 err_unmap:
 	nvme_rdma_unmap_data(queue, rq);
 err:
-	if (err == -EIO)
-		ret = nvme_host_path_error(rq);
-	else if (err == -ENOMEM || err == -EAGAIN)
-		ret = BLK_STS_RESOURCE;
-	else
-		ret = BLK_STS_IOERR;
-	nvme_cleanup_cmd(rq);
+	if (err != -EIO) {
+		nvme_cleanup_cmd(rq);
+		if (err == -ENOMEM || err == -EAGAIN)
+			ret = BLK_STS_RESOURCE;
+		else
+			ret = BLK_STS_IOERR;
+	}
 unmap_qe:
 	ib_dma_unmap_single(dev, req->sqe.dma, sizeof(struct nvme_command),
 			    DMA_TO_DEVICE);
+	if (err == -EIO)
+		return nvme_host_path_error(rq);
 	return ret;
 }
 
Signature · 1 line
2.53.0
author maintainer
#16 lore raw

PATCH 16/733 nvme: add context annotations for nvme_subsystem::lock

In reply to Greg Kroah-Hartman

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

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

From: Nilay Shroff <[email protected]>

[ Upstream commit d1fdf49b5f7fce5f65ae0d11d484bd7e31cedbb1 ]

Several helpers access or traverse data structures protected by nvme_subsystem::lock and therefore require callers to hold the lock. Annotate nvme_mpath_unfreeze(), nvme_mpath_wait_freeze(), nvme_mpath_start_freeze(), nvme_find_ns_head(), nvme_alloc_ns_head() and nvme_subsys_check_duplicate_ids() with __must_hold(&subsys->lock) so that Clang's lock context analysis can validate the locking requirements at compile time.

Also annotate nvme_subsystem::nsheads and nvme_ns_head::delayed_removal_secs with __guarded_by(&subsys->lock), as both are protected by the subsystem lock.

Annotate nvme_init_subsystem() with __context_unsafe(), as it initializes these lock-protected members before the object is published, suppressing a false positive from Clang's context analysis.

Stable-dep-of: 56e1c6bbe4bb ("nvme: fix racy access to FDP placement id array")

---
 drivers/nvme/host/core.c |  4 ++++
 drivers/nvme/host/nvme.h | 15 ++++++++++-----
 2 files changed, 14 insertions(+), 5 deletions(-)
drivers/nvme/host/core.c +4 -0
index 0b80db7a0599f..0224b99317cdd 100644
@@ -3292,6 +3292,7 @@ static bool nvme_validate_cntlid(struct nvme_subsystem *subsys,
 }
 
 static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
+	__context_unsafe(/* initialize unpublished/lock-guarded variables */)
 {
 	struct nvme_subsystem *subsys, *found;
 	int ret;
@@ -3863,6 +3864,7 @@ static const struct file_operations nvme_dev_fops = {
 
 static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl,
 		unsigned nsid)
+	__must_hold(&ctrl->subsys->lock)
 {
 	struct nvme_ns_head *h;
 
@@ -3885,6 +3887,7 @@ static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl,
 
 static int nvme_subsys_check_duplicate_ids(struct nvme_subsystem *subsys,
 		struct nvme_ns_ids *ids)
+	__must_hold(&subsys->lock)
 {
 	bool has_uuid = !uuid_is_null(&ids->uuid);
 	bool has_nguid = memchr_inv(ids->nguid, 0, sizeof(ids->nguid));
@@ -3986,6 +3989,7 @@ static void nvme_add_ns_cdev(struct nvme_ns *ns)
 
 static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
 		struct nvme_ns_info *info)
+	__must_hold(&ctrl->subsys->lock)
 {
 	struct nvme_ns_head *head;
 	size_t size = sizeof(*head);
drivers/nvme/host/nvme.h +10 -5
index 957ded0c6f53b..5e2e45ef7dadf 100644
@@ -503,7 +503,8 @@ struct nvme_subsystem {
 	struct list_head	entry;
 	struct mutex		lock;
 	struct list_head	ctrls;
-	struct list_head	nsheads;
+	struct list_head	nsheads
+		__guarded_by(&lock);
 	char			subnqn[NVMF_NQN_SIZE];
 	char			serial[20];
 	char			model[40];
@@ -575,7 +576,8 @@ struct nvme_ns_head {
 	struct mutex		lock;
 	unsigned long		flags;
 	struct delayed_work	remove_work;
-	unsigned int		delayed_removal_secs;
+	unsigned int		delayed_removal_secs
+		__guarded_by(&subsys->lock);
 	atomic_long_t		io_requeue_no_usable_path_count;
 	atomic_long_t		io_fail_no_available_path_count;
 #define NVME_NSHEAD_DISK_LIVE		0
@@ -1046,9 +1048,12 @@ static inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
 	return ctrl->ana_log_buf != NULL;
 }
 
-void nvme_mpath_unfreeze(struct nvme_subsystem *subsys);
-void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys);
-void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
+void nvme_mpath_unfreeze(struct nvme_subsystem *subsys)
+	__must_hold(&subsys->lock);
+void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
+	__must_hold(&subsys->lock);
+void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
+	__must_hold(&subsys->lock);
 void nvme_mpath_default_iopolicy(struct nvme_subsystem *subsys);
 void nvme_failover_req(struct request *req);
 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl);
Signature · 1 line
2.53.0
author maintainer
#17 lore raw

PATCH 17/733 nvme: set ns->head in nvme_alloc_ns_head

In reply to Greg Kroah-Hartman

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

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

From: Kanchan Joshi <[email protected]>

[ Upstream commit c1888444dc28310222dcc6e5c301d60d0943787f ]

so that it becomes possible to submit non-admin commands. This is a prep patch with no functional changes.

Stable-dep-of: 56e1c6bbe4bb ("nvme: fix racy access to FDP placement id array")

---
 drivers/nvme/host/core.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/nvme/host/core.c +6 -3
index 0224b99317cdd..e5051a6b33578 100644
@@ -3987,10 +3987,11 @@ static void nvme_add_ns_cdev(struct nvme_ns *ns)
 	set_bit(NVME_NS_CDEV_LIVE, &ns->flags);
 }
 
-static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
+static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ns *ns,
 		struct nvme_ns_info *info)
-	__must_hold(&ctrl->subsys->lock)
+	__must_hold(&ns->ctrl->subsys->lock)
 {
+	struct nvme_ctrl *ctrl = ns->ctrl;
 	struct nvme_ns_head *head;
 	size_t size = sizeof(*head);
 	int ret = -ENOMEM;
@@ -4018,6 +4019,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
 	ratelimit_state_init(&head->rs_nuse, 5 * HZ, 1);
 	ratelimit_set_flags(&head->rs_nuse, RATELIMIT_MSG_ON_RELEASE);
 	kref_init(&head->ref);
+	ns->head = head;
 
 	if (head->ids.csi) {
 		ret = nvme_get_effects_log(ctrl, head->ids.csi, &head->effects);
@@ -4041,6 +4043,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
 	ida_free(&ctrl->subsys->ns_ida, head->instance);
 out_free_head:
 	kfree(head);
+	ns->head = NULL;
 out:
 	if (ret > 0)
 		ret = blk_status_to_errno(nvme_error_status(ret));
@@ -4127,7 +4130,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
 				info->nsid);
 			goto out_unlock;
 		}
-		head = nvme_alloc_ns_head(ctrl, info);
+		head = nvme_alloc_ns_head(ns, info);
 		if (IS_ERR(head)) {
 			ret = PTR_ERR(head);
 			goto out_unlock;
Signature · 1 line
2.53.0
author maintainer
#18 lore raw

PATCH 18/733 nvme: fix racy access to FDP placement id array

In reply to Greg Kroah-Hartman

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

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

From: Kanchan Joshi <[email protected]>

[ Upstream commit 56e1c6bbe4bb084d7ecf61698afdf70be23dd35f ]

nvme_query_fdp_info() is called per-path and therefore prone to races.

It populates head->nr_plids/head->plids for fdp registration. But nothing protects that pair from concurrent access - two paths scanning the same namespace can race to populate it.

Avoid the race by moving this initialization work to nvme_alloc_ns_head() which is called once per shared namespace.

---
 drivers/nvme/host/core.c | 30 +++++++++++-------------------
 drivers/nvme/host/nvme.h |  1 +
 2 files changed, 12 insertions(+), 19 deletions(-)
drivers/nvme/host/core.c +11 -19
index e5051a6b33578..706df45b26e77 100644
@@ -2323,14 +2323,6 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info)
 	size_t size;
 	int i, ret;
 
-	/*
-	 * The FDP configuration is static for the lifetime of the namespace,
-	 * so return immediately if we've already registered this namespace's
-	 * streams.
-	 */
-	if (head->nr_plids)
-		return 0;
-
 	ret = nvme_get_features(ctrl, NVME_FEAT_FDP, info->endgid, NULL, 0,
 				&fdp);
 	if (ret) {
@@ -2377,6 +2369,7 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info)
 
 	for (i = 0; i < head->nr_plids; i++)
 		head->plids[i] = le16_to_cpu(ruhs->ruhsd[i].pid);
+	head->write_stream_granularity = min(info->runs, U32_MAX);
 free:
 	kfree(ruhs);
 	return ret;
@@ -2424,12 +2417,6 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
 			goto out;
 	}
 
-	if (ns->ctrl->ctratt & NVME_CTRL_ATTR_FDPS) {
-		ret = nvme_query_fdp_info(ns, info);
-		if (ret < 0)
-			goto out;
-	}
-
 	if (nvme_invalid_lba_sz(le64_to_cpu(id->nsze),
 			id->lbaf[lbaf].ds - SECTOR_SHIFT, &capacity)) {
 		dev_warn_once(ns->ctrl->device,
@@ -2489,10 +2476,7 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
 		capacity = 0;
 
 	lim.max_write_streams = ns->head->nr_plids;
-	if (lim.max_write_streams)
-		lim.write_stream_granularity = min(info->runs, U32_MAX);
-	else
-		lim.write_stream_granularity = 0;
+	lim.write_stream_granularity = ns->head->write_stream_granularity;
 
 	/*
 	 * Only set the DEAC bit if the device guarantees that reads from
@@ -4028,15 +4012,23 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ns *ns,
 	} else
 		head->effects = ctrl->effects;
 
+	if (ctrl->ctratt & NVME_CTRL_ATTR_FDPS) {
+		ret = nvme_query_fdp_info(ns, info);
+		if (ret < 0)
+			goto out_cleanup_srcu;
+	}
+
 	ret = nvme_mpath_alloc_disk(ctrl, head);
 	if (ret)
-		goto out_cleanup_srcu;
+		goto out_cleanup_fdp;
 
 	list_add_tail(&head->entry, &ctrl->subsys->nsheads);
 
 	kref_get(&ctrl->subsys->ref);
 
 	return head;
+out_cleanup_fdp:
+	kfree(head->plids);
 out_cleanup_srcu:
 	cleanup_srcu_struct(&head->srcu);
 out_ida_remove:
drivers/nvme/host/nvme.h +1 -0
index 5e2e45ef7dadf..cfdcf53db5abd 100644
@@ -568,6 +568,7 @@ struct nvme_ns_head {
 
 	u16			nr_plids;
 	u16			*plids;
+	u32			write_stream_granularity;
 #ifdef CONFIG_NVME_MULTIPATH
 	struct bio_list		requeue_list;
 	spinlock_t		requeue_lock;
Signature · 1 line
2.53.0
author maintainer
#19 lore raw

PATCH 19/733 nvmet-rdma: fix queue leak when connect backlog is exceeded

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 fb1ed67788e21832b614c23767a088c08cfdd2f2 ]

When pending disconnecting queues exceed the backlog limit, the connect path only drops the device reference and leaks the newly allocated queue and its IB resources.

Fixes badc53620fe8 ("nvme: target: rdma: fix ndev refcount leak on queue connect")
---
 drivers/nvme/target/rdma.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
drivers/nvme/target/rdma.c +7 -8
index de5a88fbb2337..542138fd669f4 100644
@@ -1627,19 +1627,13 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,
 		mutex_unlock(&nvmet_rdma_queue_mutex);
 		if (pending > NVMET_RDMA_BACKLOG) {
 			ret = NVME_SC_CONNECT_CTRL_BUSY;
-			goto put_device;
+			goto free_queue;
 		}
 	}
 
 	ret = nvmet_rdma_cm_accept(cm_id, queue, &event->param.conn);
-	if (ret) {
-		/*
-		 * Don't destroy the cm_id in free path, as we implicitly
-		 * destroy the cm_id here with non-zero ret code.
-		 */
-		queue->cm_id = NULL;
+	if (ret)
 		goto free_queue;
-	}
 
 	mutex_lock(&nvmet_rdma_queue_mutex);
 	list_add_tail(&queue->queue_list, &nvmet_rdma_queue_list);
@@ -1648,6 +1642,11 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,
 	return 0;
 
 free_queue:
+	/*
+	 * Don't destroy the cm_id in free path, as we implicitly
+	 * destroy the cm_id here with non-zero ret code.
+	 */
+	queue->cm_id = NULL;
 	nvmet_rdma_free_queue(queue);
 put_device:
 	kref_put(&ndev->ref, nvmet_rdma_free_dev);
Signature · 1 line
2.53.0
author maintainer
#20 lore raw

PATCH 20/733 sched_ext: Fix nonexistent field in sched-ext.rst example

In reply to Greg Kroah-Hartman

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

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

From: Liang Luo <[email protected]>

[ Upstream commit 4fb8d6379d2c7ceecb2b3e111954d29089d59492 ]

The ops.exit() example in sched-ext.rst reads ei->type, but struct scx_exit_info has never had a type field - the exit reason is exposed as ei->kind since the struct was introduced. A scheduler written following the example fails to compile with

error: no member named 'type' in 'struct scx_exit_info'

Use ei->kind.

Fixes fa48e8d2c7b5 ("sched_ext: Documentation: scheduler: Document extensible scheduler class")
---
 Documentation/scheduler/sched-ext.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/scheduler/sched-ext.rst +1 -1
index 2771ea4cc14af..96ff66c91ceb2 100644
@@ -229,7 +229,7 @@ optional. The following modified excerpt is from
 
     void BPF_STRUCT_OPS(simple_exit, struct scx_exit_info *ei)
     {
-            exit_type = ei->type;
+            exit_type = ei->kind;
     }
 
     SEC(".struct_ops")
Signature · 1 line
2.53.0
author maintainer
#21 lore raw

PATCH 21/733 selftests/cgroup: set the test plan after the setup checks

In reply to Greg Kroah-Hartman

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

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

From: Hemanth Selam <[email protected]>

[ Upstream commit 0c893d170ff8efe7b4067552932d26e7defba307 ]

The cgroup tests announce their plan before checking whether cgroup v2 is available, so on a host without it they promise a number of results and then skip out after the first one:

	TAP version 13
	1..3
	ok 1 # SKIP cgroup v2 isn't mounted
	# Planned tests != run tests (3 != 1)
	# Totals: pass:0 fail:0 xfail:0 xpass:0 skip:1 error:0

ksft_exit_skip() can only emit a well formed "1..0 # SKIP" line while no plan has been printed, as the comment above it in kselftest.h points out.

Move ksft_set_plan() below the setup checks that can skip, so that a skipped run reports:

TAP version 13
1..0 # SKIP cgroup v2 isn't mounted

Several of the tests skip more than once while setting up, for a missing or unwritable controller as well, so the plan goes after the last of them. test_core joins its two setup paths at the post_v2_setup label and sets the plan there.

Reporting each planned test as skipped instead would keep the plan where it is, but the setup failures here mean the whole test cannot run rather than its individual cases being skipped, which is what "1..0 # SKIP" is for.

Fixes 1dc830ee4c15 ("selftests/cgroup: conform test to KTAP format output")
---
 tools/testing/selftests/cgroup/test_core.c       | 2 +-
 tools/testing/selftests/cgroup/test_cpu.c        | 2 +-
 tools/testing/selftests/cgroup/test_cpuset.c     | 2 +-
 tools/testing/selftests/cgroup/test_freezer.c    | 2 +-
 tools/testing/selftests/cgroup/test_kill.c       | 2 +-
 tools/testing/selftests/cgroup/test_kmem.c       | 2 +-
 tools/testing/selftests/cgroup/test_memcontrol.c | 2 +-
 tools/testing/selftests/cgroup/test_pids.c       | 2 +-
 tools/testing/selftests/cgroup/test_zswap.c      | 2 +-
 9 files changed, 9 insertions(+), 9 deletions(-)
tools/testing/selftests/cgroup/test_core.c +1 -1
index 88ca832d4fc13..64f4962a4659d 100644
@@ -927,7 +927,6 @@ int main(int argc, char *argv[])
 	int i;
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), &nsdelegate)) {
 		if (setup_named_v1_root(root, sizeof(root), CG_NAMED_NAME))
 			ksft_exit_skip("cgroup v2 isn't mounted and could not setup named v1 hierarchy\n");
@@ -940,6 +939,7 @@ int main(int argc, char *argv[])
 			ksft_exit_skip("Failed to set memory controller\n");
 
 post_v2_setup:
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
tools/testing/selftests/cgroup/test_cpu.c +1 -1
index 7a40d76b95487..8f96bfd19ab9f 100644
@@ -799,7 +799,6 @@ int main(int argc, char *argv[])
 	int i;
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
 
@@ -807,6 +806,7 @@ int main(int argc, char *argv[])
 		if (cg_write(root, "cgroup.subtree_control", "+cpu"))
 			ksft_exit_skip("Failed to set cpu controller\n");
 
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
tools/testing/selftests/cgroup/test_cpuset.c +1 -1
index c5cf8b56ceb8f..52ed8fba685ae 100644
@@ -250,7 +250,6 @@ int main(int argc, char *argv[])
 	int i;
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
 
@@ -258,6 +257,7 @@ int main(int argc, char *argv[])
 		if (cg_write(root, "cgroup.subtree_control", "+cpuset"))
 			ksft_exit_skip("Failed to set cpuset controller\n");
 
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
tools/testing/selftests/cgroup/test_freezer.c +1 -1
index 0569e93fa6b00..f28bb02e9783b 100644
@@ -1491,9 +1491,9 @@ int main(int argc, char *argv[])
 	int i;
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
tools/testing/selftests/cgroup/test_kill.c +1 -1
index f6cd23a8ecc71..99cafd9dc0136 100644
@@ -278,9 +278,9 @@ int main(int argc, char *argv[])
 	int i;
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
tools/testing/selftests/cgroup/test_kmem.c +1 -1
index 1db0ba1226b9b..cb47561b4b443 100644
@@ -426,7 +426,6 @@ int main(int argc, char **argv)
 	int i;
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
 
@@ -441,6 +440,7 @@ int main(int argc, char **argv)
 		if (cg_write(root, "cgroup.subtree_control", "+memory"))
 			ksft_exit_skip("Failed to set memory controller\n");
 
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
tools/testing/selftests/cgroup/test_memcontrol.c +1 -1
index 0ebf796f3cffe..3a84d068fbf36 100644
@@ -1798,7 +1798,6 @@ int main(int argc, char **argv)
 		page_size = BUF_SIZE;
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
 
@@ -1823,6 +1822,7 @@ int main(int argc, char **argv)
 		ksft_exit_skip("Failed to query cgroup mount option\n");
 	has_localevents = proc_status;
 
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
tools/testing/selftests/cgroup/test_pids.c +1 -1
index 9a387c815d2cd..710109b53dfe9 100644
@@ -148,7 +148,6 @@ int main(int argc, char **argv)
 	char root[PATH_MAX];
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
 
@@ -163,6 +162,7 @@ int main(int argc, char **argv)
 		if (cg_write(root, "cgroup.subtree_control", "+pids"))
 			ksft_exit_skip("Failed to set pids controller\n");
 
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (int i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
tools/testing/selftests/cgroup/test_zswap.c +1 -1
index 49b36ee791606..6e7b89315bbf3 100644
@@ -810,7 +810,6 @@ int main(int argc, char **argv)
 		page_size = BUF_SIZE;
 
 	ksft_print_header();
-	ksft_set_plan(ARRAY_SIZE(tests));
 	if (cg_find_unified_root(root, sizeof(root), NULL))
 		ksft_exit_skip("cgroup v2 isn't mounted\n");
 
@@ -827,6 +826,7 @@ int main(int argc, char **argv)
 		if (cg_write(root, "cgroup.subtree_control", "+memory"))
 			ksft_exit_skip("Failed to set memory controller\n");
 
+	ksft_set_plan(ARRAY_SIZE(tests));
 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
 		switch (tests[i].fn(root)) {
 		case KSFT_PASS:
Signature · 1 line
2.53.0
author maintainer
#22 lore raw

PATCH 22/733 selftests/cgroup: Fix cg_run_in_subcgroups ignoring arg parameter

In reply to Greg Kroah-Hartman

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

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

From: Hongfu Li <[email protected]>

[ Upstream commit a8c6daab4b0e276508b7ffdd66c60fd3020a9178 ]

cg_run_in_subcgroups() discards its arg and always passes NULL to cg_run(), turning the (void *)100 from test_kmem_dead_cgroups() into NULL so no allocation occurs.

This makes test_kmem_dead_cgroups() falsely pass without exercising the "dying cgroup with charged slab" scenario it intends to test.

Pass the arg through to cg_run() to fix this.

Fixes 933dc80ec262 ("kselftests: cgroup: add kernel memory accounting tests")
---
 tools/testing/selftests/cgroup/test_kmem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/cgroup/test_kmem.c +1 -1
index cb47561b4b443..437f2d35f205e 100644
@@ -145,7 +145,7 @@ static int cg_run_in_subcgroups(const char *parent,
 			return -1;
 		}
 
-		if (cg_run(child, fn, NULL)) {
+		if (cg_run(child, fn, arg)) {
 			cg_destroy(child);
 			free(child);
 			return -1;
Signature · 1 line
2.53.0
author maintainer
#23 lore raw

PATCH 23/733 bpf: Fix REG INVARIANTS VIOLATION on speculative pointer arithmetic

In reply to Greg Kroah-Hartman

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

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

From: Jiayuan Chen <[email protected]>

[ Upstream commit 150aeba624e8b7cac51c39440d7e8e1fd11de9a0 ]

Take the following unprivileged program as an example:

	r0 = bpf_map_lookup_elem(...)	/* PTR_TO_MAP_VALUE, offset 0 */
	...
	14: r0 += r1			/* r1 is a bounded scalar */
	15: r9 = r0

Loading it triggers a verifier warning from reg_bounds_sanity_check():

	verifier bug: REG INVARIANTS VIOLATION (alu): const subreg tnum out
	of sync with range bounds r64={.base=0x0, .size=0x0}
	r32={.base=0x0, .size=0xffffffff} var_off=(0x0, 0x0)

What happens:

1. Processing insn 14 (r0 += r1) in adjust_ptr_min_max_vals(), the new offset is computed into dst_reg's var_off and 32/64-bit ranges.

2. Because pointer registers do not track 32-bit subregister bounds, __mark_reg32_unbounded() first sets r32 to the full range; r32 is re-derived from the offset at the end of the function by reg_bounds_sync().

3. On the unprivileged path, sanitize_ptr_alu() is called and, via sanitize_speculative_path() -> push_stack(), snapshots the current register state and schedules the next instruction (insn 15) to be verified directly as a speculative path.

4. That snapshot is taken between step 2 and the final reg_bounds_sync():
at this point dst_reg's var_off still holds the (const) original offset while r32 has just been blanked to the full range, i.e. the two are out of sync. When the speculative path later verifies insn 15 (r9 = r0), the inconsistent state reaches reg_bounds_sanity_check() and trips the warning.

var_off and the 32-bit range must always be consistent. There are two ways to keep the snapshot consistent:

1. sync var_off and r32 before the snapshot so they match, or
2. leave r32 at its original (already consistent) value and blank it only after the snapshot.

The whole point of sanitize_ptr_alu() is to insert a harmless masking sequence that keeps the access in bounds under speculation, so the state it snapshots should faithfully represent that. Take approach 2: move __mark_reg32_unbounded() to after sanitize_ptr_alu(), so the speculative snapshot keeps the pointer's original, consistent r32. The non-speculative path is unchanged: r32 is still blanked before the offset is applied and re-derived by reg_bounds_sync().

---
 kernel/bpf/verifier.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
kernel/bpf/verifier.c +8 -3
index 14a9fd2d54720..03187bab806a7 100644
@@ -13794,9 +13794,6 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 	    !check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))
 		return -EINVAL;
 
-	/* pointer types do not carry 32-bit bounds at the moment. */
-	__mark_reg32_unbounded(dst_reg);
-
 	if (sanitize_needed(opcode)) {
 		ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg,
 				       &info, false);
@@ -13804,6 +13801,14 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 			return sanitize_err(env, insn, ret);
 	}
 
+	/*
+	 * Pointer types do not carry 32-bit bounds at the moment. Blank r32
+	 * only after sanitize_ptr_alu() may have snapshotted dst_reg into a
+	 * speculative path: otherwise reg_bounds_sanity_check() might hit some
+	 * constraints violations.
+	 */
+	__mark_reg32_unbounded(dst_reg);
+
 	switch (opcode) {
 	case BPF_ADD:
 		/*
Signature · 1 line
2.53.0
author maintainer
#24 lore raw

PATCH 24/733 bpf: Fix BPF_F_CPU validation for sparse CPU IDs

In reply to Greg Kroah-Hartman

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

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

From: Hui Su <[email protected]>

[ Upstream commit ed54bf564ac52699cf4def3d0c2125d493e756f9 ]

BPF_F_CPU stores the target CPU ID in the upper 32 bits of the map operation flags. bpf_map_check_op_flags() currently compares that ID with num_possible_cpus(), which is the number of possible CPUs rather than a bound on CPU IDs.

On an arm64 QEMU guest with a CPU device-tree hole, the possible CPU mask was 0,2-3. A userspace program using raw bpf() syscalls creates a BPF_MAP_TYPE_PERCPU_ARRAY and performs update and lookup operations for each CPU by setting BPF_F_CPU and the CPU ID in the flags.

With the old check, CPU 1 is incorrectly accepted while valid CPU 3 is rejected with -ERANGE. The CPU 1 update then reaches the per-CPU map access path and triggers:

  Unable to handle kernel paging request at virtual address ...
  pc : __pi_memcpy_generic+0x5c/0x22c
  lr : bpf_percpu_array_update+0x2dc/0x2e8
  Call trace:
    __pi_memcpy_generic
    bpf_map_update_value
    map_update_elem
    __sys_bpf

Check the CPU ID against nr_cpu_ids and cpu_possible() instead. This rejects CPU IDs outside the valid range and CPUs absent from the possible mask, while allowing valid sparse CPU IDs.

Fixes 2b421662c788 ("bpf: Introduce BPF_F_CPU and BPF_F_ALL_CPUS flags")
---
 include/linux/bpf.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/bpf.h +1 -1
index 77e2075f77c73..7798abc7d637b 100644
@@ -4184,7 +4184,7 @@ static inline int bpf_map_check_op_flags(struct bpf_map *map, u64 flags, u64 all
 			return -EINVAL;
 
 		cpu = flags >> 32;
-		if ((flags & BPF_F_CPU) && cpu >= num_possible_cpus())
+		if ((flags & BPF_F_CPU) && (cpu >= nr_cpu_ids || !cpu_possible(cpu)))
 			return -ERANGE;
 	}
 
Signature · 1 line
2.53.0
author maintainer
#25 lore raw

PATCH 25/733 bpf: Fix percpu map update indexing with sparse CPU IDs

In reply to Greg Kroah-Hartman

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

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

From: Hui Su <[email protected]>

[ Upstream commit 75b0a6db4300e4c2c9e97a0848deaa7acfb42fb7 ]

Per-CPU array, hash, and cgroup storage map updates without BPF_F_CPU or BPF_F_ALL_CPUS use a value buffer whose per-CPU slots are packed in possible-CPU order. The buffer is sized as:

round_up(value_size, 8) * num_possible_cpus()

The update paths iterate over possible CPUs, but use the logical CPU ID to calculate the source offset:

value + size * cpu

This only works when possible CPU IDs are contiguous starting at zero.

For example, with a possible CPU mask of 0,2-3, the buffer contains three slots corresponding to CPUs 0, 2, and 3. CPU2 is therefore expected to use slot 1 and CPU3 slot 2. Instead, the current code uses slots 2 and 3 respectively, causing incorrect per-CPU values and an out-of-bounds read from the update buffer for CPU3.

The corresponding lookup paths already use a dense offset while iterating over possible CPUs. Do the same for the array, hash, and cgroup storage update paths, advancing the source offset once for each possible CPU. BPF_F_ALL_CPUS continues to use the same value for every CPU.

Fixes 8eb76cb03f0f ("bpf: Add BPF_F_CPU and BPF_F_ALL_CPUS flags support for percpu_array maps")
Fixes c6936161fd55 ("bpf: Add BPF_F_CPU and BPF_F_ALL_CPUS flags support for percpu_hash and lru_percpu_hash maps")
Fixes 47c79f05aa0d ("bpf: Add BPF_F_CPU and BPF_F_ALL_CPUS flags support for percpu_cgroup_storage maps")
---
 kernel/bpf/arraymap.c      | 5 +++--
 kernel/bpf/hashtab.c       | 5 +++--
 kernel/bpf/local_storage.c | 5 +++--
 3 files changed, 9 insertions(+), 6 deletions(-)
kernel/bpf/arraymap.c +3 -2
index 248b4818178cd..cc3f8c25a28b5 100644
@@ -405,7 +405,7 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
 	void __percpu *pptr;
 	void *ptr, *val;
 	u32 size;
-	int cpu;
+	int cpu, off = 0;
 
 	if (unlikely((map_flags & BPF_F_LOCK) || (u32)map_flags > BPF_F_ALL_CPUS))
 		/* unknown flags */
@@ -437,9 +437,10 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
 	}
 	for_each_possible_cpu(cpu) {
 		ptr = per_cpu_ptr(pptr, cpu);
-		val = (map_flags & BPF_F_ALL_CPUS) ? value : value + size * cpu;
+		val = (map_flags & BPF_F_ALL_CPUS) ? value : value + off;
 		copy_map_value(map, ptr, val);
 		bpf_obj_cancel_fields(map, ptr);
+		off += size;
 	}
 unlock:
 	rcu_read_unlock();
kernel/bpf/hashtab.c +3 -2
index 9f394e1aa2e85..dd4da18312ac1 100644
@@ -1026,7 +1026,7 @@ static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr,
 	} else {
 		u32 size = round_up(htab->map.value_size, 8);
 		void *val;
-		int cpu;
+		int cpu, off = 0;
 
 		if (map_flags & BPF_F_CPU) {
 			cpu = map_flags >> 32;
@@ -1038,9 +1038,10 @@ static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr,
 
 		for_each_possible_cpu(cpu) {
 			ptr = per_cpu_ptr(pptr, cpu);
-			val = (map_flags & BPF_F_ALL_CPUS) ? value : value + size * cpu;
+			val = (map_flags & BPF_F_ALL_CPUS) ? value : value + off;
 			copy_map_value(&htab->map, ptr, val);
 			bpf_obj_cancel_fields(&htab->map, ptr);
+			off += size;
 		}
 	}
 }
kernel/bpf/local_storage.c +3 -2
index 23267213a17fb..83cd527a2542b 100644
@@ -220,7 +220,7 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *_map, void *key,
 	struct bpf_cgroup_storage *storage;
 	void *val;
 	u32 size;
-	int cpu;
+	int cpu, off = 0;
 
 	if ((u32)map_flags & ~(BPF_ANY | BPF_EXIST | BPF_F_CPU | BPF_F_ALL_CPUS))
 		return -EINVAL;
@@ -245,8 +245,9 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *_map, void *key,
 	}
 	size = round_up(_map->value_size, 8);
 	for_each_possible_cpu(cpu) {
-		val = (map_flags & BPF_F_ALL_CPUS) ? value : value + size * cpu;
+		val = (map_flags & BPF_F_ALL_CPUS) ? value : value + off;
 		copy_map_value(_map, per_cpu_ptr(storage->percpu_buf, cpu), val);
+		off += size;
 	}
 unlock:
 	rcu_read_unlock();
Signature · 1 line
2.53.0
author maintainer
#26 lore raw

PATCH 26/733 sched_ext: Fix spurious aborts in scx_bpf_dsq_move() on ownership change races

In reply to Greg Kroah-Hartman

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

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

From: Tejun Heo <[email protected]>

[ Upstream commit cca061dccf563907061766191b2ce3f66b7c285a ]

scx_dsq_move() verifies that the task belongs to the calling scheduler before taking any locks and aborts the scheduler on mismatch. The task can lose the sched association at any point: It can run and fully exit, which clears the association, or get rehomed to a different sub-sched. Both are benign races, but the early ownership check escalates them into scheduler aborts.

Move the ownership check below the cursor-lost check. Every ownership change dequeues the task first, so a task that is still on the iterated DSQ under the lock while owned elsewhere indicates a genuine violation and should abort.

Also fix two stale comments still referencing sched_ext_free(), which has been renamed to sched_ext_dead().

Fixes bb4d9fd55158 ("sched_ext: scx_dsq_move() should validate the task belongs to the right scheduler")
---
 kernel/sched/ext/ext.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)
kernel/sched/ext/ext.c +13 -8
index 558be0cdebef8..548f46a427883 100644
@@ -7435,7 +7435,7 @@ static void scx_root_enable_workfn(struct kthread_work *work)
 	/*
 	 * Enable ops for every task. Fork is excluded by scx_fork_rwsem
 	 * preventing new tasks from being added. No need to exclude tasks
-	 * leaving as sched_ext_free() can handle both prepped and enabled
+	 * leaving as sched_ext_dead() can handle both prepped and enabled
 	 * tasks. Prep all tasks first and then enable them with preemption
 	 * disabled.
 	 *
@@ -7524,7 +7524,7 @@ static void scx_root_enable_workfn(struct kthread_work *work)
 
 	/*
 	 * We're fully committed and can't fail. The task READY -> ENABLED
-	 * transitions here are synchronized against sched_ext_free() through
+	 * transitions here are synchronized against sched_ext_dead() through
 	 * scx_tasks_lock.
 	 */
 	percpu_down_write(&scx_fork_rwsem);
@@ -9019,12 +9019,6 @@ static bool scx_dsq_move(struct bpf_iter_scx_dsq_kern *kit,
 	if (unlikely(READ_ONCE(sch->aborting)))
 		return false;
 
-	if (unlikely(!scx_task_on_sched(sch, p))) {
-		scx_error(sch, "scx_bpf_dsq_move[_vtime]() on %s[%d] but the task belongs to a different scheduler",
-			  p->comm, p->pid);
-		return false;
-	}
-
 	/*
 	 * Can be called from either ops.dispatch() holding the dispatched rq's
 	 * lock or any context where no rq lock is held. If latter, lock @p's
@@ -9056,6 +9050,17 @@ static bool scx_dsq_move(struct bpf_iter_scx_dsq_kern *kit,
 		goto out;
 	}
 
+	/*
+	 * @p has been on $src_dsq and can't move anymore. If @p is not on @sch,
+	 * the caller didn't have authority over @p at the time of the call.
+	 */
+	if (unlikely(!scx_task_on_sched(sch, p))) {
+		scx_error(sch, "scx_bpf_dsq_move[_vtime]() on %s[%d] but the task belongs to a different scheduler",
+			  p->comm, p->pid);
+		raw_spin_unlock(&src_dsq->lock);
+		goto out;
+	}
+
 	/* @p is still on $src_dsq and stable, determine the destination */
 	dst_dsq = find_dsq_for_dispatch(sch, locked_rq ?: this_rq(), dsq_id, task_cpu(p));
 
Signature · 1 line
2.53.0
author maintainer
#27 lore raw

PATCH 27/733 drm/gud: validate GUD_ROTATION_0 is present in supported rotations

In reply to Greg Kroah-Hartman

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

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

From: Sajal Gupta <[email protected]>

[ Upstream commit cb732d027aa18e1fcf9d2797f47d20b179ebc59c ]

The rotation argument to drm_plane_create_rotation_property() is set to DRM_MODE_ROTATE_0, and the device reported rotation bitmask is used as the supported_rotations argument. The driver never validates that GUD_ROTATION_0 is present, so a device that omits it from its GUD_PROPERTY_ROTATION triggers the
WARN_ON(rotation & ~supported_rotations) in drm_plane_create_rotation_property()

Fix this by skipping the creation of rotation property if the device doesn't have the GUD_ROTATION_0 bit

---
 drivers/gpu/drm/gud/gud_drv.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/gpu/drm/gud/gud_drv.c +2 -0
index 89bd6ca36003f..3a1b9e2a2eaa1 100644
@@ -289,6 +289,8 @@ static int gud_plane_add_properties(struct gud_device *gdrm)
 			 * but mask out any additions on future devices.
 			 */
 			val &= GUD_ROTATION_MASK;
+			if (!(val & GUD_ROTATION_0))
+				continue;
 			ret = drm_plane_create_rotation_property(&gdrm->plane,
 								 DRM_MODE_ROTATE_0, val);
 			break;
Signature · 1 line
2.53.0
author maintainer
#28 lore raw

PATCH 28/733 printk: Dont WARN on kthread_run failure.

In reply to Greg Kroah-Hartman

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

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

From: Tetsuo Handa <[email protected]>

[ Upstream commit 72dd0ec09e7cc98ed58ddeac26575e5d1ab8a93d ]

Since __kthread_create_on_node() returns -EINTR upon SIGKILL, we should not use WARN_ON() in order to catch kthread_run() failure.

Reported-by [email protected]
Fixes 5f53ca3ff83b ("printk: Implement legacy printer kthread for PREEMPT_RT")
Fixes 76f258bf3f2a ("printk: nbcon: Introduce printer kthreads")
---
 kernel/printk/nbcon.c  | 2 +-
 kernel/printk/printk.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
kernel/printk/nbcon.c +1 -1
index 4b03b019cd5ee..a5921a84a80ed 100644
@@ -1382,7 +1382,7 @@ bool nbcon_kthread_create(struct console *con)
 		return true;
 
 	kt = kthread_run(nbcon_kthread_func, con, "pr/%s%d", con->name, con->index);
-	if (WARN_ON(IS_ERR(kt))) {
+	if (IS_ERR(kt)) {
 		con_printk(KERN_ERR, con, "failed to start printing thread\n");
 		return false;
 	}
kernel/printk/printk.c +1 -1
index 6d363e42e2a05..96ff9547e888b 100644
@@ -3732,7 +3732,7 @@ static bool legacy_kthread_create(void)
 	lockdep_assert_console_list_lock_held();
 
 	kt = kthread_run(legacy_kthread_func, NULL, "pr/legacy");
-	if (WARN_ON(IS_ERR(kt))) {
+	if (IS_ERR(kt)) {
 		pr_err("failed to start legacy printing thread\n");
 		return false;
 	}
Signature · 1 line
2.53.0
author maintainer
#29 lore raw

PATCH 29/733 accel/amdxdna: Remove __counted_by from struct amdxdna_cmd_chain

In reply to Greg Kroah-Hartman

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

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

From: Lizhi Hou <[email protected]>

[ Upstream commit b3709d354545e70388177500761f92d906c4dfd6 ]

struct amdxdna_cmd_chain contains a flexible array annotated with __counted_by(command_count). Since the structure is stored in shared AMDXDNA_BO_SHARE memory, userspace can modify command_count concurrently. If command_count is changed to zero, the bounds check generated from __counted_by may fail and trigger a kernel panic.

Remove __counted_by to avoid relying on the userspace-controlled command_count for the flexible array bounds check.

Fixes aac243092b70 ("accel/amdxdna: Add command execution")
---
 drivers/accel/amdxdna/amdxdna_ctx.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/accel/amdxdna/amdxdna_ctx.h +1 -1
index b6bef3af7dab4..6e78bab8a02c0 100644
@@ -55,7 +55,7 @@ struct amdxdna_cmd_chain {
 	u32 submit_index;
 	u32 error_index;
 	u32 reserved[3];
-	u64 data[] __counted_by(command_count);
+	u64 data[];
 };
 
 /*
Signature · 1 line
2.53.0
author maintainer
#30 lore raw

PATCH 30/733 accel/amdxdna: reject a command chain that carries no commands

In reply to Greg Kroah-Hartman

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

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

From: Taimuraz Kaitmazov <[email protected]>

[ Upstream commit ef6d27af71e1dc43181ec797a6aaa77c27c36786 ]

A chain whose command_count is zero passes the payload length check, because struct_size(payload, data, 0) is just the header. The fill loop then does not run, so offset stays zero and the request is submitted with a zero-length buffer.

On firmware without AIE2_NPU_COMMAND that ends at the opcode check, since op is still ERT_INVALID_CMD and aie2_get_chain_msg_op() answers MSG_OP_MAX_OPCODE. aie2_get_npu_chain_msg_op() answers MSG_OP_CHAIN_EXEC_NPU whatever it is given, so there the submission continues to drm_clflush_virt_range(cmd_buf, 0), which reads the byte before the buffer and faults on the vmap guard page. EXEC_CMD is reachable by any process that can open the render node.

Reject the request instead.

Fixes 8ed8b0239617 ("accel/amdxdna: Add debug prints for command submission")
---
 drivers/accel/amdxdna/aie2_message.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/accel/amdxdna/aie2_message.c +1 -1
index dfe0fbdf066d2..b4c49259a1a23 100644
@@ -994,7 +994,7 @@ int aie2_cmdlist_multi_execbuf(struct amdxdna_hwctx *hwctx,
 	}
 
 	ccnt = payload->command_count;
-	if (payload_len < struct_size(payload, data, ccnt)) {
+	if (!ccnt || payload_len < struct_size(payload, data, ccnt)) {
 		XDNA_DBG(xdna, "Invalid command count %d", ccnt);
 		return -EINVAL;
 	}
Signature · 1 line
2.53.0
author maintainer
#31 lore raw

PATCH 31/733 accel/amdxdna: put the chained BO when its mapping fails

In reply to Greg Kroah-Hartman

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

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

From: Taimuraz Kaitmazov <[email protected]>

[ Upstream commit 7e33ba3a1d48c2d20ed270dec9d2d08332585c8e ]

amdxdna_cmd_set_error() looks up the first BO of a command chain, which takes a reference, and drops it at the end of the function. The mapping of that BO is established in between, and the failure path returns without the put, so the reference is leaked.

Ordinary use does not reach it. The chain has been submitted before any of this runs, so aie2_cmdlist_fill_slot() has already called amdxdna_cmd_get_op() on that BO and amdxdna_gem_vmap() has cached its address. What makes it reachable is that the BO is resolved again by handle here, and the handle is userspace's to recycle: closing it after submission and importing a dma-buf whose exporter implements no vmap onto the same id leaves amdxdna_gem_get_obj() returning an object this cannot map, since prime_import() types every import AMDXDNA_BO_SHARE.

Fixes d76856beb4a4 ("accel/amdxdna: Refactor GEM BO handling and add helper APIs for address retrieval")
---
 drivers/accel/amdxdna/amdxdna_ctx.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/accel/amdxdna/amdxdna_ctx.c +3 -1
index 31a414c3f0d96..888e857ec5582 100644
@@ -183,8 +183,10 @@ int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo,
 		if (!abo)
 			return -EINVAL;
 		cmd = amdxdna_gem_vmap(abo);
-		if (!cmd)
+		if (!cmd) {
+			amdxdna_gem_put_obj(abo);
 			return -ENOMEM;
+		}
 	}
 
 	memset(cmd->data, 0xff, abo->mem.size - sizeof(*cmd));
Signature · 1 line
2.53.0
author maintainer
#32 lore raw

PATCH 32/733 selftests/cgroup: Drop invalid boot isolation comparison

In reply to Greg Kroah-Hartman

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

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

From: Guopeng Zhang <[email protected]>

[ Upstream commit 2bf404b1bd94f50747443234c0a4a5e18e2569bf ]

check_isolcpus() clears ISOLCPUS before rebuilding it from sched domain data. Comparing that empty value with /sys/devices/system/cpu/isolated makes the test fail whenever isolcpus=domain is present.

That sysfs file is generated from HK_TYPE_DOMAIN_BOOT and does not change when cpuset updates HK_TYPE_DOMAIN. Re-reading it cannot validate dynamic housekeeping updates. The cpuset.cpus.isolated and sched domain checks already cover the two dynamic interfaces, so remove the invalid comparison.

This can be reproduced on a kernel booted with isolcpus=domain,15:

    # tools/testing/selftests/cgroup/test_cpuset_prs.sh

The test fails its first state-matrix isolation check before the change and continues past that check afterward.

Fixes 6df415aa46ec ("cgroup/cpuset: Defer housekeeping_update() calls from CPU hotplug to workqueue")
---
 tools/testing/selftests/cgroup/test_cpuset_prs.sh | 6 ------
 1 file changed, 6 deletions(-)
tools/testing/selftests/cgroup/test_cpuset_prs.sh +0 -6
index b2e60671273ec..ebbc5b4def243 100755
@@ -791,7 +791,6 @@ check_isolcpus()
 	EXPECTED_ISOLCPUS=$1
 	ISCPUS=${CGROUP2}/cpuset.cpus.isolated
 	ISOLCPUS=$(cat $ISCPUS)
-	HKICPUS=$(cat /sys/devices/system/cpu/isolated)
 	LASTISOLCPU=
 	SCHED_DOMAINS=/sys/kernel/debug/sched/domains
 	if [[ $EXPECTED_ISOLCPUS = . ]]
@@ -829,11 +828,6 @@ check_isolcpus()
 	ISOLCPUS=
 	EXPECTED_ISOLCPUS=$EXPECTED_SDOMAIN
 
-	#
-	# The inverse of HK_TYPE_DOMAIN cpumask in $HKICPUS should match $ISOLCPUS
-	#
-	[[ "$ISOLCPUS" != "$HKICPUS" ]] && return 1
-
 	#
 	# Use the sched domain in debugfs to check isolated CPUs, if available
 	#
Signature · 1 line
2.53.0
author maintainer
#33 lore raw

PATCH 33/733 cgroup/cpuset: Preserve boot-isolated CPUs on partition release

In reply to Greg Kroah-Hartman

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

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

From: Guopeng Zhang <[email protected]>

[ Upstream commit 6c37d7e074a4be1ba8da59f4ed5df8977b3daa43 ]

isolated_cpus tracks CPUs isolated with isolcpus= as well as CPUs in isolated cpuset partitions. When an isolated partition is released, isolated_cpus_update() removes its whole CPU mask. This also clears CPUs which were already isolated at boot.

This can be reproduced on a cgroup v2 system booted with isolcpus=domain,15:

cd /sys/fs/cgroup
echo +cpuset > cgroup.subtree_control mkdir cpuset-repro
echo 15 > cpuset-repro/cpuset.cpus
echo isolated > cpuset-repro/cpuset.cpus.partition echo member > cpuset-repro/cpuset.cpus.partition cat cpuset.cpus.isolated

CPU 15 is absent before the change. It must remain in cpuset.cpus.isolated after the partition is released.

Update isolated_cpus one CPU at a time and keep CPUs outside the boot-time domain housekeeping mask isolated.

Fixes c188f33c864e ("cgroup/cpuset: Account for boot time isolated CPUs")
---
 kernel/cgroup/cpuset.c | 39 +++++++++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 10 deletions(-)
kernel/cgroup/cpuset.c +29 -10
index 1c6d568006688..69ff86e03c630 100644
@@ -1220,6 +1220,28 @@ static void reset_partition_data(struct cpuset *cs)
 		cpumask_copy(cs->effective_cpus, parent->effective_cpus);
 }
 
+/* Return true if isolated_cpus changes. */
+static bool isolated_cpu_update(int new_prs, int cpu)
+{
+	lockdep_assert_held(&callback_lock);
+	lockdep_assert_held(&cpuset_mutex);
+
+	if (new_prs == PRS_ISOLATED) {
+		if (cpumask_test_cpu(cpu, isolated_cpus))
+			return false;
+		cpumask_set_cpu(cpu, isolated_cpus);
+		return true;
+	}
+
+	/* CPUs isolated at boot must remain isolated. */
+	if (!cpumask_test_cpu(cpu,
+			      housekeeping_cpumask(HK_TYPE_DOMAIN_BOOT)) ||
+	    !cpumask_test_cpu(cpu, isolated_cpus))
+		return false;
+	cpumask_clear_cpu(cpu, isolated_cpus);
+	return true;
+}
+
 /*
  * isolated_cpus_update - Update the isolated_cpus mask
  * @old_prs: old partition_root_state
@@ -1228,19 +1250,16 @@ static void reset_partition_data(struct cpuset *cs)
  */
 static void isolated_cpus_update(int old_prs, int new_prs, struct cpumask *xcpus)
 {
+	bool updated = false;
+	int cpu;
+
 	WARN_ON_ONCE(old_prs == new_prs);
 	lockdep_assert_held(&callback_lock);
 	lockdep_assert_held(&cpuset_mutex);
-	if (new_prs == PRS_ISOLATED) {
-		if (cpumask_subset(xcpus, isolated_cpus))
-			return;
-		cpumask_or(isolated_cpus, isolated_cpus, xcpus);
-	} else {
-		if (!cpumask_intersects(xcpus, isolated_cpus))
-			return;
-		cpumask_andnot(isolated_cpus, isolated_cpus, xcpus);
-	}
-	update_housekeeping = true;
+	for_each_cpu(cpu, xcpus)
+		updated |= isolated_cpu_update(new_prs, cpu);
+	if (updated)
+		update_housekeeping = true;
 }
 
 /*
Signature · 1 line
2.53.0
author maintainer
#34 lore raw

PATCH 34/733 accel: ethosu: Dont read the U65 rounding mode as a storage mode

In reply to Greg Kroah-Hartman

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

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

From: Tomeu Vizoso <[email protected]>

[ Upstream commit db9deec5a345abc538d081fb221dc0b00a9695bd ]

Bits 15:14 of NPU_SET_{IFM,OFM}_PRECISION select the activation storage mode on U85 only. On U65 the same field holds the rounding mode, and the command stream parser has read it as a storage mode since the driver was added.

That went unnoticed while unknown values fell through the switch, but now that they are rejected, every U65 command stream that asks for natural rounding (2) fails CMDSTREAM_BO_CREATE with -EINVAL. Mesa emits it for average pooling, concatenation, split, unpack, strided slice, LUT and argmax, which is 72 failures of the Teflon test suite on an i.MX93. Truncating rounding (1) is misread as well: it picks the two-tile address path and computes a bogus feature map size from tile bases the command stream never set.

Read the field as a storage mode only on the hardware where it is one.

Fixes 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver")
Fixes 6b7e0066294d ("accel: ethosu: Handle U85 internal chaining buffer")
Assisted-by Claude:claude-opus-5
---
 drivers/accel/ethosu/ethosu_gem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/accel/ethosu/ethosu_gem.c +1 -1
index d50fed64d4d93..fa37a190e9fff 100644
@@ -204,7 +204,7 @@ static u64 feat_matrix_length(struct ethosu_device *edev,
 			      struct feat_matrix *fm,
 			      u32 x, u32 y, u32 c, bool ofm)
 {
-	u32 element_size, storage = fm->precision >> 14;
+	u32 element_size, storage = ethosu_is_u65(edev) ? 0 : fm->precision >> 14;
 	int tile = 0;
 	u64 addr;
 
Signature · 1 line
2.53.0
author maintainer
#35 lore raw

PATCH 35/733 ufs: do not treat unreadable directory blocks as empty

In reply to Greg Kroah-Hartman

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

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

From: Ali Ahmet Memis <[email protected]>

[ Upstream commit 08edfb34ee9ca54383970c65ed3a6013e84f5e16 ]

ufs_empty_dir() scans every directory block to decide whether a directory is empty before rmdir() removes it. When ufs_get_folio() cannot read or validate a block it returns an error pointer, and the loop currently skips that block with continue and keeps scanning the remaining blocks.

If none of the readable blocks hold an entry, the function returns 1 and the caller unlinks the directory. A directory whose contents live in a block that cannot be read, for example because of an I/O error or corrupted directory metadata, is therefore seen as empty and removed, losing the entries it still holds.

Follow the ext2 behaviour and treat an unreadable block as a reason to consider the directory not empty, so rmdir() fails instead of discarding data that could not be verified.

---
 fs/ufs/dir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ufs/dir.c +1 -1
index e62fe56676710..ce43cf20b07c9 100644
@@ -590,7 +590,7 @@ int ufs_empty_dir(struct inode * inode)
 
 		kaddr = ufs_get_folio(inode, i, &folio);
 		if (IS_ERR(kaddr))
-			continue;
+			return 0;
 
 		de = (struct ufs_dir_entry *)kaddr;
 		kaddr += ufs_last_byte(inode, i) - UFS_DIR_REC_LEN(1);
Signature · 1 line
2.53.0
author maintainer
#36 lore raw

PATCH 36/733 drm/cirrus-qemu: Validate BAR0 size during probe

In reply to Greg Kroah-Hartman

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

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

From: Slawomir Stepien <[email protected]>

[ Upstream commit 92312d333bf700798f92f30406c721bce87506f3 ]

The cirrus-qemu driver relies on CIRRUS_VRAM_SIZE (4 MB) to validate framebuffer sizes. However, during PCI probe, the driver mapped BAR0 without verifying that its size matches CIRRUS_VRAM_SIZE.

If a PCI device with a BAR0 smaller than 4 MB is bound to the driver, the mapped VRAM will be smaller than expected. Because validation checks assume 4 MB VRAM, framebuffers larger than the mapped memory can be created.

When the display plane is updated (e.g. during release), cirrus_primary_plane_helper_atomic_update() copies the framebuffer to VRAM using drm_fb_memcpy(). Writing past the end of the mapped I/O memory causes a supervisor write page fault:

BUG: unable to handle page fault for address: ffffc9000389c000
...
RIP: 0010:memcpy_toio+0x7c/0xe0 arch/x86/lib/iomem.c:110
...
Call Trace:
 <TASK>
 iosys_map_memcpy_to include/linux/iosys-map.h:285 [inline]
 drm_fb_memcpy+0x325/0x5d0 drivers/gpu/drm/drm_format_helper.c:442
 cirrus_primary_plane_helper_atomic_update+0x98a/0xb00
 drivers/gpu/drm/tiny/cirrus-qemu.c:358
 drm_atomic_helper_commit_planes+0x626/0xea0
 drivers/gpu/drm/drm_atomic_helper.c:3038
 drm_atomic_helper_commit_tail+0x60/0x510
 drivers/gpu/drm/drm_atomic_helper.c:1989
 commit_tail+0x2b1/0x3c0 drivers/gpu/drm/drm_atomic_helper.c:2074
 drm_atomic_helper_commit+0xa77/0xb10
 drivers/gpu/drm/drm_atomic_helper.c:2312

Fix this by validating in cirrus_pci_probe() that the PCI BAR0 resource is not less than CIRRUS_VRAM_SIZE, returning -ENODEV if it is less.

---
 drivers/gpu/drm/tiny/cirrus-qemu.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/gpu/drm/tiny/cirrus-qemu.c +3 -0
index 075221b431d37..3bf23fcf65749 100644
@@ -582,6 +582,9 @@ static int cirrus_pci_probe(struct pci_dev *pdev,
 	struct cirrus_device *cirrus;
 	int ret;
 
+	if (pci_resource_len(pdev, 0) < CIRRUS_VRAM_SIZE)
+		return -ENODEV;
+
 	ret = aperture_remove_conflicting_pci_devices(pdev, cirrus_driver.name);
 	if (ret)
 		return ret;
Signature · 1 line
2.53.0
author maintainer
#37 lore raw

PATCH 37/733 ntfs: return DT_UNKNOWN on inode lookup failure in readdir

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit 3d3de2aee17d1431694aa085039479b5679e5ad4 ]

ntfs_reparse_tag_dt_types() returns PTR_ERR(vi) when ntfs_iget() fails, but its return type is unsigned int and the caller passes the value straight to dir_emit() as d_type. A stale or corrupt MFT reference in a directory index thus makes readdir report a garbage d_type value to userspace.

Return DT_UNKNOWN on lookup failure instead.

Fixes fc053f05ca28 ("ntfs: add reparse and ea operations")
---
 fs/ntfs/reparse.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ntfs/reparse.c +1 -1
index fa523dc3691ea..f2377e3a56ca9 100644
@@ -332,7 +332,7 @@ unsigned int ntfs_reparse_tag_dt_types(struct ntfs_volume *vol, unsigned long mr
 
 	vi = ntfs_iget(vol->sb, mref);
 	if (IS_ERR(vi))
-		return PTR_ERR(vi);
+		return DT_UNKNOWN;
 
 	reparse_attr = (struct reparse_point *)ntfs_attr_readall(NTFS_I(vi),
 			AT_REPARSE_POINT, NULL, 0, &attr_size);
Signature · 1 line
2.53.0
author maintainer
#38 lore raw

PATCH 38/733 ntfs: propagate reparse index insertion failure

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit 9692b1b4fc00cf89628bc43f71729ab21f14f8d3 ]

update_reparse_data() ignores the return value of set_reparse_index(). When index insertion fails, the code removes the just-written reparse data as cleanup but still returns 0, so symlink(2) (and WSL special file creation) reports success while no reparse data exists on disk. When there was no previous reparse data (oldsize == 0), the failure was likewise silently ignored.

Propagate the error to the caller.

Fixes fc053f05ca28 ("ntfs: add reparse and ea operations")
---
 fs/ntfs/reparse.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
fs/ntfs/reparse.c +3 -2
index f2377e3a56ca9..f8b88a110cb67 100644
@@ -620,8 +620,9 @@ static int update_reparse_data(struct ntfs_inode *ni, struct ntfs_index_context
 		goto put_rp_inode;
 	}
 
-	if (set_reparse_index(ni, xr, ((const struct reparse_point *)value)->reparse_tag) &&
-	    oldsize > 0) {
+	err = set_reparse_index(ni, xr,
+				((const struct reparse_point *)value)->reparse_tag);
+	if (err && oldsize > 0) {
 		/*
 		 * If cannot index, try to remove the reparse
 		 * data and log the error. There will be an
Signature · 1 line
2.53.0
author maintainer
#39 lore raw

PATCH 39/733 ntfs: return -ERANGE for undersized xattr buffer

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit ada728801999e25e610091362447372f1b25dd25 ]

When the value buffer passed to getxattr(2) for system.dos_attrib, system.ntfs_attrib or system.ntfs_attrib_be is smaller than the attribute value, ntfs_getxattr() returns -ENODATA, which tells userspace the attribute does not exist. The xattr API expects -ERANGE in this case, and ntfs_get_ea() in the same file already returns -ERANGE for regular EAs.

Fixes fc053f05ca28 ("ntfs: add reparse and ea operations")
---
 fs/ntfs/ea.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ntfs/ea.c +2 -2
index 25ff159dbfd38..08c35f9751114 100644
@@ -591,7 +591,7 @@ static int ntfs_getxattr(const struct xattr_handler *handler,
 		if (!buffer) {
 			err = sizeof(u8);
 		} else if (size < sizeof(u8)) {
-			err = -ENODATA;
+			err = -ERANGE;
 		} else {
 			err = sizeof(u8);
 			*(u8 *)buffer = (u8)(le32_to_cpu(ni->flags) & 0x3F);
@@ -604,7 +604,7 @@ static int ntfs_getxattr(const struct xattr_handler *handler,
 		if (!buffer) {
 			err = sizeof(u32);
 		} else if (size < sizeof(u32)) {
-			err = -ENODATA;
+			err = -ERANGE;
 		} else {
 			err = sizeof(u32);
 			*(u32 *)buffer = le32_to_cpu(ni->flags);
Signature · 1 line
2.53.0
author maintainer
#40 lore raw

PATCH 40/733 ntfs: preserve error code in ntfs_resident_attr_record_add()

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit 8efe00b098b5b3618c885d2a35a5edccfbfbec7d ]

ntfs_resident_attr_record_add() collapses every failure to -EIO at its put_err_out label. This defeats the resident-to-non-resident fallback in ntfs_attr_add(), which relies on seeing -ENOSPC to convert the attribute when the MFT record has no room, and also hides -EEXIST and -ENOMEM from callers.

Return the actual error code. Every path reaching the label has err set to a negative errno.

Fixes 495e90fa3348 ("ntfs: update attrib operations")
---
 fs/ntfs/attrib.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ntfs/attrib.c +1 -1
index b4c6137c037b6..fbb1c5f4da18a 100644
@@ -2495,7 +2495,7 @@ int ntfs_resident_attr_record_add(struct ntfs_inode *ni, __le32 type,
 	return offset;
 put_err_out:
 	ntfs_attr_put_search_ctx(ctx);
-	return -EIO;
+	return err;
 }
 
 /*
Signature · 1 line
2.53.0
author maintainer
#41 lore raw

PATCH 41/733 ntfs: return real error from ntfs_non_resident_attr_record_add()

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit ba1b61ddaa764f31b14abe1d547049682cc5824e ]

ntfs_non_resident_attr_record_add() returns -1 at its put_err_out label, which callers propagate as -EPERM to userspace.

Return the actual error code. Every path reaching the label has err set to a negative errno.

Fixes 495e90fa3348 ("ntfs: update attrib operations")
---
 fs/ntfs/attrib.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ntfs/attrib.c +1 -1
index fbb1c5f4da18a..950fc1b727cb2 100644
@@ -2634,7 +2634,7 @@ static int ntfs_non_resident_attr_record_add(struct ntfs_inode *ni, __le32 type,
 	return offset;
 put_err_out:
 	ntfs_attr_put_search_ctx(ctx);
-	return -1;
+	return err;
 }
 
 /*
Signature · 1 line
2.53.0
author maintainer
#42 lore raw

PATCH 42/733 ntfs: fix kmap_local leak in write_mft_record_nolock() error paths

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit cf06dcd572845723821b54a608fc2da995c3c8e2 ]

write_mft_record_nolock() maps the MFT record folio with kmap_local_folio(), but the pre_write_mst_fixup() and bio_add_folio() failure paths jump to the error label without unmapping it. kmap_local mappings are stack-ordered per task, so leaking one corrupts the nesting for any outer mapping.

Unmap the folio on those error paths too.

Fixes 115380f9a2f9 ("ntfs: update mft operations")
---
 fs/ntfs/mft.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ntfs/mft.c +3 -1
index 271a265491280..3ad739179c7a1 100644
@@ -580,7 +580,7 @@ int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int syn
 	err = pre_write_mst_fixup((struct ntfs_record *)fixup_m, vol->mft_record_size);
 	if (err) {
 		ntfs_error(vol->sb, "Failed to apply mst fixups!");
-		goto err_out;
+		goto unmap_err_out;
 	}
 
 	folio_size = vol->mft_record_size / ni->mft_lcn_count;
@@ -645,6 +645,8 @@ int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int syn
 	return 0;
 put_bio_out:
 	bio_put(bio);
+unmap_err_out:
+	kunmap_local(kaddr);
 err_out:
 	/*
 	 * The caller should mark the base inode as bad so no more I/O
Signature · 1 line
2.53.0
author maintainer
#43 lore raw

PATCH 43/733 ntfs: only count successfully cleared runs when freeing clusters

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit be9e89ccb8e52a3e4b67feeb03ebd8133091dc7e ]

ntfs_cluster_free_from_rl_nolock() adds a run's length to nr_freed whenever the error bookkeeping condition is false, which includes cases where ntfs_bitmap_clear_run() actually failed - e.g. a second run failing with the same errno as an earlier one, or any failure after a non-ENOMEM error was already recorded. Since a failed ntfs_bitmap_clear_run() rolls back its partial modifications, no bits were cleared for that run, yet its length still inflates vol->free_clusters, corrupting statfs output and the allocator's free space gate.

Only count runs whose bitmap clear succeeded.

Fixes 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator")
---
 fs/ntfs/lcnalloc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
fs/ntfs/lcnalloc.c +3 -3
index aa2e017a43844..795f71d26895f 100644
@@ -53,10 +53,10 @@ int ntfs_cluster_free_from_rl_nolock(struct ntfs_volume *vol,
 		if (rl->lcn < 0)
 			continue;
 		err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length);
-		if (unlikely(err && (!ret || ret == -ENOMEM) && ret != err))
-			ret = err;
-		else
+		if (likely(!err))
 			nr_freed += rl->length;
+		else if (!ret || ret == -ENOMEM)
+			ret = err;
 	}
 	ntfs_inc_free_clusters(vol, nr_freed);
 	ntfs_debug("Done.");
Signature · 1 line
2.53.0
author maintainer
#44 lore raw

PATCH 44/733 ntfs: skip free cluster decrement when rollback fails

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit 5f2a22b36fe34c98f6d5e35ddb759ee53d684145 ]

When the rollback in __ntfs_cluster_free() fails, the recursive call returns a negative errno and the subsequent ntfs_dec_free_clusters(vol, delta) subtracts that negative value, adding bogus clusters to the counter on an already-failing volume.

Skip the decrement when the rollback failed.

Fixes 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator")
---
 fs/ntfs/lcnalloc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ntfs/lcnalloc.c +2 -1
index 795f71d26895f..0d6cd08ee2e76 100644
@@ -1045,8 +1045,9 @@ s64 __ntfs_cluster_free(struct ntfs_inode *ni, const s64 start_vcn, s64 count,
 			"Failed to rollback (error %i).  Leaving inconsistent metadata!  Unmount and run chkdsk.",
 			(int)delta);
 		NVolSetErrors(vol);
+	} else {
+		ntfs_dec_free_clusters(vol, delta);
 	}
-	ntfs_dec_free_clusters(vol, delta);
 	up_write(&vol->lcnbmp_lock);
 	memalloc_nofs_restore(memalloc_flags);
 	ntfs_error(vol->sb, "Aborting (error %i).", err);
Signature · 1 line
2.53.0
author maintainer
#45 lore raw

PATCH 45/733 ntfs: do not mark the volume clean in sync_fs when errors were recorded

In reply to Greg Kroah-Hartman

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

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

From: Dennis Tighe <[email protected]>

[ Upstream commit 0e4c839905418d55bafe571a92533a1d1ac7b0a8 ]

ntfs_put_super() and the remount-read-only path both clear the dirty bit only when NVolErrors(vol) is false. ntfs_sync_fs() clears it unconditionally, so any sync() on a volume that recorded an error marks that volume clean. A volume without this set is then seen as not needing recovery and it does not run one, so whatever went wrong is never repaired.

This change skips resetting the dirty bit when there are volume errors.

Reproduced on a volume whose $MFTMirr does not match $MFT, which sets the error flag while leaving the mount read-write: after a write and a sync, the on-disk volume flags read 0x0000 with this driver and 0x0001 with the guard in place.

Fixes 6251f0b0de7d ("ntfs: update super block operations")
Assisted-by claude:claude-opus-5
---
 fs/ntfs/super.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ntfs/super.c +2 -1
index cd8fa2c133700..d287140b3fc61 100644
@@ -1862,7 +1862,8 @@ static int ntfs_sync_fs(struct super_block *sb, int wait)
 		return 0;
 
 	/* If there are some dirty buffers in the bdev inode */
-	if (ntfs_clear_volume_flags(vol, VOLUME_IS_DIRTY)) {
+	if (!NVolErrors(vol) &&
+	    ntfs_clear_volume_flags(vol, VOLUME_IS_DIRTY)) {
 		ntfs_warning(sb, "Failed to clear dirty bit in volume information flags.  Run chkdsk.");
 		err = -EIO;
 	}
Signature · 1 line
2.53.0
author maintainer
#46 lore raw

PATCH 46/733 ntfs: treat any nonzero dio zero-range return as an error

In reply to Greg Kroah-Hartman

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

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

From: Wentao Guan <[email protected]>

[ Upstream commit 607a9478833db656e7ceac8e9e382fa4acfde545 ]

ntfs_dio_zero_range() returns either 0 or a negative errno from blkdev_issue_zeroout(); it never returns a positive value. The zeroing failure check in ntfs_attr_fallocate() therefore never fired, so a failed zeroing operation was silently ignored: the loop kept going, the newly allocated clusters were folded into initialized_size and the write could succeed leaving stale on-disk data.

Treat any nonzero return as an error and abort the allocation.

Fixes 495e90fa33482 ("ntfs: update attrib operations")
Assisted-by atomcode:deepseek-v4-flash
---
 fs/ntfs/attrib.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ntfs/attrib.c +1 -1
index 950fc1b727cb2..9e41ba97e024d 100644
@@ -5693,7 +5693,7 @@ int ntfs_attr_fallocate(struct ntfs_inode *ni, loff_t start, loff_t byte_len, bo
 								  lcn << vol->cluster_size_bits,
 								  alloc_cnt <<
 								  vol->cluster_size_bits);
-					if (err > 0)
+					if (err)
 						goto out;
 				}
 
Signature · 1 line
2.53.0
author maintainer
#47 lore raw

PATCH 47/733 ntfs: bound $AttrDef table walk to the loaded table size

In reply to Greg Kroah-Hartman

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

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

From: Dennis Tighe <[email protected]>

[ Upstream commit c8504fc1245f5322af5fa5c325ab05f9cf792b87 ]

ntfs_attr_find_in_attrdef() walks the in-memory $AttrDef table, but the loop condition bounds only the start of each entry, not the whole entry:

	for (ad = vol->attrdef; (u8 *)ad - (u8 *)vol->attrdef <
			vol->attrdef_size && ad->type; ++ad)

struct attr_def is 160 bytes; the guard reads ad->type at offset 128 and the loop body reads further fields. vol->attrdef is kvzalloc(i_size), where i_size is the on-disk $AttrDef data size, checked in load_and_init_attrdef() only as 0 < i_size <= 0x7fffffff. A volume whose $AttrDef data size is smaller than one entry (e.g. 120 bytes) makes the read of ad->type run past the allocation. Creating a file reaches this through ntfs_attr_size_bounds_check() and reads out of bounds:

  BUG: KASAN: slab-out-of-bounds in ntfs_attr_find_in_attrdef+0x66/0xa0
  Read of size 4 at addr ffff888005833280 by task init/1
   ntfs_attr_find_in_attrdef
   ntfs_attr_size_bounds_check
   ntfs_attr_can_be_non_resident
   ntfs_attr_add

Require the whole entry to lie within attrdef_size in the loop guard, and reject at mount a $AttrDef too small to hold one attr_def entry.

Fixes 1e9ea7e04472 ("Revert "fs: Remove NTFS classic"")
Assisted-by Claude:claude-opus-4-8
---
 fs/ntfs/attrib.c | 4 ++--
 fs/ntfs/super.c  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
fs/ntfs/attrib.c +2 -2
index 9e41ba97e024d..918ff4db75f73 100644
@@ -1732,8 +1732,8 @@ static struct attr_def *ntfs_attr_find_in_attrdef(const struct ntfs_volume *vol,
 	struct attr_def *ad;
 
 	WARN_ON(!type);
-	for (ad = vol->attrdef; (u8 *)ad - (u8 *)vol->attrdef <
-			vol->attrdef_size && ad->type; ++ad) {
+	for (ad = vol->attrdef; (u8 *)ad - (u8 *)vol->attrdef <=
+	     vol->attrdef_size - (s32)sizeof(*ad) && ad->type; ++ad) {
 		/* We have not found it yet, carry on searching. */
 		if (likely(le32_to_cpu(ad->type) < le32_to_cpu(type)))
 			continue;
fs/ntfs/super.c +2 -2
index d287140b3fc61..242f6f9b5598e 100644
@@ -1241,9 +1241,9 @@ static bool load_and_init_attrdef(struct ntfs_volume *vol)
 		goto failed;
 	}
 	NInoSetSparseDisabled(NTFS_I(ino));
-	/* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */
+	/* FILE_AttrDef must hold at least one entry and fit inside 31 bits. */
 	i_size = i_size_read(ino);
-	if (i_size <= 0 || i_size > 0x7fffffff)
+	if (i_size < (s64)sizeof(struct attr_def) || i_size > 0x7fffffff)
 		goto iput_failed;
 	vol->attrdef = kvzalloc(i_size, GFP_NOFS);
 	if (!vol->attrdef)
Signature · 1 line
2.53.0
author maintainer
#48 lore raw

PATCH 48/733 ntfs: reject invalid sectors_per_cluster in the boot sector

In reply to Greg Kroah-Hartman

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

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

From: Dennis Tighe <[email protected]>

[ Upstream commit 323751a604e7533fa473874d999371592a614207 ]

is_boot_sector_ntfs() checks the boot sector's sectors_per_cluster field with a range test that rejects 0x81..0xf3 but accepts 0 and other non-power-of-two counts. A zero value reaches parse_ntfs_boot_sector():

	sectors_per_cluster_bits = ffs(sectors_per_cluster) - 1;
	...
	vol->cluster_size = vol->sector_size << sectors_per_cluster_bits;

ffs(0) is 0, so sectors_per_cluster_bits becomes (unsigned)-1 and the shift is undefined:

  UBSAN: shift-out-of-bounds in fs/ntfs/super.c:673:39
  shift exponent 4294967295 is too large for 32-bit type 'int'

This change rejects any non-power-of-two value, since it feeds the aforementioned shift via ffs() - 1, which only yields the correct shift for a power of two.

Fixes 6251f0b0de7d ("ntfs: update super block operations")
Assisted-by Claude:claude-opus-4-8
---
 fs/ntfs/super.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ntfs/super.c +2 -2
index 242f6f9b5598e..63aa83ff77f5d 100644
@@ -557,8 +557,8 @@ static bool is_boot_sector_ntfs(const struct super_block *sb,
 	 * Check sectors per cluster value is valid and the cluster size
 	 * is not above the maximum (2MB).
 	 */
-	if (b->bpb.sectors_per_cluster > 0x80 &&
-	    b->bpb.sectors_per_cluster < 0xf4)
+	if (b->bpb.sectors_per_cluster < 0xf4 &&
+	    !is_power_of_2(b->bpb.sectors_per_cluster))
 		goto not_ntfs;
 
 	/* Check reserved/unused fields are really zero. */
Signature · 1 line
2.53.0
author maintainer
#49 lore raw

PATCH 49/733 bpf: check_cond_jmp_op(): properly infer if register is null

In reply to Greg Kroah-Hartman

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

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

From: Eduard Zingerman <[email protected]>

[ Upstream commit d3ef6c097ba078e1f8c7239d76a0ce8b61e75095 ]

Nicholas Carlini reported a bug when verifier can incorrectly infer that a pointer is non-null. The bug occurs when two pointers are compared and one of them has a type w/o PTR_MAYBE_NULL flag, but which allows a value to be NULL at runtime.
Here is an example:

  // `a` is PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED
  // `a` is 0 at runtime.
  // `b` is PTR_TO_MAP_VALUE | PTR_MAYBE_NULL
  void *a = bpf_rdonly_cast(0, 0);
  int  *b = bpf_map_lookup_elem(...);

if (a == b)
*b = 42; // verifier does not catch null pointer dereference

This happens because of a special case in check_cond_jmp_op(), which attempts to strip PTR_MAYBE_NULL flags from pointer types, when processing comparisons like rA == rB, if either rA or rB can't be null.

The non-null property is derived based on the absence of PTR_MAYBE_NULL flag on rA's or rB's type. But that is not sufficient for types like PTR_TO_MEM, as in the example.

This patch replaces type_may_be_null() call with reg_not_null(), which contains an allowlist of types for which absence of PTR_MAYBE_NULL actually means that the value can't be NULL at runtime.

At the moment, the list in the reg_not_null() omits two types for which PTR_MAYBE_NULL is applicable: PTR_TO_XDP_SOCK and PTR_TO_BUF. In order to remain backward compatible, and assuming that only comparison between pointers of the same type makes sense, this commit extends reg_not_null(). W/o such an extension e.g. verifier_jeq_infer_not_null/null_ptr_to_map_value fails.

reg_not_null() can be extended further, but I deem that out of scope for the fix at hand. Explicit base_type(...) != PTR_TO_BTF_ID checks in the check_cond_jmp_op() can be removed with migration to reg_not_null(), but that is a behavioural change, as the special case would start matching for PTR_TO_BTF_ID that is also is_trusted_reg(). I omit the behavioural change from this commit.

---
 kernel/bpf/verifier.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
kernel/bpf/verifier.c +6 -3
index 03187bab806a7..59f12ba70eb6e 100644
@@ -370,6 +370,8 @@ static bool reg_not_null(struct bpf_verifier_env *env, const struct bpf_reg_stat
 	type = base_type(type);
 	return type == PTR_TO_SOCKET ||
 		type == PTR_TO_TCP_SOCK ||
+		type == PTR_TO_XDP_SOCK ||
+		type == PTR_TO_BUF ||
 		type == PTR_TO_MAP_VALUE ||
 		type == PTR_TO_MAP_KEY ||
 		type == PTR_TO_SOCK_COMMON ||
@@ -16173,7 +16175,6 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
 	 */
 	if (!is_jmp32 && BPF_SRC(insn->code) == BPF_X &&
 	    __is_pointer_value(false, src_reg) && __is_pointer_value(false, dst_reg) &&
-	    type_may_be_null(src_reg->type) != type_may_be_null(dst_reg->type) &&
 	    base_type(src_reg->type) != PTR_TO_BTF_ID &&
 	    base_type(dst_reg->type) != PTR_TO_BTF_ID) {
 		eq_branch_regs = NULL;
@@ -16189,9 +16190,11 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
 			break;
 		}
 		if (eq_branch_regs) {
-			if (type_may_be_null(src_reg->type))
+			/* src == dst && dst != NULL => src != NULL */
+			if (reg_not_null(env, dst_reg) && type_may_be_null(src_reg->type))
 				mark_ptr_not_null_reg(&eq_branch_regs[insn->src_reg]);
-			else
+			/* src == dst && src != NULL => dst != NULL */
+			if (reg_not_null(env, src_reg) && type_may_be_null(dst_reg->type))
 				mark_ptr_not_null_reg(&eq_branch_regs[insn->dst_reg]);
 		}
 	}
Signature · 1 line
2.53.0
author maintainer
#50 lore raw

PATCH 50/733 ntfs: leave HasEA flag untouched on setxattr failure

In reply to Greg Kroah-Hartman

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

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

From: Baolin Liu <[email protected]>

[ Upstream commit ac727d86fb84bdc9626ba9c756c26767459f3083 ]

In ntfs_set_ea(), the exit path unconditionally updates the HasEA flag based on ea_info_qsize. When an error occurs before ea_info_qsize is updated, NInoClearHasEA() hides existing on-disk EAs until the inode is evicted.

Only update the flag on success.

Fixes fc053f05ca28 ("ntfs: add reparse and ea operations")
---
 fs/ntfs/ea.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
fs/ntfs/ea.c +6 -4
index 08c35f9751114..75a251ec4ebcb 100644
@@ -390,10 +390,12 @@ static int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len,
 		*packed_ea_size = p_ea_info->ea_length;
 	mark_mft_record_dirty(ni);
 out:
-	if (ea_info_qsize > 0)
-		NInoSetHasEA(ni);
-	else
-		NInoClearHasEA(ni);
+	if (!err) {
+		if (ea_info_qsize > 0)
+			NInoSetHasEA(ni);
+		else
+			NInoClearHasEA(ni);
+	}
 
 	kvfree(ea_buf);
 	kvfree(old_ea_buf);
Signature · 1 line
2.53.0
author maintainer
#51 lore raw

PATCH 51/733 bpf: dont downgrade half-dead scalar zero spills to STACK_ZERO

In reply to Greg Kroah-Hartman

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

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

From: Eduard Zingerman <[email protected]>

[ Upstream commit 2f3536bff8823d3c5fdbbe15e17bfca696cc2b2e ]

states.c:__clean_func_state() can downgrade scalar zero spill to STACK_ZERO in the following case:

  *(u64 *)(r10 - 8) = 0;
  ... checkpoint ...
  r1 = *(u32 *)(r10 - 4);
  ... no reads from r10-8 ...

Here 4 bytes at r10-8 are dead and verifier changes scalar spill to a
combination: 0000pppp (p stands for poison). Such a change breaks precision propagation chains. All places that produce STACK_ZERO should call bpf_mark_chain_precision() for the zero source.

This patch fixes the bug in a simplest way possible:
avoids converting stack spills of zero to STACK_ZERO. Two smarter approaches are possible:
- do bpf_mark_chain_precision() from __clean_func_state()
- check slot liveness information in check_stack_write_fixed_off()

I investigated both and the changes required are a bit tricky, hence go with a simple fix for the time being.

---
 kernel/bpf/states.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)
kernel/bpf/states.c +4 -7
index 4e6aafad33bd2..66fb11b6c6a76 100644
@@ -445,22 +445,19 @@ static void __clean_func_state(struct bpf_verifier_env *env,
 				struct bpf_reg_state *spill = &st->stack[i].spilled_ptr;
 
 				if (lo_live && stype == STACK_SPILL) {
-					u8 val = STACK_MISC;
-
 					if (spill->type != SCALAR_VALUE)
 						continue;
-
 					/*
-					 * 8 byte spill of scalar 0 where half slot is dead
-					 * should become STACK_ZERO in lo 4 bytes.
+					 * Can't replace with STACK_ZERO, because
+					 * that requires bpf_mark_chain_precision().
 					 */
 					if (bpf_register_is_null(spill))
-						val = STACK_ZERO;
+						continue;
 					for (j = 0; j < 4; j++) {
 						u8 *t = &st->stack[i].slot_type[j];
 
 						if (*t == STACK_SPILL)
-							*t = val;
+							*t = STACK_MISC;
 					}
 				}
 				bpf_mark_reg_not_init(env, spill);
Signature · 1 line
2.53.0
author maintainer
#52 lore raw

PATCH 52/733 net: icmp: avoid invalid transport header access in icmp_send tracepoint

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 7fcc2fe39fed1cb98a7374a113ff3800e8f9af80 ]

syzbot reported a WARNING triggered by DEBUG_NET_WARN_ON_ONCE():

 WARNING: at skb_transport_header include/linux/skbuff.h:3087 [inline]
 WARNING: at udp_hdr include/linux/udp.h:23 [inline]
 WARNING: at do_trace_event_raw_event_icmp_send include/trace/events/icmp.h:30 [inline]
 WARNING: at trace_event_raw_event_icmp_send+0x48c/0x6ec include/trace/events/icmp.h:11
 Call trace:
  skb_transport_header include/linux/skbuff.h:3087 [inline]
  udp_hdr include/linux/udp.h:23 [inline]
  do_trace_event_raw_event_icmp_send include/trace/events/icmp.h:30 [inline]
  trace_event_raw_event_icmp_send+0x48c/0x6ec include/trace/events/icmp.h:11
  __traceiter_icmp_send include/trace/events/icmp.h:11 [inline]
  __do_trace_icmp_send include/trace/events/icmp.h:11 [inline]
  trace_icmp_send+0x320/0x49c include/trace/events/icmp.h:11
  __icmp_send+0xcfc/0x11d8 net/ipv4/icmp.c:1013
  ipv4_send_dest_unreach net/ipv4/route.c:1280 [inline]
  ipv4_link_failure+0x57c/0x8dc net/ipv4/route.c:1287
  dst_link_failure include/net/dst.h:438 [inline]
  vti_tunnel_xmit+0xe40/0x17a4 net/ipv4/ip_vti.c:307

TP_fast_assign() unconditionally calls udp_hdr(skb) before checking whether the packet is UDP. Furthermore, __icmp_send() can be invoked from paths (e.g., link failures, ARP errors, forwarding, AF_PACKET) where skb->transport_header was never initialized (~0U).

Under CONFIG_DEBUG_NET=y, calling skb_transport_header(skb) triggers DEBUG_NET_WARN_ON_ONCE(!skb_transport_header_was_set(skb)).

Fix this by:
1. Only parsing transport info when iph->protocol == IPPROTO_UDP.
2. Using skb_header_pointer() at skb_network_offset(skb) + (iph->ihl << 2) to safely fetch the UDP header without assuming transport_header is set.

---
 include/trace/events/icmp.h | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
include/trace/events/icmp.h +8 -5
index 31559796949a7..acfcf2b132d60 100644
@@ -27,17 +27,20 @@ TRACE_EVENT(icmp_send,
 
 		TP_fast_assign(
 			struct iphdr *iph = ip_hdr(skb);
-			struct udphdr *uh = udp_hdr(skb);
-			int proto_4 = iph->protocol;
+			struct udphdr _uh, *uh = NULL;
 			__be32 *p32;
 
 			__entry->skbaddr = skb;
 			__entry->type = type;
 			__entry->code = code;
 
-			if (proto_4 != IPPROTO_UDP || (u8 *)uh < skb->head ||
-				(u8 *)uh + sizeof(struct udphdr)
-				> skb_tail_pointer(skb)) {
+			if (iph->protocol == IPPROTO_UDP)
+				uh = skb_header_pointer(skb,
+							skb_network_offset(skb) +
+							(iph->ihl << 2),
+							sizeof(_uh), &_uh);
+
+			if (!uh) {
 				__entry->sport = 0;
 				__entry->dport = 0;
 				__entry->ulen = 0;
Signature · 1 line
2.53.0
author maintainer
#53 lore raw

PATCH 53/733 tcp: use GFP_ATOMIC in tcp_send_active_reset()

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 18666c73afe95eeca8707c699b63f96ce3acda42 ]

tcp_send_active_reset() can be called from contexts where gfp_any() (in tcp_disconnect()) or sk->sk_allocation (in __tcp_close() and mptcp_do_fastclose()) evaluates to GFP_KERNEL, which includes __GFP_FS and __GFP_DIRECT_RECLAIM.

Allocating with GFP_KERNEL while holding the socket lock (sk_lock) creates a lockdep dependency:
sk_lock -> fs_reclaim

This causes false-positive lockdep circular locking warnings with storage subsystems (such as nvme-tcp) that acquire socket locks in block I/O paths and invoke tcp_disconnect() or close sockets upon teardown:
set->srcu -> sk_lock -> fs_reclaim -> elevator_lock -> set->srcu

Active resets are small RST packet headers that should never enter direct reclaim or block while holding socket locks.

Use sk_gfp_mask(sk, GFP_ATOMIC | __GFP_NOWARN) inside tcp_send_active_reset() and remove its priority argument. This preserves __GFP_MEMALLOC access for SOCK_MEMALLOC sockets, suppresses allocation failure warnings, and aligns with other control packet allocations (e.g. tcp_send_fin(), __tcp_send_ack(), tcp_xmit_probe_skb()).

---
 include/net/tcp.h     |  3 +--
 net/ipv4/tcp.c        | 14 ++++++--------
 net/ipv4/tcp_output.c |  4 ++--
 net/ipv4/tcp_timer.c  |  6 +++---
 net/mptcp/protocol.c  |  3 +--
 net/mptcp/protocol.h  |  2 +-
 6 files changed, 14 insertions(+), 18 deletions(-)
include/net/tcp.h +1 -2
index 670c20876f265..436495ff2271d 100644
@@ -765,8 +765,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
 void tcp_send_probe0(struct sock *);
 int tcp_write_wakeup(struct sock *, int mib);
 void tcp_send_fin(struct sock *sk);
-void tcp_send_active_reset(struct sock *sk, gfp_t priority,
-			   enum sk_rst_reason reason);
+void tcp_send_active_reset(struct sock *sk, enum sk_rst_reason reason);
 int tcp_send_synack(struct sock *);
 void tcp_push_one(struct sock *, unsigned int mss_now);
 void __tcp_send_ack(struct sock *sk, u32 rcv_nxt, u16 flags);
net/ipv4/tcp.c +6 -8
index 10f58281be17b..47a34a993972a 100644
@@ -3181,8 +3181,7 @@ void __tcp_close(struct sock *sk, long timeout)
 		/* Unread data was tossed, zap the connection. */
 		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE);
 		tcp_set_state(sk, TCP_CLOSE);
-		tcp_send_active_reset(sk, sk->sk_allocation,
-				      SK_RST_REASON_TCP_ABORT_ON_CLOSE);
+		tcp_send_active_reset(sk, SK_RST_REASON_TCP_ABORT_ON_CLOSE);
 	} else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
 		/* Check zero linger _after_ checking for unread data. */
 		sk->sk_prot->disconnect(sk, 0);
@@ -3256,7 +3255,7 @@ void __tcp_close(struct sock *sk, long timeout)
 		struct tcp_sock *tp = tcp_sk(sk);
 		if (READ_ONCE(tp->linger2) < 0) {
 			tcp_set_state(sk, TCP_CLOSE);
-			tcp_send_active_reset(sk, GFP_ATOMIC,
+			tcp_send_active_reset(sk,
 					      SK_RST_REASON_TCP_ABORT_ON_LINGER);
 			__NET_INC_STATS(sock_net(sk),
 					LINUX_MIB_TCPABORTONLINGER);
@@ -3275,7 +3274,7 @@ void __tcp_close(struct sock *sk, long timeout)
 	if (sk->sk_state != TCP_CLOSE) {
 		if (tcp_check_oom(sk, 0)) {
 			tcp_set_state(sk, TCP_CLOSE);
-			tcp_send_active_reset(sk, GFP_ATOMIC,
+			tcp_send_active_reset(sk,
 					      SK_RST_REASON_TCP_ABORT_ON_MEMORY);
 			__NET_INC_STATS(sock_net(sk),
 					LINUX_MIB_TCPABORTONMEMORY);
@@ -3376,14 +3375,14 @@ int tcp_disconnect(struct sock *sk, int flags)
 	} else if (unlikely(tp->repair)) {
 		WRITE_ONCE(sk->sk_err, ECONNABORTED);
 	} else if (tcp_need_reset(old_state)) {
-		tcp_send_active_reset(sk, gfp_any(), SK_RST_REASON_TCP_STATE);
+		tcp_send_active_reset(sk, SK_RST_REASON_TCP_STATE);
 		WRITE_ONCE(sk->sk_err, ECONNRESET);
 	} else if (tp->snd_nxt != tp->write_seq &&
 		   (1 << old_state) & (TCPF_CLOSING | TCPF_LAST_ACK)) {
 		/* The last check adjusts for discrepancy of Linux wrt. RFC
 		 * states
 		 */
-		tcp_send_active_reset(sk, gfp_any(),
+		tcp_send_active_reset(sk,
 				      SK_RST_REASON_TCP_DISCONNECT_WITH_DATA);
 		WRITE_ONCE(sk->sk_err, ECONNRESET);
 	} else if (old_state == TCP_SYN_SENT)
@@ -5146,8 +5145,7 @@ int tcp_abort(struct sock *sk, int err)
 	bh_lock_sock(sk);
 
 	if (tcp_need_reset(sk->sk_state))
-		tcp_send_active_reset(sk, GFP_ATOMIC,
-				      SK_RST_REASON_TCP_STATE);
+		tcp_send_active_reset(sk, SK_RST_REASON_TCP_STATE);
 	tcp_done_with_error(sk, err);
 
 	bh_unlock_sock(sk);
net/ipv4/tcp_output.c +2 -2
index 8d243e91761a9..f72a6b1fe749b 100644
@@ -3849,9 +3849,9 @@ void tcp_send_fin(struct sock *sk)
  * was unread data in the receive queue.  This behavior is recommended
  * by RFC 2525, section 2.17.  -DaveM
  */
-void tcp_send_active_reset(struct sock *sk, gfp_t priority,
-			   enum sk_rst_reason reason)
+void tcp_send_active_reset(struct sock *sk, enum sk_rst_reason reason)
 {
+	gfp_t priority = sk_gfp_mask(sk, GFP_ATOMIC | __GFP_NOWARN);
 	struct sk_buff *skb;
 
 	TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTRSTS);
net/ipv4/tcp_timer.c +3 -3
index 4df1c9745c5d5..95296b1cf0ca2 100644
@@ -126,7 +126,7 @@ static int tcp_out_of_resources(struct sock *sk, bool do_reset)
 		    (!tp->snd_wnd && !tp->packets_out))
 			do_reset = true;
 		if (do_reset)
-			tcp_send_active_reset(sk, GFP_ATOMIC,
+			tcp_send_active_reset(sk,
 					      SK_RST_REASON_TCP_ABORT_ON_MEMORY);
 		tcp_done(sk);
 		__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONMEMORY);
@@ -809,7 +809,7 @@ static void tcp_keepalive_timer(struct timer_list *t)
 				goto out;
 			}
 		}
-		tcp_send_active_reset(sk, GFP_ATOMIC, SK_RST_REASON_TCP_STATE);
+		tcp_send_active_reset(sk, SK_RST_REASON_TCP_STATE);
 		goto death;
 	}
 
@@ -836,7 +836,7 @@ static void tcp_keepalive_timer(struct timer_list *t)
 		    icsk->icsk_probes_out > 0) ||
 		    (user_timeout == 0 &&
 		    icsk->icsk_probes_out >= keepalive_probes(tp))) {
-			tcp_send_active_reset(sk, GFP_ATOMIC,
+			tcp_send_active_reset(sk,
 					      SK_RST_REASON_TCP_KEEPALIVE_TIMEOUT);
 			tcp_write_err(sk);
 			goto out;
net/mptcp/protocol.c +1 -2
index 7c8180d8d5eff..8adf699894e32 100644
@@ -2985,8 +2985,7 @@ static void mptcp_do_fastclose(struct sock *sk)
 		 */
 		inet_csk(ssk)->icsk_ack.rcv_mss = TCP_MIN_MSS;
 
-		tcp_send_active_reset(ssk, ssk->sk_allocation,
-				      SK_RST_REASON_TCP_ABORT_ON_CLOSE);
+		tcp_send_active_reset(ssk, SK_RST_REASON_TCP_ABORT_ON_CLOSE);
 unlock:
 		release_sock(ssk);
 	}
net/mptcp/protocol.h +1 -1
index 1b80f2d6ec5a2..32b771e658500 100644
@@ -687,7 +687,7 @@ mptcp_send_active_reset_reason(struct sock *sk)
 	enum sk_rst_reason reason;
 
 	reason = sk_rst_convert_mptcp_reason(subflow->reset_reason);
-	tcp_send_active_reset(sk, GFP_ATOMIC, reason);
+	tcp_send_active_reset(sk, reason);
 }
 
 /* Made the fwd mem carried by the given skb available to the msk,
Signature · 1 line
2.53.0
author maintainer
#54 lore raw

PATCH 54/733 net: stmmac: fix dma mapping leak in stmmac_tso_xmit()

In reply to Greg Kroah-Hartman

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

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

From: Lorenzo Bianconi <[email protected]>

[ Upstream commit a5d946466a95621fa2769720d59ea336003aa1a5 ]

In stmmac_tso_xmit(), if the DMA mapping of an skb fragment fails, the frame is dropped but the DMA mappings already created for the linear part and for the fragments mapped before the failure are never unmapped, leaking DMA mappings.

Fix the leak by walking back over the descriptors used by the frame and releasing each of them with stmmac_free_tx_buffer(). Moreover, release the descriptors with stmmac_release_tx_desc() unmapping the DMA buffers.

---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 53 ++++++++++++-------
 1 file changed, 34 insertions(+), 19 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +34 -19
index 3a437409f78ae..1946361081fc2 100644
@@ -4319,6 +4319,7 @@ static bool stmmac_vlan_insert(struct stmmac_priv *priv, struct sk_buff *skb,
 /**
  *  stmmac_tso_allocator - close entry point of the driver
  *  @priv: driver private structure
+ *  @entry: TX queue buffer index
  *  @des: buffer start address
  *  @total_len: total length to fill in descriptors
  *  @last_segment: condition for the last descriptor
@@ -4327,8 +4328,9 @@ static bool stmmac_vlan_insert(struct stmmac_priv *priv, struct sk_buff *skb,
  *  This function fills descriptor and request new descriptors according to
  *  buffer length to fill
  */
-static void stmmac_tso_allocator(struct stmmac_priv *priv, dma_addr_t des,
-				 int total_len, bool last_segment, u32 queue)
+static void stmmac_tso_allocator(struct stmmac_priv *priv, u32 *entry,
+				 dma_addr_t des, int total_len,
+				 bool last_segment, u32 queue)
 {
 	struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
 	struct dma_desc *desc;
@@ -4340,14 +4342,13 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, dma_addr_t des,
 	while (tmp_len > 0) {
 		dma_addr_t curr_addr;
 
-		tx_q->cur_tx = STMMAC_NEXT_ENTRY(tx_q->cur_tx,
-						priv->dma_conf.dma_tx_size);
-		WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]);
+		*entry = STMMAC_NEXT_ENTRY(*entry, priv->dma_conf.dma_tx_size);
+		WARN_ON(tx_q->tx_skbuff[*entry]);
 
 		if (tx_q->tbs & STMMAC_TBS_AVAIL)
-			desc = &tx_q->dma_entx[tx_q->cur_tx].basic;
+			desc = &tx_q->dma_entx[*entry].basic;
 		else
-			desc = &tx_q->dma_tx[tx_q->cur_tx];
+			desc = &tx_q->dma_tx[*entry];
 
 		curr_addr = des + (total_len - tmp_len);
 		stmmac_set_desc_addr(priv, desc, curr_addr);
@@ -4486,7 +4487,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct dma_desc *desc, *first, *mss_desc = NULL;
 	struct stmmac_priv *priv = netdev_priv(dev);
-	unsigned int first_entry, tx_packets;
+	unsigned int first_entry, entry, tx_packets;
 	struct stmmac_txq_stats *txq_stats;
 	struct stmmac_tx_queue *tx_q;
 	bool set_ic, is_last_segment;
@@ -4549,22 +4550,24 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	first_entry = tx_q->cur_tx;
-	WARN_ON(tx_q->tx_skbuff[first_entry]);
+	entry = first_entry;
+
+	WARN_ON(tx_q->tx_skbuff[entry]);
 
 	if (tx_q->tbs & STMMAC_TBS_AVAIL)
-		desc = &tx_q->dma_entx[first_entry].basic;
+		desc = &tx_q->dma_entx[entry].basic;
 	else
-		desc = &tx_q->dma_tx[first_entry];
+		desc = &tx_q->dma_tx[entry];
 	first = desc;
 
 	/* first descriptor: fill Headers on Buf1 */
 	des = dma_map_single(priv->device, skb->data, skb_headlen(skb),
 			     DMA_TO_DEVICE);
 	if (dma_mapping_error(priv->device, des))
-		goto dma_map_err;
+		goto error;
 
 	stmmac_set_desc_addr(priv, first, des);
-	stmmac_tso_allocator(priv, des + proto_hdr_len, pay_len,
+	stmmac_tso_allocator(priv, &entry, des + proto_hdr_len, pay_len,
 			     (nfrags == 0), queue);
 
 	/* In case two or more DMA transmit descriptors are allocated for this
@@ -4579,8 +4582,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
 	 * this DMA buffer right after the DMA engine completely finishes the
 	 * full buffer transmission.
 	 */
-	stmmac_set_tx_skb_dma_entry(tx_q, tx_q->cur_tx, des, skb_headlen(skb),
-				    false);
+	stmmac_set_tx_skb_dma_entry(tx_q, entry, des, skb_headlen(skb), false);
 
 	/* Prepare fragments */
 	for (i = 0; i < nfrags; i++) {
@@ -4590,14 +4592,15 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
 				       skb_frag_size(frag),
 				       DMA_TO_DEVICE);
 		if (dma_mapping_error(priv->device, des))
-			goto dma_map_err;
+			goto error_dma_unmap;
 
-		stmmac_tso_allocator(priv, des, skb_frag_size(frag),
+		stmmac_tso_allocator(priv, &entry, des, skb_frag_size(frag),
 				     (i == nfrags - 1), queue);
 
-		stmmac_set_tx_skb_dma_entry(tx_q, tx_q->cur_tx, des,
+		stmmac_set_tx_skb_dma_entry(tx_q, entry, des,
 					    skb_frag_size(frag), true);
 	}
+	tx_q->cur_tx = entry;
 
 	stmmac_set_tx_dma_last_segment(tx_q, tx_q->cur_tx);
 
@@ -4700,7 +4703,19 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	return NETDEV_TX_OK;
 
-dma_map_err:
+error_dma_unmap:
+	for (;;) {
+		desc = stmmac_get_tx_desc(priv, tx_q, first_entry);
+		stmmac_release_tx_desc(priv, desc, priv->descriptor_mode);
+		stmmac_free_tx_buffer(priv, &priv->dma_conf, queue,
+				      first_entry);
+		if (first_entry == entry)
+			break;
+
+		first_entry = STMMAC_NEXT_ENTRY(first_entry,
+						priv->dma_conf.dma_tx_size);
+	}
+error:
 	dev_err(priv->device, "Tx dma map failed\n");
 	dev_kfree_skb(skb);
 	priv->xstats.tx_dropped++;
Signature · 1 line
2.53.0
author maintainer
#55 lore raw

PATCH 55/733 net: iptunnel: fix stale transport header during tunnel decapsulation

In reply to Greg Kroah-Hartman

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

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

From: Dong Chenchen <[email protected]>

[ Upstream commit 28a57fb2c5df4deb42a06e52fd36c14b37aa0034 ]

Syzbot reported a crash in qdisc_pkt_len_segs_init() caused by a stale transport_header offset after tunnel decapsulation.

BUG: unable to handle page fault for address: ffffed102091a42e
Oops: Oops: 0000 [#1] SMP KASAN NOPTI
CPU: 0 UID: 0 PID: 340 Comm: qdisc_uaf_repro Not tainted 7.2.0-rc4-00061-g248951ddc14d #256 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:__asan_load2
<IRQ>

qdisc_pkt_len_segs_init (net/core/dev.c:4145) __dev_queue_xmit (net/core/dev.c:4787) br_dev_queue_push_xmit (net/bridge/br_forward.c:53) br_handle_frame_finish (net/bridge/br_input.c:229) br_handle_frame (net/bridge/br_input.c:315) __netif_receive_skb_core.constprop.0 (net/core/dev.c:6099) __netif_receive_skb_list_core (net/core/dev.c:6287) netif_receive_skb_list_internal (net/core/dev.c:6445) napi_complete_done (net/core/dev.c:6813) gro_cell_poll (net/core/gro_cells.c:74) __napi_poll (net/core/dev.c:7735)
net_rx_action (net/core/dev.c:7798 net/core/dev.c:7955) handle_softirqs (kernel/softirq.c:622)
do_softirq (kernel/softirq.c:523 kernel/softirq.c:510 ) __local_bh_enable_ip (kernel/softirq.c:450) tun_get_user (drivers/net/tun.c:1986 (discriminator 1)) tun_chr_write_iter (drivers/net/tun.c:2032)

The issue is completely latent until qdisc read transport header in commit 7fb4c1967011 ("net: pull headers in qdisc_pkt_len_segs_init()"). The crash requires four conditions to line up:

1. The incoming packet is encapsulated and carries GSO metadata. The outer transport header offset is stored in skb->transport_header while the packet is still in the outer tunnel context.
2. The tunnel receiver strips the outer headers. skb->data is advanced to the inner frame, but skb->transport_header is left pointing to the now-removed outer L4 header, so it becomes a negative offset relative to the new data.
3. The inner frame is not delivered to the local IP stack. Instead, it is forwarded at L2 by a bridge or HSR, so ip_rcv_core() never runs and the transport header is not reset to the inner L4 offset.
4. The forwarding path calls __dev_queue_xmit(), which enters qdisc_pkt_len_segs_init(). That function computes the GSO header length from skb_transport_offset(skb). Because the offset is negative, the unsigned cast overflows and pskb_may_pull(skb, hdr_len + sizeof(struct tcphdr)) reads past the end of the skb, triggering a KASAN fault or page fault.

The issue specifically requires GSO packets (shinfo->gso_size != 0), which are processed/aggregated through gro_cells. Fix this by clearing transport_header to the ~0U sentinel in gro_cell for all tunnnel driver. GTP does not support GRO/GSO, drop the evil GSO packets in GTP directly.

---
 drivers/net/gtp.c      | 5 +++++
 include/linux/skbuff.h | 5 +++++
 net/core/gro_cells.c   | 2 ++
 3 files changed, 12 insertions(+)
drivers/net/gtp.c +5 -0
index 298efc76a56b0..69fe5717846b5 100644
@@ -318,6 +318,11 @@ static int gtp_inner_proto(struct sk_buff *skb, unsigned int hdrlen,
 static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb,
 		  unsigned int hdrlen, unsigned int role, __u16 inner_proto)
 {
+	if (skb_is_gso(skb)) {
+		netdev_dbg(pctx->dev, "GSO is not supported in GTP\n");
+		goto err;
+	}
+
 	if (!gtp_check_ms(skb, pctx, hdrlen, role, inner_proto)) {
 		netdev_dbg(pctx->dev, "No PDP ctx for this MS\n");
 		return 1;
include/linux/skbuff.h +5 -0
index ed6a2bc23db51..f7dd3db9459c6 100644
@@ -3082,6 +3082,11 @@ static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
 	return skb->transport_header != (typeof(skb->transport_header))~0U;
 }
 
+static inline void skb_unset_transport_header(struct sk_buff *skb)
+{
+	skb->transport_header = (typeof(skb->transport_header))~0U;
+}
+
 static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
 {
 	DEBUG_NET_WARN_ON_ONCE(!skb_transport_header_was_set(skb));
net/core/gro_cells.c +2 -0
index 1b84385c04bd9..d8c0a28671201 100644
@@ -22,6 +22,8 @@ int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
 	if (unlikely(!(dev->flags & IFF_UP)))
 		goto drop;
 
+	skb_unset_transport_header(skb);
+
 	if (!gcells->cells || skb_cloned(skb) || netif_elide_gro(dev)) {
 		res = netif_rx(skb);
 		goto unlock;
Signature · 1 line
2.53.0
author maintainer
#56 lore raw

PATCH 56/733 net/sched: act_api: budget all shared attributes in notify skbs

In reply to Greg Kroah-Hartman

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

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

From: Victor Nogueira <[email protected]>

[ Upstream commit 13eb543cebef6d6c3ec42e31afe3856f51b7126b ]

tcf_action_shared_attrs_size() is supposed to return an upper bound on the netlink attributes every action dump emits outside of TCA_ACT_OPTIONS, so that tcf_add_notify_msg(), tcf_del_notify_msg() and friends can allocate an skb large enough for the reply. It has fallen behind the dump path and is now an underestimate for every single action.

Attributes, such as, TCA_ACT_IN_HW_COUNT and TCA_STATS_BASIC_HW are emitted unconditionally and never accounted for. TCA_STATS_PKT64, TCA_ACT_USED_HW_STATS, TCA_STATS_RATE_EST, TCA_STATS_RATE_EST64 require specific conditions, but are also not accounted for.

Fix the issue by budgeting all of them so that we have a legitimate upper bound. Even tough for of them require specific conditions, they are cheap so, to avoid overcomplicating, we opted to account for them unconditionally as well to account for a real worst case scenario.

---
 net/sched/act_api.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
net/sched/act_api.c +11 -2
index b4415d358c911..766162b0b8102 100644
@@ -443,12 +443,21 @@ static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
 		+ nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */
 		+ cookie_len /* TCA_ACT_COOKIE */
 		+ nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_HW_STATS */
+		/* TCA_ACT_USED_HW_STATS */
+		+ nla_total_size(sizeof(struct nla_bitfield32))
+		+ nla_total_size(sizeof(u32)) /* TCA_ACT_IN_HW_COUNT */
 		+ nla_total_size(0) /* TCA_ACT_STATS nested */
 		+ nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_FLAGS */
 		/* TCA_STATS_BASIC */
 		+ nla_total_size_64bit(sizeof(struct gnet_stats_basic))
-		/* TCA_STATS_PKT64 */
-		+ nla_total_size_64bit(sizeof(u64))
+		/* TCA_STATS_BASIC_HW */
+		+ nla_total_size_64bit(sizeof(struct gnet_stats_basic))
+		/* TCA_STATS_PKT64, emitted by both of the basic copies above */
+		+ 2 * nla_total_size_64bit(sizeof(u64))
+		/* TCA_STATS_RATE_EST */
+		+ nla_total_size_64bit(sizeof(struct gnet_stats_rate_est))
+		/* TCA_STATS_RATE_EST64 */
+		+ nla_total_size_64bit(sizeof(struct gnet_stats_rate_est64))
 		/* TCA_STATS_QUEUE */
 		+ nla_total_size_64bit(sizeof(struct gnet_stats_queue))
 		+ nla_total_size(0) /* TCA_ACT_OPTIONS nested */
Signature · 1 line
2.53.0
author maintainer
#57 lore raw

PATCH 57/733 net/sched: act_api: size the RTM_GETACTION reply from the actions

In reply to Greg Kroah-Hartman

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

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

From: Victor Nogueira <[email protected]>

[ Upstream commit e9ca46ebc3262b498626c4095826b8fa034bbf21 ]

tca_action_gd() already walks every requested action and accumulates attr_size += tcf_action_fill_size(act), then wraps the result in tcf_action_full_attrs_size(). For RTM_DELACTION that value is handed to tcf_del_notify_msg(), which allocates max(attr_size, NLMSG_GOODSIZE). For RTM_GETACTION it is silently discarded and tcf_get_notify() allocates a fixed NLMSG_GOODSIZE skb instead.

Any action whose dump exceeds that fixed budget therefore cannot be read back. For example, act_pedit overruns the budget with 32 actions of four munge keys each, act_police with 32 policers once the optional rate/peakrate/result/avrate attributes are present

Fix this by passing attr_size through and allocate the reply the way the add and delete paths do.

Note on exposure: RTM_GETACTION is the only one of the three action commands that is not capability checked - tc_ctl_action() requires CAP_NET_ADMIN for RTM_NEWACTION and RTM_DELACTION only - so this turns a fixed NLMSG_GOODSIZE reply into a user sized allocation on an unprivileged path. It is bounded by TCA_ACT_MAX_PRIO actions per request, and tca_action_gd() does not reject duplicate indices, so a single large action can be requested 32 times; an act_bpf program near BPF_MAXINSNS is about 32KB of dump, or roughly 1MB for one request. Creating such an action still requires CAP_NET_ADMIN, and the add and delete paths have sized their skbs this way since the Fixes commit. Should this ever need bounding, GFP_KERNEL_ACCOUNT would charge the reply to the caller's memcg.

---
 net/sched/act_api.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
net/sched/act_api.c +4 -3
index 766162b0b8102..20b6501fd33b2 100644
@@ -1697,12 +1697,12 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[],
 
 static int
 tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
-	       struct tc_action *actions[], int event,
+	       struct tc_action *actions[], size_t attr_size, int event,
 	       struct netlink_ext_ack *extack)
 {
 	struct sk_buff *skb;
 
-	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+	skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
 	if (!skb)
 		return -ENOBUFS;
 	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
@@ -2053,7 +2053,8 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
 	attr_size = tcf_action_full_attrs_size(attr_size);
 
 	if (event == RTM_GETACTION)
-		ret = tcf_get_notify(net, portid, n, actions, event, extack);
+		ret = tcf_get_notify(net, portid, n, actions, attr_size, event,
+				     extack);
 	else { /* delete */
 		ret = tcf_del_notify(net, n, actions, portid, attr_size, extack);
 		if (ret)
Signature · 1 line
2.53.0
author maintainer
#58 lore raw

PATCH 58/733 net/sched: act_api: fix skb sizing and action leak on reoffload delete

In reply to Greg Kroah-Hartman

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

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

From: Victor Nogueira <[email protected]>

[ Upstream commit 251367a0a3319fa565daf7468b0afd933b1f5ab1 ]

tcf_reoffload_del_notify_msg() sizes the RTM_DELACTION skb with tcf_action_fill_size(action) alone. Unlike every other notification path it never wraps that in tcf_action_full_attrs_size(), so the nlmsg_put() header, struct tcamsg and the TCA_ACT_TAB nest that tca_get_fill() emits - 24 bytes on x86_64 - are not budgeted. As long as the single action stays well under NLMSG_GOODSIZE the floor in alloc_skb() hides this, but once its fill size crosses NLMSG_GOODSIZE the allocation is exactly 24 bytes short and tca_get_fill() runs out of tailroom. That is now easy to reach for an offloadable act_pedit with a large tcfp_nkeys, which commit 8e2efb3f45a5 ("net/sched: add get_fill_size callbacks for actions missing them") started accounting for properly.

When that happens tcf_reoffload_del_notify() returns early, before tcf_idr_release_unsafe(), and tcf_action_reoffload_cb() discards the return value:

	if (tc_act_skip_sw(p->tcfa_flags) && !tc_act_in_hw(p))
		tcf_reoffload_del_notify(net, p);

The action has just lost its last hardware instance and is skip_sw, so it is left installed while processing no packets, and with no notification to tell userspace about it. An -ENOBUFS from alloc_skb() gets the same treatment.

Fix this by budgeting the message header the way the add and delete paths do, and release the action even when the notification cannot be built - dropping the notification is strictly better than leaking a dead action, and there is no caller left to report the error to.

---
 net/sched/act_api.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)
net/sched/act_api.c +11 -6
index 20b6501fd33b2..37eced84dfa5f 100644
@@ -1867,11 +1867,13 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[])
 static struct sk_buff *tcf_reoffload_del_notify_msg(struct net *net,
 						    struct tc_action *action)
 {
-	size_t attr_size = tcf_action_fill_size(action);
 	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {
 		[0] = action,
 	};
 	struct sk_buff *skb;
+	size_t attr_size;
+
+	attr_size = tcf_action_full_attrs_size(tcf_action_fill_size(action));
 
 	skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
 	if (!skb)
@@ -1888,15 +1890,18 @@ static struct sk_buff *tcf_reoffload_del_notify_msg(struct net *net,
 static int tcf_reoffload_del_notify(struct net *net, struct tc_action *action)
 {
 	const struct tc_action_ops *ops = action->ops;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	int ret;
 
-	if (!rtnl_notify_needed(net, 0, RTNLGRP_TC)) {
-		skb = NULL;
-	} else {
+	if (rtnl_notify_needed(net, 0, RTNLGRP_TC)) {
 		skb = tcf_reoffload_del_notify_msg(net, action);
+		/* The action has already lost its hardware instance and is
+		 * skip_sw, so it must be released whether or not the
+		 * notification can be built.  Drop the notification rather
+		 * than leave an action behind that processes no packets.
+		 */
 		if (IS_ERR(skb))
-			return PTR_ERR(skb);
+			skb = NULL;
 	}
 
 	ret = tcf_idr_release_unsafe(action);
Signature · 1 line
2.53.0
author maintainer
#59 lore raw

PATCH 59/733 sctp: fix a TOCTOU race in SCTP_CMD_TIMER_START

In reply to Greg Kroah-Hartman

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

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

From: Xin Long <[email protected]>

[ Upstream commit 2188569e7e1b0bc3f3b557dc97ab7a02befc11c8 ]

The SCTP_CMD_TIMER_START handler checks timer_pending() before calling timer_reduce(). The timer can expire and detach between these operations, causing timer_reduce() to rearm the timer without taking the association reference required for the newly armed timer.

The timer callback later unconditionally drops its association reference, which can leave the association reference count unbalanced and result in use-after-free during association teardown.

Use the return value of timer_reduce() to determine whether the timer was actually armed. Take the association reference only when timer_reduce() successfully starts a new timer, closing the race between checking the timer state and rearming it.

This issue was reported by Nico Yip (@_cyeaa_) working with TrendAI Zero Day Initiative.

---
 net/sctp/sm_sideeffect.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)
net/sctp/sm_sideeffect.c +1 -10
index 94716406d602c..0d99b7e8c082f 100644
@@ -1545,17 +1545,8 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
 			timeout = asoc->timeouts[cmd->obj.to];
 			BUG_ON(!timeout);
 
-			/*
-			 * SCTP has a hard time with timer starts.  Because we process
-			 * timer starts as side effects, it can be hard to tell if we
-			 * have already started a timer or not, which leads to BUG
-			 * halts when we call add_timer. So here, instead of just starting
-			 * a timer, if the timer is already started, and just mod
-			 * the timer with the shorter of the two expiration times
-			 */
-			if (!timer_pending(timer))
+			if (!timer_reduce(timer, jiffies + timeout))
 				sctp_association_hold(asoc);
-			timer_reduce(timer, jiffies + timeout);
 			break;
 
 		case SCTP_CMD_TIMER_RESTART:
Signature · 1 line
2.53.0
author maintainer
#60 lore raw

PATCH 60/733 scsi: mpi3mr: Fix NULL pointer dereference in mpi3mr_sas_port_add()

In reply to Greg Kroah-Hartman

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

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

From: Milan P. Gandhi <[email protected]>

[ Upstream commit dba9e2181ca5e875f98b8b9b4535cdaab87dcb0d ]

sas_port_alloc_num() can return NULL on memory allocation failure. The return value is passed directly to sas_port_add() without a NULL check, which causes a NULL pointer dereference.

Additionally, if sas_port_add() fails, the allocated port is not freed before jumping to out_fail, leaking the sas_port structure. Call sas_port_free() to properly release it.

---
 drivers/scsi/mpi3mr/mpi3mr_transport.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/scsi/mpi3mr/mpi3mr_transport.c +6 -0
index 240f67a8e2e3b..ea2c04384a0e1 100644
@@ -1428,9 +1428,15 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
 	}
 
 	port = sas_port_alloc_num(mr_sas_node->parent_dev);
+	if (!port) {
+		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
+		    __FILE__, __LINE__, __func__);
+		goto out_fail;
+	}
 	if ((sas_port_add(port))) {
 		ioc_err(mrioc, "failure at %s:%d/%s()!\n",
 		    __FILE__, __LINE__, __func__);
+		sas_port_free(port);
 		goto out_fail;
 	}
 
Signature · 1 line
2.53.0
author maintainer
#61 lore raw

PATCH 61/733 scsi: mpi3mr: Fix target device refcount leak in mpi3mr_sas_port_add()

In reply to Greg Kroah-Hartman

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

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

From: Milan P. Gandhi <[email protected]>

[ Upstream commit 419d129f970aaa6567dbac366b0c93784bf9ec97 ]

mpi3mr_get_tgtdev_by_addr() increments the target device kref when it returns a device. If a subsequent error triggers a goto out_fail after the tgtdev reference is acquired, the reference is never released because the out_fail path does not call mpi3mr_tgtdev_put(). This prevents the target device structure from ever being freed.

Add a tgtdev put in the out_fail path, guarded by a NULL check since tgtdev is only acquired for SAS_END_DEVICE types and the same cleanup path is shared by earlier error cases where tgtdev is still NULL.

---
 drivers/scsi/mpi3mr/mpi3mr_transport.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/scsi/mpi3mr/mpi3mr_transport.c +2 -0
index ea2c04384a0e1..232af978d7372 100644
@@ -1507,6 +1507,8 @@ static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
 	list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
 	    port_siblings)
 		list_del(&mr_sas_phy->port_siblings);
+	if (tgtdev)
+		mpi3mr_tgtdev_put(tgtdev);
 	kfree(mr_sas_port);
 	return NULL;
 }
Signature · 1 line
2.53.0
author maintainer
#62 lore raw

PATCH 62/733 scsi: ufs: ufs-pci: Add support for Intel UFS 4.0 HS-Gear5

In reply to Greg Kroah-Hartman

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

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

From: sangram kumar yerra <[email protected]>

[ Upstream commit ef675ea168453a9b3e635b8ac543f92938bdd03b ]

Reliable HS-Gear5 operation on Intel UFS 4.0 controllers requires configuring PA_INITIAL_ADAPT before changing the power mode. Without this setting, the link fails to train reliably at Gear5.

Add a pwr_change_notify() hook to configure the adaptation mode before the power mode transition. Enable this only for UFS 4.0 and later controllers by checking hba->ufs_version.

Wire the hook into the existing Meteor Lake family variant operations table (ufs_intel_mtl_hba_vops) instead of introducing a separate table, since the Intel UFS 4.0 PCI variant (PCI ID 8086:D335) already uses this vops table and the hook is internally gated on UFS version >= 4.0.

Use PA_INITIAL_ADAPT when the negotiated TX power mode is FAST_MODE or FASTAUTO_MODE. Otherwise, reset the adaptation mode to PA_NO_ADAPT, which is the default setting.

---
 drivers/ufs/host/ufshcd-pci.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
drivers/ufs/host/ufshcd-pci.c +20 -0
index f2433879b0eba..93bfafc25018b 100644
@@ -181,6 +181,25 @@ static int ufs_intel_lkf_pwr_change_notify(struct ufs_hba *hba,
 	return err;
 }
 
+static int ufs_intel_nvl_pwr_change_notify(struct ufs_hba *hba,
+					   enum ufs_notify_change_status stage,
+					   struct ufs_pa_layer_attr *dev_req_params)
+{
+	int adapt_val;
+
+	if (stage != PRE_CHANGE || hba->ufs_version < ufshci_version(4, 0))
+		return 0;
+
+	if (dev_req_params->pwr_tx == FAST_MODE || dev_req_params->pwr_tx == FASTAUTO_MODE)
+		adapt_val = PA_INITIAL_ADAPT;
+	else
+		adapt_val = PA_NO_ADAPT;
+
+	ufshcd_dme_configure_adapt(hba, dev_req_params->gear_tx, adapt_val);
+
+	return 0;
+}
+
 static int ufs_intel_lkf_apply_dev_quirks(struct ufs_hba *hba)
 {
 	u32 granularity, peer_granularity;
@@ -527,6 +546,7 @@ static struct ufs_hba_variant_ops ufs_intel_mtl_hba_vops = {
 	.exit			= ufs_intel_common_exit,
 	.hce_enable_notify	= ufs_intel_hce_enable_notify,
 	.link_startup_notify	= ufs_intel_link_startup_notify,
+	.pwr_change_notify	= ufs_intel_nvl_pwr_change_notify,
 	.resume			= ufs_intel_resume,
 	.device_reset		= ufs_intel_device_reset,
 };
Signature · 1 line
2.53.0
author maintainer
#63 lore raw

PATCH 63/733 scsi: ufs: ufs-pci: Add MCQ support for Intel UFS 4.0 controllers

In reply to Greg Kroah-Hartman

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

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

From: sangram kumar yerra <[email protected]>

[ Upstream commit c46cc9cee39bd6f395ab9ac98b1794705df13d7c ]

The Intel UFS 4.0 PCI variant (PCI ID 8086:D335) advertises MCQ support in its capability register. However, ufshcd_alloc_mcq() also requires an .op_runtime_config hook to locate the per-queue operation and runtime (OPR) register blocks, which was not provided by this variant operations table.

As a result, MCQ initialization fails and ufshcd_add_scsi_host() prints "MCQ mode is disabled, err=%d\n" before falling back to legacy single-doorbell (SDB) mode.

Add ufs_intel_mcq_config_resource() to initialize the MCQ configuration base and add ufs_intel_op_runtime_config() to set up the OPR register offsets and stride.

Wire both hooks into the variant operations table so MCQ is enabled when supported by the hardware.

---
 drivers/ufs/host/ufshcd-pci.c | 39 +++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
drivers/ufs/host/ufshcd-pci.c +39 -0
index 93bfafc25018b..21bb11c724bea 100644
@@ -460,6 +460,43 @@ static int ufs_intel_mtl_init(struct ufs_hba *hba)
 	return ufs_intel_common_init(hba);
 }
 
+static int ufs_intel_mcq_config_resource(struct ufs_hba *hba)
+{
+	hba->mcq_base = hba->mmio_base + ufshcd_mcq_queue_cfg_addr(hba);
+
+	return 0;
+}
+
+/*
+ * This Intel UFS4.0 controller maps MCQ doorbell and interrupt-status
+ * registers into the same PCI BAR as the legacy HCI space, at this
+ * fixed offset/stride.
+ */
+#define UFS_INTEL_SQDAO0	0x2800
+#define UFS_INTEL_SQISAO0	0x2814
+#define UFS_INTEL_CQDAO0	0x281C
+#define UFS_INTEL_CQISAO0	0x2824
+#define UFS_INTEL_MCQ_STRIDE	0x30
+
+static int ufs_intel_op_runtime_config(struct ufs_hba *hba)
+{
+	struct ufshcd_mcq_opr_info_t *opr;
+	int i;
+
+	hba->mcq_opr[OPR_SQD].offset  = UFS_INTEL_SQDAO0;
+	hba->mcq_opr[OPR_SQIS].offset = UFS_INTEL_SQISAO0;
+	hba->mcq_opr[OPR_CQD].offset  = UFS_INTEL_CQDAO0;
+	hba->mcq_opr[OPR_CQIS].offset = UFS_INTEL_CQISAO0;
+
+	for (i = 0; i < OPR_MAX; i++) {
+		opr = &hba->mcq_opr[i];
+		opr->stride = UFS_INTEL_MCQ_STRIDE;
+		opr->base = hba->mmio_base + opr->offset;
+	}
+
+	return 0;
+}
+
 static int ufs_qemu_get_hba_mac(struct ufs_hba *hba)
 {
 	return MAX_SUPP_MAC;
@@ -547,6 +584,8 @@ static struct ufs_hba_variant_ops ufs_intel_mtl_hba_vops = {
 	.hce_enable_notify	= ufs_intel_hce_enable_notify,
 	.link_startup_notify	= ufs_intel_link_startup_notify,
 	.pwr_change_notify	= ufs_intel_nvl_pwr_change_notify,
+	.mcq_config_resource	= ufs_intel_mcq_config_resource,
+	.op_runtime_config	= ufs_intel_op_runtime_config,
 	.resume			= ufs_intel_resume,
 	.device_reset		= ufs_intel_device_reset,
 };
Signature · 1 line
2.53.0
author maintainer
#64 lore raw

PATCH 64/733 smb/client: validate new EOF for insert range

In reply to Greg Kroah-Hartman

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

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

From: Huiwen He <[email protected]>

[ Upstream commit 1519dc88c87f5346dae0464d7d6da1b6bf1f6e8e ]

smb3_insert_range() does not check if the new file size (i_size + len) is valid. This allows FALLOC_FL_INSERT_RANGE to bypass RLIMIT_FSIZE, exceed s_maxbytes, or produce a size outside the loff_t range.

Use check_add_overflow() to calculate the new EOF. Validate it with inode_newsize_ok() before modifying the file.

Reproducer, using a file on a CIFS mount:

bash -c '
FILE=/mnt/cifs/repro

trap "" SIGXFSZ
ulimit -f 3072 # RLIMIT_FSIZE = 3 MiB

# A regular write is stopped at 3 MiB.
dd if=/dev/zero of="$FILE" bs=1M count=4 status=none stat -c "size after write: %s" "$FILE"

# Insert 2 MiB into a 2 MiB file. truncate -s 2M "$FILE" fallocate -i -o 0 -l 2M "$FILE" stat -c "size after insert: %s" "$FILE"
'

Before this change, the regular write stops at the 3 MiB limit, but insert range grows the file to 4 MiB:

	dd: error writing '/mnt/cifs/repro': File too large
	size after write: 3145728
	size after insert: 4194304

After this change, insert range also fails at the limit and leaves the 2 MiB file unchanged:

	dd: error writing '/mnt/cifs/repro': File too large
	size after write: 3145728
	fallocate: fallocate failed: File too large
	size after insert: 2097152
Fixes 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support")
---
 fs/smb/client/smb2ops.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
fs/smb/client/smb2ops.c +10 -2
index 0e872d58fae7c..476afb4e49fd8 100644
@@ -3982,7 +3982,8 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
 	struct cifsFileInfo *cfile = file->private_data;
 	struct inode *inode = file_inode(file);
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
-	__u64 count, old_eof, new_eof;
+	u64 count;
+	loff_t old_eof, new_eof;
 
 	xid = get_xid();
 
@@ -3992,8 +3993,15 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
 		goto out;
 	}
 
+	if (check_add_overflow(old_eof, len, &new_eof)) {
+		rc = -EFBIG;
+		goto out;
+	}
+	rc = inode_newsize_ok(inode, new_eof);
+	if (rc)
+		goto out;
+
 	count = old_eof - off;
-	new_eof = old_eof + len;
 
 	filemap_invalidate_lock(inode->i_mapping);
 	rc = filemap_write_and_wait_range(inode->i_mapping, off, new_eof - 1);
Signature · 1 line
2.53.0
author maintainer
#65 lore raw

PATCH 65/733 smb/client: validate new EOF for zero range

In reply to Greg Kroah-Hartman

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

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

From: Huiwen He <[email protected]>

[ Upstream commit 88972e35750792e717af287dc71f42a03b5cbce4 ]

When FALLOC_FL_ZERO_RANGE is used without FALLOC_FL_KEEP_SIZE, smb3_zero_range() may extend EOF without checking RLIMIT_FSIZE, allowing the file to grow beyond the caller's file-size limit.

Fix this by calling inode_newsize_ok() before sending the zero-range request when the operation would extend EOF.

Reproducer, using a file on a CIFS mount:

	bash -c '
	        FILE=/mnt/cifs/repro

	        trap "" SIGXFSZ
	        ulimit -f 3072

	        truncate -s 2M "$FILE"
	        fallocate --zero-range -o 0 -l 4M "$FILE"
	        echo "fallocate rc=$?"
	        stat -c "file size=%s" "$FILE"
	'

Before this change, the operation succeeds despite the 3 MiB limit:

	fallocate rc=0
	file size=4194304

After this change, fallocate fails and leaves the file at 2 MiB.

Fixes 72c419d9b073 ("cifs: fix smb3_zero_range so it can expand the file-size when required")
---
 fs/smb/client/smb2ops.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
fs/smb/client/smb2ops.c +8 -1
index 476afb4e49fd8..3b96dc3615ab4 100644
@@ -3441,6 +3441,13 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 	trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid,
 			      ses->Suid, offset, len);
 
+	new_size = offset + len;
+	if (!keep_size && i_size_read(inode) < new_size) {
+		rc = inode_newsize_ok(inode, new_size);
+		if (rc)
+			goto out;
+	}
+
 	filemap_invalidate_lock(inode->i_mapping);
 
 	netfs_read_sizes(inode, &i_size, &remote_i_size, &zero_point);
@@ -3471,7 +3478,6 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 	/*
 	 * do we also need to change the size of the file?
 	 */
-	new_size = offset + len;
 	if (keep_size == false && (unsigned long long)i_size_read(inode) < new_size) {
 		rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
 				  cfile->fid.volatile_fid, cfile->pid, new_size);
@@ -3488,6 +3494,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 
  zero_range_exit:
 	filemap_invalidate_unlock(inode->i_mapping);
+ out:
 	free_xid(xid);
 	if (rc)
 		trace_smb3_zero_err(xid, cfile->fid.persistent_fid, tcon->tid,
Signature · 1 line
2.53.0
author maintainer
#66 lore raw

PATCH 66/733 smb/client: mark file sparse before emulating insert range

In reply to Greg Kroah-Hartman

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

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

From: Huiwen He <[email protected]>

[ Upstream commit cd03ce4950d80147ac8f20bc03c42b75b0352407 ]

The SMB client emulates FALLOC_FL_INSERT_RANGE with SET_EOF, COPYCHUNK and SET_ZERO_DATA.

SET_ZERO_DATA creates a hole only when the file is sparse. On a non-sparse file, it clears the inserted range but leaves its blocks allocated, causing the extent count check in xfstests generic/064 to fail.

Fix this by marking the file sparse before modifying it.

This patch produces the expected sparse extents in xfstests generic/064 only when the server-reported block size is compatible with the server's deallocation granularity.

For ksmbd, the reported block size follows the backing filesystem, and the test passes. For Samba, the test passes with a block size matching the backend granularity, for example, 4 KiB on Btrfs, but not with the default 1 KiB value. For Windows Server 2022, 4 KiB inserts do not generate holes, while aligned inserts of 64 KiB or larger do.

Fixes 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support")
---
 fs/smb/client/smb2ops.c | 5 +++++
 1 file changed, 5 insertions(+)
fs/smb/client/smb2ops.c +5 -0
index 3b96dc3615ab4..a2fe71df2d4fb 100644
@@ -4010,6 +4010,11 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
 
 	count = old_eof - off;
 
+	/* SET_ZERO_DATA creates a hole only in a sparse file. */
+	rc = smb2_set_sparse(xid, tcon, cfile, inode, true);
+	if (rc)
+		goto out;
+
 	filemap_invalidate_lock(inode->i_mapping);
 	rc = filemap_write_and_wait_range(inode->i_mapping, off, new_eof - 1);
 	if (rc < 0)
Signature · 1 line
2.53.0
author maintainer
#67 lore raw

PATCH 67/733 smb/client: fix data corruption in emulated insert range

In reply to Greg Kroah-Hartman

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

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

From: Huiwen He <[email protected]>

[ Upstream commit 0923ae9f23cc9460b0df6fc124cd56ec4436411b ]

smb3_insert_range() shifts [off, EOF) right with COPYCHUNK, copying from low to high offsets. When the ranges overlap, the copy can overwrite source data that has not yet been copied. For a 1 MiB insert at offset 0:

offset: 0 1M 2M 3M 4M 5M

  before:   |   A   |   B   |   C   |   D   |
  expected: | hole  |   A   |   B   |   C   |   D   |
  current:  | hole  |   A   |   A   |   A   |   A   | (corrupted)

Let x be the insertion offset, L the total length to move, delta the insert length, and C the normal chunk size allowed by the server. Insert range maps

[x, x + L) -> [x + delta, x + delta + L).

When delta >= L, the complete source and target ranges are disjoint, so the normal copy order and chunk size are safe:

offset: 0 4 8 12 16 20 24 28 32
source: [--S0--][--S1--][--S2--][--S3--]
target: [--T0--][--T1--][--T2--][--T3--]

When delta < L, the complete source and target ranges overlap, so the copy must proceed from EOF backwards. There are two subcases.

If delta >= C, each corresponding source and target chunk is disjoint. The 1 MiB example has L = 4 MiB and delta = C = 1 MiB:

offset: 0 1M 2M 3M 4M 5M
source: [--S0--][--S1--][--S2--][--S3--]
target: [--T0--][--T1--][--T2--][--T3--]

Copying S0 from [0, 1M) to [1M, 2M) overwrites S1 before it is copied. Processing chunks from EOF backwards prevents this inter-chunk overwrite.

If delta < C, the source and target ranges of a normal chunk also overlap. For example, with L = 16, delta = 2 and C = 4:

offset: 0 2 4 6 8 10 12 14 16 18
source: [--S0--][--S1--][--S2--][--S3--]
target: [--T0--][--T1--][--T2--][--T3--]

Here S0 and T0 overlap over [2,4), S1 and T1 over [6,8), and so on. Backward ordering cannot control how the server copies bytes inside one descriptor, so the chunk size must be limited to delta.

Fix this by copying overlapping right shifts from EOF backwards. Limit the chunk size to delta when delta < C so that each chunk's source and target ranges do not overlap. Using larger chunks would require a way to identify servers that safely handle overlapping COPYCHUNK descriptors.

Therefore:

delta >= L:
keep the normal copy order and chunk size

delta < L:
delta >= C: copy backwards and keep the normal chunk size delta < C: copy backwards and limit the chunk size to delta

Only the delta < C subcase requires reducing the chunk size for data integrity.

Reproducer:

bash -c '
MNT=/mnt/scratch

# Generate four 1 MiB random blocks: [A][B][C][D]. dd if=/dev/urandom of=/tmp/src bs=1M count=4 status=none

# With C = 1 MiB, test delta = C and delta < C. for delta in 1M 1K; do
truncate -s 0 /tmp/expected truncate -s "$delta" /tmp/expected cat /tmp/src >> /tmp/expected

cp /tmp/src "$MNT/file"
fallocate --insert-range -o 0 -l "$delta" "$MNT/file"

if cmp -s /tmp/expected "$MNT/file"; then
echo "delta=$delta: OK"
else
echo "delta=$delta: CORRUPTED"
fi
done
'

The corruption reproduces with Samba and ksmbd, while Windows handles the overlapping COPYCHUNK ranges safely.

The 1 MiB case tests delta >= C, while the 1 KiB case tests delta < C. Before this change, the reproducer reports:

delta=1M: CORRUPTED
delta=1K: CORRUPTED

After this change, it passes against both ksmbd and Samba:

delta=1M: OK
delta=1K: OK

Fixes 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support")
---
 fs/smb/client/smb2ops.c | 132 ++++++++++++++++++++++++++++++++--------
 1 file changed, 106 insertions(+), 26 deletions(-)
fs/smb/client/smb2ops.c +106 -26
index a2fe71df2d4fb..d113e28b5c3b7 100644
@@ -1839,31 +1839,31 @@ smb2_ioctl_query_info(const unsigned int xid,
  *
  * @tcon: destination file tcon
  * @bytes_left: how many bytes are left to copy
+ * @chunk_size: maximum size of a single chunk
  *
  * Return: maximum number of chunks with which Chunks[] can be filled.
  */
 static inline u32
-calc_chunk_count(struct cifs_tcon *tcon, u64 bytes_left)
+calc_chunk_count(struct cifs_tcon *tcon, u64 bytes_left, u32 chunk_size)
 {
 	u32 max_chunks = READ_ONCE(tcon->max_chunks);
 	u32 max_bytes_copy = READ_ONCE(tcon->max_bytes_copy);
-	u32 max_bytes_chunk = READ_ONCE(tcon->max_bytes_chunk);
 	u64 need;
 	u32 allowed;
 
-	if (!max_bytes_chunk || !max_bytes_copy || !max_chunks)
+	if (!chunk_size || !max_bytes_copy || !max_chunks)
 		return 0;
 
 	/* chunks needed for the remaining bytes */
-	need = DIV_ROUND_UP_ULL(bytes_left, max_bytes_chunk);
+	need = DIV_ROUND_UP_ULL(bytes_left, chunk_size);
 	/* chunks allowed per cc request */
-	allowed = DIV_ROUND_UP(max_bytes_copy, max_bytes_chunk);
+	allowed = DIV_ROUND_UP(max_bytes_copy, chunk_size);
 
 	return (u32)umin(need, umin(max_chunks, allowed));
 }
 
 /**
- * smb2_copychunk_range - server-side copy of data range
+ * __smb2_copychunk_range - server-side copy of data range
  *
  * @xid: transaction id
  * @src_file: source file
@@ -1875,15 +1875,15 @@ calc_chunk_count(struct cifs_tcon *tcon, u64 bytes_left)
  * Obtains a resume key for @src_file and issues FSCTL_SRV_COPYCHUNK_WRITE
  * IOCTLs, splitting the request into chunks limited by tcon->max_*.
  *
- * Return: @len on success; negative errno on failure.
+ * Return: 0 on success; negative errno on failure.
  */
-static ssize_t
-smb2_copychunk_range(const unsigned int xid,
-		     struct cifsFileInfo *src_file,
-		     struct cifsFileInfo *dst_file,
-		     u64 src_off,
-		     u64 len,
-		     u64 dst_off)
+static int
+__smb2_copychunk_range(const unsigned int xid,
+		       struct cifsFileInfo *src_file,
+		       struct cifsFileInfo *dst_file,
+		       u64 src_off,
+		       u64 len,
+		       u64 dst_off)
 {
 	int rc = 0;
 	unsigned int ret_data_len = 0;
@@ -1891,12 +1891,14 @@ smb2_copychunk_range(const unsigned int xid,
 	struct copychunk_ioctl_rsp *cc_rsp = NULL;
 	struct cifs_tcon *tcon;
 	struct srv_copychunk *chunk;
-	u32 chunks, chunk_count, chunk_bytes;
+	u32 chunks, chunk_count, chunk_bytes, chunk_size;
 	u32 copy_bytes, copy_bytes_left;
 	u32 chunks_written, bytes_written;
 	u64 total_bytes_left = len;
 	u64 src_off_prev, dst_off_prev;
+	u64 max_chunk = 0;
 	u32 retries = 0;
+	bool reverse = false;
 
 	tcon = tlink_tcon(dst_file->tlink);
 
@@ -1904,8 +1906,50 @@ smb2_copychunk_range(const unsigned int xid,
 				   dst_file->fid.volatile_fid, tcon->tid,
 				   tcon->ses->Suid, src_off, dst_off, len);
 
+	/*
+	 * Same-file left shifts are safe in forward order. For a right shift,
+	 * let L be the copy length, delta the distance between the source and
+	 * destination, and C the normal chunk size:
+	 *
+	 *   delta >= L:      copy forwards using C
+	 *   delta < L:
+	 *     delta >= C:    copy backwards using C
+	 *     delta < C:     copy backwards with chunks limited to delta
+	 *
+	 * Copying backwards prevents one chunk from overwriting data needed by
+	 * a later chunk. Limiting the chunk size to delta prevents an individual
+	 * chunk from overlapping itself.
+	 * This limit can be removed once all supported servers handle overlapping
+	 * descriptors safely.
+	 *
+	 * A small right shift over a large range may therefore require many
+	 * chunks.
+	 */
+	if (src_file == dst_file && dst_off > src_off) {
+		u64 delta = dst_off - src_off;
+
+		if (delta < len) {
+			reverse = true;
+			max_chunk = delta;
+		}
+	}
+
+	/*
+	 * A backward copy walks the offsets down from the end of the range.
+	 * Do this once, outside the retry loop, so a retry does not move the
+	 * offsets again.
+	 */
+	if (reverse) {
+		src_off += len;
+		dst_off += len;
+	}
+
 retry:
-	chunk_count = calc_chunk_count(tcon, total_bytes_left);
+	chunk_size = READ_ONCE(tcon->max_bytes_chunk);
+	if (max_chunk && max_chunk < chunk_size)
+		chunk_size = (u32)max_chunk;
+
+	chunk_count = calc_chunk_count(tcon, total_bytes_left, chunk_size);
 	if (!chunk_count) {
 		rc = -EOPNOTSUPP;
 		goto out;
@@ -1946,16 +1990,21 @@ smb2_copychunk_range(const unsigned int xid,
 		while (copy_bytes_left > 0 && chunks < chunk_count) {
 			chunk = &cc_req->Chunks[chunks++];
 
+			chunk_bytes = umin(copy_bytes_left, chunk_size);
+			if (reverse) {
+				src_off -= chunk_bytes;
+				dst_off -= chunk_bytes;
+			}
+
 			chunk->SourceOffset = cpu_to_le64(src_off);
 			chunk->TargetOffset = cpu_to_le64(dst_off);
-
-			chunk_bytes = umin(copy_bytes_left, tcon->max_bytes_chunk);
-
 			chunk->Length = cpu_to_le32(chunk_bytes);
 			/* Buffer is zeroed, no need to set chunk->Reserved = 0 */
 
-			src_off += chunk_bytes;
-			dst_off += chunk_bytes;
+			if (!reverse) {
+				src_off += chunk_bytes;
+				dst_off += chunk_bytes;
+			}
 
 			copy_bytes_left -= chunk_bytes;
 			copy_bytes += chunk_bytes;
@@ -2003,6 +2052,18 @@ smb2_copychunk_range(const unsigned int xid,
 				goto out;
 			}
 
+			/*
+			 * A successful COPYCHUNK should copy every descriptor (MS-SMB2
+			 * 3.3.5.15.6). Reject a short backward copy because the rewind
+			 * below only supports forward copying.
+			 */
+			if (unlikely(reverse && bytes_written < copy_bytes)) {
+				cifs_tcon_dbg(VFS, "Copychunk short write %u/%u (reverse)\n",
+					      bytes_written, copy_bytes);
+				rc = -EIO;
+				goto out;
+			}
+
 			/* Partial write: rewind */
 			if (bytes_written < copy_bytes) {
 				u32 delta = copy_bytes - bytes_written;
@@ -2064,10 +2125,27 @@ smb2_copychunk_range(const unsigned int xid,
 		trace_smb3_copychunk_done(xid, src_file->fid.volatile_fid,
 					  dst_file->fid.volatile_fid, tcon->tid,
 					  tcon->ses->Suid, src_off, dst_off, len);
-		return len;
+		return 0;
 	}
 }
 
+static ssize_t
+smb2_copychunk_range(const unsigned int xid,
+		     struct cifsFileInfo *src_file,
+		     struct cifsFileInfo *dst_file,
+		     u64 src_off,
+		     u64 len,
+		     u64 dst_off)
+{
+	int rc;
+
+	rc = __smb2_copychunk_range(xid, src_file, dst_file, src_off, len,
+				    dst_off);
+	if (rc)
+		return rc;
+	return len;
+}
+
 static int
 smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
 		struct cifs_fid *fid)
@@ -3989,7 +4067,6 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
 	struct cifsFileInfo *cfile = file->private_data;
 	struct inode *inode = file_inode(file);
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
-	u64 count;
 	loff_t old_eof, new_eof;
 
 	xid = get_xid();
@@ -4008,8 +4085,6 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
 	if (rc)
 		goto out;
 
-	count = old_eof - off;
-
 	/* SET_ZERO_DATA creates a hole only in a sparse file. */
 	rc = smb2_set_sparse(xid, tcon, cfile, inode, true);
 	if (rc)
@@ -4033,7 +4108,12 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
 	spin_unlock(&inode->i_lock);
 	fscache_resize_cookie(cifs_inode_cookie(inode), i_size_read(inode));
 
-	rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
+	/*
+	 * Move [off, old_eof) right by len. The helper copies backwards if the
+	 * source and destination ranges overlap.
+	 */
+	rc = __smb2_copychunk_range(xid, cfile, cfile, off, old_eof - off,
+				    off + len);
 	if (rc < 0)
 		goto out_2;
 	spin_lock(&inode->i_lock);
Signature · 1 line
2.53.0
author maintainer
#68 lore raw

PATCH 68/733 smb/client: fix integer truncation in collapse range

In reply to Greg Kroah-Hartman

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

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

From: Huiwen He <[email protected]>

[ Upstream commit 7811701d6af7db76481a82b9bc3c4adf7863acf5 ]

smb3_collapse_range() stores the ssize_t return value of smb2_copychunk_range() in an int. A successful copy larger than INT_MAX is truncated to a negative value and treated as an error.

Reproducer:

	MNT=/mnt/scratch

	truncate -s 2056M "$MNT/file"
	fallocate --collapse-range -o 1M -l 1M "$MNT/file"

Fix this by using __smb2_copychunk_range(), which reports success as zero instead of returning the copied byte count.

Before this change, the reproducer fails with:

fallocate: fallocate failed: Success

and the file size remains unchanged at 2056 MiB. After this change, the reproducer succeeds and the file size becomes the expected 2055 MiB.

Fixes 5476b5dd82c8 ("cifs: add support for FALLOC_FL_COLLAPSE_RANGE")
---
 fs/smb/client/smb2ops.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/client/smb2ops.c +2 -2
index d113e28b5c3b7..ae4e855f80500 100644
@@ -4033,8 +4033,8 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
 	spin_unlock(&inode->i_lock);
 	netfs_wait_for_outstanding_io(inode);
 
-	rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
-				  old_eof - off - len, off);
+	rc = __smb2_copychunk_range(xid, cfile, cfile, off + len,
+				    old_eof - off - len, off);
 	if (rc < 0)
 		goto out_2;
 
Signature · 1 line
2.53.0
author maintainer
#69 lore raw

PATCH 69/733 smb/client: fix stale page cache in insert/collapse range

In reply to Greg Kroah-Hartman

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

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

From: Huiwen He <[email protected]>

[ Upstream commit 01261a6fa48b62f5ead8e88aaca1e27cb9ab9032 ]

smb3_insert_range() and smb3_collapse_range() use truncate_pagecache_range() to invalidate the affected page cache. However, if off or old_eof is not page-aligned, the boundary pages are only partially zeroed and remain uptodate. As a result, the client may return stale data after a successful insert/collapse range operation.

For example, with 4K pages:

    page 0          page 1          page 2
    0------4K       4K------8K      8K------12K

^ ^
off=2K old_eof=10K

Page 1 is removed from the page cache, while the boundary pages are only partially zeroed. After COPYCHUNK moves the data on the server, these cached pages may still return stale data.

This can be reproduced on a CIFS mount:

bash -c '
FILE=/mnt/scratch/repro

# Use a 6 KiB file so EOF is not page-aligned. dd if=/dev/urandom of=/tmp/src bs=1K count=6 status=none

# Expected: a 4 KiB hole followed by the original data. rm -f /tmp/expected
truncate -s 4K /tmp/expected
cat /tmp/src >> /tmp/expected

cp /tmp/src "$FILE"

# Prime the page cache before moving data on the server. cat "$FILE" > /dev/null

fallocate --insert-range -o 0 -l 4K "$FILE"

if cmp -s /tmp/expected "$FILE"; then
echo "readback: OK"
else
echo "readback: STALE DATA"
fi
'

Fix this by writing back dirty data and discarding the page cache from the start of the page containing off to EOF before moving data on the server.

Fixes 9c8b7a293f50 ("smb3: fix temporary data corruption in insert range")
Fixes fa30a81f255a ("smb3: fix temporary data corruption in collapse range")
---
 fs/smb/client/smb2ops.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)
fs/smb/client/smb2ops.c +18 -5
index ae4e855f80500..9b662635fa134 100644
@@ -4023,15 +4023,22 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
 	}
 
 	filemap_invalidate_lock(inode->i_mapping);
-	rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof - 1);
+	rc = filemap_write_and_wait_range(inode->i_mapping,
+					  round_down(off, PAGE_SIZE),
+					  old_eof - 1);
 	if (rc < 0)
 		goto out_2;
 
-	truncate_pagecache_range(inode, off, old_eof);
+	netfs_wait_for_outstanding_io(inode);
+	/*
+	 * Invalidate cached folios from the page containing off to EOF before
+	 * moving data on the server, so subsequent reads do not see stale data.
+	 */
+	truncate_pagecache_range(inode, round_down(off, PAGE_SIZE), -1);
+
 	spin_lock(&inode->i_lock);
 	netfs_write_zero_point(inode, old_eof);
 	spin_unlock(&inode->i_lock);
-	netfs_wait_for_outstanding_io(inode);
 
 	rc = __smb2_copychunk_range(xid, cfile, cfile, off + len,
 				    old_eof - off - len, off);
@@ -4091,11 +4098,17 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
 		goto out;
 
 	filemap_invalidate_lock(inode->i_mapping);
-	rc = filemap_write_and_wait_range(inode->i_mapping, off, new_eof - 1);
+	rc = filemap_write_and_wait_range(inode->i_mapping,
+					  round_down(off, PAGE_SIZE),
+					  old_eof - 1);
 	if (rc < 0)
 		goto out_2;
-	truncate_pagecache_range(inode, off, old_eof);
 	netfs_wait_for_outstanding_io(inode);
+	/*
+	 * Invalidate cached folios from the page containing off to EOF before
+	 * moving data on the server, so subsequent reads do not see stale data.
+	 */
+	truncate_pagecache_range(inode, round_down(off, PAGE_SIZE), -1);
 
 	rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
 			  cfile->fid.volatile_fid, cfile->pid, new_eof);
Signature · 1 line
2.53.0
author maintainer
#70 lore raw

PATCH 70/733 smb/client: invalidate fscache for fallocate range operations

In reply to Greg Kroah-Hartman

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

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

From: Huiwen He <[email protected]>

[ Upstream commit 448ba0ae65ca61064183564d2983c9aa59bd6ba7 ]

smb3_zero_range(), smb3_punch_hole(), smb3_insert_range(), and smb3_collapse_range() modify file contents through server-side range operations. These operations discard the affected page cache, but leave the FS-Cache cookie valid, so a later read may return data cached before the range operation.

Fix this by invalidating FS-Cache after outstanding I/O has completed and before modifying the file on the server.

Run the following as root on a CIFS mount with fsc enabled and an active CacheFiles backend:

bash -c '
MNT=/mnt/cifs
FILE="$MNT/repro"

# Generate four 1 MiB random blocks: [A][B][C][D]. dd if=/dev/urandom of=/tmp/src bs=1M count=4 status=none

# Expected contents after zeroing B: [A][zero][C][D]. cp /tmp/src /tmp/expected
dd if=/dev/zero of=/tmp/expected bs=1M seek=1 count=1 \
conv=notrunc status=none
cp /tmp/src "$FILE"

# Populate FS-Cache, then discard the page cache. sync
echo 1 > /proc/sys/vm/drop_caches
cat "$FILE" > /dev/null
sync
echo 1 > /proc/sys/vm/drop_caches

fallocate --zero-range -o 1M -l 1M "$FILE"

if cmp -s /tmp/expected "$FILE"; then
echo "readback: OK"
else
echo "readback: STALE DATA"
fi
'

Before this change, the readback differs from /tmp/expected:

readback: STALE DATA

After this change, it matches:

readback: OK

Fixes 30175628bf7f ("[SMB3] Enable fallocate -z support for SMB3 mounts")
Fixes 31742c5a3317 ("enable fallocate punch hole ("fallocate -p") for SMB3")
Fixes 5476b5dd82c8 ("cifs: add support for FALLOC_FL_COLLAPSE_RANGE")
Fixes 7fe6fe95b936 ("cifs: add FALLOC_FL_INSERT_RANGE support")
---
 fs/smb/client/smb2ops.c | 7 +++++++
 1 file changed, 7 insertions(+)
fs/smb/client/smb2ops.c +7 -0
index 9b662635fa134..5f616384c75c0 100644
@@ -3549,6 +3549,9 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 	if (keep_size == false && !CIFS_CACHE_READ(cifsi))
 		goto zero_range_exit;
 
+	fscache_invalidate(cifs_inode_cookie(inode), NULL,
+			   i_size_read(inode), 0);
+
 	rc = smb3_zero_data(file, tcon, offset, len, xid);
 	if (rc < 0)
 		goto zero_range_exit;
@@ -3618,6 +3621,8 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
 	 */
 	truncate_pagecache_range(inode, offset, offset + len - 1);
 	netfs_wait_for_outstanding_io(inode);
+	fscache_invalidate(cifs_inode_cookie(inode), NULL,
+			   i_size_read(inode), 0);
 
 	cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
 
@@ -4035,6 +4040,7 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
 	 * moving data on the server, so subsequent reads do not see stale data.
 	 */
 	truncate_pagecache_range(inode, round_down(off, PAGE_SIZE), -1);
+	fscache_invalidate(cifs_inode_cookie(inode), NULL, old_eof, 0);
 
 	spin_lock(&inode->i_lock);
 	netfs_write_zero_point(inode, old_eof);
@@ -4109,6 +4115,7 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
 	 * moving data on the server, so subsequent reads do not see stale data.
 	 */
 	truncate_pagecache_range(inode, round_down(off, PAGE_SIZE), -1);
+	fscache_invalidate(cifs_inode_cookie(inode), NULL, old_eof, 0);
 
 	rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
 			  cfile->fid.volatile_fid, cfile->pid, new_eof);
Signature · 1 line
2.53.0
author maintainer
#71 lore raw

PATCH 71/733 smb: client: transport: Fix debug printing in __release_mid()

In reply to Greg Kroah-Hartman

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

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

From: Andy Shevchenko <[email protected]>

[ Upstream commit d83a21bb26015bfdd79b0440fe816b271b8bbab3 ]

Long time ago during upgrading printk():s to the respective pr_<level>() calls one misconversion happened and nobody has noticed that. So, previously printk(KERN_DEBUG) + printk() worked as one long debug print since the trailing '\n' is only present in the followup printk() format string. The culprit change missed that and split the message to two on the different levels. Restore the original behaviour to make users be less confused in the most likely never happen cases of partially getting that message.

Fixes 0b456f04bcdf ("cifs: convert printk(LEVEL...) to pr_<level>")
---
 fs/smb/client/transport.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
fs/smb/client/transport.c +5 -6
index fdf4e50c27ceb..e266859818a44 100644
@@ -101,12 +101,11 @@ void __release_mid(struct TCP_Server_Info *server, struct mid_q_entry *midEntry)
 		trace_smb3_slow_rsp(smb_cmd, midEntry->mid, midEntry->pid,
 			       midEntry->when_sent, midEntry->when_received);
 		if (cifsFYI & CIFS_TIMER) {
-			pr_debug("slow rsp: cmd %d mid %llu",
-				 midEntry->command, midEntry->mid);
-			cifs_info("A: 0x%lx S: 0x%lx R: 0x%lx\n",
-				  now - midEntry->when_alloc,
-				  now - midEntry->when_sent,
-				  now - midEntry->when_received);
+			pr_debug("slow rsp: cmd %d mid %llu A: 0x%lx S: 0x%lx R: 0x%lx\n",
+				 midEntry->command, midEntry->mid,
+				 now - midEntry->when_alloc,
+				 now - midEntry->when_sent,
+				 now - midEntry->when_received);
 		}
 	}
 #endif
Signature · 1 line
2.53.0
author maintainer
#72 lore raw

PATCH 72/733 sctp: fix soft lockup from unpadded ASCONF-ACK parameter iteration

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 2cb0b0b1ed69430bf73740377ea0a1c44c50db63 ]

sctp_verify_asconf() walks ASCONF-ACK parameters with sctp_walk_params(), which advances by SCTP_PAD4(length), while the consumer sctp_get_asconf_response() iterates the same parameters advancing by the raw length, without padding. A single odd-length parameter desynchronises the two walks and makes the consumer interpret attacker-controlled bytes at a misaligned offset.

When those bytes yield a length of zero, the while loop over asconf_ack_len makes no progress, spinning forever in softirq context, and the watchdog reports a soft lockup. All reads stay within the received skb, so the lockup is a pure remote denial of service. A remote peer can trigger it with a crafted ASCONF-ACK on an ADD-IP enabled association with an outstanding ASCONF (RFC 5061 section 4.1.2 requires the chunk to be authenticated, but the predefined empty key id 0 allows the peer to compute the same association HMAC from publicly exchanged parameters, so the gate does not help).

The SCTP_PARAM_ERR_CAUSE case of sctp_verify_asconf() also performs no length check, letting a parameter without a complete error header reach the consumer, which reads errhdr.cause past the end of the parameter, an out-of-bounds read.

Reject SCTP_PARAM_ERR_CAUSE parameters shorter than sizeof(struct sctp_addip_param) + sizeof(struct sctp_errhdr) at the verifier, and advance the consumer iterator with the same padding rule as the verifier to keep the two walks in lockstep. The verifier change guarantees a complete error header in every ERR_CAUSE parameter the consumer can see, so the consumer's asconf_ack_len check is dropped and it returns err_param->cause directly. The consumer padding fix is still required because odd lengths remain valid for SCTP_PARAM_ERR_CAUSE per RFC 5061.

The issue was found by ZeroHive, a vulnerability hunting agent at Tencent Yunding Lab.

---
 net/sctp/sm_make_chunk.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)
net/sctp/sm_make_chunk.c +6 -8
index 236e25abc7a42..84a4c97d0f755 100644
@@ -3215,6 +3215,9 @@ bool sctp_verify_asconf(const struct sctp_association *asoc,
 		*errp = param.p;
 		switch (param.p->type) {
 		case SCTP_PARAM_ERR_CAUSE:
+			if (length < sizeof(struct sctp_addip_param) +
+				     sizeof(struct sctp_errhdr))
+				return false;
 			break;
 		case SCTP_PARAM_IPV4_ADDRESS:
 			if (length != sizeof(struct sctp_ipv4addr_param))
@@ -3448,20 +3451,15 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
 			case SCTP_PARAM_ERR_CAUSE:
 				length = sizeof(*asconf_ack_param);
 				err_param = (void *)asconf_ack_param + length;
-				asconf_ack_len -= length;
-				if (asconf_ack_len > 0)
-					return err_param->cause;
-				else
-					return SCTP_ERROR_INV_PARAM;
-				break;
+				return err_param->cause;
 			default:
 				return SCTP_ERROR_INV_PARAM;
 			}
 		}
 
 		length = ntohs(asconf_ack_param->param_hdr.length);
-		asconf_ack_param = (void *)asconf_ack_param + length;
-		asconf_ack_len -= length;
+		asconf_ack_param = (void *)asconf_ack_param + SCTP_PAD4(length);
+		asconf_ack_len -= SCTP_PAD4(length);
 	}
 
 	return err_code;
Signature · 1 line
2.53.0
author maintainer
#73 lore raw

PATCH 73/733 raw: annotate disconnect-side IPv4 match writers

In reply to Greg Kroah-Hartman

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

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

From: Xuanqiang Luo <[email protected]>

[ Upstream commit ac08d183dac0441e41f77bbad50798fe609d90f1 ]

raw_v4_match() reads inet_daddr, inet_rcv_saddr and sk_bound_dev_if locklessly under RCU. Bind and connect writers are annotated, but __udp_disconnect() still clears the same fields using plain stores.

Commit 18f116931f52e ("raw: annotate lockless match fields in raw_v4_match()") added the lockless readers and annotated the raw bind and datagram connect writers. Its v4 revision intentionally left the shared disconnect-side IPv4 writers for follow-up cleanup.

Complete that follow-up by using WRITE_ONCE() for the disconnect-side stores, including the inet_rcv_saddr reset in inet_reset_saddr(), to pair with the lockless raw socket matcher.

---
 include/net/ip.h | 3 ++-
 net/ipv4/udp.c   | 4 ++--
 2 files changed, 4 insertions(+), 3 deletions(-)
include/net/ip.h +2 -1
index a8f57b4f4aa23..6f602df72ee62 100644
@@ -704,7 +704,8 @@ static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast,
 
 static __inline__ void inet_reset_saddr(struct sock *sk)
 {
-	inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0;
+	inet_sk(sk)->inet_saddr = 0;
+	WRITE_ONCE(inet_sk(sk)->inet_rcv_saddr, 0);
 #if IS_ENABLED(CONFIG_IPV6)
 	if (sk->sk_family == PF_INET6) {
 		struct ipv6_pinfo *np = inet6_sk(sk);
net/ipv4/udp.c +2 -2
index 70f6cbd4ef73b..45e96b7219896 100644
@@ -2164,10 +2164,10 @@ int __udp_disconnect(struct sock *sk, int flags)
 	 */
 
 	sk->sk_state = TCP_CLOSE;
-	inet->inet_daddr = 0;
+	WRITE_ONCE(inet->inet_daddr, 0);
 	inet->inet_dport = 0;
 	sock_rps_reset_rxhash(sk);
-	sk->sk_bound_dev_if = 0;
+	WRITE_ONCE(sk->sk_bound_dev_if, 0);
 	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) {
 		inet_reset_saddr(sk);
 		if (sk->sk_prot->rehash &&
Signature · 1 line
2.53.0
author maintainer
#74 lore raw

PATCH 74/733 net: amd-xgbe: discard rx packets with bad FCS

In reply to Greg Kroah-Hartman

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

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

From: James Nugraha <[email protected]>

[ Upstream commit ac8d6b28d48c5d951dcd923d33e461588e762a6d ]

amd-xgbe driver currently sets the MAC_RCR.DCRCC bit whenever RX is enabled. This disables hardware FCS validation, causing packets with bad FCS to be accepted unconditionally.

This change unsets DCRCC so that packets with bad FCS will be dropped, in-line with typical behaviours of many other network controllers.

Tests:
- Verified that packets with bad FCS are now dropped.
- Verified that receiving packets with bad FCS will increment the rx_crc_errors counter.

Fixes c5aa9e3b8156 ("amd-xgbe: Initial AMD 10GbE platform driver")
---
 drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/amd/xgbe/xgbe-dev.c +1 -2
index 2de974213090c..e2e850c1b90b1 100644
@@ -3400,7 +3400,7 @@ static void xgbe_enable_rx(struct xgbe_prv_data *pdata)
 	XGMAC_IOWRITE(pdata, MAC_RQC0R, reg_val);
 
 	/* Enable MAC Rx */
-	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 1);
+	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 0);
 	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, CST, 1);
 	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 1);
 	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 1);
@@ -3411,7 +3411,6 @@ static void xgbe_disable_rx(struct xgbe_prv_data *pdata)
 	unsigned int i;
 
 	/* Disable MAC Rx */
-	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, DCRCC, 0);
 	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, CST, 0);
 	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 0);
 	XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 0);
Signature · 1 line
2.53.0
author maintainer
#75 lore raw

PATCH 75/733 vxlan: mdb: Fix use-after-free in vxlan_mdb_remote_src_del()

In reply to Greg Kroah-Hartman

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

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

From: Baul Lee <[email protected]>

[ Upstream commit 4aa61c88b4e292e10abdfd791334b8272108d68a ]

vxlan_mdb_is_valid_source(), which validates MDBE_ATTR_SOURCE and every MDBE_ATTR_SRC_LIST member, accepts the all-zeros address.

A source list is only accepted on a (*, G) entry, whose source is the all-zeros address, and for each member of the list an (S, G) entry is derived from it by substituting the source. Entries are keyed by a plain memcmp() of struct vxlan_mdb_entry_key, so if MDBE_ATTR_SOURCE is present and holds the all-zeros address and the source list holds it as well, the derived (S, G) key is byte-identical to the (*, G) key and resolves to the same entry. Omitting MDBE_ATTR_SOURCE is not equivalent, as the key is then left with a zero address family.

vxlan_mdb_remote_src_del() removes the forwarding entry of a source before freeing the source entry:

	vxlan_mdb_remote_src_fwd_del(vxlan, group, remote, &ent->addr);
	vxlan_mdb_remote_src_entry_del(ent);

With the keys aliased, the first call deletes the remote of the entry that owns 'ent' instead of a separate (S, G) entry, and frees 'ent'. The second call then runs on the freed entry, and its hlist_del() reads ->pprev and ->next out of it and writes through them.

Adding the (*, G) entry with NLM_F_REPLACE and no source list marks the all-zeros source for deletion and reaches this from the sweep at the end of vxlan_mdb_remote_srcs_replace().

  BUG: KASAN: slab-use-after-free in __vxlan_mdb_add+0x1cd/0xd70
  Read of size 8 at addr ffff888102852500 by task poc/84
   __vxlan_mdb_add+0x1cd/0xd70
   vxlan_mdb_add+0xc0/0x140
   rtnl_mdb_add+0x157/0x2a0
   rtnetlink_rcv_msg+0x207/0x5a0
  Allocated by task 84:
   __kmalloc_cache_noprof+0x153/0x360
   vxlan_mdb_remote_srcs_add+0x2eb/0x440
   __vxlan_mdb_add+0x803/0xd70
  Freed by task 84:
   kfree+0x14c/0x3b0
   vxlan_mdb_remote_del+0x129/0x1a0
   __vxlan_mdb_del+0x4f/0xe0
   vxlan_mdb_remote_src_fwd_del.isra.0+0x162/0x1b0
   __vxlan_mdb_add+0x1c5/0xd70

The MDB operations are netns-scoped, so an unprivileged user can perform them in a new user and network namespace.

Reject the all-zeros address in vxlan_mdb_is_valid_source(), which covers both call sites. A (*, G) entry is expressed by omitting the source, so nothing legitimate is refused.

Discovered by XBOW, triaged by Baul Lee <[email protected]>

---
 drivers/net/vxlan/vxlan_mdb.c                 | 8 ++++++++
 tools/testing/selftests/net/test_vxlan_mdb.sh | 6 ++++++
 2 files changed, 14 insertions(+)
drivers/net/vxlan/vxlan_mdb.c +8 -0
index d71e1925ecfdb..841f42ffecb9a 100644
@@ -354,6 +354,10 @@ static bool vxlan_mdb_is_valid_source(const struct nlattr *attr, __be16 proto,
 			NL_SET_ERR_MSG_MOD(extack, "IPv4 multicast source address is not allowed");
 			return false;
 		}
+		if (ipv4_is_zeronet(nla_get_in_addr(attr))) {
+			NL_SET_ERR_MSG_MOD(extack, "IPv4 all-zeros source address is not allowed");
+			return false;
+		}
 		break;
 #if IS_ENABLED(CONFIG_IPV6)
 	case htons(ETH_P_IPV6): {
@@ -368,6 +372,10 @@ static bool vxlan_mdb_is_valid_source(const struct nlattr *attr, __be16 proto,
 			NL_SET_ERR_MSG_MOD(extack, "IPv6 multicast source address is not allowed");
 			return false;
 		}
+		if (ipv6_addr_any(&src)) {
+			NL_SET_ERR_MSG_MOD(extack, "IPv6 all-zeros source address is not allowed");
+			return false;
+		}
 		break;
 	}
 #endif
tools/testing/selftests/net/test_vxlan_mdb.sh +6 -0
index 58da5de99ac45..f9600aabd4a29 100755
@@ -685,6 +685,9 @@ star_g_common()
 	run_cmd "bridge -n $ns1 mdb add dev vx0 port vx0 grp $grp permanent filter_mode exclude source_list $grp dst $vtep_ip src_vni 10010"
 	log_test $? 255 "Invalid source in source list"
 
+	run_cmd "bridge -n $ns1 mdb add dev vx0 port vx0 grp $grp permanent filter_mode exclude source_list $all_zeros_grp dst $vtep_ip src_vni 10010"
+	log_test $? 255 "All-zeros source in source list"
+
 	run_cmd "bridge -n $ns1 mdb add dev vx0 port vx0 grp $grp permanent source_list $src1 dst $vtep_ip src_vni 10010"
 	log_test $? 255 "Source list without filter mode"
 }
@@ -784,6 +787,9 @@ sg_common()
 	run_cmd "bridge -n $ns1 mdb add dev vx0 port vx0 grp $grp src $grp permanent dst $vtep_ip src_vni 10010"
 	log_test $? 255 "(S, G) with an invalid source list"
 
+	run_cmd "bridge -n $ns1 mdb add dev vx0 port vx0 grp $grp src $all_zeros_grp permanent dst $vtep_ip src_vni 10010"
+	log_test $? 255 "(S, G) with an all-zeros source"
+
 	run_cmd "bridge -n $ns1 mdb add dev vx0 port vx0 grp $all_zeros_grp src $src permanent dst $vtep_ip src_vni 10010"
 	log_test $? 255 "All-zeros group with source"
 }
Signature · 1 line
2.53.0
author maintainer
#76 lore raw

PATCH 76/733 watchdog: msc313e: Fix NULL pointer dereference in PM callbacks

In reply to Greg Kroah-Hartman

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

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

From: Tzung-Bi Shih <[email protected]>

[ Upstream commit e3eceb76515910746e6268c4e4ac1c07516ebd7b ]

msc313e_wdt_probe() doesn't set the driver data for the platform device. As a result, dev_get_drvdata() in msc313e_wdt_suspend() and msc313e_wdt_resume() will return NULL, leading to a NULL pointer dereference afterward.

Set the platform device driver data in msc313e_wdt_probe().

Fixes e9800b799464 ("watchdog: Add Mstar MSC313e WDT driver")
---
 drivers/watchdog/msc313e_wdt.c | 1 +
 1 file changed, 1 insertion(+)
drivers/watchdog/msc313e_wdt.c +1 -0
index d962589e2c55a..f69d66971c41d 100644
@@ -124,6 +124,7 @@ static int msc313e_wdt_probe(struct platform_device *pdev)
 		set_bit(WDOG_HW_RUNNING, &priv->wdev.status);
 
 	watchdog_set_drvdata(&priv->wdev, priv);
+	platform_set_drvdata(pdev, priv);
 
 	watchdog_init_timeout(&priv->wdev, timeout, dev);
 	watchdog_stop_on_reboot(&priv->wdev);
Signature · 1 line
2.53.0
author maintainer
#77 lore raw

PATCH 77/733 perf symbol: Do not use debug file as the binary type

In reply to Greg Kroah-Hartman

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

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

From: Adrian Hunter <[email protected]>

[ Upstream commit ae9464c65e9d1ad4df4fed516cee9bca3bc614cc ]

dso__load() sets the binary type of a DSO to the type of the first symbol source found. For a DSO with a separate debug file linked via .gnu-debuglink, that is DSO_BINARY_TYPE__DEBUGLINK, which makes dso__get_filename() return the name of the debug file instead of the file that was actually executed.

Consumers that need to read instruction bytes, such as Intel PT decoding in 'perf script', then read from the debug file and produce wrong instructions.

Prefer DSO_BINARY_TYPE__BUILD_ID_CACHE, and otherwise DSO_BINARY_TYPE__SYSTEM_PATH_DSO, over debug-only types, which restores the behaviour of using a file that contains the executed instructions.

This is a workaround. Properly separating the binary file used for instructions from the file used for debug symbols is left for later.

Example:

Create a shared object with a separate .gnu_debuglink debug file. Note that 'objcopy --only-keep-debug' leaves .text as NOBITS, so instructions read from the debug file are zeros:

  # cat > foo.c << EOF
  unsigned long foo_work(unsigned long n)
  {
        unsigned long s = 0;
        for (unsigned long i = 0; i < n; i++)
                s = s * 31 + i;
        return s;
  }
  EOF
  # cat > main.c << EOF
  #include <stdio.h>
  unsigned long foo_work(unsigned long n);
  int main(void)
  {
        printf("%lu\n", foo_work(1000));
        return 0;
  }
  EOF
  # gcc -g -O2 -shared -fPIC -o libfoo.so foo.c
  # gcc -g -O2 -o main main.c -L. -lfoo -Wl,-rpath,'$ORIGIN'
  # objcopy --only-keep-debug libfoo.so libfoo.so.debug
  # objcopy --strip-debug libfoo.so
  # objcopy --add-gnu-debuglink=libfoo.so.debug libfoo.so
  # perf record -e intel_pt//u ./main

Note that branch samples must be requested, because it is the resolving of the branch target symbol that causes dso__load() to be called, and hence the binary type to be set, before the decoder walks the code. With '--itrace=e' alone, nothing loads symbols for libfoo.so, the binary type is left as DSO_BINARY_TYPE__NOT_FOUND, the correct file is read anyway, and no errors are reported either way.

Before:

  # perf.before script --itrace=be 2>&1 | grep "instruction trace error"
   instruction trace error type 1 time 2350.467489498 cpu 9 pid 75634 tid 75634 ip 0x77d48480718f code 6: Trace doesn't match instruction
   instruction trace error type 1 time 2350.467489832 cpu 9 pid 75634 tid 75634 ip 0x77d484807341 code 6: Trace doesn't match instruction
   instruction trace error type 1 time 2350.467496412 cpu 9 pid 75634 tid 75634 ip 0x5b4de37a8074 code 6: Trace doesn't match instruction
   instruction trace error type 1 time 2350.467593393 cpu 9 pid 75634 tid 75634 ip 0x77d4848070d0 code 6: Trace doesn't match instruction
   instruction trace error type 1 time 2350.467593954 cpu 9 pid 75634 tid 75634 ip 0x77d4848075a8 code 6: Trace doesn't match instruction
   instruction trace error type 1 time 2350.467595728 cpu 9 pid 75634 tid 75634 ip 0x77d4848324de code 6: Trace doesn't match instruction
  6 instruction trace errors

After:

  # perf script --itrace=be 2>&1 | grep "instruction trace error"
  #
---
 tools/perf/util/symbol.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
tools/perf/util/symbol.c +10 -1
index 35104a56d8e38..1de5796fc4ff6 100644
@@ -1947,7 +1947,16 @@ int dso__load(struct dso *dso, struct map *map)
 		if (next_slot) {
 			ss_pos++;
 
-			if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND)
+			/*
+			 * The binary type is used to find the file containing
+			 * the executed instructions, so prefer the types that
+			 * refer to the actual object over debug-only files such
+			 * as DSO_BINARY_TYPE__DEBUGLINK.
+			 */
+			if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND ||
+			    symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE ||
+			    (symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_DSO &&
+			     dso__binary_type(dso) != DSO_BINARY_TYPE__BUILD_ID_CACHE))
 				dso__set_binary_type(dso, symtab_type);
 
 			if (syms_ss && runtime_ss)
Signature · 1 line
2.53.0
author maintainer
#78 lore raw

PATCH 78/733 OPP: of: Fix potential multiplication overflow when calculating freq

In reply to Greg Kroah-Hartman

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

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

From: Colin Ian King <[email protected]>

[ Upstream commit e11811a552252740bd396ec38378e9570ee16578 ]

The multiplication be32_to_cpup(val++) * 1000 is performed using 32 bit unsigned integers and hence uses a 32 bit multiplication; this will overflow if be32_to_cpup(val++) is greater than 4294967 (which is very unlikely at present). The result is assigned to an unsigned long (which is a 64 bit value on 64 bit systems), so fix this potential overflow by casting the first operand of the multiplication to an unsigned int.

Fixes b496dfbc94ab ("PM / OPP: Initialize OPP table from device tree")
---
 drivers/opp/of.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/opp/of.c +1 -1
index c02e20632fa64..9c4fd1f0e944a 100644
@@ -1039,7 +1039,7 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
 
 	val = prop->value;
 	while (nr) {
-		unsigned long freq = be32_to_cpup(val++) * 1000;
+		unsigned long freq = (unsigned long)be32_to_cpup(val++) * 1000;
 		unsigned long volt = be32_to_cpup(val++);
 		struct dev_pm_opp_data data = {
 			.freq = freq,
Signature · 1 line
2.53.0
author maintainer
#79 lore raw

PATCH 79/733 perf powerpc-vpadtl: Fix raw_size of DTL samples

In reply to Greg Kroah-Hartman

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

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

From: Wang Yan <[email protected]>

[ Upstream commit aadea57f532882d8bab444646863c7ef8a778ff1 ]

In powerpc_vpadtl_sample(), raw_data of the synthetic sample points to a struct powerpc_vpadtl_entry (48 bytes), but raw_size is set to sizeof(record). record is a struct powerpc_vpadtl_entry pointer, so sizeof(record) is the size of the pointer (8 bytes on 64-bit) rather than the size of the record itself.

As a result, consumers that bound their access to raw_data by raw_size only see or copy the first 8 bytes of each DTL entry instead of the full record.

Use sizeof(*record) so that raw_size reflects the actual length of the raw data.

Fixes 8644834a482a ("perf powerpc: Process the DTL entries in queue and deliver samples")
---
 tools/perf/util/powerpc-vpadtl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/powerpc-vpadtl.c +1 -1
index 710f3093f3f90..af6783cfdb53d 100644
@@ -196,7 +196,7 @@ static int powerpc_vpadtl_sample(struct powerpc_vpadtl_entry *record,
 	sample.cpumode = PERF_RECORD_MISC_KERNEL;
 	sample.time = save;
 	sample.raw_data = record;
-	sample.raw_size = sizeof(record);
+	sample.raw_size = sizeof(*record);
 	event.sample.header.type = PERF_RECORD_SAMPLE;
 	event.sample.header.misc = sample.cpumode;
 	event.sample.header.size = sizeof(struct perf_event_header);
Signature · 1 line
2.53.0
author maintainer
#80 lore raw

PATCH 80/733 netfs: Fix unbuffered/DIO write partial transfer error return

In reply to Greg Kroah-Hartman

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

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

From: David Howells <[email protected]>

[ Upstream commit c753a33664e4e86246f7491a93d9a77c1a673b5d ]

Fix unbuffered/DIO write to return the amount of data transferred in preference to an error if a partial transfer has been achieved, and to prefer an error stashed in the request over the one returned by netfs_unbuffered_write() (likely -EINTR or -ERESTARTSYS).

---
 fs/netfs/direct_write.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)
fs/netfs/direct_write.c +5 -7
index c16fbad286a17..d53b42ceadd23 100644
@@ -139,13 +139,11 @@ static int netfs_unbuffered_write(struct netfs_io_request *wreq)
 		if (test_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) {
 			retry = true;
 		} else if (test_bit(NETFS_SREQ_FAILED, &subreq->flags)) {
-			ret = subreq->error;
-			wreq->error = ret;
+			wreq->error = subreq->error;
 			netfs_see_subrequest(subreq, netfs_sreq_trace_see_failed);
 			subreq = NULL;
 			break;
 		}
-		ret = 0;
 
 		if (!retry) {
 			netfs_unbuffered_write_collect(wreq, stream, subreq);
@@ -288,11 +286,11 @@ ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *
 		ret = -EIOCBQUEUED;
 	} else {
 		ret = netfs_unbuffered_write(wreq);
-		if (ret < 0) {
-			_debug("begin = %zd", ret);
-		} else {
+		if (wreq->transferred) {
 			iocb->ki_pos += wreq->transferred;
-			ret = wreq->transferred ?: wreq->error;
+			ret = wreq->transferred;
+		} else if (wreq->error) {
+			ret = wreq->error;
 		}
 
 		netfs_put_request(wreq, netfs_rreq_trace_put_complete);
Signature · 1 line
2.53.0
author maintainer
#81 lore raw

PATCH 81/733 netfs: Fix error vs transferred passed to ->ki_complete()

In reply to Greg Kroah-Hartman

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

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

From: David Howells <[email protected]>

[ Upstream commit 0bfe2571a6af653611860d0e24c4e4c83bae7a54 ]

Fix netfs_unbuffered_write_done() to pass the amount written to ->ki_complete() rather than the error in the event of a partially complete transfer.

---
 fs/netfs/direct_write.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/netfs/direct_write.c +1 -1
index d53b42ceadd23..e563532c2e598 100644
@@ -51,7 +51,7 @@ static void netfs_unbuffered_write_done(struct netfs_io_request *wreq)
 		wreq->iocb->ki_pos += written;
 		if (wreq->iocb->ki_complete) {
 			trace_netfs_rreq(wreq, netfs_rreq_trace_ki_complete);
-			wreq->iocb->ki_complete(wreq->iocb, wreq->error ?: written);
+			wreq->iocb->ki_complete(wreq->iocb, written ?: wreq->error);
 		}
 		wreq->iocb = VFS_PTR_POISON;
 	}
Signature · 1 line
2.53.0
author maintainer
#82 lore raw

PATCH 82/733 netfs: Fix i_size update for partial transfer

In reply to Greg Kroah-Hartman

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

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

From: David Howells <[email protected]>

[ Upstream commit 741416a8003b77e636dafade408f808d96ac3f47 ]

Fix netfs_unbuffered_write_done() to pass the amount written to netfs_update_i_size() in the event of a partial transfer that ends in an error.

That said, it might be better for the filesystem to mark the inode data as invalid and recheck it in case something like a network error occurred that prevented the reply from the server from being received.

---
 fs/netfs/direct_write.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/netfs/direct_write.c +1 -1
index e563532c2e598..e07e7850a5a21 100644
@@ -21,7 +21,7 @@ static void netfs_unbuffered_write_done(struct netfs_io_request *wreq)
 	/* Okay, declare that all I/O is complete. */
 	trace_netfs_rreq(wreq, netfs_rreq_trace_write_done);
 
-	if (!wreq->error)
+	if (wreq->transferred)
 		netfs_update_i_size(ictx, &ictx->inode, wreq->start, wreq->transferred);
 
 	if (wreq->origin == NETFS_DIO_WRITE &&
Signature · 1 line
2.53.0
author maintainer
#83 lore raw

PATCH 83/733 netfs: Fix subreq ref leak

In reply to Greg Kroah-Hartman

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

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

From: David Howells <[email protected]>

[ Upstream commit 3c30087e27598d9d359763e8be9bd3017fe08348 ]

Fix a subrequest ref leak in netfs_unbuffered_write() in the event that subreq->io_iter ends up zero length during preparation.

---
 fs/netfs/direct_write.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
fs/netfs/direct_write.c +7 -1
index e07e7850a5a21..86beeb337ed7f 100644
@@ -121,8 +121,14 @@ static int netfs_unbuffered_write(struct netfs_io_request *wreq)
 		}
 
 		iov_iter_truncate(&subreq->io_iter, wreq->len - wreq->transferred);
-		if (!iov_iter_count(&subreq->io_iter))
+		if (!iov_iter_count(&subreq->io_iter)) {
+			pr_warn("netfs: Unexpected zero-length iterator R=%08x\n",
+				wreq->debug_id);
+			__set_bit(NETFS_SREQ_FAILED, &subreq->flags);
+			netfs_write_subrequest_terminated(subreq, -EIO);
+			wreq->error = -EIO;
 			break;
+		}
 
 		subreq->len = netfs_limit_iter(&subreq->io_iter, 0,
 					       stream->sreq_max_len,
Signature · 1 line
2.53.0
author maintainer
#84 lore raw

PATCH 84/733 netfs: break unbuffered write when netfs_alloc_subrequest() fails

In reply to Greg Kroah-Hartman

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

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

From: Edward Adam Davis <[email protected]>

[ Upstream commit 8fb45a934661419c04a44d4cfea1e0df7dcf2805 ]

syzbot reported a null-ptr-deref below [1] following a fault injection in netfs_alloc_subrequest(). [0]

When netfs_alloc_subrequest() fails, subreq is NULL. Later, netfs_prepare_write() tries to initialize members of subreq(e.g., source), the issue in [1] is triggered.

Let's handle the error of netfs_prepare_write() properly.

[0]
FAULT_INJECTION: forcing a failure.
name failslab, interval 1, probability 0, space 0, times 0

Call Trace:
 netfs_alloc_subrequest+0x116/0x3f0
 netfs_prepare_write+0x76/0x7b0
 netfs_unbuffered_write+0x75c/0x2020
 netfs_unbuffered_write_iter_locked+0x7d6/0xa80
 netfs_unbuffered_write_iter+0x442/0x720
 v9fs_file_write_iter+0xbf/0x100
 vfs_write+0x6ac/0x1050

[1]

KASAN: null-ptr-deref in range [0x00000000000000a8-0x00000000000000af]
RIP: 0010:netfs_prepare_write+0xbc/0x7b0 fs/netfs/write_issue.c:173
Call Trace:
 netfs_unbuffered_write+0x75c/0x2020 fs/netfs/direct_write.c:111
 netfs_unbuffered_write_iter_locked+0x7d6/0xa80 fs/netfs/direct_write.c:290
 netfs_unbuffered_write_iter+0x442/0x720 fs/netfs/direct_write.c:382
 v9fs_file_write_iter+0xbf/0x100 fs/9p/vfs_file.c:409
 new_sync_write fs/read_write.c:595 [inline]
---
 fs/netfs/direct_write.c | 5 +++++
 fs/netfs/write_issue.c  | 2 ++
 2 files changed, 7 insertions(+)
fs/netfs/direct_write.c +5 -0
index 86beeb337ed7f..982b78d7bdb98 100644
@@ -110,6 +110,11 @@ static int netfs_unbuffered_write(struct netfs_io_request *wreq)
 		if (!subreq) {
 			netfs_prepare_write(wreq, stream, wreq->start + wreq->transferred);
 			subreq = stream->construct;
+			if (!subreq) {
+				wreq->error = -ENOMEM;
+				ret = -ENOMEM;
+				break;
+			}
 			stream->construct = NULL;
 		}
 
fs/netfs/write_issue.c +2 -0
index 2d9cfcd43658f..851f6f93ad45a 100644
@@ -170,6 +170,8 @@ void netfs_prepare_write(struct netfs_io_request *wreq,
 		rolling_buffer_make_space(&wreq->buffer, wreq->gfp);
 
 	subreq = netfs_alloc_subrequest(wreq);
+	if (!subreq)
+		return;
 	subreq->source		= stream->source;
 	subreq->start		= start;
 	subreq->stream_nr	= stream->stream_nr;
Signature · 1 line
2.53.0
author maintainer
#85 lore raw

PATCH 85/733 netfs: Fix readahead synchronisation issues by loading all folios upfront

In reply to Greg Kroah-Hartman

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

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

From: David Howells <[email protected]>

[ Upstream commit fed0b33e6c584986ba70018ec9f9787a98216e64 ]

There are some synchronisation issues that derive from the app thread adding more folios to the rolling buffer whilst the collector thread is looking at them or trying to clear them, such as determining the setting of front_folio_order when the next folio hasn't been added yet,

The reason for the rolling buffer approach is that loading the buffer upfront and then dropping all the refs just acquired is quite a slow operation, and loading progressively allows some of the cost to be deferred until after at least some of the I/O is started.

Instead, a better way is to load all the folios into the rolling buffer upfront - and then drop the refs later, once the I/O is in progress. (Even better would be for the refs not to be there at all.)

Fix this by changing the rolling buffer loader to load all the folios selected by the VM for readahead upfront into the folio queue. The folio queue is allocated a batch worth at a time as we don't know how many folios are involved (the readahead_control struct, alas, has a page count, not a folio count).

The folio refs acquired from readahead are then dropped in bulk once the first subrequest is dispatched as it's quite a slow operation. The collector waits for NETFS_RREQ_NEED_PUT_RA_REFS to be cleared so that it doesn't unlock folios before the xarray has been scanned for them.

This simplifies the buffer handling later and isn't noticeably slower as the xarray doesn't need to be modified and the folios are all already pre-locked.

---
 fs/netfs/buffered_read.c       | 101 ++++++++++++++++++++-------------
 fs/netfs/internal.h            |   1 +
 fs/netfs/misc.c                |  19 +++++++
 fs/netfs/read_collect.c        |   7 +++
 fs/netfs/read_retry.c          |   7 +++
 fs/netfs/rolling_buffer.c      |  81 ++++++++++++++++----------
 include/linux/netfs.h          |   1 +
 include/linux/rolling_buffer.h |   6 +-
 include/trace/events/netfs.h   |   3 +
 9 files changed, 154 insertions(+), 72 deletions(-)
fs/netfs/buffered_read.c +61 -40
index 7fdfa4f27e349..303fdce54fbaf 100644
@@ -54,6 +54,42 @@ static void netfs_rreq_expand(struct netfs_io_request *rreq,
 	}
 }
 
+/*
+ * Drop the folio refs acquired from the readahead API.
+ */
+static void netfs_bulk_drop_ra_refs(struct netfs_io_request *rreq)
+{
+	struct folio_batch fbatch;
+	struct folio *folio;
+	pgoff_t nr_pages = DIV_ROUND_UP(rreq->len, PAGE_SIZE);
+	pgoff_t first = rreq->start / PAGE_SIZE;
+	XA_STATE(xas, &rreq->mapping->i_pages, first);
+
+	folio_batch_init(&fbatch);
+
+	rcu_read_lock();
+
+	xas_for_each(&xas, folio,  first + nr_pages - 1) {
+		if (xas_retry(&xas, folio))
+			continue;
+
+		if (!folio_batch_add(&fbatch, folio))
+			folio_batch_release(&fbatch);
+	}
+
+	rcu_read_unlock();
+	folio_batch_release(&fbatch);
+	trace_netfs_rreq(rreq, netfs_rreq_trace_ra_put_ref);
+	clear_bit_unlock(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags);
+	wake_up(&rreq->waitq);
+}
+
+static void netfs_maybe_bulk_drop_ra_refs(struct netfs_io_request *rreq)
+{
+	if (test_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags))
+		netfs_bulk_drop_ra_refs(rreq);
+}
+
 /*
  * Begin an operation, and fetch the stored zero point value from the cookie if
  * available.
@@ -74,12 +110,8 @@ static int netfs_begin_cache_read(struct netfs_io_request *rreq, struct netfs_in
  *
  * Returns the limited size if successful and -ENOMEM if insufficient memory
  * available.
- *
- * [!] NOTE: This must be run in the same thread as ->issue_read() was called
- * in as we access the readahead_control struct.
  */
-static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *subreq,
-					   struct readahead_control *ractl)
+static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *subreq)
 {
 	struct netfs_io_request *rreq = subreq->rreq;
 	size_t rsize = subreq->len;
@@ -87,30 +119,6 @@ static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *subreq,
 	if (subreq->source == NETFS_DOWNLOAD_FROM_SERVER)
 		rsize = umin(rsize, rreq->io_streams[0].sreq_max_len);
 
-	if (ractl) {
-		/* If we don't have sufficient folios in the rolling buffer,
-		 * extract a folioq's worth from the readahead region at a time
-		 * into the buffer.  Note that this acquires a ref on each page
-		 * that we will need to release later - but we don't want to do
-		 * that until after we've started the I/O.
-		 */
-		struct folio_batch put_batch;
-
-		folio_batch_init(&put_batch);
-		while (rreq->submitted < subreq->start + rsize) {
-			ssize_t added;
-
-			added = rolling_buffer_load_from_ra(&rreq->buffer, ractl,
-							    &put_batch);
-			if (added < 0) {
-				folio_batch_release(&put_batch);
-				return added;
-			}
-			rreq->submitted += added;
-		}
-		folio_batch_release(&put_batch);
-	}
-
 	subreq->len = rsize;
 	if (unlikely(rreq->io_streams[0].sreq_max_segs)) {
 		size_t limit = netfs_limit_iter(&rreq->buffer.iter, 0, rsize,
@@ -208,8 +216,7 @@ static void netfs_issue_read(struct netfs_io_request *rreq,
  * slicing up the region to be read according to available cache blocks and
  * network rsize.
  */
-static void netfs_read_to_pagecache(struct netfs_io_request *rreq,
-				    struct readahead_control *ractl)
+static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
 {
 	unsigned long long start = rreq->start;
 	ssize_t size = rreq->len;
@@ -288,7 +295,7 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq,
 		break;
 
 	issue:
-		slice = netfs_prepare_read_iterator(subreq, ractl);
+		slice = netfs_prepare_read_iterator(subreq);
 		if (slice < 0) {
 			ret = slice;
 			netfs_cancel_read(subreq, ret);
@@ -302,6 +309,7 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq,
 		}
 
 		netfs_issue_read(rreq, subreq);
+		netfs_maybe_bulk_drop_ra_refs(rreq);
 
 		if (test_bit(NETFS_RREQ_PAUSE, &rreq->flags))
 			netfs_wait_for_paused_read(rreq);
@@ -339,7 +347,8 @@ void netfs_readahead(struct readahead_control *ractl)
 {
 	struct netfs_io_request *rreq;
 	struct netfs_inode *ictx = netfs_inode(ractl->mapping->host);
-	unsigned long long start = readahead_pos(ractl);
+	ssize_t added;
+	uoff_t start = readahead_pos(ractl);
 	size_t size = readahead_length(ractl);
 	int ret;
 
@@ -360,11 +369,23 @@ void netfs_readahead(struct readahead_control *ractl)
 
 	netfs_rreq_expand(rreq, ractl);
 
-	rreq->submitted = rreq->start;
-	if (rolling_buffer_init(&rreq->buffer, rreq->debug_id, ITER_DEST, rreq->gfp) < 0)
+	/* Load the folios to be read into a bvecq chain.  Note that this
+	 * acquires a ref on each folio that we will need to release later -
+	 * but we don't want to do that until after we've started the I/O.
+	 */
+	added = rolling_buffer_bulk_load_from_ra(&rreq->buffer, ractl,
+						 rreq->debug_id, rreq->gfp);
+	if (added < 0) {
+		ret = added;
 		goto cleanup_free;
-	netfs_read_to_pagecache(rreq, ractl);
+	}
+	__set_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags);
+
+	rreq->submitted = rreq->start + added;
+	rreq->cleaned_to = rreq->start;
 
+	netfs_read_to_pagecache(rreq);
+	netfs_maybe_bulk_drop_ra_refs(rreq);
 	return netfs_put_request(rreq, netfs_rreq_trace_put_return);
 
 cleanup_free:
@@ -457,7 +478,7 @@ static int netfs_read_gaps(struct file *file, struct folio *folio)
 	iov_iter_bvec(&rreq->buffer.iter, ITER_DEST, bvec, i, rreq->len);
 	rreq->submitted = rreq->start + flen;
 
-	netfs_read_to_pagecache(rreq, NULL);
+	netfs_read_to_pagecache(rreq);
 
 	ret = netfs_wait_for_read(rreq);
 	if (ret >= 0) {
@@ -532,7 +553,7 @@ int netfs_read_folio(struct file *file, struct folio *folio)
 	if (ret < 0)
 		goto discard;
 
-	netfs_read_to_pagecache(rreq, NULL);
+	netfs_read_to_pagecache(rreq);
 	ret = netfs_wait_for_read(rreq);
 	netfs_put_request(rreq, netfs_rreq_trace_put_return);
 	return ret < 0 ? ret : 0;
@@ -689,7 +710,7 @@ int netfs_write_begin(struct netfs_inode *ctx,
 	if (ret < 0)
 		goto error_put;
 
-	netfs_read_to_pagecache(rreq, NULL);
+	netfs_read_to_pagecache(rreq);
 	ret = netfs_wait_for_read(rreq);
 	netfs_put_request(rreq, netfs_rreq_trace_put_return);
 	if (ret < 0)
@@ -754,7 +775,7 @@ int netfs_prefetch_for_write(struct file *file, struct folio *folio,
 	if (ret < 0)
 		goto error_put;
 
-	netfs_read_to_pagecache(rreq, NULL);
+	netfs_read_to_pagecache(rreq);
 	ret = netfs_wait_for_read(rreq);
 	netfs_put_request(rreq, netfs_rreq_trace_put_return);
 	return ret < 0 ? ret : 0;
fs/netfs/internal.h +1 -0
index 420ee7b26580f..bd8b2d633f968 100644
@@ -79,6 +79,7 @@ ssize_t netfs_wait_for_read(struct netfs_io_request *rreq);
 ssize_t netfs_wait_for_write(struct netfs_io_request *rreq);
 void netfs_wait_for_paused_read(struct netfs_io_request *rreq);
 void netfs_wait_for_paused_write(struct netfs_io_request *rreq);
+void netfs_wait_for_put_ra_refs(struct netfs_io_request *rreq);
 
 /*
  * objects.c
fs/netfs/misc.c +19 -0
index 5d554512ed23a..f5c1c463f4ff7 100644
@@ -563,3 +563,22 @@ void netfs_wait_for_paused_write(struct netfs_io_request *rreq)
 {
 	return netfs_wait_for_pause(rreq, netfs_write_collection);
 }
+
+/*
+ * Wait for the readahead-acquired refs to be put.
+ */
+void netfs_wait_for_put_ra_refs(struct netfs_io_request *rreq)
+{
+	DEFINE_WAIT(myself);
+
+	for (;;) {
+		trace_netfs_rreq(rreq, netfs_rreq_trace_wait_put_ra_refs);
+		prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE);
+		if (!test_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags))
+			break;
+		schedule();
+	}
+
+	trace_netfs_rreq(rreq, netfs_rreq_trace_waited_put_ra_refs);
+	finish_wait(&rreq->waitq, &myself);
+}
fs/netfs/read_collect.c +7 -0
index 23660a5901246..edf7cea7e2f91 100644
@@ -118,6 +118,13 @@ static void netfs_read_unlock_folios(struct netfs_io_request *rreq,
 		slot = 0;
 	}
 
+	/* We have to wait for readahead refs to have been released before we
+	 * can unlock any folios as the ref-dropper walks i_pages and the only
+	 * thing preventing these folios from being removed is the folio lock.
+	 */
+	if (test_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags))
+		netfs_wait_for_put_ra_refs(rreq);
+
 	for (;;) {
 		struct folio *folio;
 		unsigned long long fpos, fend;
fs/netfs/read_retry.c +7 -0
index 2b42758e01ec9..dd463a485139c 100644
@@ -292,6 +292,13 @@ void netfs_unlock_abandoned_read_pages(struct netfs_io_request *rreq)
 {
 	struct folio_queue *p;
 
+	/* We have to wait for readahead refs to have been released before we
+	 * can unlock any folios as the ref-dropper walks i_pages and the only
+	 * thing preventing these folios from being removed is the folio lock.
+	 */
+	if (test_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags))
+		netfs_wait_for_put_ra_refs(rreq);
+
 	for (p = rreq->buffer.tail; p; p = p->next) {
 		for (int slot = 0; slot < folioq_count(p); slot++) {
 			struct folio *folio = folioq_folio(p, slot);
fs/netfs/rolling_buffer.c +52 -29

94 lines not on this page · raw message

include/linux/netfs.h +1 -0
index d0b62d53eea99..e60539f039f19 100644
@@ -279,6 +279,7 @@ struct netfs_io_request {
 #define NETFS_RREQ_FOLIO_COPY_TO_CACHE	10	/* Copy current folio to cache from read */
 #define NETFS_RREQ_UPLOAD_TO_SERVER	11	/* Need to write to the server */
 #define NETFS_RREQ_USE_IO_ITER		12	/* Use ->io_iter rather than ->i_pages */
+#define NETFS_RREQ_NEED_PUT_RA_REFS	17	/* Need to put the folio refs RA gave us */
 #define NETFS_RREQ_USE_PGPRIV2		31	/* [DEPRECATED] Use PG_private_2 to mark
 						 * write to cache on read */
 	const struct netfs_request_ops *netfs_ops;
include/linux/rolling_buffer.h +3 -3
index 9e5dad29669cf..a97f7cfaacaad 100644
@@ -45,9 +45,9 @@ struct rolling_buffer_snapshot {
 int rolling_buffer_init(struct rolling_buffer *roll, unsigned int rreq_id,
 			unsigned int direction, gfp_t gfp);
 int rolling_buffer_make_space(struct rolling_buffer *roll, gfp_t gfp);
-ssize_t rolling_buffer_load_from_ra(struct rolling_buffer *roll,
-				    struct readahead_control *ractl,
-				    struct folio_batch *put_batch);
+ssize_t rolling_buffer_bulk_load_from_ra(struct rolling_buffer *roll,
+					 struct readahead_control *ractl,
+					 unsigned int rreq_id, gfp_t gfp);
 ssize_t rolling_buffer_append(struct rolling_buffer *roll, struct folio *folio,
 			      unsigned int flags, gfp_t gfp);
 struct folio_queue *rolling_buffer_delete_spent(struct rolling_buffer *roll);
include/trace/events/netfs.h +3 -0
index 082cb03c61316..9bda9302be90c 100644
@@ -59,6 +59,7 @@
 	EM(netfs_rreq_trace_free,		"FREE   ")	\
 	EM(netfs_rreq_trace_intr,		"INTR   ")	\
 	EM(netfs_rreq_trace_ki_complete,	"KI-CMPL")	\
+	EM(netfs_rreq_trace_ra_put_ref,		"RA-PUT ")	\
 	EM(netfs_rreq_trace_recollect,		"RECLLCT")	\
 	EM(netfs_rreq_trace_redirty,		"REDIRTY")	\
 	EM(netfs_rreq_trace_resubmit,		"RESUBMT")	\
@@ -70,9 +71,11 @@
 	EM(netfs_rreq_trace_unpause,		"UNPAUSE")	\
 	EM(netfs_rreq_trace_wait_ip,		"WAIT-IP")	\
 	EM(netfs_rreq_trace_wait_pause,		"--PAUSED--")	\
+	EM(netfs_rreq_trace_wait_put_ra_refs,	"WAIT-P-RA")	\
 	EM(netfs_rreq_trace_wait_quiesce,	"WAIT-QUIESCE")	\
 	EM(netfs_rreq_trace_waited_ip,		"DONE-IP")	\
 	EM(netfs_rreq_trace_waited_pause,	"--UNPAUSED--")	\
+	EM(netfs_rreq_trace_waited_put_ra_refs,	"DONE-P-RA")	\
 	EM(netfs_rreq_trace_waited_quiesce,	"DONE-QUIESCE")	\
 	EM(netfs_rreq_trace_wake_ip,		"WAKE-IP")	\
 	EM(netfs_rreq_trace_wake_queue,		"WAKE-Q ")	\
Signature · 1 line
2.53.0
author maintainer
#86 lore raw

PATCH 86/733 netfs: Mark folios with COPY_TO_CACHE whilst issuing subreqs

In reply to Greg Kroah-Hartman

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

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

From: David Howells <[email protected]>

[ Upstream commit 533203c4183123dad8ffecd694e7573a0ccd0da0 ]

Mark folios with NETFS_FOLIO_COPY_TO_CACHE whilst issuing subreqs rather than when collecting them. This means that the collector thread doesn't have to try and keep track of which subreqs contribute to which folios - and thus which folios will need to be copied to the cache because at least one byte wasn't in the cache. Instead, this is marked on the folios up front and the collector need only consider the folios.

For PG_private_2-using filesystems, PG_private_2 is set instead of NETFS_FOLIO_COPY_TO_CACHE, but otherwise it works the same.

The NETFS_RREQ_COPY_TO_CACHE is replaced with NETFS_RREQ_CANCEL_CACHING, which is now set if caching fails somewhere, thereby causing the collection thread to cancel the copy-to-cache marks on the remaining folios.

Stable-dep-of: e00827a4d0cf ("netfs: Fix read progress reporting")

---
 fs/netfs/buffered_read.c     | 61 +++++++++++++++++++++++++++++++-
 fs/netfs/internal.h          |  1 +
 fs/netfs/read_collect.c      | 67 ++++++++++++++++++++++--------------
 fs/netfs/read_pgpriv2.c      | 15 ++++----
 fs/netfs/read_retry.c        |  6 +++-
 include/linux/netfs.h        |  2 +-
 include/trace/events/netfs.h |  6 ++--
 7 files changed, 121 insertions(+), 37 deletions(-)
fs/netfs/buffered_read.c +60 -1
index 303fdce54fbaf..16d4db776f6ae 100644
@@ -211,6 +211,56 @@ static void netfs_issue_read(struct netfs_io_request *rreq,
 	}
 }
 
+/*
+ * Mark folios that we want to copy to the cache.  For filesystems that use
+ * netfslib fully, we set folio->private to NETFS_FOLIO_COPY_TO_CACHE;
+ * otherwise we set the deprecated PG_private_2.
+ */
+static void netfs_mark_copy_to_cache(struct netfs_io_request *rreq,
+				     struct folio_queue **fq,
+				     unsigned int *offset,
+				     int *slot,
+				     size_t len,
+				     bool copy)
+{
+	while (len > 0) {
+		struct folio *folio;
+		size_t fsize, overlap;
+
+		if (!*fq)
+			break;
+		if (*slot >= folioq_count(*fq)) {
+			*fq = (*fq)->next;
+			*slot = 0;
+			*offset = 0;
+			continue;
+		}
+
+		/* Determine how much the subreq overlaps the folio, if at all. */
+		fsize = folioq_folio_size(*fq, *slot);
+		overlap = min(len, fsize - *offset);
+
+		if (overlap > 0 && copy) {
+			folio = folioq_folio(*fq, *slot);
+			if (unlikely(test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags))) {
+				if (!folio_test_private_2(folio))
+					folio_start_private_2(folio);
+			} else {
+				if (!folio_get_private(folio))
+					folio_attach_private(folio, NETFS_FOLIO_COPY_TO_CACHE);
+			}
+			trace_netfs_folio(folio, netfs_folio_trace_mark_copy);
+		}
+
+		len -= overlap;
+		*offset += overlap;
+		if (*offset >= fsize) {
+			*slot += 1;
+			*offset = 0;
+		}
+	}
+}
+
 /*
  * Perform a read to the pagecache from a series of sources of different types,
  * slicing up the region to be read according to available cache blocks and
@@ -218,9 +268,11 @@ static void netfs_issue_read(struct netfs_io_request *rreq,
  */
 static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
 {
+	struct folio_queue *fq = rreq->buffer.tail;
 	unsigned long long start = rreq->start;
+	unsigned int offset = 0;
 	ssize_t size = rreq->len;
-	int ret = 0;
+	int ret = 0, slot = 0;
 
 	do {
 		struct netfs_io_subrequest *subreq;
@@ -308,6 +360,13 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
 			set_bit(NETFS_RREQ_ALL_QUEUED, &rreq->flags);
 		}
 
+		if (fq) {
+			/* See if the cache indicated this should be cached. */
+			bool copy = test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags);
+
+			netfs_mark_copy_to_cache(rreq, &fq, &slot, &offset, slice, copy);
+		}
+
 		netfs_issue_read(rreq, subreq);
 		netfs_maybe_bulk_drop_ra_refs(rreq);
 
fs/netfs/internal.h +1 -0
index bd8b2d633f968..dfe7939f35f37 100644
@@ -110,6 +110,7 @@ static inline void netfs_see_subrequest(struct netfs_io_subrequest *subreq,
 /*
  * read_collect.c
  */
+void netfs_cancel_copy_to_cache(struct netfs_io_request *rreq, struct folio *folio);
 bool netfs_read_collection(struct netfs_io_request *rreq);
 void netfs_read_collection_worker(struct work_struct *work);
 void netfs_cancel_read(struct netfs_io_subrequest *subreq, int error);
fs/netfs/read_collect.c +41 -26

117 lines not on this page · raw message

fs/netfs/read_pgpriv2.c +9 -6
index c31190993b762..a4b7bb88cbdb6 100644
@@ -54,8 +54,8 @@ static void netfs_pgpriv2_copy_folio(struct netfs_io_request *creq, struct folio
 
 	/* Attach the folio to the rolling buffer. */
 	if (rolling_buffer_append(&creq->buffer, folio, 0, creq->gfp) < 0) {
+		set_bit(NETFS_RREQ_CANCEL_CACHING, &creq->flags);
 		folio_end_private_2(folio);
-		clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &creq->flags);
 		return;
 	}
 
@@ -122,13 +122,14 @@ static struct netfs_io_request *netfs_pgpriv2_begin_copy_to_cache(
 	netfs_put_failed_request(creq);
 cancel:
 	rreq->copy_to_cache = ERR_PTR(-ENOBUFS);
-	clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags);
+	set_bit(NETFS_RREQ_CANCEL_CACHING, &rreq->flags);
 	return ERR_PTR(-ENOBUFS);
 }
 
 /*
  * [DEPRECATED] Mark page as requiring copy-to-cache using PG_private_2 and add
- * it to the copy write request.
+ * it to the copy write request.  PG_private_2 should already be set on the
+ * folio.
  */
 void netfs_pgpriv2_copy_to_cache(struct netfs_io_request *rreq, struct folio *folio)
 {
@@ -136,11 +137,13 @@ void netfs_pgpriv2_copy_to_cache(struct netfs_io_request *rreq, struct folio *fo
 
 	if (!creq)
 		creq = netfs_pgpriv2_begin_copy_to_cache(rreq, folio);
-	if (IS_ERR(creq))
+	if (IS_ERR(creq)) {
+		set_bit(NETFS_RREQ_CANCEL_CACHING, &rreq->flags);
+		netfs_cancel_copy_to_cache(rreq, folio);
 		return;
+	}
 
-	trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache);
-	folio_start_private_2(folio);
+	trace_netfs_folio(folio, netfs_folio_trace_pgpriv2_copy);
 	netfs_pgpriv2_copy_folio(creq, folio);
 }
 
fs/netfs/read_retry.c +5 -1
index dd463a485139c..4f6a36c6e214f 100644
@@ -303,7 +303,11 @@ void netfs_unlock_abandoned_read_pages(struct netfs_io_request *rreq)
 		for (int slot = 0; slot < folioq_count(p); slot++) {
 			struct folio *folio = folioq_folio(p, slot);
 
-			if (folio && !folioq_is_marked2(p, slot)) {
+			if (!folio)
+				continue;
+			netfs_cancel_copy_to_cache(rreq, folio);
+
+			if (!folioq_is_marked2(p, slot)) {
 				if (folio == rreq->no_unlock_folio &&
 				    test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO,
 					     &rreq->flags)) {
include/linux/netfs.h +1 -1
index e60539f039f19..029456e034849 100644
@@ -276,7 +276,7 @@ struct netfs_io_request {
 #define NETFS_RREQ_SHORT_TRANSFER	5	/* Set if we have a short transfer */
 #define NETFS_RREQ_OFFLOAD_COLLECTION	8	/* Offload collection to workqueue */
 #define NETFS_RREQ_NO_UNLOCK_FOLIO	9	/* Don't unlock no_unlock_folio on completion */
-#define NETFS_RREQ_FOLIO_COPY_TO_CACHE	10	/* Copy current folio to cache from read */
+#define NETFS_RREQ_CANCEL_CACHING	10	/* Set to cancel caching */
 #define NETFS_RREQ_UPLOAD_TO_SERVER	11	/* Need to write to the server */
 #define NETFS_RREQ_USE_IO_ITER		12	/* Use ->io_iter rather than ->i_pages */
 #define NETFS_RREQ_NEED_PUT_RA_REFS	17	/* Need to put the folio refs RA gave us */
include/trace/events/netfs.h +4 -2
index 9bda9302be90c..a22084813cb59 100644
@@ -198,7 +198,6 @@
 	EM(netfs_folio_trace_clear_cc,		"clear-cc")	\
 	EM(netfs_folio_trace_clear_g,		"clear-g")	\
 	EM(netfs_folio_trace_clear_s,		"clear-s")	\
-	EM(netfs_folio_trace_copy_to_cache,	"mark-copy")	\
 	EM(netfs_folio_trace_end_copy,		"end-copy")	\
 	EM(netfs_folio_trace_filled_gaps,	"filled-gaps")	\
 	EM(netfs_folio_trace_invalidate_all,	"inval-all")	\
@@ -209,16 +208,19 @@
 	EM(netfs_folio_trace_kill_cc,		"kill-cc")	\
 	EM(netfs_folio_trace_kill_g,		"kill-g")	\
 	EM(netfs_folio_trace_kill_s,		"kill-s")	\
+	EM(netfs_folio_trace_mark_copy,		"mark-copy")	\
 	EM(netfs_folio_trace_mkwrite,		"mkwrite")	\
 	EM(netfs_folio_trace_mkwrite_plus,	"mkwrite+")	\
-	EM(netfs_folio_trace_not_under_wback,	"!wback")	\
 	EM(netfs_folio_trace_not_locked,	"!locked")	\
+	EM(netfs_folio_trace_not_under_wback,	"!wback")	\
+	EM(netfs_folio_trace_pgpriv2_copy,	"pgpriv2-copy")	\
 	EM(netfs_folio_trace_put,		"put")		\
 	EM(netfs_folio_trace_read,		"read")		\
 	EM(netfs_folio_trace_read_done,		"read-done")	\
 	EM(netfs_folio_trace_read_gaps,		"read-gaps")	\
 	EM(netfs_folio_trace_read_unlock,	"read-unlock")	\
 	EM(netfs_folio_trace_redirtied,		"redirtied")	\
+	EM(netfs_folio_trace_sched_copy,	"sched-copy")	\
 	EM(netfs_folio_trace_store,		"store")	\
 	EM(netfs_folio_trace_store_copy,	"store-copy")	\
 	EM(netfs_folio_trace_store_plus,	"store+")	\
Signature · 1 line
2.53.0
author maintainer
#87 lore raw

PATCH 87/733 netfs: Fix read progress reporting

In reply to Greg Kroah-Hartman

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

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

From: David Howells <[email protected]>

[ Upstream commit e00827a4d0cfebf8d78dfd0a9a024237f57c9273 ]

For really big read RPC ops that span multiple folios, netfslib allows the filesystem to give progress notifications to wake up the collector thread to do a collection of folios that have now been fetched, even if the RPC is still ongoing, thereby allowing the application to make progress.

This works by taking the current rreq->cleaned_to value (which indicates which folios have been unlocked) and adding the stashed size of the next folio to it. cleaned_to, however, is subject to 64-bit tearing on a 32-bit arch.

Fix this by stashing the next progress notification point as a size_t (which won't tear) to be added to rreq->start (which won't change), with the collector thread calculating that from cleaned_to plus the next folio size.

Further, however, if the folios are small, the collector thread gets constantly woken up - which has a negative performance impact on the system.

Fix that too by setting a minimum trigger of 256KiB or the size of the folio at the front of the queue, whichever is larger. Note that this has an issue that different subreqs have different need-to-be-cached properties; this is solved by a preceding patch that marks the property on the folios whilst issuing subreqs rather than when collecting them.

Also, make sure rreq->cleaned_to is initialised up front, along with rreq->collected_to and stream->collected_to.

---
 fs/netfs/buffered_read.c     |  2 ++
 fs/netfs/internal.h          |  1 +
 fs/netfs/objects.c           | 32 +++++++++++++--------
 fs/netfs/read_collect.c      | 54 ++++++++++++++++++++++++++++--------
 fs/netfs/read_single.c       |  2 ++
 include/linux/netfs.h        |  2 +-
 include/trace/events/netfs.h | 21 ++++++++++++++
 7 files changed, 89 insertions(+), 25 deletions(-)
fs/netfs/buffered_read.c +2 -0
index 16d4db776f6ae..424df70a5c30f 100644
@@ -442,6 +442,7 @@ void netfs_readahead(struct readahead_control *ractl)
 
 	rreq->submitted = rreq->start + added;
 	rreq->cleaned_to = rreq->start;
+	netfs_read_set_unlock_at(rreq);
 
 	netfs_read_to_pagecache(rreq);
 	netfs_maybe_bulk_drop_ra_refs(rreq);
@@ -467,6 +468,7 @@ static int netfs_create_singular_buffer(struct netfs_io_request *rreq, struct fo
 	if (added < 0)
 		return added;
 	rreq->submitted = rreq->start + added;
+	rreq->progress_at = added;
 	return 0;
 }
 
fs/netfs/internal.h +1 -0
index dfe7939f35f37..c79c8e69d60ca 100644
@@ -111,6 +111,7 @@ static inline void netfs_see_subrequest(struct netfs_io_subrequest *subreq,
  * read_collect.c
  */
 void netfs_cancel_copy_to_cache(struct netfs_io_request *rreq, struct folio *folio);
+void netfs_read_set_unlock_at(struct netfs_io_request *rreq);
 bool netfs_read_collection(struct netfs_io_request *rreq);
 void netfs_read_collection_worker(struct work_struct *work);
 void netfs_cancel_read(struct netfs_io_subrequest *subreq, int error);
fs/netfs/objects.c +20 -12
index 01461a74642d6..7f6a3e912602e 100644
@@ -41,24 +41,32 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping,
 
 	memset(rreq, 0, kmem_cache_size(cache));
 	INIT_WORK(&rreq->cleanup_work, netfs_free_request);
-	rreq->gfp	= gfp;
-	rreq->start	= start;
-	rreq->len	= len;
-	rreq->origin	= origin;
-	rreq->netfs_ops	= ctx->ops;
-	rreq->mapping	= mapping;
-	rreq->inode	= inode;
-	rreq->i_size	= i_size_read(inode);
-	rreq->debug_id	= atomic_inc_return(&debug_ids);
-	rreq->wsize	= INT_MAX;
+	rreq->gfp		= gfp;
+	rreq->start		= start;
+	rreq->collected_to	= start;
+	rreq->cleaned_to	= start;
+	rreq->len		= len;
+	rreq->progress_at	= 0;
+	rreq->origin		= origin;
+	rreq->netfs_ops		= ctx->ops;
+	rreq->mapping		= mapping;
+	rreq->inode		= inode;
+	rreq->i_size		= i_size_read(inode);
+	rreq->debug_id		= atomic_inc_return(&debug_ids);
+	rreq->wsize		= INT_MAX;
 	rreq->io_streams[0].sreq_max_len = ULONG_MAX;
 	rreq->io_streams[0].sreq_max_segs = 0;
 	spin_lock_init(&rreq->lock);
-	INIT_LIST_HEAD(&rreq->io_streams[0].subrequests);
-	INIT_LIST_HEAD(&rreq->io_streams[1].subrequests);
 	init_waitqueue_head(&rreq->waitq);
 	refcount_set(&rreq->ref, 2);
 
+	for (int s = 0; s < NR_IO_STREAMS; s++) {
+		struct netfs_io_stream *stream = &rreq->io_streams[s];
+
+		INIT_LIST_HEAD(&stream->subrequests);
+		stream->collected_to = rreq->start;
+	}
+
 	if (origin == NETFS_READAHEAD ||
 	    origin == NETFS_READPAGE ||
 	    origin == NETFS_READ_GAPS ||
fs/netfs/read_collect.c +42 -12

111 lines not on this page · raw message

fs/netfs/read_single.c +2 -0
index 8833550d2eb60..de67ac41548d1 100644
@@ -170,6 +170,8 @@ ssize_t netfs_read_single(struct inode *inode, struct file *file, struct iov_ite
 	if (IS_ERR(rreq))
 		return PTR_ERR(rreq);
 
+	rreq->progress_at = rreq->len;
+
 	ret = netfs_single_begin_cache_read(rreq, ictx);
 	if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
 		goto cleanup_free;
include/linux/netfs.h +1 -1
index 029456e034849..67c2d9ef7c623 100644
@@ -247,6 +247,7 @@ struct netfs_io_request {
 	unsigned long long	submitted;	/* Amount submitted for I/O so far */
 	unsigned long long	len;		/* Length of the request */
 	size_t			transferred;	/* Amount to be indicated as transferred */
+	size_t			progress_at;	/* Report read progress when hit this much read */
 	long			error;		/* 0 or error that occurred */
 	unsigned long long	i_size;		/* Size of the file */
 	unsigned long long	start;		/* Start position */
@@ -263,7 +264,6 @@ struct netfs_io_request {
 	atomic_t		subreq_counter;	/* Next subreq->debug_index */
 	unsigned int		nr_group_rel;	/* Number of refs to release on ->group */
 	spinlock_t		lock;		/* Lock for queuing subreqs */
-	unsigned char		front_folio_order; /* Order (size) of front folio */
 	enum netfs_io_origin	origin;		/* Origin of the request */
 	bool			direct_bv_unpin; /* T if direct_bv[] must be unpinned */
 	refcount_t		ref;
include/trace/events/netfs.h +21 -0
index a22084813cb59..3fec3e8f91c85 100644
@@ -791,6 +791,27 @@ TRACE_EVENT(netfs_folioq,
 		      __print_symbolic(__entry->trace, netfs_folioq_traces))
 	    );
 
+TRACE_EVENT(netfs_read_progress_at,
+	    TP_PROTO(const struct netfs_io_request *rreq),
+
+	    TP_ARGS(rreq),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int,	rreq)
+		    __field(size_t,		progress_at)
+		    __field(size_t,		cleaned_to)
+			     ),
+
+	    TP_fast_assign(
+		    __entry->rreq	= rreq->debug_id;
+		    __entry->cleaned_to	= rreq->cleaned_to - rreq->start;
+		    __entry->progress_at = rreq->progress_at;
+			   ),
+
+	    TP_printk("R=%08x cln=%zx prg=%zx",
+		      __entry->rreq, __entry->cleaned_to, __entry->progress_at)
+	    );
+
 #undef EM
 #undef E_
 #endif /* _TRACE_NETFS_H */
Signature · 1 line
2.53.0
author maintainer
#88 lore raw

PATCH 88/733 cachefiles: Fix potential UAF/KASAN warning

In reply to Greg Kroah-Hartman

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

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

From: David Howells <[email protected]>

[ Upstream commit a67632c8c2688d6e0091529bcefe54bc5ee80e9b ]

Currently, trace_cachefiles_coherency() is being passed a pointer to a __be64 lain over the coherency data in struct cachefiles_xattr so that it can display the first 8 bytes. However, the data is of variable length and could even be 0 bytes. This could lead to a UAF or KASAN warning.

Fix this by making sure the buffer has room for at least 8 bytes and that those 8 bytes are pre-cleared.

Further, those bytes are not 8-byte aligned, so fix the tracepoint to extract the data as four 2-byte words (they are 2-byte aligned) and reassemble the __be64. The compiler will convert this into a single 8-byte load where the CPU supports it.

---
 fs/cachefiles/xattr.c             | 16 ++++++++--------
 include/trace/events/cachefiles.h | 19 +++++++++++++++++--
 2 files changed, 25 insertions(+), 10 deletions(-)
fs/cachefiles/xattr.c +8 -8
index f8ae78b3f7b6d..c70bf67e52b01 100644
@@ -13,6 +13,7 @@
 #include <linux/quotaops.h>
 #include <linux/xattr.h>
 #include <linux/slab.h>
+#include <linux/unaligned.h>
 #include "internal.h"
 
 #define CACHEFILES_COOKIE_TYPE_DATA 1
@@ -50,7 +51,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
 
 	_enter("%x,#%d", object->debug_id, len);
 
-	buf = kmalloc(sizeof(struct cachefiles_xattr) + len, GFP_KERNEL);
+	buf = kmalloc(sizeof(struct cachefiles_xattr) + max(len, sizeof(__be64)), GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
@@ -60,6 +61,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
 	buf->content		= object->content_info;
 	if (test_bit(FSCACHE_COOKIE_LOCAL_WRITE, &object->cookie->flags))
 		buf->content	= CACHEFILES_CONTENT_DIRTY;
+	put_unaligned_be64(0, (__be64 *)buf->data);
 	if (len > 0)
 		memcpy(buf->data, fscache_get_aux(object->cookie), len);
 
@@ -77,8 +79,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
 		trace_cachefiles_vfs_error(object, file_inode(file), ret,
 					   cachefiles_trace_setxattr_error);
 		trace_cachefiles_coherency(object, file_inode(file)->i_ino,
-					   be64_to_cpup((__be64 *)buf->data),
-					   buf->content,
+					   buf->data, buf->content,
 					   cachefiles_coherency_set_fail);
 		if (ret != -ENOMEM)
 			cachefiles_io_error_obj(
@@ -86,8 +87,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
 				"Failed to set xattr with error %d", ret);
 	} else {
 		trace_cachefiles_coherency(object, file_inode(file)->i_ino,
-					   be64_to_cpup((__be64 *)buf->data),
-					   buf->content,
+					   buf->data, buf->content,
 					   cachefiles_coherency_set_ok);
 	}
 
@@ -110,9 +110,10 @@ int cachefiles_check_auxdata(struct cachefiles_object *object, struct file *file
 	int ret = -ESTALE;
 
 	tlen = sizeof(struct cachefiles_xattr) + len;
-	buf = kmalloc(tlen, GFP_KERNEL);
+	buf = kmalloc(sizeof(struct cachefiles_xattr) + max(len, sizeof(__be64)), GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
+	put_unaligned_be64(0, (__be64 *)buf->data);
 
 	xlen = cachefiles_inject_read_error();
 	if (xlen == 0)
@@ -148,8 +149,7 @@ int cachefiles_check_auxdata(struct cachefiles_object *object, struct file *file
 
 out:
 	trace_cachefiles_coherency(object, file_inode(file)->i_ino,
-				   be64_to_cpup((__be64 *)buf->data),
-				   buf->content, why);
+				   buf->data, buf->content, why);
 	kfree(buf);
 	return ret;
 }
include/trace/events/cachefiles.h +17 -2
index 6e3b1424eea4d..d002ed508a435 100644
@@ -380,7 +380,7 @@ TRACE_EVENT(cachefiles_rename,
 TRACE_EVENT(cachefiles_coherency,
 	    TP_PROTO(struct cachefiles_object *obj,
 		     ino_t ino,
-		     u64 disk_aux,
+		     const void *disk_aux,
 		     enum cachefiles_content content,
 		     enum cachefiles_coherency_trace why),
 
@@ -397,12 +397,27 @@ TRACE_EVENT(cachefiles_coherency,
 			     ),
 
 	    TP_fast_assign(
+		    union {
+			    __be16 s[4];
+			    __be64 ll;
+		    } x;
+
 		    __entry->obj	= obj->debug_id;
 		    __entry->why	= why;
 		    __entry->content	= content;
 		    __entry->ino	= ino;
 		    __entry->aux	= be64_to_cpup((__be64 *)obj->cookie->inline_aux);
-		    __entry->disk_aux	= disk_aux;
+
+		    /* cachefiles_xattr::data is 2-byte aligned but not 8-byte aligned. */
+		    if (disk_aux) {
+			    x.s[0] = ((__be16 *)disk_aux)[0];
+			    x.s[1] = ((__be16 *)disk_aux)[1];
+			    x.s[2] = ((__be16 *)disk_aux)[2];
+			    x.s[3] = ((__be16 *)disk_aux)[3];
+			    __entry->disk_aux = be64_to_cpu(x.ll);
+		    } else {
+			    __entry->disk_aux = 0;
+		    }
 			   ),
 
 	    TP_printk("o=%08x %s B=%llx c=%u aux=%llx dsk=%llx",
Signature · 1 line
2.53.0
author maintainer
#89 lore raw

PATCH 89/733 ALSA: pcm: Serialize PCM mmap with buffer reallocation to fix page UAF

In reply to Greg Kroah-Hartman

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

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

From: Yilin Zhang <[email protected]>

[ Upstream commit 9b110a9dcecc59516c77cb3c0caf1f492f75df2d ]

snd_pcm_hw_params() and snd_pcm_hw_free() guard buffer reallocation with an mmap_count check performed under the PCM stream lock, but the lock is released long before the buffer is actually freed:
snd_pcm_sync_stop(), constraint refinement and do_free_pages() all happen in between. snd_pcm_mmap_data(), on the other hand, takes no lock at all: it validates against the old buffer's state and dma_bytes, remaps its pages into the VMA, and only then increments mmap_count.

A concurrent mmap() can therefore slip in between the check and the free. remap_pfn_range() installs writable PTEs for the old buffer's pages without taking page references, and the subsequent do_free_pages() returns those pages to the page allocator while the VMA still maps them. This leaves a stale, writable mapping of freed
pages: a page-level use-after-free that can be leveraged for local privilege escalation.

Make snd_pcm_mmap_data() participate in the buffer-access scheme introduced for hw_params/hw_free: acquire runtime->buffer_accessing before validating and remapping, and release it afterwards. Buffer reallocation already fails with -EBUSY while accessors are active, and the mmap side now fails with -EBUSY while a reallocation is in progress, so the validate/remap sequence and the check/free sequence can no longer interleave.

A reproducer that turns this race into a stale writable mapping of the freed DMA buffer pages is available on request.

Fixes 92ee3c60ec9f ("ALSA: pcm: Fix races among concurrent hw_params and hw_free calls")
---
 sound/core/pcm_native.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)
sound/core/pcm_native.c +25 -10
index fa6723a6e8271..2fcdde09a0305 100644
@@ -4019,20 +4019,33 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
 			return -EINVAL;
 	}
 	runtime = substream->runtime;
-	if (runtime->state == SNDRV_PCM_STATE_OPEN)
-		return -EBADFD;
-	if (!(runtime->info & SNDRV_PCM_INFO_MMAP))
-		return -ENXIO;
+	/* don't race with buffer reallocation in hw_params/hw_free */
+	if (!atomic_inc_unless_negative(&runtime->buffer_accessing))
+		return -EBUSY;
+	if (runtime->state == SNDRV_PCM_STATE_OPEN) {
+		err = -EBADFD;
+		goto out;
+	}
+	if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) {
+		err = -ENXIO;
+		goto out;
+	}
 	if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
-	    runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
-		return -EINVAL;
+	    runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
+		err = -EINVAL;
+		goto out;
+	}
 	size = area->vm_end - area->vm_start;
 	offset = area->vm_pgoff << PAGE_SHIFT;
 	dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
-	if ((size_t)size > dma_bytes)
-		return -EINVAL;
-	if (offset > dma_bytes - size)
-		return -EINVAL;
+	if ((size_t)size > dma_bytes) {
+		err = -EINVAL;
+		goto out;
+	}
+	if (offset > dma_bytes - size) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	area->vm_ops = &snd_pcm_vm_ops_data;
 	area->vm_private_data = substream;
@@ -4042,6 +4055,8 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
 		err = snd_pcm_lib_default_mmap(substream, area);
 	if (!err)
 		atomic_inc(&substream->mmap_count);
+out:
+	atomic_dec(&runtime->buffer_accessing);
 	return err;
 }
 EXPORT_SYMBOL(snd_pcm_mmap_data);
Signature · 1 line
2.53.0
author maintainer
#90 lore raw

PATCH 90/733 dma-buf: fix some kernel-doc warnings

In reply to Greg Kroah-Hartman

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

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

From: Randy Dunlap <[email protected]>

[ Upstream commit c8329cb590df4a8b3a4e878d289d4b17824db8d1 ]

- drop Excess description of @lock from kernel-doc
- add missing function/macro short descriptions

WARNING: include/linux/dma-fence-array.h:47 Excess struct member 'lock' description in 'dma_fence_array'
WARNING: include/linux/dma-fence-chain.h:48 Excess struct member 'lock' description in 'dma_fence_chain'

Warning: include/linux/dma-fence-chain.h:82 missing initial short description on line:
* dma_fence_chain_alloc
Warning: include/linux/dma-fence-chain.h:94 missing initial short description on line:
* dma_fence_chain_free

Fixes 5943243914b9 ("dma-buf: use inline lock for the dma-fence-array")
Fixes a408c0ca0c41 ("dma-buf: use inline lock for the dma-fence-chain")
---
 include/linux/dma-fence-array.h | 1 -
 include/linux/dma-fence-chain.h | 9 ++++-----
 2 files changed, 4 insertions(+), 6 deletions(-)
include/linux/dma-fence-array.h +0 -1
index 1b1d87579c382..0c49d7ccefb64 100644
@@ -28,7 +28,6 @@ struct dma_fence_array_cb {
 /**
  * struct dma_fence_array - fence to represent an array of fences
  * @base: fence base class
- * @lock: spinlock for fence handling
  * @num_fences: number of fences in the array
  * @num_pending: fences in the array still pending
  * @fences: array of the fences
include/linux/dma-fence-chain.h +4 -5
index df3beadf15157..705c4394ac0d0 100644
@@ -20,7 +20,6 @@
  * @prev: previous fence of the chain
  * @prev_seqno: original previous seqno before garbage collection
  * @fence: encapsulated fence
- * @lock: spinlock for fence handling
  */
 struct dma_fence_chain {
 	struct dma_fence base;
@@ -81,9 +80,8 @@ dma_fence_chain_contained(struct dma_fence *fence)
 }
 
 /**
- * dma_fence_chain_alloc
- *
- * Returns a new struct dma_fence_chain object or NULL on failure.
+ * dma_fence_chain_alloc - Returns a new &struct dma_fence_chain object or
+ * %NULL on failure.
  *
  * This specialized allocator has to be a macro for its allocations to be
  * accounted separately (to have a separate alloc_tag). The typecast is
@@ -93,7 +91,8 @@ dma_fence_chain_contained(struct dma_fence *fence)
 		kmalloc_obj(struct dma_fence_chain)
 
 /**
- * dma_fence_chain_free
+ * dma_fence_chain_free - Frees an allocated but not used
+ * &struct dma_fence_chain object.
  * @chain: chain node to free
  *
  * Frees up an allocated but not used struct dma_fence_chain object. This
Signature · 1 line
2.53.0
author maintainer
#91 lore raw

PATCH 91/733 octeontx2-af: fix CN20K default MCAM rule removal on port cleanup

In reply to Greg Kroah-Hartman

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

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

From: Kiran Kumar K <[email protected]>

[ Upstream commit 1376afc7660bad2a1a5ee0876898312a486cf8bd ]

npc_mcam_free_all_entries() disables every MCAM entry mapped to a port before freeing it. On CN20K, that also disables the default broadcast, multicast, promiscuous, and unicast rules, which causes packet drops when all rules are removed per port.

Only disable and free non-default entries. Leave CN20K default rules enabled when freeing the remaining port entries.

Fixes 013717353c03 ("octeontx2-af: npc: cn20k: Tear down default MCAM rules explicitly on free")
---
 drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +2 -3
index 38554d51164e1..6f2e6bce164de 100644
@@ -2957,10 +2957,9 @@ static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
 			}
 		}
 
-		/* Disable the entry */
-		npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
-
 		if (!cn20k_dft_rl) {
+			/* Disable the entry */
+			npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
 			mcam->entry2pfvf_map[index] = NPC_MCAM_INVALID_MAP;
 			/* Free the entry in bitmap */
 			npc_mcam_clear_bit(mcam, index);
Signature · 1 line
2.53.0
author maintainer
#92 lore raw

PATCH 92/733 drm/i915/dp_mst: Remove duplicate intel_pfit_compute_config() call

In reply to Greg Kroah-Hartman

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

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

From: Chaitanya Kumar Borah <[email protected]>

[ Upstream commit 6463655ab2946d13d2ec5efe04a5c2bf9d675f01 ]

mst_stream_compute_config() called intel_pfit_compute_config() twice in a row.

commit 5ce9ac1531b8 ("drm/i915/mst: Call intel_pfit_compute_config() for sharpness filter")
was erroneously cherry-picked to the fixes tree while commit ca97f5546f19 ("drm/i915/mst: Call intel_pfit_compute_config() for sharpness filter")
was already in there.

Drop the redundant duplicate call.

Cc Rodrigo Vivi <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Nemesa Garg <[email protected]>
Cc Jani Nikula <[email protected]>
Fixes 5ce9ac1531b8 ("drm/i915/mst: Call intel_pfit_compute_config() for sharpness filter")
[Rodrigo: adjusted commit message]
(cherry picked from commit ea9f3470d33602fb776ea55443467baacf66f23a)
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ----
 1 file changed, 4 deletions(-)
drivers/gpu/drm/i915/display/intel_dp_mst.c +0 -4
index 0aa3e6b4c781d..bcdc504913471 100644
@@ -722,10 +722,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 
-	ret = intel_pfit_compute_config(pipe_config, conn_state);
-	if (ret)
-		return ret;
-
 	ret = intel_pfit_compute_config(pipe_config, conn_state);
 	if (ret)
 		return ret;
Signature · 1 line
2.53.0
author maintainer
#93 lore raw

PATCH 93/733 drm/i915/cdclk: Fix dg2_power_well_count() return type

In reply to Greg Kroah-Hartman

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

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

From: Ville Syrjälä <[email protected]>

[ Upstream commit a154f2ae8eecbf2a4f97376d29b8d38c198b54e7 ]

dg2_power_well_count() is supposed to return an integer, not a boolean. Make it so.

Fixes 9112ce99c1d7 ("drm/i915/cdclk: Extract dg2_power_well_count()")
(cherry picked from commit dcf423710d0253d7d729c3992bbae0c6197c9c22)
---
 drivers/gpu/drm/i915/display/intel_cdclk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/display/intel_cdclk.c +2 -2
index 7bc9b956554ba..44a6503b2be73 100644
@@ -2697,8 +2697,8 @@ static void intel_set_cdclk(struct intel_display *display,
 	}
 }
 
-static bool dg2_power_well_count(struct intel_display *display,
-				 const struct intel_cdclk_state *cdclk_state)
+static int dg2_power_well_count(struct intel_display *display,
+				const struct intel_cdclk_state *cdclk_state)
 {
 	return display->platform.dg2 ? hweight8(cdclk_state->active_pipes) : 0;
 }
Signature · 1 line
2.53.0
author maintainer
#94 lore raw

PATCH 94/733 ovl: return EINVAL instead of EIO in case of mismatched user_ns

In reply to Greg Kroah-Hartman

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

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

From: Miklos Szeredi <[email protected]>

[ Upstream commit a518e63c377574784f49653ef5314c70e2463b0c ]

The EIO was used to signal an internal error (commit 9efb069de4ba ("ovl:
add warning on user_ns mismatch")), which is no longer the case.

Fixes 63981fc786da ("ovl: don't warn when the mount is completed from another user namespace")
---
 fs/overlayfs/super.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/overlayfs/super.c +1 -1
index 60b808b85fc43..43eb0c053dacd 100644
@@ -1543,7 +1543,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
 	struct ovl_fs *ofs = sb->s_fs_info;
 	int err;
 
-	err = -EIO;
+	err = -EINVAL;
 	/* The fscontext fd may have been passed to another user namespace. */
 	if (fc->user_ns != current_user_ns())
 		goto out_err;
Signature · 1 line
2.53.0
author maintainer
#95 lore raw

PATCH 95/733 smb/server: cancel async requests when closing connection

In reply to Greg Kroah-Hartman

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

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

From: ChenXiaoSong <[email protected]>

[ Upstream commit 4fd5bad647bfa45eb86bfd2f03ba1bef3fcd5851 ]

An async request may still be waiting when a connection is closed. This can stop the connection from closing.

Cancel active async requests before waiting for them to finish.

Stable-dep-of: d12168084c8c ("ksmbd: safely drain sessions during logoff")

---
 fs/smb/server/connection.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
fs/smb/server/connection.c +21 -0
index af73c2ed5d249..17f4ac5597789 100644
@@ -294,6 +294,26 @@ void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
 	wake_up_all(&conn->req_running_q);
 }
 
+static void ksmbd_conn_cancel_async_requests(struct ksmbd_conn *conn)
+{
+	struct ksmbd_work *work, *tmp;
+
+	ksmbd_debug(CONN, "Cancel pending async requests on releasing connection\n");
+	spin_lock(&conn->request_lock);
+	list_for_each_entry_safe(work, tmp, &conn->async_requests,
+				 async_request_entry) {
+		if (work->state != KSMBD_WORK_ACTIVE)
+			continue;
+
+		ksmbd_debug(CONN, "Cancel async request id %d\n",
+			    work->async_id);
+		work->state = KSMBD_WORK_CANCELLED;
+		if (work->cancel_fn)
+			work->cancel_fn(work->cancel_argv);
+	}
+	spin_unlock(&conn->request_lock);
+}
+
 void ksmbd_conn_lock(struct ksmbd_conn *conn)
 {
 	mutex_lock(&conn->srv_mutex);
@@ -608,6 +628,7 @@ int ksmbd_conn_handler_loop(void *p)
 	}
 
 	ksmbd_conn_set_releasing(conn);
+	ksmbd_conn_cancel_async_requests(conn);
 	/* Wait till all reference dropped to the Server object*/
 	ksmbd_debug(CONN, "Wait for all pending requests(%d)\n", atomic_read(&conn->r_count));
 	wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
Signature · 1 line
2.53.0
author maintainer
#96 lore raw

PATCH 96/733 ksmbd: safely drain sessions during logoff

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 d12168084c8c1b6d883c8eca5853929ac5136a9e ]

SMB3 multichannel allows requests for one session to run on multiple connections. Wait for all channels bound to a session before freeing shared session objects.

A deferred byte-range lock remains counted as a running request and only wakes when its file closes. Wake blocked locks during the drain without unpublishing or modifying their file objects. Synchronous CANCEL requests must invoke their cancellation callback to wake pending operations, while CHANGE_NOTIFY completion remains specific to the asynchronous path.

Serialize session teardown with channel registration and previous-session cleanup, and use atomic work-state transitions so LOGOFF, CANCEL, and connection teardown invoke cancellation callbacks only once.

Fixes 76e98a158b20 ("ksmbd: fix race condition between destroy_previous_session() and smb2 operations()")
---
 fs/smb/server/connection.c        |  8 ++++--
 fs/smb/server/mgmt/user_session.c | 13 ++++++++-
 fs/smb/server/mgmt/user_session.h |  1 +
 fs/smb/server/smb2pdu.c           | 47 +++++++++++++++++++++++++++----
 fs/smb/server/vfs_cache.c         | 17 +++++++++--
 fs/smb/server/vfs_cache.h         |  1 +
 6 files changed, 77 insertions(+), 10 deletions(-)
fs/smb/server/connection.c +6 -2
index 17f4ac5597789..39ac777fd4527 100644
@@ -13,6 +13,7 @@
 #include "mgmt/ksmbd_ida.h"
 #include "mgmt/user_session.h"
 #include "connection.h"
+#include "vfs_cache.h"
 #include "compress.h"
 #include "transport_tcp.h"
 #include "transport_rdma.h"
@@ -302,12 +303,12 @@ static void ksmbd_conn_cancel_async_requests(struct ksmbd_conn *conn)
 	spin_lock(&conn->request_lock);
 	list_for_each_entry_safe(work, tmp, &conn->async_requests,
 				 async_request_entry) {
-		if (work->state != KSMBD_WORK_ACTIVE)
+		if (cmpxchg(&work->state, KSMBD_WORK_ACTIVE,
+			    KSMBD_WORK_CANCELLED) != KSMBD_WORK_ACTIVE)
 			continue;
 
 		ksmbd_debug(CONN, "Cancel async request id %d\n",
 			    work->async_id);
-		work->state = KSMBD_WORK_CANCELLED;
 		if (work->cancel_fn)
 			work->cancel_fn(work->cancel_argv);
 	}
@@ -391,6 +392,9 @@ int ksmbd_conn_wait_idle_sess(struct ksmbd_conn *curr_conn,
 	if (retry_count >= max_timeout)
 		return -EIO;
 
+	/* A blocked byte-range lock cannot drain until teardown wakes it. */
+	ksmbd_wake_session_blocked_works(sess);
+
 	down_read(&conn_list_lock);
 	hash_for_each(conn_list, bkt, conn, hlist) {
 		if (ksmbd_session_is_bound_to_conn(sess, conn)) {
fs/smb/server/mgmt/user_session.c +12 -1
index d91dde3f9e619..10b31df185a60 100644
@@ -650,10 +650,21 @@ void destroy_previous_session(struct ksmbd_conn *conn,
 	    memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
 		goto out;
 
+	down_write(&prev_sess->chann_lock);
+	if (prev_sess->tearing_down) {
+		up_write(&prev_sess->chann_lock);
+		goto out;
+	}
+	prev_sess->tearing_down = true;
+	up_write(&prev_sess->chann_lock);
+
 	ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_RECONNECT);
 	err = ksmbd_conn_wait_idle_sess(conn, prev_sess);
 	if (err) {
-		ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_SETUP);
+		down_write(&prev_sess->chann_lock);
+		prev_sess->tearing_down = false;
+		up_write(&prev_sess->chann_lock);
+		ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_GOOD);
 		goto out;
 	}
 
fs/smb/server/mgmt/user_session.h +1 -0
index f8a24c33f7fe4..3e52d4cc13247 100644
@@ -42,6 +42,7 @@ struct ksmbd_session {
 
 	bool				sign;
 	bool				enc;
+	bool				tearing_down;
 
 	int				state;
 	__u8				*Preauth_HashValue;
fs/smb/server/smb2pdu.c +42 -5

96 lines not on this page · raw message

fs/smb/server/vfs_cache.c +15 -2
index 293dab9b43be1..a23bd9b1a68bc 100644
@@ -727,12 +727,25 @@ static void set_close_state_blocked_works(struct ksmbd_file *fp)
 	spin_lock(&fp->f_lock);
 	list_for_each_entry(cancel_work, &fp->blocked_works,
 				 fp_entry) {
-		cancel_work->state = KSMBD_WORK_CLOSED;
-		cancel_work->cancel_fn(cancel_work->cancel_argv);
+		if (xchg(&cancel_work->state, KSMBD_WORK_CLOSED) ==
+		    KSMBD_WORK_ACTIVE)
+			cancel_work->cancel_fn(cancel_work->cancel_argv);
 	}
 	spin_unlock(&fp->f_lock);
 }
 
+void ksmbd_wake_session_blocked_works(struct ksmbd_session *sess)
+{
+	struct ksmbd_file_table *ft = &sess->file_table;
+	struct ksmbd_file *fp;
+	unsigned int id;
+
+	read_lock(&ft->lock);
+	idr_for_each_entry(ft->idr, fp, id)
+		set_close_state_blocked_works(fp);
+	read_unlock(&ft->lock);
+}
+
 int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
 {
 	struct ksmbd_file	*fp;
fs/smb/server/vfs_cache.h +1 -0
index 8bb4396f95238..d6a9cd4b6d563 100644
@@ -211,6 +211,7 @@ void ksmbd_launch_ksmbd_durable_scavenger(void);
 void ksmbd_stop_durable_scavenger(void);
 void ksmbd_close_tree_conn_fds(struct ksmbd_work *work);
 void ksmbd_close_session_fds(struct ksmbd_work *work);
+void ksmbd_wake_session_blocked_works(struct ksmbd_session *sess);
 int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode);
 int ksmbd_init_global_file_table(void);
 void ksmbd_free_global_file_table(void);
Signature · 1 line
2.53.0
author maintainer
#97 lore raw

PATCH 97/733 ksmbd: propagate DACL parsing 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 c61dc7b1b4a3234b4aa3965502908a292238805c ]

parse_dacl() silently accepts truncated ACEs and allocation failures, allowing set_info_sec() to continue with an incomplete ACL conversion.

Return parsing and allocation errors to parse_sec_desc() so malformed security descriptors are rejected before inode attributes or ACL xattrs are updated.

Fixes e2f34481b24d ("cifsd: add server-side procedures for SMB3")
---
 fs/smb/server/smbacl.c | 63 +++++++++++++++++++++++++-----------------
 1 file changed, 38 insertions(+), 25 deletions(-)
fs/smb/server/smbacl.c +38 -25
index 33825c1356b47..7830f4fa836bb 100644
@@ -380,10 +380,10 @@ void free_acl_state(struct posix_acl_state *state)
 	kfree(state->groups);
 }
 
-static void parse_dacl(struct mnt_idmap *idmap,
-		       struct smb_acl *pdacl, char *end_of_acl,
-		       struct smb_sid *pownersid, struct smb_sid *pgrpsid,
-		       struct smb_fattr *fattr)
+static int parse_dacl(struct mnt_idmap *idmap,
+		      struct smb_acl *pdacl, char *end_of_acl,
+		      struct smb_sid *pownersid, struct smb_sid *pgrpsid,
+		      struct smb_fattr *fattr)
 {
 	int i, ret;
 	u16 num_aces = 0;
@@ -397,13 +397,13 @@ static void parse_dacl(struct mnt_idmap *idmap,
 	bool owner_found = false, group_found = false, others_found = false;
 
 	if (!pdacl)
-		return;
+		return 0;
 
 	/* validate that we do not go past end of acl */
 	if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) ||
 	    end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
 		pr_err("ACL too small to parse DACL\n");
-		return;
+		return -EINVAL;
 	}
 
 	ksmbd_debug(SMB, "DACL revision %d size %d num aces %d\n",
@@ -415,31 +415,31 @@ static void parse_dacl(struct mnt_idmap *idmap,
 
 	num_aces = le16_to_cpu(pdacl->num_aces);
 	if (num_aces <= 0)
-		return;
+		return 0;
 
 	dacl_size = le16_to_cpu(pdacl->size);
 	if (dacl_size < sizeof(struct smb_acl))
-		return;
+		return -EINVAL;
 
 	if (num_aces > (dacl_size - sizeof(struct smb_acl)) /
 			(offsetof(struct smb_ace, sid) +
 			 offsetof(struct smb_sid, sub_auth) + sizeof(__le16)))
-		return;
+		return -EINVAL;
 
 	ret = init_acl_state(&acl_state, num_aces);
 	if (ret)
-		return;
+		return ret;
 	ret = init_acl_state(&default_acl_state, num_aces);
 	if (ret) {
 		free_acl_state(&acl_state);
-		return;
+		return ret;
 	}
 
 	ppace = kmalloc_objs(struct smb_ace *, num_aces, KSMBD_DEFAULT_GFP);
 	if (!ppace) {
 		free_acl_state(&default_acl_state);
 		free_acl_state(&acl_state);
-		return;
+		return -ENOMEM;
 	}
 
 	/*
@@ -448,8 +448,10 @@ static void parse_dacl(struct mnt_idmap *idmap,
 	 * user/group/other have no permissions
 	 */
 	for (i = 0; i < num_aces; ++i) {
-		if (end_of_acl - acl_base < acl_size)
-			break;
+		if (end_of_acl - acl_base < acl_size) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		ppace[i] = (struct smb_ace *)(acl_base + acl_size);
 		acl_base = (char *)ppace[i];
@@ -462,8 +464,10 @@ static void parse_dacl(struct mnt_idmap *idmap,
 		    (end_of_acl - acl_base <
 		     acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
 		    (le16_to_cpu(ppace[i]->size) <
-		     acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth))
-			break;
+		     acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth)) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		acl_size = le16_to_cpu(ppace[i]->size);
 		ppace[i]->access_req =
@@ -538,7 +542,6 @@ static void parse_dacl(struct mnt_idmap *idmap,
 				((acl_mode & 0700) >> 6) | 0004;
 		}
 	}
-	kfree(ppace);
 
 	if (owner_found) {
 		/* The owner must be set to at least read-only. */
@@ -581,10 +584,12 @@ static void parse_dacl(struct mnt_idmap *idmap,
 			fattr->cf_acls =
 				posix_acl_alloc(acl_state.users->n +
 					acl_state.groups->n + 4, KSMBD_DEFAULT_GFP);
-			if (fattr->cf_acls) {
-				cf_pace = fattr->cf_acls->a_entries;
-				posix_state_to_acl(&acl_state, cf_pace);
+			if (!fattr->cf_acls) {
+				ret = -ENOMEM;
+				goto out;
 			}
+			cf_pace = fattr->cf_acls->a_entries;
+			posix_state_to_acl(&acl_state, cf_pace);
 		}
 	}
 
@@ -595,14 +600,20 @@ static void parse_dacl(struct mnt_idmap *idmap,
 			fattr->cf_dacls =
 				posix_acl_alloc(default_acl_state.users->n +
 				default_acl_state.groups->n + 4, KSMBD_DEFAULT_GFP);
-			if (fattr->cf_dacls) {
-				cf_pdace = fattr->cf_dacls->a_entries;
-				posix_state_to_acl(&default_acl_state, cf_pdace);
+			if (!fattr->cf_dacls) {
+				ret = -ENOMEM;
+				goto out;
 			}
+			cf_pdace = fattr->cf_dacls->a_entries;
+			posix_state_to_acl(&default_acl_state, cf_pdace);
 		}
 	}
+	ret = 0;
+out:
+	kfree(ppace);
 	free_acl_state(&acl_state);
 	free_acl_state(&default_acl_state);
+	return ret;
 }
 
 static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
@@ -963,8 +974,10 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
 		if (dacloffset < sizeof(struct smb_ntsd))
 			return -EINVAL;
 
-		parse_dacl(idmap, dacl_ptr, end_of_acl,
-			   owner_sid_ptr, group_sid_ptr, fattr);
+		rc = parse_dacl(idmap, dacl_ptr, end_of_acl,
+				owner_sid_ptr, group_sid_ptr, fattr);
+		if (rc)
+			return rc;
 	}
 
 	return 0;
Signature · 1 line
2.53.0
author maintainer
#98 lore raw

PATCH 98/733 ksmbd: rate limit unmapped SID 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 feca5e70fc963b088377b20879e8cd8237c2fd7d ]

A client can include many structurally valid but unmapped SIDs in a DACL. Logging every mapping failure lets one request generate hundreds of kernel error messages.

Rate limit the message to prevent an authenticated client from flooding the kernel log.

Fixes e2f34481b24d ("cifsd: add server-side procedures for SMB3")
---
 fs/smb/server/smbacl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/server/smbacl.c +2 -2
index 7830f4fa836bb..ae1527aa62697 100644
@@ -525,8 +525,8 @@ static int parse_dacl(struct mnt_idmap *idmap,
 			temp_fattr.cf_uid = INVALID_UID;
 			ret = sid_to_id(idmap, &ppace[i]->sid, SIDOWNER, &temp_fattr);
 			if (ret || uid_eq(temp_fattr.cf_uid, INVALID_UID)) {
-				pr_err("%s: Error %d mapping Owner SID to uid\n",
-				       __func__, ret);
+				pr_err_ratelimited("%s: Error %d mapping Owner SID to uid\n",
+						   __func__, ret);
 				continue;
 			}
 
Signature · 1 line
2.53.0
author maintainer
#99 lore raw

PATCH 99/733 ksmbd: fix listener task lifetime on netdev events

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 a506290f59e1c6ce9ac0a13158640bb8fee93471 ]

The listener thread exits when its listening socket is shutdown. The netdevice notifier shuts down the socket before calling kthread_stop(), so the task_struct can be freed before kthread_stop() gets its reference.

Create the listener in a stopped state and hold an extra task_struct reference until kthread_stop_put() completes. Also stop and release listeners before freeing their interface records during TCP teardown.

Fixes 3316a8fc840d ("ksmbd: server: avoid busy polling in accept loop")
---
 fs/smb/server/transport_tcp.c | 36 ++++++++++++++++++++++++++---------
 1 file changed, 27 insertions(+), 9 deletions(-)
fs/smb/server/transport_tcp.c +27 -9
index 990b14e5d3ea2..668fc333c5be3 100644
@@ -39,6 +39,7 @@ struct tcp_transport {
 static const struct ksmbd_transport_ops ksmbd_tcp_transport_ops;
 
 static void tcp_stop_kthread(struct task_struct *kthread);
+static void ksmbd_tcp_stop_listener(struct interface *iface);
 static struct interface *alloc_iface(char *ifname);
 static void ksmbd_tcp_disconnect(struct ksmbd_transport *t);
 
@@ -315,13 +316,20 @@ static int ksmbd_tcp_run_kthread(struct interface *iface)
 	int rc;
 	struct task_struct *kthread;
 
-	kthread = kthread_run(ksmbd_kthread_fn, (void *)iface, "ksmbd-%s",
-			      iface->name);
+	kthread = kthread_create(ksmbd_kthread_fn, (void *)iface, "ksmbd-%s",
+				 iface->name);
 	if (IS_ERR(kthread)) {
 		rc = PTR_ERR(kthread);
 		return rc;
 	}
+
+	/*
+	 * The listener can exit after its socket is shutdown, so keep the
+	 * task_struct alive until the caller has stopped it.
+	 */
+	get_task_struct(kthread);
 	iface->ksmbd_kthread = kthread;
+	wake_up_process(kthread);
 
 	return 0;
 }
@@ -585,12 +593,7 @@ static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
 		if (iface && iface->state == IFACE_STATE_CONFIGURED) {
 			ksmbd_debug(CONN, "netdev-down event: netdev(%s) is going down\n",
 					iface->name);
-			kernel_sock_shutdown(iface->ksmbd_socket, SHUT_RDWR);
-			tcp_stop_kthread(iface->ksmbd_kthread);
-			iface->ksmbd_kthread = NULL;
-			sock_release(iface->ksmbd_socket);
-			iface->ksmbd_socket = NULL;
-
+			ksmbd_tcp_stop_listener(iface);
 			iface->state = IFACE_STATE_DOWN;
 			break;
 		}
@@ -618,11 +621,25 @@ static void tcp_stop_kthread(struct task_struct *kthread)
 	if (!kthread)
 		return;
 
-	ret = kthread_stop(kthread);
+	ret = kthread_stop_put(kthread);
 	if (ret)
 		pr_err("failed to stop forker thread\n");
 }
 
+static void ksmbd_tcp_stop_listener(struct interface *iface)
+{
+	if (iface->ksmbd_socket)
+		kernel_sock_shutdown(iface->ksmbd_socket, SHUT_RDWR);
+
+	tcp_stop_kthread(iface->ksmbd_kthread);
+	iface->ksmbd_kthread = NULL;
+
+	if (iface->ksmbd_socket) {
+		sock_release(iface->ksmbd_socket);
+		iface->ksmbd_socket = NULL;
+	}
+}
+
 void ksmbd_tcp_destroy(void)
 {
 	struct interface *iface, *tmp;
@@ -630,6 +647,7 @@ void ksmbd_tcp_destroy(void)
 	unregister_netdevice_notifier(&ksmbd_netdev_notifier);
 
 	list_for_each_entry_safe(iface, tmp, &iface_list, entry) {
+		ksmbd_tcp_stop_listener(iface);
 		list_del(&iface->entry);
 		kfree(iface->name);
 		kfree(iface);
Signature · 1 line
2.53.0
author maintainer
#100 lore raw

PATCH 100/733 s390/time: Use jiffies instead of jiffies_64

In reply to Greg Kroah-Hartman

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

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

From: Heiko Carstens <[email protected]>

[ Upstream commit ca1f4a5ecab084af7f405baa902edbed171b57e6 ]

Christoph Schlameuss and Alexander Egorenkov reported a data-race reported by KCSAN when jiffies_64 is read:

==================================================================

BUG: KCSAN: data-race in do_account_vtime / tick_do_update_jiffies64

write to 0x0000016599ea8600 of 8 bytes by interrupt on cpu 6:
tick_do_update_jiffies64+0x140/0x250
=============================================================>

BUG: KCSAN: data-race in do_account_vtime / tick_do_update_ji>

write to 0x0000016599ea8600 of 8 bytes by interrupt on cpu 6:

 tick_do_update_jiffies64+0x140/0x250
 tick_nohz_handler+0x2e6/0x300
 __run_hrtimer+0x156/0x4d0
 __hrtimer_run_queues+0xd2/0x150

...
system_call+0x72/0x90

read to 0x0000016599ea8600 of 8 bytes by interrupt on cpu 12:

 do_account_vtime+0x7d6/0x860
 vtime_flush+0x26/0xe0
 update_process_times+0x32/0x160
 tick_nohz_handler+0x12a/0x300

...
system_call+0x72/0x90

value changed: 0x00000000ffffaa6c -> 0x00000000ffffaa6d
...
=============================================================>

Problem is that jiffies_64 instead of jiffies is used. Both are at the same address, but only jiffies is of volatile type, which prevents this warning.

Change the vtime code so jiffies instead of jiffies_64 is used everywhere. This addresses also the inconsistency that both jiffies and jiffies_64 were used in the original patch which introduced this.

---
 arch/s390/kernel/vtime.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
arch/s390/kernel/vtime.c +3 -3
index d804e1140c2e9..efcbf406f03e7 100644
@@ -32,7 +32,7 @@ static atomic64_t virt_timer_elapsed;
 DEFINE_PER_CPU(u64, mt_cycles[8]);
 static DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 };
 static DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 };
-static DEFINE_PER_CPU(u64, mt_scaling_jiffies);
+static DEFINE_PER_CPU(unsigned long, mt_scaling_jiffies);
 
 static inline void set_vtimer(u64 expires)
 {
@@ -81,7 +81,7 @@ static void update_mt_scaling(void)
 		memcpy(cycles_old, cycles_new,
 		       sizeof(u64) * (smp_cpu_mtid + 1));
 	}
-	__this_cpu_write(mt_scaling_jiffies, jiffies_64);
+	__this_cpu_write(mt_scaling_jiffies, jiffies);
 }
 
 static inline u64 update_tsk_timer(unsigned long *tsk_vtime, u64 new)
@@ -144,7 +144,7 @@ static int do_account_vtime(struct task_struct *tsk)
 		lc->system_timer += timer;
 
 	/* Update MT utilization calculation */
-	if (smp_cpu_mtid && time_after64(jiffies_64, __this_cpu_read(mt_scaling_jiffies)))
+	if (smp_cpu_mtid && time_after(jiffies, __this_cpu_read(mt_scaling_jiffies)))
 		update_mt_scaling();
 
 	/* Calculate cputime delta */
Signature · 1 line
2.53.0
author maintainer
#101 lore raw

PATCH 101/733 s390/ipl: Fix NULL deref in kdump without re-IPL parm block

In reply to Greg Kroah-Hartman

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

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

From: Vasily Gorbik <[email protected]>

[ Upstream commit 7f918871112e8e7c581e99eb8e545af4e59c8367 ]

Some IPL types, like HMC FTP boot or QEMU direct kernel boot, might not provide an IPL parameter block. In this case, reipl_type_init() selects IPL_TYPE_UNKNOWN, and reipl_block_actual remains NULL.

kdump passes the re-IPL parameter block to the dump kernel through os_info. Before commit 3b9678472bab ("s390/ipl: correct kdump reipl block checksum calculation"), the os_info entry was added only for IPL types which initialized reipl_block_actual. That commit moved the os_info update to machine_crash_shutdown(), making it unconditional. As a result, set_os_info_reipl_block() dereferences reipl_block_actual for IPL_TYPE_UNKNOWN. This may happen to work by chance when address zero contains readable lowcore data and the resulting empty os_info entry is ignored by the dump kernel.

Skip the os_info update when no re-IPL parameter block is available. Kdump then collect the dump and reboot without setting re-IPL parameter block.

Fixes 3b9678472bab ("s390/ipl: correct kdump reipl block checksum calculation")
---
 arch/s390/kernel/ipl.c | 2 ++
 1 file changed, 2 insertions(+)
arch/s390/kernel/ipl.c +2 -0
index 3c346b02ceb95..7024fc4137152 100644
@@ -1157,6 +1157,8 @@ static struct attribute_group reipl_nss_attr_group = {
 
 void set_os_info_reipl_block(void)
 {
+	if (!reipl_block_actual)
+		return;
 	os_info_entry_add_data(OS_INFO_REIPL_BLOCK, reipl_block_actual,
 			       reipl_block_actual->hdr.len);
 }
Signature · 1 line
2.53.0
author maintainer
#102 lore raw

PATCH 102/733 s390/ipl: Fix NULL deref in dump_reipl without re-IPL parm block

In reply to Greg Kroah-Hartman

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

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

From: Vasily Gorbik <[email protected]>

[ Upstream commit 37f61b71cbc0caefc01022a19ee56fc2510e2e6e ]

Unlike kdump, which passes the re-IPL parameter block through os_info, the stand-alone dump passes it through the IPL parm block address and checksum in lowcore.

Some IPL types, like HMC FTP boot or QEMU direct kernel boot, might not provide an IPL parameter block. In this case reipl_type_init() selects IPL_TYPE_UNKNOWN and reipl_block_actual remains NULL. Nevertheless, dump_reipl_run() unconditionally dereferences it when preparing the lowcore fields. This may happen to work by chance when address zero contains readable lowcore data. A zero IPL parameter block address is then stored in lowcore, causing the stand-alone dumper to enter disabled wait after completing the dump.

Explicitly store a zero IPL parameter block address and checksum when no re-IPL parameter block is available. This does not change the behavior:
the stand-alone dumper completes the dump and halts, while valid re-IPL parameter blocks continue to be handled as before.

Fixes 099b76513992 ("[S390] Automatic IPL after dump")
---
 arch/s390/kernel/ipl.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
arch/s390/kernel/ipl.c +7 -3
index 7024fc4137152..68fdd5616dfe1 100644
@@ -1929,7 +1929,8 @@ static struct shutdown_action __refdata dump_action = {
 static void dump_reipl_run(struct shutdown_trigger *trigger)
 {
 	struct lowcore *abs_lc;
-	unsigned int csum;
+	unsigned long ipib = 0;
+	unsigned int csum = 0;
 
 	/*
 	 * Set REIPL_CLEAR flag in os_info flags entry indicating
@@ -1945,9 +1946,12 @@ static void dump_reipl_run(struct shutdown_trigger *trigger)
 	    reipl_type == IPL_TYPE_UNKNOWN)
 		os_info_flags |= OS_INFO_FLAG_REIPL_CLEAR;
 	os_info_entry_add_data(OS_INFO_FLAGS_ENTRY, &os_info_flags, sizeof(os_info_flags));
-	csum = (__force unsigned int)cksm(reipl_block_actual, reipl_block_actual->hdr.len, 0);
+	if (reipl_block_actual) {
+		ipib = __pa(reipl_block_actual);
+		csum = (__force unsigned int)cksm(reipl_block_actual, reipl_block_actual->hdr.len, 0);
+	}
 	abs_lc = get_abs_lowcore();
-	abs_lc->ipib = __pa(reipl_block_actual);
+	abs_lc->ipib = ipib;
 	abs_lc->ipib_checksum = csum;
 	put_abs_lowcore(abs_lc);
 	dump_run(trigger);
Signature · 1 line
2.53.0
author maintainer
#103 lore raw

PATCH 103/733 s390/diag324: Preserve -EBUSY return code

In reply to Greg Kroah-Hartman

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

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

From: Sumanth Korikkar <[email protected]>

[ Upstream commit 439077c39d8f7108aea4dd8d4d819b9b864fe84c ]

When diag324 reports -EBUSY, the error code is
overwritten by the result of copy_to_user() and put_user(). As a result, the ioctl may incorrectly return success instead of -EBUSY.

Preserve the original diag324 return code and only return -EFAULT when copying data to userspace fails.

Fixes 90e6f191e1ee ("s390/diag324: Retrieve power readings via diag 0x324")
---
 arch/s390/kernel/diag/diag324.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
arch/s390/kernel/diag/diag324.c +1 -2
index fe325c2a2d0dc..3eec0cc8fb9e0 100644
@@ -182,8 +182,7 @@ long diag324_pibbuf(unsigned long arg)
 		goto out;
 	rc = copy_to_user((void __user *)address, data->pib, data->pib->len);
 	rc |= put_user(data->sequence, &udata->sequence);
-	if (rc)
-		rc = -EFAULT;
+	rc = rc ? -EFAULT : data->rc;
 out:
 	mutex_unlock(&pibmutex);
 	return rc;
Signature · 1 line
2.53.0
author maintainer
#104 lore raw

PATCH 104/733 s390/pai: Reduce excessive debug feature size

In reply to Greg Kroah-Hartman

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

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

From: Heiko Carstens <[email protected]>

[ Upstream commit 8cff0ac21658fedd4598e9904dd0c518bdaf5856 ]

The pai debug feature is registered with 256 areas, where each area contains 32 pages. This sums up to a total of 32MiB. The code does not use any debug exceptions, which means that 255 of those areas are never used. In addition all existing debug feature calls have a lower level (5) than the default level (3).

This in turn means that without user interaction the debug feature is unused.

Reduce the number of areas to 1, and also reduce the number of pages for the remaining area to 1. Since user interaction is required, the user can also increase the size of the remaining area, instead of wasting memory by default.

This reduces the total size of the debug feature to 4KiB.

Fixes a3f8423622ef ("s390/pai_crypto: Add PAI crypto characteristics table for parameters")
---
 arch/s390/kernel/perf_pai.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/perf_pai.c +1 -1
index cdb8006220ca0..ab76ed7ad791e 100644
@@ -1221,7 +1221,7 @@ static int __init paipmu_setup(void)
 static int __init pai_init(void)
 {
 	/* Setup s390dbf facility */
-	paidbg = debug_register("pai", 32, 256, 128);
+	paidbg = debug_register("pai", 1, 1, 128);
 	if (!paidbg) {
 		pr_err("Registration of s390dbf pai failed\n");
 		return -ENOMEM;
Signature · 1 line
2.53.0
author maintainer
#105 lore raw

PATCH 105/733 sched_ext: Fix timer pinning and return value in scx_central

In reply to Greg Kroah-Hartman

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

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

From: Wanwu Li <[email protected]>

[ Upstream commit 23761359861ca4bb087540937dfea8b0716914c2 ]

central_timerfn() re-arms the timer with a hardcoded BPF_F_TIMER_CPU_PIN flag and ignores the return value, defeating start_central_timer()'s -EINVAL fallback for kernels without the flag (<6.7): on such kernels the first tick kills the timer permanently with no diagnostic. Honor timer_pinned and check the return like the initial arm does.

Fixes 22a920209ab6 ("sched_ext: Implement tickless support")
---
 tools/sched_ext/scx_central.bpf.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
tools/sched_ext/scx_central.bpf.c +5 -1
index 64dd60b3e9223..65dae9e454009 100644
@@ -299,6 +299,7 @@ static int central_timerfn(void *map, int *key, struct bpf_timer *timer)
 	u64 now = scx_bpf_now();
 	u64 nr_to_kick = nr_queued;
 	s32 i, curr_cpu;
+	int ret;
 
 	curr_cpu = bpf_get_smp_processor_id();
 	if (timer_pinned && (curr_cpu != central_cpu)) {
@@ -332,7 +333,10 @@ static int central_timerfn(void *map, int *key, struct bpf_timer *timer)
 		scx_bpf_kick_cpu(cpu, SCX_KICK_PREEMPT);
 	}
 
-	bpf_timer_start(timer, TIMER_INTERVAL_NS, BPF_F_TIMER_CPU_PIN);
+	ret = bpf_timer_start(timer, TIMER_INTERVAL_NS,
+			      timer_pinned ? BPF_F_TIMER_CPU_PIN : 0);
+	if (ret)
+		scx_bpf_error("bpf_timer_start failed (%d)", ret);
 	__sync_fetch_and_add(&nr_timers, 1);
 	return 0;
 }
Signature · 1 line
2.53.0
author maintainer
#106 lore raw

PATCH 106/733 sched_ext: Fix vtime delta loss in scx_flatcg cgroup migration

In reply to Greg Kroah-Hartman

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

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

From: Wanwu Li <[email protected]>

[ Upstream commit b6ee92d7f7f0498d1f776d0b125a2f6bcedf0891 ]

fcg_cgroup_move() lost the signed vtime offset across cgroup migration in the mechanical conversion to time helpers:
time_delta() clamps negative deltas to 0, so a queued task (whose dsq_vtime is normally behind the source frontier) loses its accumulated vtime credit and lands exactly at the destination frontier instead of keeping its relative position. Restore the wrapping signed subtraction.

Fixes 62addc6dbf36 ("sched_ext: Use time helpers in BPF schedulers")
---
 tools/sched_ext/scx_flatcg.bpf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/sched_ext/scx_flatcg.bpf.c +1 -1
index ddcf6bc03b11c..98fdd4b040331 100644
@@ -934,7 +934,7 @@ void BPF_STRUCT_OPS(fcg_cgroup_move, struct task_struct *p,
 	if (!(from_cgc = find_cgrp_ctx(from)) || !(to_cgc = find_cgrp_ctx(to)))
 		return;
 
-	delta = time_delta(p->scx.dsq_vtime, from_cgc->tvtime_now);
+	delta = (s64)(p->scx.dsq_vtime - from_cgc->tvtime_now);
 	scx_bpf_task_set_dsq_vtime(p, to_cgc->tvtime_now + delta);
 }
 
Signature · 1 line
2.53.0
author maintainer
#107 lore raw

PATCH 107/733 Bluetooth: btintel_pcie: Clear automask on spurious interrupts

In reply to Greg Kroah-Hartman

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

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

From: Kiran K <[email protected]>

[ Upstream commit ea2ee8b222306208d2b094d1a11894da6c106d42 ]

On spurious interrupt where the TX and RX causes are not set, driver was not clearing the auto mask which can block all the interrupts. Driver needs to clear the automask even if no causes are set.

Fixes c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
---
 drivers/bluetooth/btintel_pcie.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/bluetooth/btintel_pcie.c +3 -0
index 2b7231be5973d..6b6258d03dd84 100644
@@ -1634,6 +1634,9 @@ static irqreturn_t btintel_pcie_irq_msix_handler(int irq, void *dev_id)
 
 	if (unlikely(!(intr_fh | intr_hw))) {
 		/* Ignore interrupt, inta == 0 */
+		bt_warn_ratelimited("Bluetooth: btintel_pcie: Received spurious interrupt\n");
+		btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_AUTOMASK_ST,
+				      BIT(entry->entry));
 		return IRQ_NONE;
 	}
 
Signature · 1 line
2.53.0
author maintainer
#108 lore raw

PATCH 108/733 workqueue: reject watchdog thresholds that overflow jiffies

In reply to Greg Kroah-Hartman

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

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

From: Jiacheng Xu <[email protected]>

[ Upstream commit 068c35b5d0546c8625b3d7c61910f73775cf1216 ]

The watchdog threshold is supplied in seconds but is multiplied by HZ before being used as a jiffies interval. Reject values that exceed MAX_JIFFY_OFFSET / HZ so the multiplication cannot wrap and the time_after() comparisons remain within their supported range.

The check is performed before changing the threshold or watchdog timer. Zero remains the value used to disable the watchdog.

Fixes 82607adcf9cdf ("workqueue: implement lockup detector")
---
 kernel/workqueue.c | 3 +++
 1 file changed, 3 insertions(+)
kernel/workqueue.c +3 -0
index 929c04a9581bd..36aaeb38e2174 100644
@@ -7923,6 +7923,9 @@ static int wq_watchdog_param_set_thresh(const char *val,
 	if (ret)
 		return ret;
 
+	if (thresh > MAX_JIFFY_OFFSET / HZ)
+		return -ERANGE;
+
 	if (system_percpu_wq)
 		wq_watchdog_set_thresh(thresh);
 	else
Signature · 1 line
2.53.0
author maintainer
#109 lore raw

PATCH 109/733 Bluetooth: btintel: validate version TLV value lengths

In reply to Greg Kroah-Hartman

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

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

From: Laxman Acharya Padhya <[email protected]>

[ Upstream commit a086c0892969bf8a0151b0f12bd14a68827c88b2 ]

btintel_parse_version_tlv() verifies that a complete TLV is present in the response, but it does not ensure that the value is long enough for the specific TLV type. A short value can therefore cause an out-of-bounds read through get_unaligned_le16(), get_unaligned_le32(), or memcpy().

Reject values shorter than the minimum required by each known TLV type. Also reject responses that do not contain the Command Complete Status field.

Fixes 57375beef71a ("Bluetooth: btintel: Add infrastructure to read controller information")
---
 drivers/bluetooth/btintel.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)
drivers/bluetooth/btintel.c +36 -1
index cc2234470960a..ecee50373f566 100644
@@ -570,12 +570,44 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
 }
 EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
 
+static u8 btintel_version_tlv_min_len(u8 type)
+{
+	switch (type) {
+	case INTEL_TLV_CNVI_TOP:
+	case INTEL_TLV_CNVR_TOP:
+	case INTEL_TLV_CNVI_BT:
+	case INTEL_TLV_CNVR_BT:
+	case INTEL_TLV_BUILD_NUM:
+	case INTEL_TLV_GIT_SHA1:
+		return sizeof(u32);
+	case INTEL_TLV_DEV_REV_ID:
+	case INTEL_TLV_TIME_STAMP:
+		return sizeof(u16);
+	case INTEL_TLV_IMAGE_TYPE:
+	case INTEL_TLV_BUILD_TYPE:
+	case INTEL_TLV_SECURE_BOOT:
+	case INTEL_TLV_OTP_LOCK:
+	case INTEL_TLV_API_LOCK:
+	case INTEL_TLV_DEBUG_LOCK:
+	case INTEL_TLV_LIMITED_CCE:
+	case INTEL_TLV_SBE_TYPE:
+		return sizeof(u8);
+	case INTEL_TLV_MIN_FW:
+		return 3;
+	case INTEL_TLV_OTP_BDADDR:
+		return sizeof(bdaddr_t);
+	default:
+		return 0;
+	}
+}
+
 int btintel_parse_version_tlv(struct hci_dev *hdev,
 			      struct intel_version_tlv *version,
 			      struct sk_buff *skb)
 {
 	/* Consume Command Complete Status field */
-	skb_pull(skb, 1);
+	if (!skb_pull(skb, 1))
+		return -EINVAL;
 
 	/* Event parameters contain multiple TLVs. Read each of them
 	 * and only keep the required data. Also, it use existing legacy
@@ -595,6 +627,9 @@ int btintel_parse_version_tlv(struct hci_dev *hdev,
 		if (skb->len < tlv->len + sizeof(*tlv))
 			return -EINVAL;
 
+		if (tlv->len < btintel_version_tlv_min_len(tlv->type))
+			return -EINVAL;
+
 		switch (tlv->type) {
 		case INTEL_TLV_CNVI_TOP:
 			version->cnvi_top = get_unaligned_le32(tlv->val);
Signature · 1 line
2.53.0
author maintainer
#110 lore raw

PATCH 110/733 Bluetooth: btintel: bound firmware ID by TLV length

In reply to Greg Kroah-Hartman

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

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

From: Laxman Acharya Padhya <[email protected]>

[ Upstream commit ac8aa9e0ec93a12a60230066f199f49c3b9aac3d ]

The firmware ID is treated as a NUL-terminated string even though the TLV length is its only boundary. If the value does not contain a NUL terminator, snprintf() can read beyond the received response.

Limit the conversion to the advertised TLV value length.

Fixes 164c62f958f8 ("Bluetooth: btintel: Add firmware ID to firmware name")
---
 drivers/bluetooth/btintel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/bluetooth/btintel.c +1 -1
index ecee50373f566..96a55d5badda1 100644
@@ -701,7 +701,7 @@ int btintel_parse_version_tlv(struct hci_dev *hdev,
 			break;
 		case INTEL_TLV_FW_ID:
 			snprintf(version->fw_id, sizeof(version->fw_id),
-				 "%s", tlv->val);
+				 "%.*s", tlv->len, tlv->val);
 			break;
 		default:
 			/* Ignore rest of information */
Signature · 1 line
2.53.0
author maintainer
#111 lore raw

PATCH 111/733 Bluetooth: hci_core: Fix race condition during device registration

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 57938bbdb9bf7fd41cbd5cd509ec10c4b22bec18 ]

In hci_register_dev(), the power_on work item is queued to hdev->req_workqueue before initializing hdev->adv_monitors_idr and registering the MSFT extension via msft_register(). For devices marked with quirks such as HCI_QUIRK_RAW_DEVICE, the HCI_UNCONFIGURED flag is set on the device. When the power_on work item runs concurrently on another CPU, hci_power_on() detects that the device is unconfigured and immediately invokes hci_dev_do_close(), which calls msft_do_close().

Concurrently, msft_register() allocates the msft structure and exposes it to hdev->msft_data prior to calling mutex_init(&msft->filter_lock). If msft_do_close() executes while hdev->msft_data is already assigned but the mutex has not yet been initialized, mutex_lock(&msft->filter_lock) operates on an uninitialized mutex, triggering a DEBUG_LOCKS warning:

DEBUG_LOCKS_WARN_ON(lock->magic != lock)

WARNING: kernel/locking/mutex.c:625 at __mutex_lock_common
kernel/locking/mutex.c:625 [inline]
WARNING: kernel/locking/mutex.c:625 at __mutex_lock+0x12d8/0x1550
kernel/locking/mutex.c:821
...
Call Trace:
 <TASK>
 msft_do_close+0x308/0x7b0 net/bluetooth/msft.c:693
 hci_dev_close_sync+0x86b/0x10a0 net/bluetooth/hci_sync.c:5522
 hci_dev_do_close net/bluetooth/hci_core.c:499 [inline]
 hci_power_on+0x32c/0x750 net/bluetooth/hci_core.c:937
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0x92d/0xe10 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>

Fix this by moving the queue_work() call in hci_register_dev() to after idr_init(&hdev->adv_monitors_idr) and msft_register(hdev) so that device structures and extensions are fully initialized before asynchronous tasks can access them. Additionally, assign hdev->msft_data in msft_register() only after mutex_init(&msft->filter_lock) has completed.

Fixes 9e14606d8f38 ("Bluetooth: msft: Extended monitor tracking by address filter")
Assisted-by Gemini:gemini-3.7-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by [email protected]
---
 net/bluetooth/hci_core.c | 4 ++--
 net/bluetooth/msft.c     | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
net/bluetooth/hci_core.c +2 -2
index f346505c3f88c..f747492da5f66 100644
@@ -2629,11 +2629,11 @@ int hci_register_dev(struct hci_dev *hdev)
 	if (error)
 		BT_WARN("register suspend notifier failed error:%d\n", error);
 
-	queue_work(hdev->req_workqueue, &hdev->power_on);
-
 	idr_init(&hdev->adv_monitors_idr);
 	msft_register(hdev);
 
+	queue_work(hdev->req_workqueue, &hdev->power_on);
+
 	return id;
 
 err_wqueue:
net/bluetooth/msft.c +1 -1
index ded68568e6c9b..d9dd722db3ebd 100644
@@ -769,8 +769,8 @@ void msft_register(struct hci_dev *hdev)
 
 	INIT_LIST_HEAD(&msft->handle_map);
 	INIT_LIST_HEAD(&msft->address_filters);
-	hdev->msft_data = msft;
 	mutex_init(&msft->filter_lock);
+	hdev->msft_data = msft;
 }
 
 void msft_release(struct hci_dev *hdev)
Signature · 1 line
2.53.0
author maintainer
#112 lore raw

PATCH 112/733 Bluetooth: L2CAP: fix chan mode for LE_CONN_REQ + EXT_FLOWCTL pchan

In reply to Greg Kroah-Hartman

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

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

From: Pauli Virtanen <[email protected]>

[ Upstream commit 4ef05db5b08b176a551b4a6287372045998806b0 ]

l2cap_new_connection() sets default value of channel mode to match the parent channel. l2cap_le_connect_req() left this at the default, and created L2CAP_MODE_EXT_FLOWCTL channels if listening pchan has that mode. This causes FLAG_DEFER_SETUP channels to reply to L2CAP_LE_CONN_REQ with L2CAP_ECRED_CONN_RSP, which is incorrect.

It can also result to stack OOB write (of l2cap_alloc_cid determined values) in l2cap_ecred_rsp_defer(), as l2cap_le_connect_req() does not limit maximum number of deferred channels or check for duplicate ident.

Fix by setting chan->mode correctly in l2cap_le_connect_req().

Also check channel mode in l2cap_ecred_rsp_defer(), and do WARN_ON_ONCE instead of OOB write to make it less brittle.

Fixes 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
---
 net/bluetooth/l2cap_core.c | 8 ++++++++
 1 file changed, 8 insertions(+)
net/bluetooth/l2cap_core.c +8 -0
index 30d7120d3a150..d9d72cac9269b 100644
@@ -3893,6 +3893,9 @@ static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
 	struct l2cap_ecred_conn_rsp *rsp_flex =
 		container_of(&rsp->pdu.rsp, struct l2cap_ecred_conn_rsp, hdr);
 
+	if (chan->mode != L2CAP_MODE_EXT_FLOWCTL)
+		return;
+
 	/* Check if channel for outgoing connection or if it wasn't deferred
 	 * since in those cases it must be skipped.
 	 */
@@ -3903,6 +3906,10 @@ static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
 	/* Reset ident so only one response is sent */
 	chan->ident = 0;
 
+	/* Unreachable, check in l2cap_ecred_conn_req. If reached, drop rest */
+	if (WARN_ON_ONCE(rsp->count >= ARRAY_SIZE(rsp->pdu.scid)))
+		rsp->pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_NO_MEM);
+
 	/* Include all channels pending with the same ident */
 	if (!rsp->pdu.rsp.result)
 		rsp_flex->dcid[rsp->count++] = cpu_to_le16(chan->scid);
@@ -5062,6 +5069,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
 
 	chan->ident = cmd->ident;
+	chan->mode = L2CAP_MODE_LE_FLOWCTL;
 
 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
 		l2cap_state_change(chan, BT_CONNECT2);
Signature · 1 line
2.53.0
author maintainer
#113 lore raw

PATCH 113/733 Bluetooth: L2CAP: fix out-of-bounds write in l2cap_ecred_connect

In reply to Greg Kroah-Hartman

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

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

From: Pauli Virtanen <[email protected]>

[ Upstream commit 56c2b5831d39dc84aad2573dc3e197af1a872a05 ]

l2cap_chan_connect() tries to ensure there are no more than L2CAP_ECRED_CONN_SCID_MAX pending ECRED channels, so they fit in the same L2CAP_ECRED_CONN_REQ that l2cap_ecred_connect() constructs.

However, the check only counts deferred channels. If 6 L2CAP sockets are connected at the same time in order DDDDND (D=deferred, N=non-deferred), the last can bump the total to max+1. It results to one __le16 written out of bounds of the scid array, and an invalid ECRED_CONN_REQ being sent.

Fix by leaving room for the non-deferred pending ECRED channels in the counting in l2cap_chan_connect(), so the limit can't be exceeded.

Move counting under same critical section where the channel is added. Although race conditions involving this appear unreachable, it's easier to see.

Also add WARN_ON_ONCE check in l2cap_ecred_defer_connect() to make this less brittle.

Fixes da49b602f7f7 ("Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections")
---
 net/bluetooth/l2cap_core.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)
net/bluetooth/l2cap_core.c +14 -6
index d9d72cac9269b..b31afc4d7dae2 100644
@@ -1337,7 +1337,7 @@ static void l2cap_le_connect(struct l2cap_chan *chan)
 struct l2cap_ecred_conn_data {
 	struct {
 		struct l2cap_ecred_conn_req_hdr req;
-		__le16 scid[5];
+		__le16 scid[L2CAP_ECRED_CONN_SCID_MAX];
 	} __packed pdu;
 	struct l2cap_chan *chan;
 	struct pid *pid;
@@ -1365,6 +1365,10 @@ static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
 		return;
 
+	/* Unreachable, checked in l2cap_connect (+timer drops it if reached) */
+	if (WARN_ON_ONCE(conn->count >= ARRAY_SIZE(conn->pdu.scid)))
+		return;
+
 	l2cap_ecred_init(chan, 0);
 
 	/* Set the same ident so we can match on the rsp */
@@ -7373,6 +7377,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 		goto done;
 	}
 
+	mutex_lock(&conn->lock);
+	l2cap_chan_lock(chan);
+
 	if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
 		struct l2cap_chan_data data;
 
@@ -7380,19 +7387,20 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 		data.pid = chan->ops->get_peer_pid(chan);
 		data.count = 1;
 
-		l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
+		__l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
+
+		/* Leave room for non-deferred channel that ends the group. */
+		if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
+			data.count += 1;
 
 		/* Check if there isn't too many channels being connected */
 		if (data.count > L2CAP_ECRED_CONN_SCID_MAX) {
 			hci_conn_drop(hcon);
 			err = -EPROTO;
-			goto done;
+			goto chan_unlock;
 		}
 	}
 
-	mutex_lock(&conn->lock);
-	l2cap_chan_lock(chan);
-
 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
 		hci_conn_drop(hcon);
 		err = -EBUSY;
Signature · 1 line
2.53.0
author maintainer
#114 lore raw

PATCH 114/733 Bluetooth: L2CAP: clear FLAG_DEFER_SETUP only for same PID/PSM

In reply to Greg Kroah-Hartman

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

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

From: Pauli Virtanen <[email protected]>

[ Upstream commit 0d77683237270702fa93489ca759c89b4e970554 ]

l2cap_ecred_defer_connect() clears FLAG_DEFER_SETUP also for channels with different PID/PSM, which will not be added to the same ECRED_CONN_REQ in any case. Consequently, only one ECRED connection group can work at a time although it appears intended they would be separate for each PID/PSM combination.

Fix by clearing FLAG_DEFER_SETUP only for the connections that could be added in the request. Retain test_bit(FLAG_DEFER_SETUP) before calling get_peer_pid as it may be NULL otherwise.

Fixes da49b602f7f7 ("Bluetooth: L2CAP: Use DEFER_SETUP to group ECRED connections")
---
 net/bluetooth/l2cap_core.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +4 -1
index b31afc4d7dae2..800f7517bfeb0 100644
@@ -1352,7 +1352,7 @@ static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
 	if (chan == conn->chan)
 		return;
 
-	if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
+	if (!test_bit(FLAG_DEFER_SETUP, &chan->flags))
 		return;
 
 	pid = chan->ops->get_peer_pid(chan);
@@ -1362,6 +1362,9 @@ static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
 		return;
 
+	if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
+		return;
+
 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
 		return;
 
Signature · 1 line
2.53.0