Skip to contentSkip to conversation

6.18.51-rc1 review

PATCH In review Greg Kroah-Hartman 11 participants 598 messages Sep 9 – Sep 12 Page 1 of 5

Subsystems (5)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 6.18.51-rc1 review

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

Responses should be made by Fri, 11 Sep 2026 13:40:31 +0000. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.51-rc1.gz

or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.18.y
and the diffstat can be found below.

thanks,

greg k-h

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

Greg Kroah-Hartman <[email protected]>

    Linux 6.18.51-rc1

Frank Sorenson <[email protected]>
cifs: add fscache_resize_cookie() to cifs_setsize()

Muchun Song <[email protected]>
mm/hugetlb_vmemmap: fix incorrect vmemmap restore in rollback

Christian Brauner <[email protected]>
pidfs: protect PIDFD_GET_* ioctls() via ifdef

Zi Yan <[email protected]>
mm/huge_memory: use folio's memcg inside __folio_split()

Matthew Wilcox (Oracle) <[email protected]>
migrate: replace RMP_ flags with TTU_ flags

Zi Yan <[email protected]>
mm/huge_memory: replace can_split_folio() with direct refcount calculation

Zi Yan <[email protected]>
mm/huge_memory: change folio_split_supported() to folio_check_splittable()

Muchun Song <[email protected]>
mm: thp: use folio_batch to handle THP splitting in deferred_split_scan()

Muchun Song <[email protected]>
mm: thp: introduce folio_split_queue_lock and its variants

SJ Park <[email protected]>

    mm/damon/core: initialize damos->last_applied

SJ Park <[email protected]>
mm/damon/core-kunit: handle region split failure in filter_out()

SJ Park <[email protected]>
mm/damon/sysfs: read addr_unit only once in damon_sysfs_apply_inputs()

SJ Park <[email protected]>
mm/damon/core: skip aging from repeated aggressive merging

SJ Park <[email protected]>
mm/damon/ops-common: use nr_accesses moving sum for quota score

SJ Park <[email protected]>
mm/damon/paddr: drop last same folio access check reuse optimization

SJ Park <[email protected]>
mm/damon/vaddr: drop last same folio access check optimization

SJ Park <[email protected]>
mm/damon/tests/core-kunit: catch test failure in test_merge_regions_of()

Robin Murphy <[email protected]>
iommu/arm-smmu-v3: Add HAFT support for SVA

Fan Wu <[email protected]>
power: supply: ab8500_fg: fix use-after-free on remove

Pan Chuang <[email protected]>
power: supply: ab8500_fg: Remove redundant dev_err()/dev_err_probe()

Song Hu <[email protected]>
Docs/ABI/damon: fix typo in intervals_goal sysfs path

Muchun Song <[email protected]>
mm/hugetlb_vmemmap: fix __hugetlb_vmemmap_optimize_folios()

Kiryl Shutsemau <[email protected]>
hugetlb: remove VMEMMAP_SYNCHRONIZE_RCU

Kiryl Shutsemau <[email protected]>
mm: rework compound_head() for power-of-2 sizeof(struct page)

Sergey Senozhatsky <[email protected]>
zram: set default primary compressor in zram_destroy_comps()

Yuwen Chen <[email protected]>
zram: fix the issue that the write - back limits might overflow

Sergey Senozhatsky <[email protected]>
zram: read slot block idx under slot lock

Sergey Senozhatsky <[email protected]>
zram: drop wb_limit_lock

Sergey Senozhatsky <[email protected]>
zram: take write lock in wb limit store handlers

Longlong Xia <[email protected]>
zram: fix out-of-bounds access in read_block_state()

Sergey Senozhatsky <[email protected]>
zram: fixup read_block_state()

Chuck Lever <[email protected]>
NFSD: Prevent client use-after-free during close_lru reaping

Chuck Lever <[email protected]>
NFSD: Prevent client use-after-free during blocked-lock reaping

Chuck Lever <[email protected]>
NFSD: Consolidate the revocation-path client unpin

Bryam Vargas <[email protected]>
smb: client: reject a tree connect response whose byte count is too small

David Howells <[email protected]>
cifs: Do some preparation prior to organising the function declarations

Frank Sorenson <[email protected]>
smb: client: fix OOB read/write from unvalidated DataOffset in coalesce_t2()

Frank Sorenson <[email protected]>
smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2

David Howells <[email protected]>
cifs: SMB1 split: Separate out SMB1 decls into smb1proto.h

David Howells <[email protected]>
cifs: SMB1 split: Create smb1proto.h for SMB1 declarations

David Howells <[email protected]>
cifs: Remove dead function prototypes

Jiangshan Yi <[email protected]>
smb: client: clear setuid/setgid bit on write with cifsacl/modefromsid/posix extensions

David Howells <[email protected]>
cifs: Scripted clean up fs/smb/client/smb2proto.h

David Howells <[email protected]>
cifs: Scripted clean up fs/smb/client/fs_context.h

David Howells <[email protected]>
cifs: Scripted clean up fs/smb/client/fscache.h

David Howells <[email protected]>
cifs: Scripted clean up fs/smb/client/cifs_unicode.h

Chuck Lever <[email protected]>
NFSD: Prevent client use-after-free during admin state revocation

Chuck Lever <[email protected]>
NFSD: Prevent client use-after-free during delegation revoke

Jeff Layton <[email protected]>
nfsd: convert global state_lock to per-net deleg_lock

Jeff Layton <[email protected]>
nfsd: close shrinker/GC/fsnotify vs per-net shutdown race in filecache

Jeff Layton <[email protected]>
nfsd: fix UAF in async copy cancel and shutdown

Jeff Layton <[email protected]>
nfsd: fix fcache_disposal UAF by inlining dispose state into nfsd_net

Jeff Layton <[email protected]>
nfsd: fix clock domain mismatch in clients_still_reclaiming()

Jeff Layton <[email protected]>
nfsd: widen nfsd_genl_rqstp address fields to sockaddr_storage

Jeff Layton <[email protected]>
nfsd: move struct nfsd_genl_rqstp to nfsctl.c

Jeff Layton <[email protected]>
nfsd: check nfsd4_acl_to_attr() return value in nfsd4_create()

Jiayuan Chen <[email protected]>
net: advertise TCP MSS from the configured MTU, not the learned PMTU

Yong Wang <[email protected]>
tcp: clamp route advmss to TCP_MIN_MSS

Eric Dumazet <[email protected]>
ipv4: use dst4_mtu() instead of dst_mtu()

Eric Dumazet <[email protected]>
ipv6: use dst6_mtu() instead of dst_mtu()

Eric Dumazet <[email protected]>
inet: add dst4_mtu() and dst6_mtu() helpers

Eric Dumazet <[email protected]>
ipv6: add some unlikely()/likely() clauses in ip6_output.c

Eric Dumazet <[email protected]>
ipv6: pass proto by value to ipv6_push_nfrag_opts() and ipv6_push_frag_opts()

Xiang Mei <[email protected]>
fuse: copy request headers via a stack buffer for io-uring

Joanne Koong <[email protected]>
fuse-uring: use named constants for io-uring iovec indices

Joanne Koong <[email protected]>
fuse-uring: refactor setting up copy state for payload copying

Joanne Koong <[email protected]>
fuse-uring: use enum types for header copying

Joanne Koong <[email protected]>
fuse-uring: refactor io-uring header copying from ring

Joanne Koong <[email protected]>
fuse-uring: refactor io-uring header copying to ring

Joanne Koong <[email protected]>
fuse: fix missing barrier when checking io-uring readiness

Ali Tariq <[email protected]>
PCI: starfive: Fix resource leaks on error paths in host_init()

Hal Feng <[email protected]>
PCI: starfive: Use regulator APIs to control the 3v3 power supply of PCIe slots

Oscar Ou <[email protected]>
lockd: fix swapped arguments in nlmsvc_match_ip()

Doruk Tan Ozturk <[email protected]>
ocfs2: validate directory-index entry counts when reading metadata

Joseph Qi <[email protected]>
ocfs2: validate dx_root extent list fields during block read

Vincent Donnefort <[email protected]>
ring-buffer: Make cpu_buffer::free_page a buffer_data_read_page

Jorijn van der Graaf <[email protected]>
ASoC: codecs: aw88261: only check PLL and clock state at power-up

Val Packett <[email protected]>
ASoC: codecs: aw88261: reduce log spam

Mukesh Ojha <[email protected]>
remoteproc: qcom: pas: Guard dtb metadata release with dtb_pas_id check

Mukesh Ojha <[email protected]>
firmware: qcom_scm: Rename peripheral as pas_id

Tejun Heo <[email protected]>
sched/core: Make core-sched flips wait for in-flight selections

John Stultz <[email protected]>
sched: Rework prev_balance() to avoid stale prev references

John Stultz <[email protected]>
sched: Add assert_balance_callbacks_empty helper

Tejun Heo <[email protected]>
sched_ext: Fix inverted ops.core_sched_before() invocation

Linkai Gong <[email protected]>
scsi: fnic: Use GFP_ATOMIC for VLAN alloc under spinlock

Abhijit Gangurde <[email protected]>
RDMA/ionic: Embed counter driver data in rdma_counter allocation

fangqiurong <[email protected]>
sched_ext: Fix exit_task leak on fork failure during enable

Chuck Lever <[email protected]>
svcrdma: Reject Read lists that exceed the page budget

Chuck Lever <[email protected]>
svcrdma: Reject oversized Read segments at decode time

Chuck Lever <[email protected]>
rpcrdma: arm rn_done before publishing the notification

Chuck Lever <[email protected]>
svcrdma: Reorder rpcrdma_rn_unregister before rdma_destroy_id

Chuck Lever <[email protected]>
svcrdma: Release transport resources synchronously

Chris Mason <[email protected]>
SUNRPC: fix gssx_dec_option_array error path bugs

Dave Jiang <[email protected]>
cxl/mce: Make the MCE notifier per-region

Smita Koralahalli <[email protected]>
cxl/region: Add helper to check Soft Reserved containment by CXL regions

Dan Williams <[email protected]>
dax/cxl, hmem: Initialize hmem early and defer dax_cxl binding

Terry Bowman <[email protected]>
cxl/ras: Fix cxl_rch_get_aer_severity() wrong severity register

Jiri Olsa <[email protected]>
bpf: Disable preemption in bpf_get_stackid

Jiri Olsa <[email protected]>
bpf: Use stack id functions instead of __bpf_get_stackid

Jiri Olsa <[email protected]>
bpf: Factor stackid_new_bucket from __bpf_get_stackid

Jiri Olsa <[email protected]>
bpf: Factor stackid_fastpath function from __bpf_get_stackid

Jiri Olsa <[email protected]>
bpf: Factor stackid_init function from __bpf_get_stackid

Haoxiang Li <[email protected]>
cpufreq: apple-soc: Fix OPP table cleanup

Rafael J. Wysocki <[email protected]>
ACPI: TAD: Add locking around AML evaluations

Rafael J. Wysocki <[email protected]>
ACPI: TAD: Rearrange RT data validation checking

Rafael J. Wysocki <[email protected]>
ACPI: x86/rtc-cmos: Use platform device for driver binding

Rafael J. Wysocki <[email protected]>
ACPI: x86: cmos_rtc: Create a CMOS RTC platform device

Christian Loehle <[email protected]>
ACPI: CPPC: Reject desired_perf reads on _CPC revision 4+

Nikhil Gurudasani <[email protected]>
erofs: skip sufficiently large global buffers when resizing

Jiangshan Yi <[email protected]>
HID: mcp2221: clear rxbuf after I2C/SMBus transfer completes

Florian Pradines <[email protected]>

    HID: mcp2221: fix OOB write in mcp2221_raw_event()

Doruk Tan Ozturk <[email protected]>
HID: sony: clean up device list on probe failure

Rosalie Wanders <[email protected]>
HID: sony: use guard() and scoped_guard()

Frank Sorenson <[email protected]>
cifs: add cifs_resize_file_locked() to guard fscache_resize_cookie() under i_rwsem

Huiwen He <[email protected]>
smb/client: emulate small EOF-extending mode 0 fallocate ranges

Huiwen He <[email protected]>
smb/client: reduce fallocate zero buffer allocation

ZhangGuoDong <[email protected]>
smb: move some definitions from common/smb2pdu.h into common/fscc.h

Sam Edwards <[email protected]>
ceph: properly decrypt filenames in vmalloc() buffers

Chuck Lever <[email protected]>
NFSD: Guard admin state-revocation walks with NFSD_NET_UP

Max Kellermann <[email protected]>
ceph: force a cap message when a deferred revoke can't be acked immediately

Michael Bommarito <[email protected]>
ceph: cap delegated inode count in ceph_parse_deleg_inos()

Terry Bowman <[email protected]>
cxl/ras: Fix cxl_rch_get_aer_info() out-of-bounds AER register read

Terry Bowman <[email protected]>
cxl/pci: Move CXL driver's RCH error handling into core/ras_rch.c

Neill Kapron <[email protected]>
usb: gadget: f_fs: Fix Use-After-Free in AIO error path

Gabriel Prostitis <[email protected]>
USB: gadget: ffs: fix mm lifetime handling

Brendan Jackman <[email protected]>
mm/page_alloc: don't spin_trylock() in NMI on UP

Roger Pau Monne <[email protected]>
x86/xen: fix init of balloon stats again

Roger Pau Monne <[email protected]>
xen/balloon: improve accuracy of initial balloon target for dom0

Li Xiasong <[email protected]>
mm/slub: fix missing debugfs entries for caches created before sysfs init

Vlastimil Babka <[email protected]>
mm/slab: move and refactor __kmem_cache_alias()

Dev Jain <[email protected]>
mm/rmap: use huge_ptep_get() in try_to_migrate_one()

Kairui Song <[email protected]>
mm/mglru: fix and remove redundant unevictable folio handling

Kairui Song <[email protected]>
mm/mglru: use the common routine for dirty/writeback reactivation

Muchun Song <[email protected]>
mm/hugetlb: initialize gigantic bootmem hugepage struct pages earlier

Kiryl Shutsemau <[email protected]>
mm/hugetlb: refactor code around vmemmap_walk

Kiryl Shutsemau (Meta) <[email protected]>
mm/hugetlb: defer vmemmap population for bootmem hugepages

FUJITA Tomonori <[email protected]>
rust: bug: prevent dead_code warning from warn_on!'s flags constant

Danilo Krummrich <[email protected]>
rust: devres: fix race between concurrent revokers

Danilo Krummrich <[email protected]>
rust: devres: fix race condition due to nesting

Chen Linxuan <[email protected]>
pidfd: hold exec_update_lock around namespace ioctl

Christian Brauner <[email protected]>
pidfs: simplify PIDFD_GET_<type>_NAMESPACE ioctls

Vivek Parikh <[email protected]>
ovl: fix double end_creating() on the casefold-mismatch path

Thorsten Blum <[email protected]>
crypto: atmel-ecc - avoid stale fallback key after set_secret failure

Thorsten Blum <[email protected]>
crypto: atmel-ecc - clean up and improve ECDH comments

Thorsten Blum <[email protected]>
crypto: atmel-ecc - replace min_t with min

Vinicius Costa Gomes <[email protected]>
crypto: iaa - unmap dst before software fallback on decompress

Giovanni Cabiddu <[email protected]>
crypto: iaa - fall back to software for multi-entry scatterlists

Eric Dumazet <[email protected]>
vlan: fix skb_under_panic and races when toggling HW VLAN offload

Kyle Zeng <[email protected]>
net/packet: defer vmalloc TX_RING free until skbs finish

Miklos Szeredi <[email protected]>
fuse: fix race between interrupt and resend

Miklos Szeredi <[email protected]>

    fuse: remove fm arg of args->end callback

Miklos Szeredi <[email protected]>
fuse: split off fuse_args and related definitions into a separate header

Joanne Koong <[email protected]>
fuse: publish io-uring queues with release semantics

Breno Leitao <[email protected]>
usb: xhci: bail out of setup if the controller is inaccessible

Niklas Neronin <[email protected]>
usb: xhci: simplify handling of Structural Parameters 1 values

Niklas Neronin <[email protected]>
usb: xhci: use cached HCSPARAMS1 value

Niklas Neronin <[email protected]>
usb: xhci: implement USB Port Register Set struct

Niklas Neronin <[email protected]>
usb: xhci: add USB Port Register Set struct

Niklas Neronin <[email protected]>
usb: xhci: add helper to read PORTSC register

Niklas Neronin <[email protected]>
usb: xhci: add tracing for PORTSC register writes

David Howells <[email protected]>
afs: Fix leak of ungot volume

Abdifatah Suruur <[email protected]>
ksmbd: fix use-after-free in oplock break notification

Mohamed Ahmed <[email protected]>

    drm/nouveau/gsp: fix vblank interrupts on GB20x

Mohamed Ahmed <[email protected]>

    drm/nouveau/disp: fix head state readback on GB20x

Mohamed Ahmed <[email protected]>

    drm/nouveau/disp: fix HDMI GCP AVMute register offsets on GB20x

Mohamed Ahmed <[email protected]>

    drm/nouveau/disp: fix HDMI vendor infoframes on GB20x

Mohamed Ahmed <[email protected]>
drm/nouveau/disp: route GSP-RM display MMIO through nvkm_disp_func hooks

Mohamed Ahmed <[email protected]>
drm/nouveau/disp: move the GSP HDMI GCP AVMute write to engine/disp

Mohamed Ahmed <[email protected]>
drm/nouveau/disp: move GSP head-timing ISR and vblank helpers to tu102.c

Zhenhao Wan <[email protected]>
drm/nouveau/uvmm: clear the dirty flag when unwinding an OP_UNMAP_SPARSE

Zhenhao Wan <[email protected]>
drm/nouveau/uvmm: fix premature region free on failed OP_UNMAP_SPARSE

Zhenhao Wan <[email protected]>
drm/nouveau/uvmm: fix NULL deref unwinding an OP_MAP_SPARSE op

Faith Ekstrand <[email protected]>
drm/nouveau: Use write-combined maps for coherent

Marek Czernohous <[email protected]>
drm/nouveau: unsubscribe the channel-kill event before the fence context

Mohamed Ahmed <[email protected]>
drm/nouveau/gsp: use per-version DP_CONFIG_STREAM params on r570 firmware

Shixiong Ou <[email protected]>
drm/sysfb: ofdrm: Fix is_avivo() constant comparison bug

Shixiong Ou <[email protected]>
drm/sysfb: ofdrm: Fix integer overflow in fb_size calculation

Thomas Zimmermann <[email protected]>
drm/sysfb: simpledrm: Improve stride validation

Thomas Zimmermann <[email protected]>
drm/sysfb: simpledrm: Improve panel-size validation

Thomas Zimmermann <[email protected]>
drm/sysfb: simpledrm: Improve framebuffer-size validation

Sunday Clement <[email protected]>
drm/amdkfd: Reject zero-sized AQL queue allocations after size halving

Vladimir Marioukhine <[email protected]>
drm/amdkfd: guard against NULL restore_mqd in CRIU queue restore

Xiaogang Chen <[email protected]>
drm/amdkfd: Fix the case that vm range is hole at svm_migrate_copy_to_vram

Xiaogang Chen <[email protected]>
drm/amdkfd: Fix error path at svm_migrate_copy_to_ram

Priya Hosur <[email protected]>
drm/amdkfd: Add TLB flush after MES queue eviction/suspension

Sunil Khatri <[email protected]>
drm/amdgpu: use AMDGPU_GPU_PAGE_SHIFT instead of PAGE_SHIFT

Sunil Khatri <[email protected]>
drm/amdgpu: update the fw version for gfx12 userqueues

Sunil Khatri <[email protected]>
drm/amdgpu: update the fw version for gfx11 userqueues

Kanala Ramalingeswara Reddy <[email protected]>
drm/amdgpu: Skip accessing psp rum time db for APUs

Guangshuo Li <[email protected]>
drm/amdgpu: fix autosuspend cleanup during removal

Yang Wang <[email protected]>
drm/amdgpu: Disable runtime PM for externally attached dGPUs

Xiang Liu <[email protected]>
drm/amdgpu: clamp the isolation index for rings outside a partition

Yang Wang <[email protected]>
drm/amdgpu: check thunderbolt before switcheroo registration

Thadeu Lima de Souza Cascardo <[email protected]>
drm: Fix drm_crtc_commit leak if signaled when PAGE_FLIP_EVENT is used

Kavan Smith <[email protected]>
drm/msm/dsi: round 6G byte clock rate to the PLL-achievable value

Tao Yu <[email protected]>
drm/gud: validate TV mode names before creating enum property

Deepanshu Kartikey <[email protected]>
drm/gud: NUL-terminate TV mode names read from the device

David (Ming Qiang) Wu <[email protected]>
drm/amdgpu/vcn: fix integer overflow in dec_msg buffer count check

Harry Wentland <[email protected]>
drm/amd/display: validate plane degamma LUT size for private color prop

Linkai Gong <[email protected]>
drm/amd/display: fix dc_lock leak on GPU reset error paths

Harry Wentland <[email protected]>
drm/amd/display: avoid divide-by-zero in __is_lut_linear()

Thomas Zimmermann <[email protected]>
drm/hibmc: Use drm_atomic_helper_check_plane_state()

Thomas Zimmermann <[email protected]>
drm/hibmc: Fix list of formats on the primary plane

Lyude Paul <[email protected]>
drm/nouveau/disp/r535: Add scanline position support + head state support

Amit Barzilai <[email protected]>

    drm/ssd130x: fix column and row end address in partial updates in ssd133x

Wentao Liang <[email protected]>
drm/sun4i: fix refcount leak in sun4i_backend_init_sat()

Amit Barzilai <[email protected]>

    drm/ssd130x: fix column and row end address in partial updates for ssd132x

Deepanshu Kartikey <[email protected]>
drm/i915: Guard against NULL driver_data in i915_pci_probe()

Danilo Krummrich <[email protected]>
drm: fix race between partial drm_dev_register() failure and ioctl

Johan Hovold <[email protected]>
drm/panel-edp: fix i2c adapter leak on probe failure

Johan Hovold <[email protected]>
drm/bridge: dw-hdmi: fix i2c adapter leak on probe failure

Osama Abdelkader <[email protected]>
drm/panthor: fix firmware control interface bounds checks

Osama Abdelkader <[email protected]>
drm/panthor: harden firmware build-info bounds checks

Matthew Auld <[email protected]>
drm/xe/vram: report FLAT_CCS base misalignment

Thomas Hellström <[email protected]>
drm/amdgpu: Fix init ordering in amdgpu_vram_mgr_init()

Chao Yu <[email protected]>
f2fs: fix to zero post-EOF data when extending file size

Chao Yu <[email protected]>

    f2fs: fix to pass folio->index to f2fs_sanity_check_node_footer()

Chen Changcheng <[email protected]>
f2fs: fix valid block count leak on data block allocation failure

Chao Yu <[email protected]>
f2fs: fix to clear dirty flag on folio in error path

Chao Yu <[email protected]>
f2fs: fix to off-by-one issue in f2fs_zero_post_eof_page()

Zhan Xusheng <[email protected]>
f2fs: fix i_size when pinned fallocate partially fails

Chao Yu <[email protected]>
f2fs: fix to avoid potential deadloop in f2fs_fsync_node_pages()

Daeho Jeong <[email protected]>
f2fs: fix to migrate all curseg types during free_segment_range

Wenjie Qi <[email protected]>
f2fs: avoid NULL checkpoint thread access in sysfs

Guanghui Yang <[email protected]>
f2fs: fix dentry folio leak in find_in_level

Chao Yu <[email protected]>
f2fs: fix to avoid potential section-unaligned pinfile

Wenjie Qi <[email protected]>
f2fs: return writeback error from collapse range

Zhan Xusheng <[email protected]>
f2fs: use the mount idmap for the owner check in f2fs_xattr_advise_set()

Joanne Chang <[email protected]>
f2fs: dirty directory inodes on mtime/ctime update

Chao Yu <[email protected]>
f2fs: fix to avoid move_range and defragment on device_alias file

Wenjie Qi <[email protected]>
f2fs: only redirty pinned folios in redirty_blocks

Hao-Qun Huang <[email protected]>
f2fs: reject overlapping move range after len expansion

Wenjie Qi <[email protected]>
f2fs: return symlink writeback errors

Nilesh Javali <[email protected]>
scsi: qla2xxx: Skip NVMe LS reject IOCB when FW not started

Nilesh Javali <[email protected]>
scsi: qla2xxx: Zero-init bsg stack buffers to avoid info leak

Nilesh Javali <[email protected]>
scsi: qla2xxx: Use coherent DMA buffer for D_Port diagnostics

Nilesh Javali <[email protected]>
scsi: qla2xxx: Hold vport_slock for host map update in report ID acquisition

Nilesh Javali <[email protected]>
scsi: qla2xxx: Drop vport reference under lock in report ID acquisition

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix NVMe abort reference leak on repeated abort

Nilesh Javali <[email protected]>
scsi: qla2xxx: Avoid req_q_map double-read in qla2x00_error_entry()

Nilesh Javali <[email protected]>
scsi: qla2xxx: Bound rsp_info_len to avoid OOB sense-data read

Nilesh Javali <[email protected]>
scsi: qla2xxx: Avoid double completion in async IOCB timeout

Nilesh Javali <[email protected]>
scsi: qla2xxx: Quiesce response IRQ before freeing request queue

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix response queue over-consumption in __qla_consume_iocb()

Nilesh Javali <[email protected]>
scsi: qla2xxx: Reject non-SCSI SRB on status IOCB fast path

Nilesh Javali <[email protected]>
scsi: qla2xxx: Don't query firmware state while chip is down

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix FCE trace enable parsing in debugfs

Nilesh Javali <[email protected]>
scsi: qla2xxx: Zero mailbox struct in qla2x00_get_firmware_state()

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix FCE trace use-after-free during firmware dump

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix cs84xx use-after-free on host teardown

Nilesh Javali <[email protected]>
scsi: qla2xxx: Serialize flash version read in reset handler

Nilesh Javali <[email protected]>
scsi: qla2xxx: Clamp MSI-X derived queue counts to avoid truncation

Nilesh Javali <[email protected]>
scsi: qla2xxx: Hold qpair lock when sending NVMe LS reject

Nilesh Javali <[email protected]>
scsi: qla2xxx: Bound image count in qla2x00_update_fru_versions()

Nilesh Javali <[email protected]>
scsi: qla2xxx: Check entry_status in qla24xx_modify_vp_config()

Nilesh Javali <[email protected]>
scsi: qla2xxx: Initialize NVMe abort_work once at submission

Nilesh Javali <[email protected]>
scsi: qla2xxx: Hold vport reference in qla24xx_report_id_acquisition()

Nilesh Javali <[email protected]>
scsi: qla2xxx: Fix Name Server logout detection on FWI2 adapters

Nilesh Javali <[email protected]>
scsi: qla2xxx: edif: Fix NULL pointer deref in RX SA delete check

Nilesh Javali <[email protected]>

    scsi: qla2xxx: Bound i2c->length in I2C bsg handlers

Nilesh Javali <[email protected]>
scsi: qla2xxx: Zero SFP DMA buffer in FRU/I2C bsg handlers

Jackson Lee <[email protected]>

    media: chips-media: wave5: Set inst->std during default format initialization

Jackson Lee <[email protected]>
media: chips-media: wave5: Guard bit depth check with initial_info_obtained

Hungyu Lin <[email protected]>
media: qcom: iris: use disable_irq() during power-off

Dikshita Agarwal <[email protected]>
media: qcom: iris: fix state-change debug log printing stale value

Ruoyu Wang <[email protected]>
media: zoran: Avoid freeing a registered video_device twice

Arash Golgol <[email protected]>
media: vimc: fix pixel format lookup in enum_framesizes

Uday Khare <[email protected]>
media: video-i2c: fix kthread error pointer left in kthread_vid_cap on failure

Mohammed EL Kadiri <[email protected]>
media: venus: fix payload size calculation in parse_raw_formats()

Mohammed EL Kadiri <[email protected]>
media: venus: fix payload size returned by parse_caps() and parse_alloc_mode()

Biren Pandya <[email protected]>
media: v4l2-fwnode: Fix fwnode leak in v4l2_fwnode_parse_link

Ming Qian <[email protected]>
media: v4l2-ctrls: Allow unknown HDR10 white point and luminance

Xu Rao <[email protected]>
media: v4l2-async: avoid deleting unlinked ASC entry on link error

Ilya Krutskih <[email protected]>
media: tda18250: fix possible integer overflow

Guangshuo Li <[email protected]>
media: saa7164: fix cleanup on resource allocation failure

Lei Huang <[email protected]>
media: s2255: check firmware size before reading trailing marker

HyeongJun An <[email protected]>
media: s2255: bound JPEG frame size before copying into the buffer

Tommaso Merciai <[email protected]>
media: rzg2l-cru: Align bytesperline to hardware DMA stride requirement

Valery Borovsky <[email protected]>
media: rtl2832_sdr: release URBs and stream buffers on start_streaming() failure

Valery Borovsky <[email protected]>
media: rtl2832_sdr: use vb2_video_unregister_device() on remove to fix DMA leak

Narasimharao Vadlamudi <[email protected]>
media: rkvdec: Propagate platform_get_irq() errors

Myeonghun Pak <[email protected]>
media: rc: sunxi-cir: Unregister rc device on probe failure

Guoniu Zhou <[email protected]>
media: nxp: imx8-isi: Use BIT_ULL() for 64-bit stream masks

Guoniu Zhou <[email protected]>
media: nxp: imx8-isi: Correct color map between V4L2 and ISI

Guoniu Zhou <[email protected]>
media: nxp: imx8-isi: Fix stream ID validation bypass in crossbar routing

Johan Hovold <[email protected]>
media: platform: mtk-mdp3: fix NULL deref on failed SCP lookup

Guangshuo Li <[email protected]>
media: platform: mtk-mdp3: Fix SCP device refcounting

Christian Hewitt <[email protected]>
media: meson: vdec: fix NULL pointer deref in vdec_try_fmt_common

Bryan O'Donoghue <[email protected]>

    media: iris: Enumerate cap->bus_info to differentiate between encoder and decoder

Cong Nguyen <[email protected]>
media: intel/ipu6: fix async notifier cleanup leak on parse error

Dave Stevenson <[email protected]>
media: imx355: Avoid calling imx355_power_off twice in error path

Biren Pandya <[email protected]>
media: i2c: ov7740: fix use-after-destroy in remove

Biren Pandya <[email protected]>
media: i2c: ov02a10: fix endpoint parsing use-after-free

Narasimharao Vadlamudi <[email protected]>
media: i2c: imx415: Return test pattern write errors

Narasimharao Vadlamudi <[email protected]>
media: i2c: imx415: Release runtime PM reference on VBLANK error

Martin Hecht <[email protected]>
media: i2c: alvium: Fix: Correct name of register in alvium_set_ctrl_auto_exposure

Shuangpeng Bai <[email protected]>
media: go7007: defer the ALSA v4l2 put until card release

Jiangong.Han <[email protected]>

    media: em28xx: fix use-after-free of dev_next->devlist on disconnect

Diego Fernando Mancera Gomez <[email protected]>
media: em28xx: defer audio-only extension registration

Fan Wu <[email protected]>
media: cx23885: cancel NetUP CI work before teardown

Bryam Vargas <[email protected]>
media: cx231xx: reject geometry changes while the VBI queue is busy

Ruoyu Wang <[email protected]>
media: cobalt: Avoid freeing ALSA private data twice

Dawei Feng <[email protected]>
media: cedrus: fix memory leak in cedrus_init_ctrls()

Ruoyu Wang <[email protected]>
media: cec: Serialize exclusive follower delivery

Yi Ding <[email protected]>
media: cec: meson: ao-cec-g12a: name the CEC core regmap to avoid debugfs clash

Hans Verkuil <[email protected]>
media: cec: extron-da-hd-4k-plus: add sanity check

Biren Pandya <[email protected]>
media: cec: disable delayed work before freeing an interrupted transmit

Jonas Karlman <[email protected]>
media: cec: core: Fix kmemleak due to missed rc_free_device() call

Ming Qian <[email protected]>
media: amphion: Remove obsolete frame_count check in venc_start_session

Valery Borovsky <[email protected]>
media: airspy: use vb2_video_unregister_device() on disconnect to fix NULL deref

Danilo Krummrich <[email protected]>
rust: drm: ioctl: fix unbounded lifetimes in ioctl handler arguments

Jérémy Jean <[email protected]>
LoongArch: Avoid preempt count underflow without probe

Wentao Guan <[email protected]>
LoongArch: Do not save/restore percpu base register in rethook trampoline

Nathan Chancellor <[email protected]>
LoongArch: Do not select HAVE_RUST when KASAN is enabled

Bibo Mao <[email protected]>

    LoongArch: Fix acpi_package_ids[] array overflow

Tiezhu Yang <[email protected]>
LoongArch: BPF: Refactor jump offset calculation in tail call

Tiezhu Yang <[email protected]>
LoongArch: BPF: Optimize redundant TCC loads in epilogue

Han Gao <[email protected]>
LoongArch: Add DIRECT_MAP_PHYSMEM_END definition

Zeng Chi <[email protected]>
LoongArch: KVM: Preserve memslot arch flags on KVM_MR_FLAGS_ONLY

Chaithanya Lagisetty <[email protected]>
LoongArch: KVM: Free init resources if kvm_init() fails

Tao Cui <[email protected]>
LoongArch: KVM: Fix TOCTOU race on pv_features

Zeng Chi <[email protected]>
LoongArch: KVM: Fix PC double advance in kernel MMIO read fast path

Marc Zyngier <[email protected]>
KVM: arm64: Correctly cap TLBI Range to the architural limit

Fuad Tabba <[email protected]>
KVM: arm64: vgic-its: Don't dereference a NULL collection on ITT save

Fuad Tabba <[email protected]>
KVM: arm64: vgic: Reset in_kernel on private IRQ allocation failure

Kajetan Puchalski <[email protected]>
KVM: arm64: vgic: Fix detection of MI on no pending LR

Qihang <[email protected]>
KVM: arm64: vgic-v3: take an LPI reference in vgic_v3_save_pending_tables

Marc Zyngier <[email protected]>
KVM: arm64: Sign-extend VA for range-based TLBI invalidation

Marc Zyngier <[email protected]>
KVM: arm64: Make VNCR invalidation participate in MMU invalidation retry

Marc Zyngier <[email protected]>
KVM: arm64: Correctly handle end of VA space TLBI invalidation

Marc Zyngier <[email protected]>
KVM: arm64: Handle negative S1 walk levels in VNCR TLB size evaluation

Marc Zyngier <[email protected]>
KVM: arm64: Consider SCTLR_EL2.M when mapping the L1 VNCR page

Christian Borntraeger <[email protected]>
KVM: s390: Restore sigset on error path

Christian Borntraeger <[email protected]>
KVM: s390: pv: Fix rc/rrc offset for PVM_DUMP

Christian Borntraeger <[email protected]>
KVM: s390: Fix memory corruption by not reinjecting CK machine checks

Christian Borntraeger <[email protected]>
KVM: s390: Zero initialize irq in reinject_machine_check

Christian Borntraeger <[email protected]>
KVM: s390: Take srcu when importing watchpoint data

Christian Borntraeger <[email protected]>
KVM: s390: Free guest debug data on vcpu destroy

Christian Borntraeger <[email protected]>
KVM: s390: Fix old_data leak in guest debug error path

Christian Borntraeger <[email protected]>
KVM: s390: Fix memory leak in guest debug handling

Christian Borntraeger <[email protected]>
KVM: s390: Fix length check __import_wp_info()

Sean Christopherson <[email protected]>
KVM: x86: Ensure runtime reads of disabled_quirks are resolved once

Sean Christopherson <[email protected]>

    KVM: x86: Serialize writes to disabled_quirks using kvm->lock

Carlos López <[email protected]>
KVM: x86: hyper-v: Clamp stimer deadline to avoid livelock

Phil Rosenthal <[email protected]>
KVM: x86/mmu: Consume the locked rmap value in the lockless rmap walk

Sean Christopherson <[email protected]>
KVM: x86/mmu: Use split "zap all fast" helpers when invalidating memslot

Sean Christopherson <[email protected]>
KVM: x86/mmu: Use CMPXCHG when clearing Accessed bit in TDP MMU

Sean Christopherson <[email protected]>
KVM: x86/mmu: Split kvm_mmu_zap_all_fast() into "front" and "back" halves

Sean Christopherson <[email protected]>
KVM: x86/mmu: Fold kvm_mmu_zap_memslot() into kvm_arch_flush_shadow_memslot()

Yosry Ahmed <[email protected]>
KVM: nVM: Ensure INVVPID is emulated on the correct physical CPU

Yosry Ahmed <[email protected]>
KVM: nVMX: Service local TLB flushes on failed nested VM-Enter

Sean Christopherson <[email protected]>
KVM: nVMX: Ensure KVM_REQ_GET_NESTED_STATE_PAGES is cleared on VM-Exit

Sean Christopherson <[email protected]>
KVM: nVMX: Decouple INVVPID operand checks from flushing of vpid02

Yosry Ahmed <[email protected]>
KVM: nVMX: Always flush vpid02 on first use

Amit Machhiwal <[email protected]>
KVM: PPC: Book3S HV: Validate arch_compat against host compatibility mode

Nikhil Gautam <[email protected]>
iio: light: opt4001: Fix reversed GENMASK() arguments in fault count mask

Nikhil Gautam <[email protected]>
iio: light: opt4001: Reject integration times with a non-zero seconds part

Nikhil Gautam <[email protected]>
iio: light: opt4001: Fix incompatible pointer type passed to div_u64_rem()

Nikhil Gautam <[email protected]>
iio: light: opt4001: Fix power down clearing bits of the wrong register

Vidhu Sarwal <[email protected]>
iio: light: opt4060: Fix incorrect register name in threshold read error message

Vidhu Sarwal <[email protected]>
iio: light: opt4060: Reject integration times with a non-zero seconds part

Paul Geurts <[email protected]>
iio: ti-ads7138: Disable STATS_EN bit while reading conversion results

Sanjay Chitroda <[email protected]>
iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register()

Cong Nguyen <[email protected]>
iio: srf04: fix pm_runtime handling on probe error path

Can Peng <[email protected]>
iio: pressure: mpl115: Fix runtime PM cleanup

Rupesh Majhi <[email protected]>
iio: pressure: dps310: fix NULL pointer dereference on ACPI probe

Vidhu Sarwal <[email protected]>
iio: light: ltrf216a: fix runtime PM reference leak in error path

Laxman Acharya Padhya <[email protected]>
iio: light: gp2ap002: Disable regulators on resume failure

Giorgi Tchankvetadze <[email protected]>
iio: light: cm32181: return zero after writing calibscale

Cong Nguyen <[email protected]>
iio: gyro: mpu3050: fix sign of raw angular velocity readings

Erick Henrique <[email protected]>
iio: dac: m62332: Fix regulator reference count imbalance

Babanpreet Singh <[email protected]>
iio: dac: ad3552r-hs: fix scnprintf() buffer bound in data source show

Linmao Li <[email protected]>
iio: chemical: sgp30: Handle IAQ thread creation failure

Fan Wu <[email protected]>
iio: chemical: atlas-sensor: use iio_trigger_poll_nested() to fix remove UAF

Moksh Panicker <[email protected]>
iio: chemical: atlas-sensor: fix PM reference leak in buffer postenable

Lars-Peter Clausen <[email protected]>
iio: buffer: Tie IIO dma fence lock lifetime to the fence

Lars-Peter Clausen <[email protected]>
iio: buffer: Make IIO DMA fence release RCU-safe

Lars-Peter Clausen <[email protected]>
iio: buffer: Fix potential use-after-free in anonymous buffer release

Cong Nguyen <[email protected]>
iio: adc: pac1921: fix wrong channel used in trigger handler read

Joshua Crofts <[email protected]>
iio: adc: max34408: add missing 'select REGMAP_I2C' to Kconfig

Antoniu Miclaus <[email protected]>
iio: adc: adi-axi-adc: add data size support for AD408X backend

Peter Ujfalusi <[email protected]>
ASoC: tegra210_i2s: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: tegra210_i2s: sort the Tegra264 register default table

Jon Hunter <[email protected]>
ASoC: tegra: Fix the MIXER enable default value

Jon Hunter <[email protected]>
ASoC: tegra: Sort ADMAIF register defaults

Jon Hunter <[email protected]>
ASoC: tegra: Sort MBDRC register defaults

Peter Ujfalusi <[email protected]>
ASoC: tegra210_mixer: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: tas2783-sdw: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: tas2783-sdw: drop duplicate reg_default entry

Peter Ujfalusi <[email protected]>
ASoC: tas2780: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: tas2764: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: tas2552: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: sti-sas: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: sgtl5000: sort the register default table

WenTao Liang <[email protected]>
ASoC: samsung: aries_audio_probe: double of_node_put due to direct assignment without of_node_get

Peter Ujfalusi <[email protected]>
ASoC: rt721-sdca-sdw: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt715: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt715-sdca: sort the register default tables

Peter Ujfalusi <[email protected]>
ASoC: rt715-sdca: drop duplicate reg_default entries

Peter Ujfalusi <[email protected]>
ASoC: rt712-sdca-sdw: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt712-sdca-dmic: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt711: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt711-sdca: sort the register default tables

Peter Ujfalusi <[email protected]>
ASoC: rt700: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt700: drop duplicate reg_default entry

Peter Ujfalusi <[email protected]>
ASoC: rt298: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt286: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt274: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt1318: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt1318-sdw: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt1316-sdw: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: rt1017-sdca-sdw: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: pm4125-sdw: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: pcm512x: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: ml26124: sort the register default table

Peter Ujfalusi <[email protected]>
ASoC: max9860: sort the register default table

Binbin Zhou <[email protected]>
ASoC: loongson: Fix error handling in ACPI property parsing

Haoxiang Li <[email protected]>
AsoC: intel: sst: fix PCI device reference leak on probe failure

Haoxiang Li <[email protected]>
ASoC: hdac_hda: Fix hlink refcount leak on component registration failure

Peter Ujfalusi <[email protected]>
ASoC: fsl_easrc: sort the register default table

wangdicheng <[email protected]>

    ASoC: fsl_easrc: Use div64_u64 for 64-by-64 division

Haoxiang Li <[email protected]>
ASoC: fsl: mpc5200-i2s: Free DMA resources on probe failure

Peter Ujfalusi <[email protected]>
ASoC: cx2072x: sort the register default table

Runyu Xiao <[email protected]>
ASoC: cs35l34: drain threaded IRQ before runtime suspend

Runyu Xiao <[email protected]>
ASoC: cs35l33: drain threaded IRQ before runtime suspend

Peter Ujfalusi <[email protected]>
ASoC: adau1761: sort the register default table

Linkai Gong <[email protected]>
i2c: mux: demux-pinctrl: fix OF node leak on kstrdup failure

Stephan Gerhold <[email protected]>
clk: qcom: gcc-mdm9607: Drop incorrect BIMC PLL and related clocks

Stephan Gerhold <[email protected]>
clk: qcom: gcc-mdm9607: Fix halt_reg for gcc_apss_axi_clk

Stephan Gerhold <[email protected]>
clk: qcom: gcc-mdm9607: Fix enable_reg for gcc_blsp1_sleep_clk

Stephan Gerhold <[email protected]>
clk: qcom: gcc-mdm9607: Drop incorrect system_noc_bfdcd_clk_src

Stephan Gerhold <[email protected]>
clk: qcom: gcc-mdm9607: Drop incorrect apss_tcu_clk_src

Heiko Stuebner <[email protected]>
clk: rockchip: rk3588: Don't change PLL rates when setting dclk_vop2_src

Stephan Gerhold <[email protected]>
clk: qcom: gcc-msm8939: Fix enable_reg for gcc_blsp1_sleep_clk

Stephan Gerhold <[email protected]>
clk: qcom: gcc-msm8916: Fix enable_reg for gcc_blsp1_sleep_clk

Martin Blumenstingl <[email protected]>
clk: meson: align gxbb_32k_clk_sel number of parents with actual count

Akari Tsuyukusa <[email protected]>
clk: mediatek: mt8196: Select REGMAP_MMIO for vlpckgen

Pavel Löbl <[email protected]>
clk: clocking-wizard: fix integer overflow in rate calculation

Sven Eckelmann <[email protected]>
batman-adv: bla: prevent CRC corruptions after claim flush

Sven Eckelmann <[email protected]>
batman-adv: bla: fix freeing of claims on meshif deletion

Sven Eckelmann <[email protected]>
batman-adv: dat: avoid unaligned fault in IP extraction

Sven Eckelmann <[email protected]>
batman-adv: mcast: linearize skbuff for packet generation

Sven Eckelmann <[email protected]>
batman-adv: mcast: ensure unshared skb for multicast packets

Zhiling Zou <[email protected]>
batman-adv: fix stale receive device on merged fragments

Pengpeng Hou <[email protected]>
mtd: rawnand: validate ONFI extended parameter page sections

Pengpeng Hou <[email protected]>
mtd: nand: realtek-ecc: add missing MODULE_DEVICE_TABLE()

Xu Rao <[email protected]>
mtd: mtdoops: free page bitmap when the backing MTD is removed

Pengpeng Hou <[email protected]>
mtd: afs: validate v2 image info bounds

Anthony Krowiak <[email protected]>
s390/vfio-ap: Fix required lock not held during update of ap_matrix_mdev object

Anthony Krowiak <[email protected]>
s390/vfio-ap: fix potential use of uninitialized apm_filtered bitmap

Anthony Krowiak <[email protected]>
s390/vfio-ap: Fix NULL deref in status_show() during queue probe

Anthony Krowiak <[email protected]>
s390/vfio-ap: Fix missing lock required to access list of ap_matrix_mdev objects

Anthony Krowiak <[email protected]>
s390/vfio-ap: Fix hot-unplug skipped when last AP adapter or domain removed

Anthony Krowiak <[email protected]>

    s390/vfio-ap: Fix dereference matrix_mdev->kvm without checking for NULL

Anthony Krowiak <[email protected]>
s390/vfio-ap: Fix control domain removal in vfio_ap_mdev_cfg_remove

Anthony Krowiak <[email protected]>
s390/vfio-ap: Fix stale do_remove flag across iterations in vfio_ap_mdev_cfg_remove

Anthony Krowiak <[email protected]>
s390/vfio-ap: fix stale pqap_hook pointer on error in vfio_ap_mdev_set_kvm()

Sourabh Jain <[email protected]>
powerpc/crash: stop watchdogs before booting kdump kernel

Sourabh Jain <[email protected]>
powerpc/pseries: Move H_WATCHDOG definitions to a common header

Sourabh Jain <[email protected]>
powerpc/pseries: Handle and log pseries-wdt registration failures

Muchun Song <[email protected]>
powerpc/mm: fix wrong addr_pfn tracking in compound vmemmap population

Jinjie Ruan <[email protected]>
powerpc/kexec_file: Prevent kexec range truncation

Jinjie Ruan <[email protected]>
powerpc/kexec_file: Fix null-ptr-def in extra size calculation

Helge Deller <[email protected]>
parisc: Fix alignment of asm statements in head.S

Pei Xiao <[email protected]>
parisc: eisa: Fix infinite loop when parsing invalid IRQ value

Bryam Vargas <[email protected]>
nvdimm/btt: reject an arena whose nfree is below the lane count

Narek Jilavyan <[email protected]>
mm/hugetlb_cgroup: call page_counter_set_max() outside VM_BUG_ON()

Longlong Xia <[email protected]>
mm/hugetlb: keep max_huge_pages when dissolving surplus folios

Wupeng Ma <[email protected]>
mm/hugetlb: fix missing migratable flag on same-node hugetlb migration

caina <[email protected]>
Revert "irqchip/mbigen: Fix mbigen node address layout"

Christian Marangi <[email protected]>
pmdomain: airoha: fix unselectable AIROHA_CPU_PM_DOMAIN kconfig

Shivam Kumar <[email protected]>
nvmet-tcp: reject unsolicited H2CData PDUs

Shivam Kumar <[email protected]>
nvmet-tcp: fix out-of-bounds write when receiving an over-long PDU

Kazuki Hanai <[email protected]>
nvmet-auth: Synchronize timeout work during SQ teardown

Tristan Madani <[email protected]>
nvme: add missing SRCU grace period in error path

Yehyeong Lee <[email protected]>
nvme-tcp: check the data direction of a C2HData PDU

Niklas Cassel <[email protected]>
nvme-fc: fix double free of fabrics options when nvme_add_ctrl() fails

Xu Rao <[email protected]>
nvme-fabrics: fix DHCHAP secret leak on parse failure

Takashi Iwai <[email protected]>
ALSA: pcm: Fix race between non-atomic ops and trigger-start

Runyu Xiao <[email protected]>
ALSA: harmony: initialize locks before requesting IRQ

HyeongJun An <[email protected]>
ALSA: rawmidi: Return the error from snd_rawmidi_input_params()

Khushit Shah <[email protected]>
arm64: errata: pass REVIDR when matching target implementation CPUs

Karl Mehltretter <[email protected]>
arm64: mm: Fix the lockless page-table walk in show_pte()

Ahmad Byagowi <[email protected]>
i2c: mux: Fix channel node leak on adapter add failure

Vasileios Almpanis <[email protected]>
i2c: core: fix debugfs UAF on adapter removal

Kathiravan Thirumoorthy <[email protected]>
i2c: qcom-geni: update frequency table to fix timing parameters

Hongbo Yao <[email protected]>
i2c: designware: Enable interrupt mask workaround for HJMC3001

Sizhe Liu <[email protected]>
perf hisi-ptt: Fix PTT trace TLP header parsing

Viktor Malik <[email protected]>
perf trace: Refactor augmented_raw_syscalls using bpf_for

Viktor Malik <[email protected]>
perf trace: Factor out BPF loop body

Dapeng Mi <[email protected]>
perf/x86/intel: Fix kernel address leakages in LBR stack

Lad Prabhakar <[email protected]>
rtc: rzn1: Disable alarm interrupt before reprogramming alarm registers

Lad Prabhakar <[email protected]>
rtc: rzn1: Handle unset alarm weekday in rzn1_rtc_read_alarm

Lad Prabhakar <[email protected]>
rtc: rzn1: Fix weekday underflow when alarm crosses month boundary

Lad Prabhakar <[email protected]>
rtc: rzn1: Handle EPROBE_DEFER for optional pps interrupt

Shakeel Butt <[email protected]>
memcg: make the v1 soft limit knob inert

Shakeel Butt <[email protected]>
memcg: bypass the reclaim and oom killer for dying tasks once oom_reaper is done

Pengpeng Hou <[email protected]>
Input: aiptek - validate raw macro indices before updating state

HE WEI(ギカク) <[email protected]>
fs/ntfs3: fix slab-out-of-bounds write in ni_create_attr_list()

Nirbhay Sharma <[email protected]>
fs/ntfs3: fix KMSAN uninit-value in ni_create_attr_list

Eric Dumazet <[email protected]>
mm/mempolicy: fix sleeping allocation in alloc_pages_bulk_weighted_interleave()

Masami Hiramatsu (Google) <[email protected]>
kprobes: Protect kprobe_blacklist with RCU

Ju Nan <[email protected]>
irqchip/stm32mp-exti: Fix the unit of the hwspinlock timeout

Bradley Morgan <[email protected]>
ima: Check for ERR_PTR from dentry_path() in validate_hash_algo()

Hajo Noerenberg <[email protected]>
ata: ahci: work around lost interrupts on Marvell 88SE61xx

Max Kellermann <[email protected]>
ceph: lock mutex in ceph_mds_check_access()

Hui Su <[email protected]>
bpf: Fix infinite loop in pcpu_freelist push with one possible CPU

Damien Le Moal <[email protected]>
block: flag zoned disks with GENHD_FL_NO_PART

Ulf Hansson <[email protected]>
cpuidle: psci: Fix support for probe deferral by dropping the faux device

Linkai Gong <[email protected]>
cpuidle: dt_idle_genpd: kfree() the original name allocation

Koichiro Den <[email protected]>
dmaengine: dw-edma: Initialize IRQ data before requesting IRQs

Koichiro Den <[email protected]>
dmaengine: dw-edma: Complete descriptors before pausing

Koichiro Den <[email protected]>
dmaengine: dw-edma: Fix HDMA channel status register access

Martin Kaiser <[email protected]>
dmaengine: fsl-edma: tracing: no ptr dereference during log output

Aneesh Kumar K.V (Arm) <[email protected]>
dma-direct: return struct page from dma_direct_alloc_from_pool()

Mikulas Patocka <[email protected]>
dm: fix resume-vs-remove race

Mikulas Patocka <[email protected]>
dm: fix race when loading and unloading a table

Ibrahim Hashimov <[email protected]>
HID: wacom: validate report length in wacom_intuos_pro2_bt_irq

Wei Jie Law <[email protected]>
HID: rmi: fix OOB access with undersized RMI reports

Shen Yongchao <[email protected]>
HID: bpf: serialize device reference release in struct_ops destroy path

Steven Rostedt <[email protected]>
ftrace: Synchronize the initialization of ftrace_ops

Yao Kai <[email protected]>
futex: Prevent rcuwait use-after-free during requeue PI

SJ Park <[email protected]>
mm/damon/core-kunit: check region count before testing in split_at()

SJ Park <[email protected]>
mm/damon/sysfs: kobject_del() target (normal), context and kdamond dirs

SJ Park <[email protected]>
mm/damon/sysfs: kobject_del() region and target (error) dirs

SJ Park <[email protected]>
mm/damon/sysfs-schemes: kobject_del() scheme region dirs

SJ Park <[email protected]>
mm/damon/sysfs-schemes: kobject_del() scheme quota goal dirs

SJ Park <[email protected]>
mm/damon/sysfs-schemes: kobject_del() scheme filter dirs

SJ Park <[email protected]>
mm/damon/sysfs-schemes: kobject_del() scheme dirs

SJ Park <[email protected]>
mm/damon/sysfs-schemes: kobject_del() scheme action destination dirs

SJ Park <[email protected]>
samples/damon/wsse: stop and free damon ctx when damon_call() fails

SJ Park <[email protected]>
samples/damon/wsse: handle damon_start() failure

SJ Park <[email protected]>
samples/damon/prcl: stop and free damon ctx when damon_call() fails

SJ Park <[email protected]>
samples/damon/prcl: handle damon_start() failure

SJ Park <[email protected]>
samples/damon/mtier: handle damon_stop() failure

SJ Park <[email protected]>
samples/damon/mtier: handle damon_start() failure

SJ Park <[email protected]>
mm/damon/vaddr-kunit: check region count in three_regions test

Runyu Xiao <[email protected]>
scsi: pm8001: Use rollback index when freeing MSI-X vectors

Thomas Lamprecht <[email protected]>
scsi: megaraid_sas: Limit NVMe request size to the PRP chain frame

Sujal Tuladhar <[email protected]>
scsi: target: iscsi: Reserve a terminator byte for the login payload

Honghui Jiang <[email protected]>
spi: Fix DMA mapping ownership on partial map failure

Can Peng <[email protected]>
spi: bcmbca-hsspi: disable clocks on resume failure

Can Peng <[email protected]>
spi: bcm63xx: disable clock on resume failure

Can Peng <[email protected]>
spi: bcm63xx-hsspi: disable clocks on resume failure

Viken Dadhaniya <[email protected]>
soc: qcom: geni-se: Use HW PROG_RAM_DEPTH to validate firmware size

Kanishka De Silva <[email protected]>
ublk: clear VM_MAYWRITE on read-only ublk char device mmap

Bryan Lim <[email protected]>
userfaultfd: reset err to be 0 when move_pages_ptes succeeded

Can Peng <[email protected]>
thermal/drivers/qoriq: Disable clock on resume failure

Can Peng <[email protected]>
thermal/drivers/imx: Disable clock on runtime resume failure

Arthur Gautier <[email protected]>
xhci: fix lost bounce buffers on TDs spanning several ring segments

Muhammad Bilal <[email protected]>
staging: rtl8723bs: fix OOB read in rtw_action_frame_parse()

Muhammad Bilal <[email protected]>
staging: rtl8723bs: fix OOB read / stack overflow in rtw_get_wps_attr()

Jeffin Philip <[email protected]>
usb: gadget: fix null pointer dereference in usb_put_function_instance()

Lovekesh Solanki <[email protected]>
USB: gadget: fix NULL pointer dereference in gadget_dev_ioctl()

Jeffin Philip <[email protected]>
usb: gadget: f_midi: initialize work in f_midi_alloc()

Ivy Lopez <[email protected]>
usb: gadget: f_midi2: fix use-after-free in string attribute show path

Aleksandr Nogikh <[email protected]>
usb: gadget: midi2: Fix null-pointer dereference in f_midi2_free_ep_reqs

Jameson Thies <[email protected]>
usb: typec: ucsi: displayport: Fix OOB altmode array index

Sven Peter <[email protected]>
usb: typec: tipd: Fix Thunderbolt altmode VDOs for cd321x

Amit Sunil Dhamne <[email protected]>
usb: typec: tcpm: constrain TCPM_SOURCING_VBUS event handling

Fan Wu <[email protected]>
usb: typec: qcom-pmic: cancel reset_work on stop

Fan Wu <[email protected]>
usb: typec: qcom-pmic-typec: drain cc_debounce_dwork if port_start() fails

Fan Wu <[email protected]>
usb: typec: qcom-pmic-typec: disable cc_debounce_dwork on stop

Myeonghun Pak <[email protected]>
usb: storage: realtek_cr: fix use-after-free on disconnect

Elson Serrao <[email protected]>
usb: dwc3: clear forceRM when issuing EndTransfer

Andy Shevchenko <[email protected]>
usb: f_mass_storage: Bump local buffer size in fsg_common_create_luns()

Liu Qi <[email protected]>
usb-storage: ene_ub6250: fix race between scan work and probe

Shuangpeng Bai <[email protected]>
media: usbtv: keep device alive while ALSA card exists

Stephan Gerhold <[email protected]>
clk: qcom: gcc-mdm9607: Increase delay for USB PHY reset

HyeongJun An <[email protected]>
ALSA: usb-audio: fix OOB write in snd_usbmidi_us122l_output()

Griffin Kroah-Hartman <[email protected]>
usb: image: mdc800: change kmalloc() to kzalloc()

Hari Mishal <[email protected]>
drm/amd/display: fix division by zero in get_estimated_bw()

Anton Protopopov <[email protected]>
bpf: fix the return value of push_stack

Linus Torvalds <[email protected]>
drm/xe: Don't hand out the flat CCS storage as usable VRAM

Sun Jian <[email protected]>
fsnotify: inotify: pass mark connector to fsnotify_recalc_mask()

Mario Limonciello <[email protected]>
drm/amd: Drop calls to restore power limit and clock from smu_resume()

Ali Ahmet Memis <[email protected]>
mfd: qnap-mcu: keep the reply buffer alive past a command timeout

FUJITA Tomonori <[email protected]>
objtool/rust: add one more noreturn Rust function

Youngjae Kwon <[email protected]>
fsnotify: Fix stale object mask after concurrent mark updates

Jinjie Ruan <[email protected]>
entry: Fix seccomp bypass after ptrace with TSYNC

Dev Jain <[email protected]>
mm/page_vma_mapped: use huge_ptep_get() for hugetlb

Yuqi Xu <[email protected]>
openvswitch: Fix CT limit teardown use-after-free

Norbert Szetei <[email protected]>
net: skbuff: don't skb_tx_error() the source skb in skb_zerocopy()

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

Diffstat:

 Documentation/ABI/testing/sysfs-kernel-mm-damon    |   8 +-
 Documentation/admin-guide/cgroup-v1/memory.rst     |  49 +--
 Documentation/trace/hisi-ptt.rst                   |  28 +-
 .../media/v4l/ext-ctrls-colorimetry.rst            |  12 +-
 Makefile                                           |   4 +-
 arch/arm64/include/asm/kvm_nested.h                |  20 ++
 arch/arm64/kernel/cpu_errata.c                     |   2 +-
 arch/arm64/kvm/at.c                                |   2 -
 arch/arm64/kvm/nested.c                            |  94 ++++--
 arch/arm64/kvm/sys_regs.c                          |  11 +
 arch/arm64/kvm/vgic/vgic-init.c                    |   1 +
 arch/arm64/kvm/vgic/vgic-its.c                     |   8 +
 arch/arm64/kvm/vgic/vgic-v3-nested.c               |   2 +-
 arch/arm64/kvm/vgic/vgic-v3.c                      |  12 +-
 arch/arm64/mm/fault.c                              |  12 +-
 arch/loongarch/Kconfig                             |   2 +-
 arch/loongarch/include/asm/kvm_host.h              |   1 +
 arch/loongarch/include/asm/pgtable.h               |   7 +
 arch/loongarch/kernel/acpi.c                       |   3 +-
 arch/loongarch/kernel/kprobes.c                    |   3 +
 arch/loongarch/kernel/rethook_trampoline.S         |   2 -
 arch/loongarch/kvm/exit.c                          |   1 -
 arch/loongarch/kvm/main.c                          |   6 +-
 arch/loongarch/kvm/mmu.c                           |  10 +
 arch/loongarch/kvm/vcpu.c                          |   6 +-
 arch/loongarch/kvm/vm.c                            |   1 +
 arch/loongarch/net/bpf_jit.c                       |  22 +-
 arch/parisc/kernel/head.S                          |   1 +
 arch/powerpc/include/asm/papr-watchdog.h           |  64 ++++
 arch/powerpc/include/asm/reg.h                     |  12 +
 arch/powerpc/kexec/file_load_64.c                  |   2 +-
 arch/powerpc/kexec/ranges.c                        |  12 +-
 arch/powerpc/kvm/book3s_hv.c                       |  15 +-
 arch/powerpc/kvm/powerpc.c                         |   6 +
 arch/powerpc/mm/book3s64/radix_pgtable.c           |   7 +-
 arch/powerpc/platforms/pseries/setup.c             |  28 +-
 arch/s390/include/asm/nmi.h                        |   3 +
 arch/s390/kernel/nmi.c                             |   5 +-
 arch/s390/kvm/guestdbg.c                           |   9 +-
 arch/s390/kvm/interrupt.c                          |  26 +-
 arch/s390/kvm/kvm-s390.c                           |  15 +-
 arch/x86/events/intel/lbr.c                        |  12 +-
 arch/x86/kernel/rtc.c                              |   4 +
 arch/x86/kvm/hyperv.c                              |  25 +-
 arch/x86/kvm/mmu/mmu.c                             | 102 +++---
 arch/x86/kvm/mmu/tdp_iter.h                        |   7 +
 arch/x86/kvm/mmu/tdp_mmu.c                         |  20 +-
 arch/x86/kvm/vmx/nested.c                          |  75 +++--
 arch/x86/kvm/x86.c                                 |   5 +-
 arch/x86/kvm/x86.h                                 |   2 +-
 block/genhd.c                                      |   7 +
 drivers/acpi/acpi_pnp.c                            |   2 +-
 drivers/acpi/acpi_tad.c                            | 186 +++++++----
 drivers/acpi/cppc_acpi.c                           |  13 +-
 drivers/acpi/x86/cmos_rtc.c                        |  13 +-
 drivers/ata/ahci.c                                 |  49 +++
 drivers/block/ublk_drv.c                           |   6 +
 drivers/block/zram/zram_drv.c                      |  65 ++--
 drivers/block/zram/zram_drv.h                      |   1 -
 drivers/clk/mediatek/Kconfig                       |   1 +
 drivers/clk/meson/gxbb.c                           |   2 +-
 drivers/clk/qcom/gcc-mdm9607.c                     | 182 +----------
 drivers/clk/qcom/gcc-msm8916.c                     |   5 +-
 drivers/clk/qcom/gcc-msm8939.c                     |   5 +-
 drivers/clk/rockchip/clk-rk3588.c                  |   2 +-
 drivers/clk/xilinx/clk-xlnx-clock-wizard.c         |   4 +-
 drivers/cpufreq/apple-soc-cpufreq.c                |  36 +--
 drivers/cpufreq/cppc_cpufreq.c                     |   2 +-
 drivers/cpuidle/cpuidle-psci.c                     |  42 +--
 drivers/cpuidle/dt_idle_genpd.c                    |   3 +-
 drivers/crypto/atmel-ecc.c                         |  50 ++-
 drivers/crypto/intel/iaa/iaa_crypto_main.c         | 138 ++++----
 drivers/crypto/intel/iaa/iaa_crypto_stats.c        |   9 +
 drivers/crypto/intel/iaa/iaa_crypto_stats.h        |   2 +
 drivers/cxl/core/Makefile                          |   1 +
 drivers/cxl/core/core.h                            |  11 +-
 drivers/cxl/core/mbox.c                            |   8 -
 drivers/cxl/core/mce.c                             |  27 +-
 drivers/cxl/core/pci.c                             | 115 -------
 drivers/cxl/core/ras_rch.c                         | 136 ++++++++
 drivers/cxl/core/region.c                          | 122 ++++---
 drivers/cxl/cxl.h                                  |   9 +-
 drivers/cxl/cxlmem.h                               |   2 -
 drivers/dax/Makefile                               |   3 +-
 drivers/dax/cxl.c                                  |  27 +-
 drivers/dma/dw-edma/dw-edma-core.c                 |  23 +-
 drivers/dma/dw-edma/dw-hdma-v0-core.c              |   2 +-
 drivers/dma/fsl-edma-trace.h                       |   4 +-
 drivers/firmware/qcom/qcom_scm.c                   |  30 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c   |   7 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |  26 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c            |   6 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c             |   6 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c       |   7 +-
 drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c             |   8 +-
 drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c             |   8 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c              |  10 +-
 drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c              |  10 +-
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c           |   3 +-
 .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c  |  23 +-
 drivers/gpu/drm/amd/amdkfd/kfd_migrate.c           |  56 ++--
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |   6 +
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_color.c    |  13 +
 .../display/dc/link/protocols/link_dp_dpia_bw.c    |   5 +
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c          |  13 -
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c          |   3 +-
 drivers/gpu/drm/drm_atomic_uapi.c                  |   2 +
 drivers/gpu/drm/drm_drv.c                          |  34 +-
 drivers/gpu/drm/gud/gud_connector.c                |  12 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c     |  54 +---
 drivers/gpu/drm/i915/i915_pci.c                    |   3 +
 drivers/gpu/drm/msm/dsi/dsi_host.c                 |  12 +
 drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h |   1 +
 drivers/gpu/drm/nouveau/nouveau_chan.c             |   9 +-
 drivers/gpu/drm/nouveau/nouveau_sgdma.c            |   4 +-
 drivers/gpu/drm/nouveau/nouveau_uvmm.c             |   6 +-
 drivers/gpu/drm/nouveau/nvkm/engine/device/base.c  |  10 +-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild    |   1 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c   |  13 +-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gb202.c   | 191 +++++++++++
 drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c   |   4 +-
 drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h    |   4 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h     |   1 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h    |  17 +
 drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c   |  86 ++++-
 .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c | 129 +++-----
 .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c |  64 ++++
 .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c  |   9 +
 .../nouveau/nvkm/subdev/gsp/rm/r570/nvrm/disp.h    |   2 +
 drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h    |   5 +
 drivers/gpu/drm/panel/panel-edp.c                  |  19 +-
 drivers/gpu/drm/panthor/panthor_fw.c               |  22 +-
 drivers/gpu/drm/solomon/ssd130x.c                  |   9 +-
 drivers/gpu/drm/sun4i/sun4i_backend.c              |   2 +-
 drivers/gpu/drm/sysfb/ofdrm.c                      |   8 +-
 drivers/gpu/drm/sysfb/simpledrm.c                  |  74 ++++-
 drivers/gpu/drm/xe/xe_vram.c                       |  26 +-
 drivers/hid/bpf/hid_bpf_struct_ops.c               |  17 +-
 drivers/hid/hid-mcp2221.c                          |  15 +-
 drivers/hid/hid-rmi.c                              |  46 ++-
 drivers/hid/hid-sony.c                             |  78 ++---
 drivers/hid/wacom_wac.c                            |  13 +
 drivers/i2c/busses/i2c-designware-platdrv.c        |   2 +-
 drivers/i2c/busses/i2c-qcom-geni.c                 |   4 +-
 drivers/i2c/i2c-core-base.c                        |   6 +
 drivers/i2c/i2c-mux.c                              |   1 +
 drivers/i2c/muxes/i2c-demux-pinctrl.c              |   1 +
 drivers/iio/adc/Kconfig                            |   1 +
 drivers/iio/adc/adi-axi-adc.c                      |  30 ++
 drivers/iio/adc/pac1921.c                          |   2 +-
 drivers/iio/adc/ti-ads7138.c                       |  42 ++-
 drivers/iio/chemical/atlas-sensor.c                |  19 +-
 drivers/iio/chemical/sgp30.c                       |   3 +
 drivers/iio/dac/ad3552r-hs.c                       |   2 +-
 drivers/iio/dac/m62332.c                           |  17 +-
 drivers/iio/gyro/mpu3050-core.c                    |   2 +-
 drivers/iio/industrialio-buffer.c                  |  38 ++-
 drivers/iio/light/cm32181.c                        |   2 +-
 drivers/iio/light/gp2ap002.c                       |  10 +-
 drivers/iio/light/ltrf216a.c                       |   3 +-
 drivers/iio/light/opt4001.c                        |  37 +--
 drivers/iio/light/opt4060.c                        |   5 +-
 drivers/iio/pressure/dps310.c                      |   3 +-
 drivers/iio/pressure/mpl115.c                      |  11 +-
 drivers/iio/proximity/srf04.c                      |   1 +
 drivers/iio/temperature/hid-sensor-temperature.c   |   3 +-
 drivers/infiniband/hw/ionic/ionic_hw_stats.c       |  95 +++---
 drivers/infiniband/hw/ionic/ionic_ibdev.h          |  11 +-
 drivers/input/tablet/aiptek.c                      |  13 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c    |  14 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c        |   9 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h        |   3 +
 drivers/irqchip/irq-mbigen.c                       |  20 +-
 drivers/irqchip/irq-stm32mp-exti.c                 |   4 +-
 drivers/md/dm.c                                    |  14 +-
 drivers/media/cec/core/cec-adap.c                  |  10 +-
 drivers/media/cec/core/cec-core.c                  |   2 -
 drivers/media/cec/platform/meson/ao-cec-g12a.c     |   1 +
 .../extron-da-hd-4k-plus/extron-da-hd-4k-plus.c    |   3 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c          |  23 +-
 drivers/media/i2c/alvium-csi2.c                    |   2 +-
 drivers/media/i2c/imx355.c                         |   3 +-
 drivers/media/i2c/imx415.c                         |   4 +-
 drivers/media/i2c/ov02a10.c                        |  12 +-
 drivers/media/i2c/ov7740.c                         |   4 +-
 drivers/media/i2c/video-i2c.c                      |   8 +-
 drivers/media/pci/cobalt/cobalt-alsa-main.c        |   1 -
 drivers/media/pci/cx23885/cimax2.c                 |   1 +
 drivers/media/pci/intel/ipu6/ipu6-isys.c           |   1 +
 drivers/media/pci/saa7164/saa7164-core.c           |   8 +-
 drivers/media/pci/zoran/zoran_card.c               |   2 +-
 drivers/media/platform/amphion/venc.c              |   2 -
 .../platform/chips-media/wave5/wave5-vpu-dec.c     |   3 +-
 .../platform/chips-media/wave5/wave5-vpu-enc.c     |   6 +-
 .../media/platform/mediatek/mdp3/mtk-mdp3-core.c   |   6 +-
 .../platform/nxp/imx8-isi/imx8-isi-crossbar.c      |   6 +-
 .../media/platform/nxp/imx8-isi/imx8-isi-video.c   |   2 +-
 drivers/media/platform/qcom/iris/iris_state.c      |   2 +-
 drivers/media/platform/qcom/iris/iris_vidc.c       |  11 +-
 drivers/media/platform/qcom/iris/iris_vpu_common.c |   2 +-
 drivers/media/platform/qcom/venus/hfi_parser.c     |   9 +-
 .../media/platform/renesas/rzg2l-cru/rzg2l-video.c |   5 +
 drivers/media/platform/rockchip/rkvdec/rkvdec.c    |   4 +-
 drivers/media/rc/sunxi-cir.c                       |   9 +-
 drivers/media/test-drivers/vimc/vimc-capture.c     |   4 +-
 drivers/media/tuners/tda18250.c                    |   4 +-
 drivers/media/usb/airspy/airspy.c                  |  19 +-
 drivers/media/usb/cx231xx/cx231xx-video.c          |   4 +-
 drivers/media/usb/em28xx/em28xx-cards.c            |   3 +-
 drivers/media/usb/em28xx/em28xx-core.c             |   2 +
 drivers/media/usb/go7007/snd-go7007.c              |  10 +-
 drivers/media/usb/s2255/s2255drv.c                 |  11 +
 drivers/media/usb/usbtv/usbtv-audio.c              |  11 +
 drivers/media/v4l2-core/v4l2-async.c               |   1 -
 drivers/media/v4l2-core/v4l2-ctrls-core.c          |  49 ++-
 drivers/media/v4l2-core/v4l2-fwnode.c              |   2 +
 drivers/mfd/qnap-mcu.c                             |  13 +-
 drivers/mtd/mtdoops.c                              |   3 +
 drivers/mtd/nand/ecc-realtek.c                     |   1 +
 drivers/mtd/nand/raw/nand_onfi.c                   |  27 +-
 drivers/mtd/parsers/afs.c                          |   7 +
 drivers/nvdimm/btt.c                               |   8 +
 drivers/nvme/host/core.c                           |   3 +
 drivers/nvme/host/fabrics.c                        |   2 +
 drivers/nvme/host/fc.c                             |  26 +-
 drivers/nvme/host/tcp.c                            |   7 +
 drivers/nvme/target/auth.c                         |   6 +
 drivers/nvme/target/core.c                         |   2 +-
 drivers/nvme/target/nvmet.h                        |   2 +
 drivers/nvme/target/tcp.c                          |  10 +
 drivers/parisc/eisa.c                              |   5 +
 drivers/pci/controller/plda/pcie-starfive.c        |  36 ++-
 drivers/pmdomain/mediatek/Kconfig                  |   5 +-
 drivers/power/supply/ab8500_fg.c                   |  32 +-
 drivers/remoteproc/qcom_q6v5_pas.c                 |   9 +-
 drivers/rtc/rtc-cmos.c                             |  10 +
 drivers/rtc/rtc-rzn1.c                             |  30 +-
 drivers/s390/crypto/vfio_ap_ops.c                  | 203 ++++++++----
 drivers/scsi/fnic/fip.c                            |   2 +-
 drivers/scsi/megaraid/megaraid_sas_base.c          |  13 +-
 drivers/scsi/pm8001/pm8001_init.c                  |   4 +-
 drivers/scsi/qla2xxx/qla_attr.c                    |   6 +-
 drivers/scsi/qla2xxx/qla_bsg.c                     |  39 ++-
 drivers/scsi/qla2xxx/qla_dbg.c                     |   2 +-
 drivers/scsi/qla2xxx/qla_dfs.c                     |   4 +-
 drivers/scsi/qla2xxx/qla_edif.c                    |   3 +
 drivers/scsi/qla2xxx/qla_gs.c                      |   4 +-
 drivers/scsi/qla2xxx/qla_init.c                    |  61 +++-
 drivers/scsi/qla2xxx/qla_inline.h                  |  13 +
 drivers/scsi/qla2xxx/qla_isr.c                     |  39 ++-
 drivers/scsi/qla2xxx/qla_mbx.c                     |  28 +-
 drivers/scsi/qla2xxx/qla_nvme.c                    |  31 +-
 drivers/scsi/qla2xxx/qla_os.c                      |  14 +-
 drivers/soc/qcom/qcom-geni-se.c                    |  24 +-
 drivers/spi/spi-bcm63xx-hsspi.c                    |   8 +-
 drivers/spi/spi-bcm63xx.c                          |   6 +-
 drivers/spi/spi-bcmbca-hsspi.c                     |   8 +-
 drivers/spi/spi.c                                  |  34 +-
 drivers/staging/media/meson/vdec/vdec.c            |   4 +-
 drivers/staging/media/sunxi/cedrus/cedrus.c        |   4 +-
 drivers/staging/rtl8723bs/core/rtw_ieee80211.c     |   7 +
 drivers/target/iscsi/iscsi_target_login.c          |   2 +-
 drivers/thermal/imx_thermal.c                      |   9 +-
 drivers/thermal/qoriq_thermal.c                    |  13 +-
 drivers/usb/dwc3/ep0.c                             |   2 +-
 drivers/usb/dwc3/gadget.c                          |  21 +-
 drivers/usb/gadget/function/f_fs.c                 |  31 +-
 drivers/usb/gadget/function/f_mass_storage.c       |   2 +-
 drivers/usb/gadget/function/f_midi.c               |   2 +-
 drivers/usb/gadget/function/f_midi2.c              |  17 +-
 drivers/usb/gadget/functions.c                     |   2 +-
 drivers/usb/gadget/legacy/inode.c                  |   3 +-
 drivers/usb/host/xhci-debugfs.c                    |  21 +-
 drivers/usb/host/xhci-hub.c                        | 117 ++++---
 drivers/usb/host/xhci-mem.c                        |  34 +-
 drivers/usb/host/xhci-pci.c                        |   6 +-
 drivers/usb/host/xhci-ring.c                       |  40 ++-
 drivers/usb/host/xhci-tegra.c                      |  12 +-
 drivers/usb/host/xhci-trace.h                      |   5 +
 drivers/usb/host/xhci.c                            |  81 +++--
 drivers/usb/host/xhci.h                            |  46 ++-
 drivers/usb/image/mdc800.c                         |   4 +-
 drivers/usb/storage/ene_ub6250.c                   |   2 +
 drivers/usb/storage/realtek_cr.c                   |   9 +-
 .../usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c    |   2 +
 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c |   5 +
 drivers/usb/typec/tcpm/tcpm.c                      |  28 +-
 drivers/usb/typec/tipd/core.c                      |  17 +-
 drivers/usb/typec/tipd/tps6598x.h                  |   4 +-
 drivers/usb/typec/ucsi/displayport.c               |   2 +-
 drivers/watchdog/pseries-wdt.c                     |  53 +--
 drivers/xen/balloon.c                              |  56 ++--
 fs/afs/callback.c                                  |   1 +
 fs/ceph/caps.c                                     |  63 +++-
 fs/ceph/crypto.c                                   |  46 ++-
 fs/ceph/mds_client.c                               |  71 +++-
 fs/ceph/mds_client.h                               |   2 +
 fs/ceph/super.h                                    |  13 +
 fs/erofs/zutil.c                                   |   2 +
 fs/f2fs/data.c                                     |   5 +-
 fs/f2fs/dir.c                                      |   7 +-
 fs/f2fs/file.c                                     | 154 ++++++---
 fs/f2fs/gc.c                                       |   2 +-
 fs/f2fs/inline.c                                   |   2 +-
 fs/f2fs/namei.c                                    |  17 +-
 fs/f2fs/node.c                                     |   9 +-
 fs/f2fs/sysfs.c                                    |   7 +-
 fs/f2fs/xattr.c                                    |   2 +-
 fs/fuse/args.h                                     |  65 ++++
 fs/fuse/cuse.c                                     |   7 +-
 fs/fuse/dev.c                                      |  44 +--
 fs/fuse/dev_uring.c                                | 189 +++++++----
 fs/fuse/file.c                                     |  22 +-
 fs/fuse/fuse_i.h                                   |  53 +--
 fs/fuse/inode.c                                    |  10 +-
 fs/lockd/svcsubs.c                                 |   2 +-
 fs/nfsd/filecache.c                                | 115 +++----
 fs/nfsd/netns.h                                    |  11 +-
 fs/nfsd/nfs4proc.c                                 | 139 ++++++--
 fs/nfsd/nfs4state.c                                | 170 +++++++---
 fs/nfsd/nfsctl.c                                   |  25 +-
 fs/nfsd/nfsd.h                                     |  15 -
 fs/nfsd/state.h                                    |   2 +-
 fs/notify/fanotify/fanotify_user.c                 |  12 +-
 fs/notify/inotify/inotify_user.c                   |  15 +-
 fs/ntfs3/frecord.c                                 |  20 +-
 fs/ocfs2/dir.c                                     |  71 +++-
 fs/overlayfs/dir.c                                 |   1 -
 fs/pidfs.c                                         | 136 +++++---
 fs/smb/client/cifs_debug.c                         |   4 +-
 fs/smb/client/cifs_spnego.h                        |   2 -
 fs/smb/client/cifs_unicode.h                       |   3 -
 fs/smb/client/cifsfs.c                             |   5 +-
 fs/smb/client/cifsfs.h                             |   6 +-
 fs/smb/client/cifsglob.h                           |  10 +-
 fs/smb/client/cifsproto.h                          |  29 +-
 fs/smb/client/cifssmb.c                            | 146 +++++++++
 fs/smb/client/compress.c                           |  21 +-
 fs/smb/client/compress.h                           |  19 +-
 fs/smb/client/connect.c                            | 142 --------
 fs/smb/client/dir.c                                |   2 +-
 fs/smb/client/dns_resolve.h                        |   4 -
 fs/smb/client/fs_context.c                         |   2 +-
 fs/smb/client/fs_context.h                         |  16 +-
 fs/smb/client/fscache.h                            |  10 +-
 fs/smb/client/inode.c                              |  61 +++-
 fs/smb/client/misc.c                               |   1 +
 fs/smb/client/netmisc.c                            |   2 +-
 fs/smb/client/smb1ops.c                            | 171 ----------
 fs/smb/client/smb1proto.h                          |  40 +++
 fs/smb/client/smb1transport.c                      | 198 ++++++++++++
 fs/smb/client/smb2file.c                           |   3 +-
 fs/smb/client/smb2inode.c                          |   1 -
 fs/smb/client/smb2maperror.c                       |   3 +-
 fs/smb/client/smb2ops.c                            |  99 ++++--
 fs/smb/client/smb2pdu.c                            |   5 +-
 fs/smb/client/smb2proto.h                          |  14 +-
 fs/smb/client/trace.h                              | 151 +++++++++
 fs/smb/server/oplock.c                             |  61 +++-
 include/linux/acpi.h                               |  14 +
 include/linux/firmware/qcom/qcom_scm.h             |  10 +-
 include/linux/huge_mm.h                            |   7 +-
 include/linux/hugetlb.h                            |   5 +
 include/linux/kprobes.h                            |   1 +
 include/linux/lockd/lockd.h                        |   2 +-
 include/linux/memcontrol.h                         |  10 +
 include/linux/mm.h                                 |   2 -
 include/linux/rmap.h                               |   9 +-
 include/linux/soc/qcom/geni-se.h                   |   4 +
 include/net/dst.h                                  |   6 +
 include/net/ip.h                                   |  25 ++
 include/net/ip6_route.h                            |  43 +++
 include/net/ipv6.h                                 |  10 +-
 include/net/tcp.h                                  |   5 +
 kernel/bpf/percpu_freelist.c                       |  35 +-
 kernel/bpf/percpu_freelist.h                       |   1 +
 kernel/bpf/stackmap.c                              | 173 ++++++----
 kernel/bpf/verifier.c                              |  81 ++---
 kernel/dma/direct.c                                |  18 +-
 kernel/entry/syscall-common.c                      |   3 +
 kernel/futex/requeue.c                             |  12 +-
 kernel/kprobes.c                                   |  14 +-
 kernel/sched/core.c                                |  60 ++--
 kernel/sched/deadline.c                            |   8 +-
 kernel/sched/ext.c                                 |  17 +-
 kernel/sched/fair.c                                |   4 +-
 kernel/sched/idle.c                                |   2 +-
 kernel/sched/rt.c                                  |   8 +-
 kernel/sched/sched.h                               |  12 +-
 kernel/sched/stop_task.c                           |   2 +-
 kernel/trace/ftrace.c                              |  13 +-
 kernel/trace/ring_buffer.c                         |  20 +-
 mm/damon/core.c                                    |  22 +-
 mm/damon/ops-common.c                              |   5 +-
 mm/damon/paddr.c                                   |  20 +-
 mm/damon/sysfs-schemes.c                           |  18 +-
 mm/damon/sysfs.c                                   |  23 +-
 mm/damon/tests/core-kunit.h                        |  15 +-
 mm/damon/tests/vaddr-kunit.h                       |   5 +
 mm/damon/vaddr.c                                   |  34 +-
 mm/huge_memory.c                                   | 358 ++++++++++++---------
 mm/hugetlb.c                                       |  25 +-
 mm/hugetlb_cgroup.c                                |   7 +-
 mm/hugetlb_vmemmap.c                               | 298 +++++++----------
 mm/memcontrol-v1.c                                 |  43 ++-
 mm/memcontrol.c                                    |  13 +
 mm/mempolicy.c                                     |   2 +-
 mm/migrate.c                                       |  12 +-
 mm/mm_init.c                                       |   1 +
 mm/page_alloc.c                                    |   6 +-
 mm/page_vma_mapped.c                               |   8 +-
 mm/rmap.c                                          |  15 +-
 mm/slab.h                                          |   8 +-
 mm/slab_common.c                                   |  44 ++-
 mm/slub.c                                          | 108 +++----
 mm/sparse-vmemmap.c                                |  53 ---
 mm/userfaultfd.c                                   |   4 +-
 mm/vmscan.c                                        |  41 +--
 net/8021q/vlan.c                                   |   7 +-
 net/8021q/vlan_dev.c                               |  32 +-
 net/batman-adv/bridge_loop_avoidance.c             |  15 +-
 net/batman-adv/distributed-arp-table.c             |   8 +-
 net/batman-adv/main.c                              |   4 +
 net/batman-adv/multicast_forw.c                    |   7 +-
 net/core/skbuff.c                                  |   5 +-
 net/ipv4/icmp.c                                    |   2 +-
 net/ipv4/ip_output.c                               |   4 +-
 net/ipv4/ip_sockglue.c                             |   2 +-
 net/ipv4/ipmr.c                                    |   2 +-
 net/ipv4/netfilter/nf_reject_ipv4.c                |   2 +-
 net/ipv4/route.c                                   |   4 +-
 net/ipv4/tcp_ipv4.c                                |  15 +-
 net/ipv4/tcp_minisocks.c                           |   2 +-
 net/ipv4/tcp_output.c                              |   6 +-
 net/ipv6/exthdrs.c                                 |  55 ++--
 net/ipv6/ip6_gre.c                                 |   2 +-
 net/ipv6/ip6_output.c                              |  47 +--
 net/ipv6/ip6_tunnel.c                              |   6 +-
 net/ipv6/ipv6_sockglue.c                           |   4 +-
 net/ipv6/route.c                                   |  10 +-
 net/ipv6/sit.c                                     |   2 +-
 net/ipv6/tcp_ipv6.c                                |  11 +-
 net/openvswitch/conntrack.c                        | 121 ++++---
 net/openvswitch/conntrack.h                        |   6 +-
 net/openvswitch/datapath.c                         |  10 +-
 net/openvswitch/datapath.h                         |   8 +-
 net/packet/af_packet.c                             |  96 +++++-
 net/sunrpc/auth_gss/gss_rpc_xdr.c                  |   9 +-
 net/sunrpc/xprtrdma/ib_client.c                    |  26 +-
 net/sunrpc/xprtrdma/svc_rdma_recvfrom.c            |  12 +-
 net/sunrpc/xprtrdma/svc_rdma_rw.c                  |   5 +-
 net/sunrpc/xprtrdma/svc_rdma_transport.c           |  32 +-
 rust/kernel/bug.rs                                 |  10 +-
 rust/kernel/devres.rs                              | 163 ++++------
 rust/kernel/drm/ioctl.rs                           |   6 +
 samples/damon/mtier.c                              |  14 +-
 samples/damon/prcl.c                               |  11 +-
 samples/damon/wsse.c                               |  11 +-
 security/integrity/ima/ima_appraise.c              |   2 +
 sound/core/pcm_native.c                            |   2 +
 sound/core/rawmidi.c                               |   2 +-
 sound/parisc/harmony.c                             |   6 +-
 sound/soc/codecs/adau1761.c                        |  34 +-
 sound/soc/codecs/aw88261.c                         |  30 +-
 sound/soc/codecs/aw88261.h                         |   6 -
 sound/soc/codecs/cs35l33.c                         |  14 +-
 sound/soc/codecs/cs35l34.c                         |  14 +-
 sound/soc/codecs/cx2072x.c                         | 134 ++++----
 sound/soc/codecs/hdac_hda.c                        |   4 +-
 sound/soc/codecs/max9860.c                         |   2 +-
 sound/soc/codecs/ml26124.c                         |   4 +-
 sound/soc/codecs/pcm512x.c                         |  40 +--
 sound/soc/codecs/pm4125-sdw.c                      |   2 +-
 sound/soc/codecs/rt1017-sdca-sdw.h                 |  10 +-
 sound/soc/codecs/rt1316-sdw.c                      |   2 +-
 sound/soc/codecs/rt1318-sdw.c                      |   2 +-
 sound/soc/codecs/rt1318.c                          |   4 +-
 sound/soc/codecs/rt274.c                           |   8 +-
 sound/soc/codecs/rt286.c                           |  14 +-
 sound/soc/codecs/rt298.c                           |  14 +-
 sound/soc/codecs/rt700-sdw.h                       |  11 +-
 sound/soc/codecs/rt711-sdca-sdw.h                  |   6 +-
 sound/soc/codecs/rt711-sdw.h                       |  10 +-
 sound/soc/codecs/rt712-sdca-dmic.h                 |   6 +-
 sound/soc/codecs/rt712-sdca-sdw.h                  |  11 +-
 sound/soc/codecs/rt715-sdca-sdw.h                  |  48 ++-
 sound/soc/codecs/rt715-sdw.h                       |  32 +-
 sound/soc/codecs/rt721-sdca-sdw.h                  |  44 +--
 sound/soc/codecs/sgtl5000.c                        |   2 +-
 sound/soc/codecs/sti-sas.c                         |   2 +-
 sound/soc/codecs/tas2552.c                         |  14 +-
 sound/soc/codecs/tas2764.c                         |   2 +-
 sound/soc/codecs/tas2780.c                         |   2 +-
 sound/soc/codecs/tas2783-sdw.c                     | 177 +++++-----
 sound/soc/fsl/fsl_easrc.c                          |   8 +-
 sound/soc/fsl/mpc5200_psc_i2s.c                    |   1 +
 sound/soc/intel/atom/sst/sst_pci.c                 |   4 +-
 sound/soc/loongson/loongson_card.c                 |   6 +-
 sound/soc/samsung/aries_wm8994.c                   |   1 +
 sound/soc/tegra/tegra210_admaif.c                  | 210 ++++++++----
 sound/soc/tegra/tegra210_i2s.c                     |   8 +-
 sound/soc/tegra/tegra210_mbdrc.c                   |  42 +--
 sound/soc/tegra/tegra210_mixer.c                   |  10 +-
 sound/usb/midi.c                                   |   2 +
 tools/objtool/check.c                              |   3 +-
 .../util/bpf_skel/augmented_raw_syscalls.bpf.c     | 155 +++++----
 .../util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c   |  47 +--
 .../util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h   |  12 +
 tools/sched_ext/scx_qmap.bpf.c                     |   2 +-
 tools/testing/cxl/Kbuild                           |   1 +
 511 files changed, 7548 insertions(+), 4554 deletions(-)
author maintainer
#1 lore raw

PATCH 1/583 net: skbuff: dont skb_tx_error() the source skb in skb_zerocopy()

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

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

From: Norbert Szetei <[email protected]>

[ Upstream commit 8ece906150128d5ec2462aabcc978c568433eca4 ]

skb_zerocopy() copies frags from @from into @to. On an skb_orphan_frags() failure it calls skb_tx_error(@from), a destructive operation on the source skb the copy helper does not own. That completes @from's zerocopy uarg and clears SKBFL_ALL_ZEROCOPY, including the SKBFL_SHARED_FRAG page-ownership marker.

Both callers already report the failure on their own drop path. nfnetlink_queue does it at nla_put_failure, and Open vSwitch does it in the flow-miss drop arm of ovs_dp_process_packet(), so nothing is lost by dropping it here.

On Open vSwitch's OVS_ACTION_ATTR_USERSPACE path the skb is not freed on this error: do_execute_actions() ignores output_userspace()'s return value and, unless the upcall was the last action, keeps forwarding the same skb through the flow's remaining actions. The uarg is completed while that skb is still in flight, telling the producer its buffers are free, and SKBFL_SHARED_FRAG is cleared on an skb the rest of the stack still handles. That flag is what makes esp_input() call skb_cow_data() instead of decrypting in place, so a later local ESP delivery can decrypt over frags the skb does not own privately.

Leave error reporting to the callers.

Fixes 36d5fe6a0007 ("core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors")
[ 7.2 and earlier do not have the put_page() call on the error path ]
---
 net/core/skbuff.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
net/core/skbuff.c +2 -3
index 31c2c5a97a353..9c97591068228 100644
@@ -3859,10 +3859,9 @@ skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
 
 	skb_len_add(to, len + plen);
 
-	if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) {
-		skb_tx_error(from);
+	if (unlikely(skb_orphan_frags(from, GFP_ATOMIC)))
 		return -ENOMEM;
-	}
+
 	skb_zerocopy_clone(to, from, GFP_ATOMIC);
 
 	for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
Signature · 1 line
2.53.0
author maintainer
#2 lore raw

PATCH 2/583 openvswitch: Fix CT limit teardown use-after-free

In reply to Greg Kroah-Hartman

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

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

From: Yuqi Xu <[email protected]>

[ Upstream commit 403f96c32c9e24600093d7d0c61c17daeedca957 ]

Packet processing uses CT limit state under RCU, while netns teardown frees that state under ovs_mutex. The CT limit pointer was neither removed from readers nor protected by a grace period, allowing packet processing to dereference the freed state.

An unprivileged user can trigger this bug from a user and network namespace, causing a slab-use-after-free in ovs_ct_execute() when the netns is torn down.

Publish the CT limit pointer through RCU, remove it before teardown, and wait for readers before freeing its contents. Keep ovs_mutex around individual CT limit updates, and use the RCU read-side lock while GET traverses the RCU-protected limit lists.

Netns teardown detaches the RCU-protected CT limit state in the pernet .pre_exit callback while holding ovs_mutex. The pernet core guarantees an RCU grace period between the .pre_exit and .exit callbacks, so the .exit callback completes the teardown without adding any extra synchronization.

The netlink command handlers do not need NULL checks because the userspace netlink socket holds an active reference to its network namespace while a request is processed. The per-netns exit path therefore cannot run concurrently with SET, DEL, or GET for that socket's namespace.

---
 net/openvswitch/conntrack.c | 121 +++++++++++++++++++++++-------------
 net/openvswitch/conntrack.h |   6 +-
 net/openvswitch/datapath.c  |  10 ++-
 net/openvswitch/datapath.h  |   8 ++-
 4 files changed, 98 insertions(+), 47 deletions(-)
net/openvswitch/conntrack.c +79 -42
index fb68aa17e479d..3f51f19686541 100644
@@ -932,10 +932,14 @@ static int ovs_ct_check_limit(struct net *net,
 			      const struct ovs_conntrack_info *info)
 {
 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
-	const struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
+	const struct ovs_ct_limit_info *ct_limit_info;
 	u32 per_zone_limit, connections;
 	u32 conncount_key;
 
+	ct_limit_info = rcu_dereference(ovs_net->ct_limit_info);
+	if (!ct_limit_info)
+		return 0;
+
 	conncount_key = info->zone.id;
 
 	per_zone_limit = ct_limit_get(ct_limit_info, info->zone.id);
@@ -1584,42 +1588,56 @@ static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
 #if	IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
 static int ovs_ct_limit_init(struct net *net, struct ovs_net *ovs_net)
 {
+	struct ovs_ct_limit_info *info;
 	int i, err;
 
-	ovs_net->ct_limit_info = kmalloc(sizeof(*ovs_net->ct_limit_info),
-					 GFP_KERNEL);
-	if (!ovs_net->ct_limit_info)
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
 		return -ENOMEM;
 
-	ovs_net->ct_limit_info->default_limit = OVS_CT_LIMIT_DEFAULT;
-	ovs_net->ct_limit_info->limits =
+	info->default_limit = OVS_CT_LIMIT_DEFAULT;
+	info->limits =
 		kmalloc_array(CT_LIMIT_HASH_BUCKETS, sizeof(struct hlist_head),
 			      GFP_KERNEL);
-	if (!ovs_net->ct_limit_info->limits) {
-		kfree(ovs_net->ct_limit_info);
+	if (!info->limits) {
+		kfree(info);
 		return -ENOMEM;
 	}
 
 	for (i = 0; i < CT_LIMIT_HASH_BUCKETS; i++)
-		INIT_HLIST_HEAD(&ovs_net->ct_limit_info->limits[i]);
+		INIT_HLIST_HEAD(&info->limits[i]);
 
-	ovs_net->ct_limit_info->data = nf_conncount_init(net, sizeof(u32));
+	info->data = nf_conncount_init(net, sizeof(u32));
 
-	if (IS_ERR(ovs_net->ct_limit_info->data)) {
-		err = PTR_ERR(ovs_net->ct_limit_info->data);
-		kfree(ovs_net->ct_limit_info->limits);
-		kfree(ovs_net->ct_limit_info);
+	if (IS_ERR(info->data)) {
+		err = PTR_ERR(info->data);
+		kfree(info->limits);
+		kfree(info);
 		pr_err("openvswitch: failed to init nf_conncount %d\n", err);
 		return err;
 	}
+	rcu_assign_pointer(ovs_net->ct_limit_info, info);
 	return 0;
 }
 
-static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
+static void *ovs_ct_limit_exit_start(struct ovs_net *ovs_net)
+{
+	return rcu_replace_pointer(ovs_net->ct_limit_info, NULL,
+				   lockdep_ovsl_is_held());
+}
+
+/* The CT limit state must be detached by ovs_ct_limit_exit_start() and an
+ * RCU grace period must elapse before this function runs.  The pernet core
+ * guarantees the grace period between the .pre_exit and .exit callbacks.
+ */
+static void ovs_ct_limit_exit_finish(struct net *net, void *data)
 {
-	const struct ovs_ct_limit_info *info = ovs_net->ct_limit_info;
+	const struct ovs_ct_limit_info *info = data;
 	int i;
 
+	if (!info)
+		return;
+
 	nf_conncount_destroy(net, info->data);
 	for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
 		struct hlist_head *head = &info->limits[i];
@@ -1627,7 +1645,7 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
 		struct hlist_node *next;
 
 		hlist_for_each_entry_safe(ct_limit, next, head, hlist_node)
-			kfree_rcu(ct_limit, rcu);
+			kfree(ct_limit);
 	}
 	kfree(info->limits);
 	kfree(info);
@@ -1666,12 +1684,13 @@ static bool check_zone_id(int zone_id, u16 *pzone)
 	return false;
 }
 
-static int ovs_ct_limit_set_zone_limit(struct nlattr *nla_zone_limit,
-				       struct ovs_ct_limit_info *info)
+static int ovs_ct_limit_set_zone_limit(struct ovs_net *ovs_net,
+				       struct nlattr *nla_zone_limit)
 {
 	struct ovs_zone_limit *zone_limit;
-	int rem;
+	struct ovs_ct_limit_info *info;
 	u16 zone;
+	int rem;
 
 	rem = NLA_ALIGN(nla_len(nla_zone_limit));
 	zone_limit = (struct ovs_zone_limit *)nla_data(nla_zone_limit);
@@ -1680,6 +1699,7 @@ static int ovs_ct_limit_set_zone_limit(struct nlattr *nla_zone_limit,
 		if (unlikely(zone_limit->zone_id ==
 				OVS_ZONE_LIMIT_DEFAULT_ZONE)) {
 			ovs_lock();
+			info = ovsl_dereference(ovs_net->ct_limit_info);
 			info->default_limit = zone_limit->limit;
 			ovs_unlock();
 		} else if (unlikely(!check_zone_id(
@@ -1697,6 +1717,7 @@ static int ovs_ct_limit_set_zone_limit(struct nlattr *nla_zone_limit,
 			ct_limit->limit = zone_limit->limit;
 
 			ovs_lock();
+			info = ovsl_dereference(ovs_net->ct_limit_info);
 			ct_limit_set(info, ct_limit);
 			ovs_unlock();
 		}
@@ -1711,12 +1732,13 @@ static int ovs_ct_limit_set_zone_limit(struct nlattr *nla_zone_limit,
 	return 0;
 }
 
-static int ovs_ct_limit_del_zone_limit(struct nlattr *nla_zone_limit,
-				       struct ovs_ct_limit_info *info)
+static int ovs_ct_limit_del_zone_limit(struct ovs_net *ovs_net,
+				       struct nlattr *nla_zone_limit)
 {
 	struct ovs_zone_limit *zone_limit;
-	int rem;
+	struct ovs_ct_limit_info *info;
 	u16 zone;
+	int rem;
 
 	rem = NLA_ALIGN(nla_len(nla_zone_limit));
 	zone_limit = (struct ovs_zone_limit *)nla_data(nla_zone_limit);
@@ -1725,6 +1747,7 @@ static int ovs_ct_limit_del_zone_limit(struct nlattr *nla_zone_limit,
 		if (unlikely(zone_limit->zone_id ==
 				OVS_ZONE_LIMIT_DEFAULT_ZONE)) {
 			ovs_lock();
+			info = ovsl_dereference(ovs_net->ct_limit_info);
 			info->default_limit = OVS_CT_LIMIT_DEFAULT;
 			ovs_unlock();
 		} else if (unlikely(!check_zone_id(
@@ -1732,6 +1755,7 @@ static int ovs_ct_limit_del_zone_limit(struct nlattr *nla_zone_limit,
 			OVS_NLERR(true, "zone id is out of range");
 		} else {
 			ovs_lock();
+			info = ovsl_dereference(ovs_net->ct_limit_info);
 			ct_limit_del(info, zone);
 			ovs_unlock();
 		}
@@ -1775,6 +1799,7 @@ static int __ovs_ct_limit_get_zone_limit(struct net *net,
 	return nla_put_nohdr(reply, sizeof(zone_limit), &zone_limit);
 }
 
+/* Called with RCU read lock held. */
 static int ovs_ct_limit_get_zone_limit(struct net *net,
 				       struct nlattr *nla_zone_limit,
 				       struct ovs_ct_limit_info *info,
@@ -1798,12 +1823,10 @@ static int ovs_ct_limit_get_zone_limit(struct net *net,
 							&zone))) {
 			OVS_NLERR(true, "zone id is out of range");
 		} else {
-			rcu_read_lock();
 			limit = ct_limit_get(info, zone);
 
 			err = __ovs_ct_limit_get_zone_limit(
 				net, info->data, zone, limit, reply);
-			rcu_read_unlock();
 			if (err)
 				return err;
 		}
@@ -1818,6 +1841,7 @@ static int ovs_ct_limit_get_zone_limit(struct net *net,
 	return 0;
 }
 
+/* Called with RCU read lock held. */
 static int ovs_ct_limit_get_all_zone_limit(struct net *net,
 					   struct ovs_ct_limit_info *info,
 					   struct sk_buff *reply)
@@ -1830,19 +1854,16 @@ static int ovs_ct_limit_get_all_zone_limit(struct net *net,
 	if (err)
 		return err;
 
-	rcu_read_lock();
 	for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
 		head = &info->limits[i];
 		hlist_for_each_entry_rcu(ct_limit, head, hlist_node) {
 			err = __ovs_ct_limit_get_zone_limit(net, info->data,
 				ct_limit->zone, ct_limit->limit, reply);
 			if (err)
-				goto exit_err;
+				return err;
 		}
 	}
 
-exit_err:
-	rcu_read_unlock();
 	return err;
 }
 
@@ -1852,7 +1873,6 @@ static int ovs_ct_limit_cmd_set(struct sk_buff *skb, struct genl_info *info)
 	struct sk_buff *reply;
 	struct ovs_header *ovs_reply_header;
 	struct ovs_net *ovs_net = net_generic(sock_net(skb->sk), ovs_net_id);
-	struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
 	int err;
 
 	reply = ovs_ct_limit_cmd_reply_start(info, OVS_CT_LIMIT_CMD_SET,
@@ -1865,8 +1885,8 @@ static int ovs_ct_limit_cmd_set(struct sk_buff *skb, struct genl_info *info)
 		goto exit_err;
 	}
 
-	err = ovs_ct_limit_set_zone_limit(a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT],
-					  ct_limit_info);
+	err = ovs_ct_limit_set_zone_limit(ovs_net,
+					  a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]);
 	if (err)
 		goto exit_err;
 
@@ -1886,7 +1906,6 @@ static int ovs_ct_limit_cmd_del(struct sk_buff *skb, struct genl_info *info)
 	struct sk_buff *reply;
 	struct ovs_header *ovs_reply_header;
 	struct ovs_net *ovs_net = net_generic(sock_net(skb->sk), ovs_net_id);
-	struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
 	int err;
 
 	reply = ovs_ct_limit_cmd_reply_start(info, OVS_CT_LIMIT_CMD_DEL,
@@ -1899,8 +1918,8 @@ static int ovs_ct_limit_cmd_del(struct sk_buff *skb, struct genl_info *info)
 		goto exit_err;
 	}
 
-	err = ovs_ct_limit_del_zone_limit(a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT],
-					  ct_limit_info);
+	err = ovs_ct_limit_del_zone_limit(ovs_net,
+					  a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]);
 	if (err)
 		goto exit_err;
 
@@ -1920,7 +1939,7 @@ static int ovs_ct_limit_cmd_get(struct sk_buff *skb, struct genl_info *info)
 	struct ovs_header *ovs_reply_header;
 	struct net *net = sock_net(skb->sk);
 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
-	struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
+	struct ovs_ct_limit_info *ct_limit_info;
 	int err;
 
 	reply = ovs_ct_limit_cmd_reply_start(info, OVS_CT_LIMIT_CMD_GET,
@@ -1934,18 +1953,19 @@ static int ovs_ct_limit_cmd_get(struct sk_buff *skb, struct genl_info *info)
 		goto exit_err;
 	}
 
+	rcu_read_lock();
+	ct_limit_info = rcu_dereference(ovs_net->ct_limit_info);
 	if (a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]) {
 		err = ovs_ct_limit_get_zone_limit(
 			net, a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT], ct_limit_info,
 			reply);
-		if (err)
-			goto exit_err;
 	} else {
 		err = ovs_ct_limit_get_all_zone_limit(net, ct_limit_info,
 						      reply);
-		if (err)
-			goto exit_err;
 	}
+	rcu_read_unlock();
+	if (err)
+		goto exit_err;
 
 	nla_nest_end(reply, nla_reply);
 	genlmsg_end(reply, ovs_reply_header);
@@ -2020,12 +2040,29 @@ int ovs_ct_init(struct net *net)
 	return err;
 }
 
-void ovs_ct_exit(struct net *net)
+/* Must be called with ovs_mutex held.  Detaches the RCU-protected
+ * ct_limit_info and stores it in ovs_net->ct_limit_exit_data for
+ * ovs_ct_exit_finish() to complete the teardown after an RCU grace period.
+ */
+void ovs_ct_exit_start(struct net *net __maybe_unused)
+{
+#if	IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
+	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
+
+	ovs_net->ct_limit_exit_data = ovs_ct_limit_exit_start(ovs_net);
+#endif
+}
+
+/* Completes the CT limit teardown.  The pernet core guarantees an RCU
+ * grace period between detaching the state in ovs_ct_exit_start() and
+ * this call, so no RCU readers remain.
+ */
+void ovs_ct_exit_finish(struct net *net)
 {
 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
 
 #if	IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
-	ovs_ct_limit_exit(net, ovs_net);
+	ovs_ct_limit_exit_finish(net, ovs_net->ct_limit_exit_data);
 #endif
 
 	if (ovs_net->xt_label)
net/openvswitch/conntrack.h +4 -2
index 317e525c8a113..ab21d032fde3d 100644
@@ -14,7 +14,8 @@ enum ovs_key_attr;
 
 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
 int ovs_ct_init(struct net *);
-void ovs_ct_exit(struct net *);
+void ovs_ct_exit_start(struct net *net);
+void ovs_ct_exit_finish(struct net *net);
 bool ovs_ct_verify(struct net *, enum ovs_key_attr attr);
 int ovs_ct_copy_action(struct net *, const struct nlattr *,
 		       const struct sw_flow_key *, struct sw_flow_actions **,
@@ -40,7 +41,8 @@ void ovs_ct_free_action(const struct nlattr *a);
 
 static inline int ovs_ct_init(struct net *net) { return 0; }
 
-static inline void ovs_ct_exit(struct net *net) { }
+static inline void ovs_ct_exit_start(struct net *net) { }
+static inline void ovs_ct_exit_finish(struct net *net) { }
 
 static inline bool ovs_ct_verify(struct net *net, int attr)
 {
net/openvswitch/datapath.c +9 -1
index 1c032d4a66656..c7991b9db6a76 100644
@@ -2758,6 +2758,13 @@ static void __net_exit list_vports_from_net(struct net *net, struct net *dnet,
 	}
 }
 
+static void __net_exit ovs_pre_exit_net(struct net *dnet)
+{
+	ovs_lock();
+	ovs_ct_exit_start(dnet);
+	ovs_unlock();
+}
+
 static void __net_exit ovs_exit_net(struct net *dnet)
 {
 	struct datapath *dp, *dp_next;
@@ -2768,7 +2775,7 @@ static void __net_exit ovs_exit_net(struct net *dnet)
 
 	ovs_lock();
 
-	ovs_ct_exit(dnet);
+	ovs_ct_exit_finish(dnet);
 
 	list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
 		__dp_destroy(dp);
@@ -2792,6 +2799,7 @@ static void __net_exit ovs_exit_net(struct net *dnet)
 
 static struct pernet_operations ovs_net_ops = {
 	.init = ovs_init_net,
+	.pre_exit = ovs_pre_exit_net,
 	.exit = ovs_exit_net,
 	.id   = &ovs_net_id,
 	.size = sizeof(struct ovs_net),
net/openvswitch/datapath.h +6 -2
index 696640e88fa7e..b2c2b8da12d40 100644
@@ -164,7 +164,10 @@ struct dp_upcall_info {
  * Protected by genl_mutex.
  * @dp_notify_work: A work notifier to handle port unregistering.
  * @masks_rebalance: A work to periodically optimize flow table caches.
- * @ct_limit_info: A hash table of conntrack zone connection limits.
+ * @ct_limit_info: Hash table of conntrack zone connection limits. Protected
+ * by RCU; updates and teardown are serialized by ovs_mutex. May be NULL during
+ * netns teardown.
+ * @ct_limit_exit_data: CT limit state detached at .pre_exit, freed at .exit.
  * @xt_label: Whether connlables are configured for the network or not.
  */
 struct ovs_net {
@@ -172,7 +175,8 @@ struct ovs_net {
 	struct work_struct dp_notify_work;
 	struct delayed_work masks_rebalance;
 #if	IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
-	struct ovs_ct_limit_info *ct_limit_info;
+	struct ovs_ct_limit_info __rcu *ct_limit_info;
+	struct ovs_ct_limit_info *ct_limit_exit_data;
 #endif
 	bool xt_label;
 };
Signature · 1 line
2.53.0
author maintainer
#3 lore raw

PATCH 3/583 mm/page_vma_mapped: use huge_ptep_get() for hugetlb

In reply to Greg Kroah-Hartman

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

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

From: Dev Jain <[email protected]>

[ Upstream commit e87df0d5d6962bde50f55f6d02b779daa394f894 ]

check_pte() is the final validation step in page_vma_mapped_walk(). It reads pvmw->pte with ptep_get() to decide whether the entry maps the PFN range being walked. For hugetlb VMAs, that pointer refers to a hugetlb entry.

On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.

It is not clear whether this has a trivially visible effect to userspace.

Use huge_ptep_get() to dereference a huge pte pointer.

Fixes ace71a19cec5 ("mm: introduce page_vma_mapped_walk()")
Cc Alistair Popple <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Anshuman Khandual <[email protected]>
Cc Byungchul Park <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Gregory Price <[email protected]>
Cc Harry Yoo <[email protected]>
Cc "Huang, Ying" <[email protected]>
Cc Jann Horn <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Joshua Hahn <[email protected]>
Cc Jun'ichi "Nick" Nomura <[email protected]>
Cc Kiryl Shutsemau <[email protected]>
Cc Lance Yang <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Naoya Horiguchi <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Pedro Falcato <[email protected]>
Cc Rakie Kim <[email protected]>
Cc Ralph Campbell <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Will Deacon <[email protected]>
Cc Zi Yan <[email protected]>
---
 mm/page_vma_mapped.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
mm/page_vma_mapped.c +7 -1
index 2fdd31a5a48ff..41cf3192a8f62 100644
@@ -104,7 +104,13 @@ static bool map_pte(struct page_vma_mapped_walk *pvmw, pmd_t *pmdvalp,
 static bool check_pte(struct page_vma_mapped_walk *pvmw, unsigned long pte_nr)
 {
 	unsigned long pfn;
-	pte_t ptent = ptep_get(pvmw->pte);
+	pte_t ptent;
+
+	if (is_vm_hugetlb_page(pvmw->vma))
+		ptent = huge_ptep_get(pvmw->vma->vm_mm, pvmw->address,
+				      pvmw->pte);
+	else
+		ptent = ptep_get(pvmw->pte);
 
 	if (pvmw->flags & PVMW_MIGRATION) {
 		swp_entry_t entry;
Signature · 1 line
2.53.0
author maintainer
#4 lore raw

PATCH 4/583 entry: Fix seccomp bypass after ptrace with TSYNC

In reply to Greg Kroah-Hartman

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

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

From: Jinjie Ruan <[email protected]>

commit 4a3591287fb7f808e209b4974ed337f609a2006b upstream.

Sashiko review pointed out the following issue.

If a thread is stopped in syscall_trace_enter() for ptrace, another thread can install a seccomp filter with SECCOMP_FILTER_FLAG_TSYNC (e.g., via seccomp_attach_filter()). This will successfully set SYSCALL_WORK_SECCOMP on the stopped thread, but syscall_trace_enter() evaluates a cached 'work' variable sampled on entry. Consequently, the subsequent check for SYSCALL_WORK_SECCOMP misses the newly assigned flag, and the filter is silently bypassed.

This race condition could allow an unprivileged process to execute a prohibited system call (e.g., execve) that the newly installed filter was intended to block, especially since the tracer might have modified the system call number during the ptrace stop.

Fix this by re-reading the syscall_work flags after ptrace handling, so that any new SYSCALL_WORK_SECCOMP flag set by another thread via TSYNC during the ptrace stop is observed before the subsequent seccomp check.

---
 kernel/entry/syscall-common.c | 3 +++
 1 file changed, 3 insertions(+)
kernel/entry/syscall-common.c +3 -0
index 66e6ba7fa80c8..dbc5551935f78 100644
@@ -37,6 +37,9 @@ long syscall_trace_enter(struct pt_regs *regs, long syscall,
 		ret = ptrace_report_syscall_entry(regs);
 		if (ret || (work & SYSCALL_WORK_SYSCALL_EMU))
 			return -1L;
+
+		/* ptrace might have changed work flags */
+		work = READ_ONCE(current_thread_info()->syscall_work);
 	}
 
 	/* Do seccomp after ptrace, to catch any tracer changes. */
Signature · 1 line
2.53.0
author maintainer
#5 lore raw

PATCH 5/583 fsnotify: Fix stale object mask after concurrent mark updates

In reply to Greg Kroah-Hartman

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

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

From: Youngjae Kwon <[email protected]>

[ Upstream commit e422777fdd4746de1109575c51e65038d4c5c1be ]

When a mark gets a new event bit, fanotify and inotify may avoid recalculating the object mask if the cached aggregate already contains that bit. This is racy with a recalculation triggered by a concurrent update to another mark on the same connector.

The concurrent scan can read the mark before the new bit is added, while the updater reads the old aggregate before that scan publishes its result. The updater then skips recalculation and the scan publishes a mask without the bit, leaving the object mask stale after both updates complete.

This can be reproduced with two fanotify groups watching the same inode:
one thread removes FAN_MODIFY from one existing mark while another thread adds FAN_MODIFY to the other mark. After both fanotify_mark() calls return, writes can fail to produce FAN_MODIFY for the group whose mark now contains the bit. This was reproduced on an unmodified v6.12.95 kernel. The equivalent inotify interleaving loses IN_MODIFY events.

For normal fanotify additions, recalculate whenever the raw mark mask changes. The normal mask is not cleared asynchronously, so an unchanged addition cannot introduce missing interest. Always recalculate ignore-mask updates because FS_MODIFY handling may clear the ignore mask without taking mark->lock, making snapshot comparisons unreliable.

Always recalculate after updating an existing inotify watch. Its replace path temporarily sets mark->mask to zero, so a concurrent scan can observe zero even when the old and final masks are equal. Assigning the replacement mask directly would avoid the transient zero, but existing-watch updates are infrequent, so unconditional recalculation is simpler.

Fixes 63c882a05416 ("inotify: reimplement inotify using fsnotify")
Fixes 912ee3946c5e ("fanotify: do not call fanotify_update_object_mask in fanotify_add_mark")
Cc [email protected] # needs adjustments for <= 7.0
(cherry picked from commit e422777fdd4746de1109575c51e65038d4c5c1be)

[yjkwon0026: Resolve the inotify conflict by retaining the branch-native inode->i_fsnotify_marks argument to fsnotify_recalc_mask(). This tree lacks 4520b96b8136 ("fsnotify: inotify: pass mark connector to fsnotify_recalc_mask()"). The surrounding conditional is deleted by this patch, so that commit is not a prerequisite for this fix.]

---
 fs/notify/fanotify/fanotify_user.c | 12 +++++++-----
 fs/notify/inotify/inotify_user.c   | 15 +--------------
 2 files changed, 8 insertions(+), 19 deletions(-)
fs/notify/fanotify/fanotify_user.c +7 -5
index c1ce663952c86..eb808eda11f2f 100644
@@ -1324,16 +1324,18 @@ static bool fanotify_mark_update_flags(struct fsnotify_mark *fsn_mark,
 static bool fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
 				      __u32 mask, unsigned int fan_flags)
 {
+	__u32 old_mask;
 	bool recalc;
 
 	spin_lock(&fsn_mark->lock);
-	if (!(fan_flags & FANOTIFY_MARK_IGNORE_BITS))
+	if (!(fan_flags & FANOTIFY_MARK_IGNORE_BITS)) {
+		old_mask = fsn_mark->mask;
 		fsn_mark->mask |= mask;
-	else
+		recalc = old_mask != fsn_mark->mask;
+	} else {
 		fsn_mark->ignore_mask |= mask;
-
-	recalc = fsnotify_calc_mask(fsn_mark) &
-		~fsnotify_conn_mask(fsn_mark->connector);
+		recalc = true;
+	}
 
 	recalc |= fanotify_mark_update_flags(fsn_mark, fan_flags);
 	spin_unlock(&fsn_mark->lock);
fs/notify/inotify/inotify_user.c +1 -14
index 0d813c52ff9c3..2a8a83d8f4a7f 100644
@@ -539,7 +539,6 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
 {
 	struct fsnotify_mark *fsn_mark;
 	struct inotify_inode_mark *i_mark;
-	__u32 old_mask, new_mask;
 	int replace = !(arg & IN_MASK_ADD);
 	int create = (arg & IN_MASK_CREATE);
 	int ret;
@@ -555,27 +554,15 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
 	i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
 
 	spin_lock(&fsn_mark->lock);
-	old_mask = fsn_mark->mask;
 	if (replace) {
 		fsn_mark->mask = 0;
 		fsn_mark->flags &= ~INOTIFY_MARK_FLAGS;
 	}
 	fsn_mark->mask |= inotify_arg_to_mask(inode, arg);
 	fsn_mark->flags |= inotify_arg_to_flags(arg);
-	new_mask = fsn_mark->mask;
 	spin_unlock(&fsn_mark->lock);
 
-	if (old_mask != new_mask) {
-		/* more bits in old than in new? */
-		int dropped = (old_mask & ~new_mask);
-		/* more bits in this fsn_mark than the inode's mask? */
-		int do_inode = (new_mask & ~READ_ONCE(inode->i_fsnotify_mask));
-
-		/* update the inode with this new fsn_mark */
-		if (dropped || do_inode)
-			fsnotify_recalc_mask(inode->i_fsnotify_marks);
-
-	}
+	fsnotify_recalc_mask(inode->i_fsnotify_marks);
 
 	/* return the wd */
 	ret = i_mark->wd;
Signature · 1 line
2.53.0
author maintainer
#6 lore raw

PATCH 6/583 objtool/rust: add one more `noreturn` Rust function

In reply to Greg Kroah-Hartman

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

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

From: FUJITA Tomonori <[email protected]>

[ Upstream commit c18f35e4904920db4c51620ba634e4d175b24741 ]

Fix the following warning:

rust/kernel.o: warning: objtool: _RNvXNtNtCs1ewLyjEZ7Le_6kernel3str9parse_intaNtNtB2_7private12FromStrRadix14from_str_radix() falls through to next function _RNvXNtNtCs1ewLyjEZ7Le_6kernel3str9parse_intaNtNtB2_7private12FromStrRadix16from_u64_negated()

The commit 51d9ee90ea90 ("rust: str: add radix prefixed integer parsing functions") introduces u64::from_str_radix(), whose implementation contains a panic path for out-of-range radix values. The panic helper is core::num::from_ascii_radix_panic().

Note that radix is derived from strip_radix() here and is always within the valid range, so kernel never panics.

Fixes 51d9ee90ea90 ("rust: str: add radix prefixed integer parsing functions")
[ Reworded typo. - Miguel ]
---
 tools/objtool/check.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
tools/objtool/check.c +2 -1
index c7d64ab2ea4c4..141ff11f70a4b 100644
@@ -216,7 +216,8 @@ static bool is_rust_noreturn(const struct symbol *func)
 	 * as well as changes to the source code itself between versions (since
 	 * these come from the Rust standard library).
 	 */
-	return str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail")		||
+	return str_ends_with(func->name, "_4core3num22from_ascii_radix_panic")				||
+	       str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail")		||
 	       str_ends_with(func->name, "_4core6option13expect_failed")				||
 	       str_ends_with(func->name, "_4core6option13unwrap_failed")				||
 	       str_ends_with(func->name, "_4core6result13unwrap_failed")				||
Signature · 1 line
2.53.0
author maintainer
#7 lore raw

PATCH 7/583 mfd: qnap-mcu: keep the reply buffer alive past a command timeout

In reply to Greg Kroah-Hartman

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

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

From: Ali Ahmet Memis <[email protected]>

commit 47504742cea7878ebd1bf1491bbed923df6b90b1 upstream.

qnap_mcu_exec() publishes an on-stack buffer to the receive path:

	unsigned char rx[QNAP_MCU_RX_BUFFER_SIZE];
	...
	reply->data = rx;
	reply->length = length;

and qnap_mcu_receive_buf() writes into it from the serdev receive path, which runs out of flush_to_ldisc() and is not serialized against qnap_mcu_exec() at all. bus_lock cannot cover it, because qnap_mcu_exec() holds that mutex across wait_for_completion_timeout().

On a timeout qnap_mcu_exec() returns with reply->data still pointing at its own frame. A reply that arrives late, or an unsolicited message from the MCU, is then written into a stack frame that has been left, corrupting whatever runs next on that stack. The same applies when qnap_mcu_write() fails, since that path returns without touching the reply state either.

Move the receive buffer into struct qnap_mcu. It is 37 bytes and the structure is devm_kzalloc()ed, so it lives as long as the driver, and a late write lands in memory that is still valid and is reinitialized by the next command. bus_lock keeps commands from sharing it.

This deliberately does not clear reply->data or reply->length on the timeout path. Doing so races with qnap_mcu_receive_buf(), which reads both after its

	if (!reply->length)
		return size;

check: clearing reply->data gives a NULL dereference, and clearing reply->length alone removes the reply->received == reply->length exit condition, so the copy loop runs until the uart chunk is consumed and overruns the buffer. Leaving both set keeps the write bounded by reply->length, which qnap_mcu_exec() has already checked against sizeof(mcu->rx).

Fixes 998f70d1806b ("mfd: Add base driver for qnap-mcu devices")
(cherry picked from commit 47504742cea7878ebd1bf1491bbed923df6b90b1)

[ 6.18 lacks qnap_mcu_verify_checksum() and
qnap_mcu_reply_is_any_error(), so the checksum check there still open-codes qnap_mcu_csum(); only its rx references were moved to mcu->rx. The fix itself is unchanged. ]

---
 drivers/mfd/qnap-mcu.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/mfd/qnap-mcu.c +7 -6
index 4ec1f4cf902f6..22a7a77fdeaf9 100644
@@ -55,6 +55,7 @@ struct qnap_mcu_reply {
  * @reply:	Reply data structure
  * @variant:	Device variant specific information
  * @version:	MCU firmware version
+ * @rx:		Receive buffer the reply is assembled in
  */
 struct qnap_mcu {
 	struct serdev_device *serdev;
@@ -62,6 +63,7 @@ struct qnap_mcu {
 	struct qnap_mcu_reply reply;
 	const struct qnap_mcu_variant *variant;
 	u8 version[QNAP_MCU_VERSION_LEN];
+	u8 rx[QNAP_MCU_RX_BUFFER_SIZE];
 };
 
 /*
@@ -146,20 +148,19 @@ int qnap_mcu_exec(struct qnap_mcu *mcu,
 		  const u8 *cmd_data, size_t cmd_data_size,
 		  u8 *reply_data, size_t reply_data_size)
 {
-	unsigned char rx[QNAP_MCU_RX_BUFFER_SIZE];
 	size_t length = reply_data_size + QNAP_MCU_CHECKSUM_SIZE;
 	struct qnap_mcu_reply *reply = &mcu->reply;
 	int ret = 0;
 	u8 crc;
 
-	if (length > sizeof(rx)) {
+	if (length > sizeof(mcu->rx)) {
 		dev_err(&mcu->serdev->dev, "expected data too big for receive buffer");
 		return -EINVAL;
 	}
 
 	guard(mutex)(&mcu->bus_lock);
 
-	reply->data = rx;
+	reply->data = mcu->rx;
 	reply->length = length;
 	reply->received = 0;
 	reinit_completion(&reply->done);
@@ -175,13 +176,13 @@ int qnap_mcu_exec(struct qnap_mcu *mcu,
 		return -ETIMEDOUT;
 	}
 
-	crc = qnap_mcu_csum(rx, reply_data_size);
-	if (crc != rx[reply_data_size]) {
+	crc = qnap_mcu_csum(mcu->rx, reply_data_size);
+	if (crc != mcu->rx[reply_data_size]) {
 		dev_err(&mcu->serdev->dev, "Invalid Checksum received\n");
 		return -EIO;
 	}
 
-	memcpy(reply_data, rx, reply_data_size);
+	memcpy(reply_data, mcu->rx, reply_data_size);
 
 	return 0;
 }
Signature · 1 line
2.53.0
author maintainer
#8 lore raw

PATCH 8/583 drm/amd: Drop calls to restore power limit and clock from smu_resume()

In reply to Greg Kroah-Hartman

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

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

From: Mario Limonciello <[email protected]>

[ Upstream commit 4b6ec94fdae2407d9b8e69e3ec5f879e72ad667e ]

User requested power limits and clock settings are already restored as part of smu_restore_dpm_user_profile(). It's unnecessary to call the same restore as part of smu_resume().

Revert the following commits to drop that extra restore:
commit ed4efe426a49 ("drm/amd: Restore cached power limit during resume")
commit 796ff8a7e01b ("drm/amd: Restore cached manual clock settings during resume") commit f9b80514a722 ("drm/amd: Only restore cached manual clock settings in restore if OD enabled")

---
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 13 -------------
 1 file changed, 13 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +0 -13
index 53d071eddbf44..8473eaac1e7fc 100644
@@ -2234,7 +2234,6 @@ static int smu_resume(struct amdgpu_ip_block *ip_block)
 	int ret;
 	struct amdgpu_device *adev = ip_block->adev;
 	struct smu_context *smu = adev->powerplay.pp_handle;
-	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
 
 	if (amdgpu_sriov_multi_vf_mode(adev))
 		return 0;
@@ -2266,18 +2265,6 @@ static int smu_resume(struct amdgpu_ip_block *ip_block)
 
 	adev->pm.dpm_enabled = true;
 
-	if (smu->current_power_limit) {
-		ret = smu_set_power_limit(smu, smu->current_power_limit);
-		if (ret && ret != -EOPNOTSUPP)
-			return ret;
-	}
-
-	if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL && smu->od_enabled) {
-		ret = smu_od_edit_dpm_table(smu, PP_OD_COMMIT_DPM_TABLE, NULL, 0);
-		if (ret)
-			return ret;
-	}
-
 	dev_info(adev->dev, "SMU is resumed successfully!\n");
 
 	return 0;
Signature · 1 line
2.53.0
author maintainer
#9 lore raw

PATCH 9/583 fsnotify: inotify: pass mark connector to fsnotify_recalc_mask()

In reply to Greg Kroah-Hartman

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

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

From: Sun Jian <[email protected]>

[ Upstream commit 4520b96b8136ba2465a3f4dc5c3fb8bdf3d92e4e ]

fsnotify_recalc_mask() expects a plain struct fsnotify_mark_connector *, but inode->i_fsnotify_marks is an __rcu pointer. Use fsn_mark->connector instead to avoid sparse "different address spaces" warnings.

(cherry picked from commit 4520b96b8136ba2465a3f4dc5c3fb8bdf3d92e4e)
---
 fs/notify/inotify/inotify_user.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/notify/inotify/inotify_user.c +1 -1
index 2a8a83d8f4a7f..6eaf0d382eec8 100644
@@ -562,7 +562,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
 	fsn_mark->flags |= inotify_arg_to_flags(arg);
 	spin_unlock(&fsn_mark->lock);
 
-	fsnotify_recalc_mask(inode->i_fsnotify_marks);
+	fsnotify_recalc_mask(fsn_mark->connector);
 
 	/* return the wd */
 	ret = i_mark->wd;
Signature · 1 line
2.53.0
author maintainer
#10 lore raw

PATCH 10/583 drm/xe: Dont hand out the flat CCS storage as usable VRAM

In reply to Greg Kroah-Hartman

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

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

From: Linus Torvalds <[email protected]>

commit 818bebeb63dd6bf5f4e07e145f6cdbace520a34c upstream.

get_flat_ccs_offset() reads the base of the flat CCS storage from the hardware, scales it by the number of enabled L3 nodes, and rounds the result up to 128K. Everything below that offset is then handed to the VRAM allocator as usable memory.

Rounding a limit that means "usable memory ends here" upwards publishes whatever lies between the real base and the rounded one as free memory, and that memory belongs to the compression hardware. The scaled value has no reason to be 128K aligned, and on a Battlemage G21 with 16 GiB it is not:

	flat CCS base: raw 0x3fafff800, rounded 0x3fb000000

so the last 2 KiB of page 0x3fafff000 is CCS storage, in the allocator's pool. Whatever is allocated there gets that tail overwritten by the compression hardware, which needs no page-table entry, no buffer object and no GPU submission to do it, and does it before userspace exists.

On this machine a Mesa VM's level-3 page table landed on that page on every cold boot. It lost the entry covering the compositor's batch-buffer heap, so the compositor's first submission faulted fetching its batch and gdm restarted it forever: a black screen on an otherwise working machine. Restarting gdm cleared it because the next VM's page tables were allocated somewhere else.

Round down instead, to the page size the allocator works in. On this machine that excludes exactly one page.

Reading the reserved page afterwards shows what had been writing it:

	[369] 0xcccc000000000000
	[371] 0xcc77000000000000
	[373] 0xcccc000000000000
	[375] 0xcc77000000000000

compression metadata, two bytes per sixteen, sitting where the driver used to hand out memory.

The assertion that should have caught this compares the offset against GSMBASE - ccs_size for equality. That value is 128K aligned, so it agrees with the rounded-up offset precisely when the base is not aligned - the check cannot fail in the case it exists to catch, and is compiled out unless CONFIG_DRM_XE_DEBUG is set. Replace it with one that can fail: CCS storage must not run into GSM.

[ And this was a debug session from hell, enormously helped by an AI
doing much of the grunt-work.

I'd like to call it my tireless helper, but the AI several times stated flat out that this was impossible and unsolvable and that we should just write a report about it.

I suspect those things have been trained by people who may not be quite as stubborn as I am.

But while the AI was ready to give up several times, it did keep adding debug code and analyzing it faithfully when I pushed. So credit where credit is due and I let the AI write the commit message above.

This is basically a one-liner fixing a bogus "round_up()" to a "round_down()", but there were 24 patches adding more and more debug information to this, and 18 kernel boot to finally narrow it down to
this. - Linus ]

Fixes 37173392741c ("drm/xe/vram: fix ccs offset calculation")
---
 drivers/gpu/drm/xe/xe_vram.c |   23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)
drivers/gpu/drm/xe/xe_vram.c +18 -5
@@ -206,12 +206,25 @@ static inline u64 get_flat_ccs_offset(st
 		offset = offset_hi << 32; /* HW view bits 39:32 */
 		offset |= offset_lo << 6; /* HW view bits 31:6 */
 		offset *= num_enabled; /* convert to SW view */
-		offset = round_up(offset, SZ_128K); /* SW must round up to nearest 128K */
 
-		/* We don't expect any holes */
-		xe_assert_msg(xe, offset == (xe_mmio_read64_2x32(&gt_to_tile(gt)->mmio, GSMBASE) -
-					     ccs_size),
-			      "Hole between CCS and GSM.\n");
+		/*
+		 * Everything below this offset is handed to the VRAM
+		 * allocator, so it has to be the *first* address the
+		 * compression hardware owns, rounded down.  Rounding it up
+		 * publishes CCS storage as free memory.
+		 */
+		offset = round_down(offset, SZ_4K);
+
+		/*
+		 * CCS storage must not run into GSM.  The old check compared
+		 * the offset against GSMBASE - ccs_size for equality, which
+		 * could not fail: that value is 128K aligned, so it agreed
+		 * with the rounded-up offset even when the base was not 128K
+		 * aligned - exactly the case this fixes.
+		 */
+		xe_assert_msg(xe, offset + ccs_size <=
+			      xe_mmio_read64_2x32(&gt_to_tile(gt)->mmio, GSMBASE),
+			      "CCS overlaps GSM.\n");
 	} else {
 		reg = xe_gt_mcr_unicast_read_any(gt, XEHP_FLAT_CCS_BASE_ADDR);
 		offset = (u64)REG_FIELD_GET(XEHP_FLAT_CCS_PTR, reg) * SZ_64K;
author maintainer
#11 lore raw

PATCH 11/583 bpf: fix the return value of push_stack

In reply to Greg Kroah-Hartman

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

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

From: Anton Protopopov <[email protected]>

commit 6ea5fc92a0fc1cde976cb701db2c1dba4dcab7cf upstream.

In [1] Eduard mentioned that on push_stack failure verifier code should return -ENOMEM instead of -EFAULT. After checking with the other call sites I've found that code randomly returns either -ENOMEM or -EFAULT. This patch unifies the return values for the push_stack (and similar push_async_cb) functions such that error codes are always assigned properly.

[1] https://lore.kernel.org/bpf/[email protected]

---
 kernel/bpf/verifier.c |   81 +++++++++++++++++++++++++-------------------------
 1 file changed, 41 insertions(+), 40 deletions(-)
kernel/bpf/verifier.c +41 -40
@@ -2117,7 +2117,7 @@ static struct bpf_verifier_state *push_s
 
 	elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL_ACCOUNT);
 	if (!elem)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	elem->insn_idx = insn_idx;
 	elem->prev_insn_idx = prev_insn_idx;
@@ -2127,12 +2127,12 @@ static struct bpf_verifier_state *push_s
 	env->stack_size++;
 	err = copy_verifier_state(&elem->st, cur);
 	if (err)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	elem->st.speculative |= speculative;
 	if (env->stack_size > BPF_COMPLEXITY_LIMIT_JMP_SEQ) {
 		verbose(env, "The sequence of %d jumps is too complex.\n",
 			env->stack_size);
-		return NULL;
+		return ERR_PTR(-E2BIG);
 	}
 	if (elem->st.parent) {
 		++elem->st.parent->branches;
@@ -2981,7 +2981,7 @@ static struct bpf_verifier_state *push_a
 
 	elem = kzalloc(sizeof(struct bpf_verifier_stack_elem), GFP_KERNEL_ACCOUNT);
 	if (!elem)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	elem->insn_idx = insn_idx;
 	elem->prev_insn_idx = prev_insn_idx;
@@ -2993,7 +2993,7 @@ static struct bpf_verifier_state *push_a
 		verbose(env,
 			"The sequence of %d jumps is too complex for async cb.\n",
 			env->stack_size);
-		return NULL;
+		return ERR_PTR(-E2BIG);
 	}
 	/* Unlike push_stack() do not copy_verifier_state().
 	 * The caller state doesn't matter.
@@ -3004,7 +3004,7 @@ static struct bpf_verifier_state *push_a
 	elem->st.in_sleepable = is_sleepable;
 	frame = kzalloc(sizeof(*frame), GFP_KERNEL_ACCOUNT);
 	if (!frame)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	init_func_state(env, frame,
 			BPF_MAIN_FUNC /* callsite */,
 			0 /* frameno within this callchain */,
@@ -9137,8 +9137,8 @@ static int process_iter_next_call(struct
 		prev_st = find_prev_entry(env, cur_st->parent, insn_idx);
 		/* branch out active iter state */
 		queued_st = push_stack(env, insn_idx + 1, insn_idx, false);
-		if (!queued_st)
-			return -ENOMEM;
+		if (IS_ERR(queued_st))
+			return PTR_ERR(queued_st);
 
 		queued_iter = get_iter_from_state(queued_st, meta);
 		queued_iter->iter.state = BPF_ITER_STATE_ACTIVE;
@@ -10708,8 +10708,8 @@ static int push_callback_call(struct bpf
 		async_cb = push_async_cb(env, env->subprog_info[subprog].start,
 					 insn_idx, subprog,
 					 is_async_cb_sleepable(env, insn));
-		if (!async_cb)
-			return -EFAULT;
+		if (IS_ERR(async_cb))
+			return PTR_ERR(async_cb);
 		callee = async_cb->frame[0];
 		callee->async_entry_cnt = caller->async_entry_cnt + 1;
 
@@ -10725,8 +10725,8 @@ static int push_callback_call(struct bpf
 	 * proceed with next instruction within current frame.
 	 */
 	callback_state = push_stack(env, env->subprog_info[subprog].start, insn_idx, false);
-	if (!callback_state)
-		return -ENOMEM;
+	if (IS_ERR(callback_state))
+		return PTR_ERR(callback_state);
 
 	err = setup_func_entry(env, subprog, insn_idx, set_callee_state_cb,
 			       callback_state);
@@ -13979,9 +13979,9 @@ static int check_kfunc_call(struct bpf_v
 		struct bpf_reg_state *regs;
 
 		branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
-		if (!branch) {
+		if (IS_ERR(branch)) {
 			verbose(env, "failed to push state for failed lock acquisition\n");
-			return -ENOMEM;
+			return PTR_ERR(branch);
 		}
 
 		regs = branch->frame[branch->curframe]->regs;
@@ -14447,16 +14447,15 @@ struct bpf_sanitize_info {
 	bool mask_to_left;
 };
 
-static struct bpf_verifier_state *
-sanitize_speculative_path(struct bpf_verifier_env *env,
-			  const struct bpf_insn *insn,
-			  u32 next_idx, u32 curr_idx)
+static int sanitize_speculative_path(struct bpf_verifier_env *env,
+				     const struct bpf_insn *insn,
+				     u32 next_idx, u32 curr_idx)
 {
 	struct bpf_verifier_state *branch;
 	struct bpf_reg_state *regs;
 
 	branch = push_stack(env, next_idx, curr_idx, true);
-	if (branch && insn) {
+	if (!IS_ERR(branch) && insn) {
 		regs = branch->frame[branch->curframe]->regs;
 		if (BPF_SRC(insn->code) == BPF_K) {
 			mark_reg_unknown(env, regs, insn->dst_reg);
@@ -14465,7 +14464,7 @@ sanitize_speculative_path(struct bpf_ver
 			mark_reg_unknown(env, regs, insn->src_reg);
 		}
 	}
-	return branch;
+	return PTR_ERR_OR_ZERO(branch);
 }
 
 static int sanitize_ptr_alu(struct bpf_verifier_env *env,
@@ -14484,7 +14483,6 @@ static int sanitize_ptr_alu(struct bpf_v
 	u8 opcode = BPF_OP(insn->code);
 	u32 alu_state, alu_limit;
 	struct bpf_reg_state tmp;
-	bool ret;
 	int err;
 
 	if (can_skip_alu_sanitation(env, insn))
@@ -14557,11 +14555,12 @@ do_sim:
 		tmp = *dst_reg;
 		copy_register_state(dst_reg, ptr_reg);
 	}
-	ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
-					env->insn_idx);
-	if (!ptr_is_dst_reg && ret)
+	err = sanitize_speculative_path(env, NULL, env->insn_idx + 1, env->insn_idx);
+	if (err < 0)
+		return REASON_STACK;
+	if (!ptr_is_dst_reg)
 		*dst_reg = tmp;
-	return !ret ? REASON_STACK : 0;
+	return 0;
 }
 
 static void sanitize_mark_insn_seen(struct bpf_verifier_env *env)
@@ -17029,8 +17028,8 @@ static int check_cond_jmp_op(struct bpf_
 
 		/* branch out 'fallthrough' insn as a new state to explore */
 		queued_st = push_stack(env, idx + 1, idx, false);
-		if (!queued_st)
-			return -ENOMEM;
+		if (IS_ERR(queued_st))
+			return PTR_ERR(queued_st);
 
 		queued_st->may_goto_depth++;
 		if (prev_st)
@@ -17108,10 +17107,11 @@ static int check_cond_jmp_op(struct bpf_
 		 * the fall-through branch for simulation under speculative
 		 * execution.
 		 */
-		if (!env->bypass_spec_v1 &&
-		    !sanitize_speculative_path(env, insn, *insn_idx + 1,
-					       *insn_idx))
-			return -EFAULT;
+		if (!env->bypass_spec_v1) {
+			err = sanitize_speculative_path(env, insn, *insn_idx + 1, *insn_idx);
+			if (err < 0)
+				return err;
+		}
 		if (env->log.level & BPF_LOG_LEVEL)
 			print_insn_state(env, this_branch, this_branch->curframe);
 		*insn_idx += insn->off;
@@ -17121,11 +17121,12 @@ static int check_cond_jmp_op(struct bpf_
 		 * program will go. If needed, push the goto branch for
 		 * simulation under speculative execution.
 		 */
-		if (!env->bypass_spec_v1 &&
-		    !sanitize_speculative_path(env, insn,
-					       *insn_idx + insn->off + 1,
-					       *insn_idx))
-			return -EFAULT;
+		if (!env->bypass_spec_v1) {
+			err = sanitize_speculative_path(env, insn, *insn_idx + insn->off + 1,
+							*insn_idx);
+			if (err < 0)
+				return err;
+		}
 		if (env->log.level & BPF_LOG_LEVEL)
 			print_insn_state(env, this_branch, this_branch->curframe);
 		return 0;
@@ -17148,8 +17149,8 @@ static int check_cond_jmp_op(struct bpf_
 
 	other_branch = push_stack(env, *insn_idx + insn->off + 1, *insn_idx,
 				  false);
-	if (!other_branch)
-		return -EFAULT;
+	if (IS_ERR(other_branch))
+		return PTR_ERR(other_branch);
 	other_branch_regs = other_branch->frame[other_branch->curframe]->regs;
 
 	if (BPF_SRC(insn->code) == BPF_X) {
@@ -17448,8 +17449,8 @@ static int check_ld_abs(struct bpf_verif
 
 		mark_reg_scratched(env, BPF_REG_0);
 		branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
-		if (!branch)
-			return -EFAULT;
+		if (IS_ERR(branch))
+			return PTR_ERR(branch);
 		mark_reg_known_zero(env, regs, BPF_REG_0);
 		err = prepare_func_exit(env, &env->insn_idx);
 		if (err)
author maintainer
#12 lore raw

PATCH 12/583 drm/amd/display: fix division by zero in get_estimated_bw()

In reply to Greg Kroah-Hartman

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

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

From: Hari Mishal <[email protected]>

commit f63de9054da858d57054474c32464106f8375e0d upstream.

get_estimated_bw() divides by link->dpia_bw_alloc_config.bw_granularity, which is zeroed by reset_bw_alloc_struct() and only populated once DP_TUNNELING_BW_ALLOC_CAP_CHANGED has been handled.

link_dp_dpia_handle_bw_alloc_status(), the DPCD interrupt handler, calls get_estimated_bw() whenever DP_TUNNELING_ESTIMATED_BW_CHANGED is set, independently of whether DP_TUNNELING_BW_ALLOC_CAP_CHANGED has ever fired for that link. A connected USB4/DPIA tunneling device that reports an estimated-bandwidth change before ever reporting a capability change drives a division by zero in this IRQ path.

link_dpia_send_bw_alloc_request() already guards the same bw_granularity division; add the identical guard here rather than introducing a new pattern.

Fixes 8e5cfe547bf3 ("drm/amd/display: upstream link_dp_dpia_bw.c")
Assisted-by gkh_clanker_t1000
(cherry picked from commit f2a961457c33dc34223aad5c9e8971de34a4eed3)
---
 drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c |    5 +++++
 1 file changed, 5 insertions(+)
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c +5 -0
@@ -103,6 +103,11 @@ static int get_estimated_bw(struct dc_li
 {
 	uint8_t bw_estimated_bw = 0;
 
+	if (link->dpia_bw_alloc_config.bw_granularity == 0) {
+		DC_LOG_ERROR("%s: BW granularity is zero!\n", __func__);
+		return 0;
+	}
+
 	core_link_read_dpcd(
 			link,
 			ESTIMATED_BW,
author maintainer
#13 lore raw

PATCH 13/583 usb: image: mdc800: change kmalloc() to kzalloc()

In reply to Greg Kroah-Hartman

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

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

From: Griffin Kroah-Hartman <[email protected]>

commit 2430eb81e44111b30eeb5273bbcf8b24ca517ef9 upstream.

Change the kmalloc() calls in usb_mdc800_init() for irq_urb_buffer and download_urb_buffer to kzalloc(), avoiding potential stack leaks if a shorter message is received in mdc800_usb_irq() and mdc800_usb_download_notify()

---
 drivers/usb/image/mdc800.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/image/mdc800.c +2 -2
@@ -1000,13 +1000,13 @@ static int __init usb_mdc800_init (void)
 	mdc800->downloaded = 0;
 	mdc800->written = 0;
 
-	mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);
+	mdc800->irq_urb_buffer=kzalloc (8, GFP_KERNEL);
 	if (!mdc800->irq_urb_buffer)
 		goto cleanup_on_fail;
 	mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);
 	if (!mdc800->write_urb_buffer)
 		goto cleanup_on_fail;
-	mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);
+	mdc800->download_urb_buffer=kzalloc (64, GFP_KERNEL);
 	if (!mdc800->download_urb_buffer)
 		goto cleanup_on_fail;
 
author maintainer
#14 lore raw

PATCH 14/583 ALSA: usb-audio: fix OOB write in snd_usbmidi_us122l_output()

In reply to Greg Kroah-Hartman

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

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

From: HyeongJun An <[email protected]>

commit e4637ce34607f1733a34a57294966d26b263e626 upstream.

The snd_usbmidi_us122l_output() picks a count of 2 on anything slower than high speed and never relates it to ep->max_transfer. The URB buffer holds exactly max_transfer bytes, so a device declaring a one byte bulk endpoint takes two bytes from snd_rawmidi_transmit(), and the memset that pads the rest computes 1 - 2 in int and wraps to SIZE_MAX.

Only 0x800e and 0x800f are pinned to nine bytes. The US-122MKII at 0x0644:0x8021 falls to the default and takes usb_maxpacket(), which the USB core only clamps downward.

The akai and novation output ops in this file were given the same guard recently. Do the same here.

Fixes 030a07e44129 ("ALSA: Add USB US122L driver")
Assisted-by Claude:claude-opus-5
---
 sound/usb/midi.c |    2 ++
 1 file changed, 2 insertions(+)
sound/usb/midi.c +2 -0
@@ -967,6 +967,8 @@ static void snd_usbmidi_us122l_output(st
 	default:
 		count = 2;
 	}
+	if (ep->max_transfer < count)
+		return;
 	count = snd_rawmidi_transmit(ep->ports[0].substream,
 				     urb->transfer_buffer,
 				     count);
author maintainer
#15 lore raw

PATCH 15/583 clk: qcom: gcc-mdm9607: Increase delay for USB PHY reset

In reply to Greg Kroah-Hartman

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

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

From: Stephan Gerhold <[email protected]>

commit c99bc8e83848358bd4a0436e4bdae5b7919babb2 upstream.

To conform to the specifications of the USB PHY, the reset signal should be asserted for at least 10us. Guarantee that by increasing the delay for the USB2_HS_PHY_ONLY_BCR reset control similar to commit dcc6c9fb7128 ("clk:
qcom: gcc-msm8909: Increase delay for USB PHY reset").

---
 drivers/clk/qcom/gcc-mdm9607.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/qcom/gcc-mdm9607.c +1 -1
@@ -1567,7 +1567,7 @@ static const struct qcom_reset_map gcc_m
 	[USB_HS_HSIC_BCR] = { 0x3d05c },
 	[GCC_MSS_RESTART] = { 0x3e000 },
 	[USB_HS_BCR] = { 0x41000 },
-	[USB2_HS_PHY_ONLY_BCR] = { 0x41034 },
+	[USB2_HS_PHY_ONLY_BCR] = { .reg = 0x41034, .udelay = 15 },
 	[QUSB2_PHY_BCR] = { 0x4103c },
 };
 
author maintainer
#16 lore raw

PATCH 16/583 media: usbtv: keep device alive while ALSA card exists

In reply to Greg Kroah-Hartman

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

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

From: Shuangpeng Bai <[email protected]>

commit fc530fe168bb2b745a93f553ad21fc25fd9cba3d upstream.

The ALSA PCM callbacks store the driver state in pcm->private_data. An open PCM file can outlive USB disconnect because usbtv_audio_free() uses snd_card_free_when_closed(). The disconnect path can then drop the V4L2 device reference and free struct usbtv before ALSA releases the substream, so a later close dereferences freed memory in snd_usbtv_pcm_close().

Take a V4L2 device reference for the ALSA card and drop it from the card private_free callback. This keeps struct usbtv valid until ALSA has closed the remaining files and freed the card.

---
 drivers/media/usb/usbtv/usbtv-audio.c |   11 +++++++++++
 1 file changed, 11 insertions(+)
drivers/media/usb/usbtv/usbtv-audio.c +11 -0
@@ -317,6 +317,13 @@ static const struct snd_pcm_ops snd_usbt
 	.pointer = snd_usbtv_pointer,
 };
 
+static void usbtv_audio_card_free(struct snd_card *card)
+{
+	struct usbtv *usbtv = card->private_data;
+
+	v4l2_device_put(&usbtv->v4l2_dev);
+}
+
 int usbtv_audio_init(struct usbtv *usbtv)
 {
 	int rv;
@@ -331,6 +338,10 @@ int usbtv_audio_init(struct usbtv *usbtv
 	if (rv < 0)
 		return rv;
 
+	v4l2_device_get(&usbtv->v4l2_dev);
+	card->private_data = usbtv;
+	card->private_free = usbtv_audio_card_free;
+
 	strscpy(card->driver, usbtv->dev->driver->name, sizeof(card->driver));
 	strscpy(card->shortname, "usbtv", sizeof(card->shortname));
 	snprintf(card->longname, sizeof(card->longname),
author maintainer
#17 lore raw

PATCH 17/583 usb-storage: ene_ub6250: fix race between scan work and probe

In reply to Greg Kroah-Hartman

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

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

From: Liu Qi <[email protected]>

commit 445fc368c6bc73eff0aeb3818cf5f355facfbb16 upstream.

ene_ub6250_probe() calls usb_stor_probe2(), which starts the usb-storage infrastructure and schedules the delayed scan work. The driver then calls ene_get_card_type(), which sends an ENE command through ene_send_scsi_cmd() and the usb-storage bulk transfer helpers.

Both the delayed scan work, through usb_stor_Bulk_max_lun(), and ene_get_card_type() use us->current_urb. The scan work serializes this access with us->dev_mutex, but the ENE card-type probe does not. If the scan work runs while ene_get_card_type() is still using us->current_urb, usb_submit_urb() warns that the URB is already active.

Serialize ene_get_card_type() with us->dev_mutex, matching the locking used by the scan path.

---
 drivers/usb/storage/ene_ub6250.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/usb/storage/ene_ub6250.c +2 -0
@@ -2358,7 +2358,9 @@ static int ene_ub6250_probe(struct usb_i
 		return result;
 
 	/* probe card type */
+	mutex_lock(&us->dev_mutex);
 	result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf);
+	mutex_unlock(&us->dev_mutex);
 	if (result != USB_STOR_XFER_GOOD) {
 		usb_stor_disconnect(intf);
 		return USB_STOR_TRANSPORT_ERROR;
author maintainer
#18 lore raw

PATCH 18/583 usb: f_mass_storage: Bump local buffer size in fsg_common_create_luns()

In reply to Greg Kroah-Hartman

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

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

From: Andy Shevchenko <[email protected]>

commit 9f6f095beec82a80daa666a3b2186a5b95841e9a upstream.

GCC (Debian 14.2.0-19) is not happy about the buffer size:

drivers/usb/gadget/function/f_mass_storage.c:2970:48: error: ‘%d’ directive output may be truncated writing between 1 and 9 bytes into a region of size 5 [-Werror=format-truncation=]

Bump the size to get it enough for all possible values.

Note, although cfg->nluns is limited to FSG_MAX_LUNS (16), the compiler doesn't realize this and complains about the buffer size.

Also note, the existing comment is wrong as size 8 for the whole buffer doesn't cover 100 mil numbers, hence drop it altogether.

Fixes b27c08c953e9 ("usb: gadget: f_mass_storage: create lun creation helpers for use in fsg_common_init")
Cc stable <[email protected]>
---
 drivers/usb/gadget/function/f_mass_storage.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/function/f_mass_storage.c +1 -1
@@ -2961,7 +2961,7 @@ EXPORT_SYMBOL_GPL(fsg_common_create_lun)
 
 int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
 {
-	char buf[8]; /* enough for 100000000 different numbers, decimal */
+	char buf[14];
 	int i, rc;
 
 	fsg_common_remove_luns(common);
author maintainer
#19 lore raw

PATCH 19/583 usb: dwc3: clear forceRM when issuing EndTransfer

In reply to Greg Kroah-Hartman

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

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

From: Elson Serrao <[email protected]>

commit b58e6200450d350314db0ecda7d6d1bde3281e80 upstream.

The forceRM bit of the DEPCMD register controls the behavior of the EndTransfer command used to stop an active transfer. Older DWC3 programming guide revisions recommended setting forceRM=1 when issuing EndTransfer. Newer programming guide revisions recommend issuing EndTransfer with forceRM cleared.

With forceRM=1 on DWC_usb31 v2.00a and v2.10a controllers, a transfer aborted through the ep_dequeue path was observed to remain active after EndTransfer completion. A subsequent StartTransfer issued on the same endpoint triggered writes associated with the aborted transfer. This resulted in an SMMU fault because the transfer buffer had already been unmapped during EndTransfer command-completion cleanup.

Using forceRM=0 eliminates the issue. Although older DWC3 programming guide revisions recommended setting forceRM=1, no issues are known from using forceRM=0. Clear forceRM when issuing EndTransfer to provide consistent EndTransfer behavior and align with newer programming guide recommendations.

Fixes 1e43c86d84fb ("usb: dwc3: core: Add DWC31 version 2.00a controller")
Cc stable <[email protected]>
---
 drivers/usb/dwc3/ep0.c    |    2 +-
 drivers/usb/dwc3/gadget.c |   21 +++++++++++++--------
 2 files changed, 14 insertions(+), 9 deletions(-)
drivers/usb/dwc3/ep0.c +1 -1
@@ -304,7 +304,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc
 
 		dwc3_ep->flags &= ~DWC3_EP_DELAY_STOP;
 		if (dwc->connected)
-			dwc3_stop_active_transfer(dwc3_ep, true, true);
+			dwc3_stop_active_transfer(dwc3_ep, false, true);
 		else
 			dwc3_remove_requests(dwc, dwc3_ep, -ESHUTDOWN);
 	}
drivers/usb/dwc3/gadget.c +13 -8
@@ -1004,7 +1004,7 @@ static int __dwc3_gadget_ep_enable(struc
 			 * controller to generate an ERDY to initiate the
 			 * stream.
 			 */
-			dwc3_stop_active_transfer(dep, true, true);
+			dwc3_stop_active_transfer(dep, false, true);
 
 			/*
 			 * All stream eps will reinitiate stream on NoStream
@@ -1032,7 +1032,7 @@ void dwc3_remove_requests(struct dwc3 *d
 {
 	struct dwc3_request		*req;
 
-	dwc3_stop_active_transfer(dep, true, false);
+	dwc3_stop_active_transfer(dep, false, false);
 
 	/* If endxfer is delayed, avoid unmapping requests */
 	if (dep->flags & DWC3_EP_DELAY_STOP)
@@ -1720,7 +1720,7 @@ static int __dwc3_gadget_kick_transfer(s
 		if (ret == -EAGAIN)
 			return ret;
 
-		dwc3_stop_active_transfer(dep, true, true);
+		dwc3_stop_active_transfer(dep, false, true);
 
 		list_for_each_entry_safe(req, tmp, &dep->started_list, list)
 			dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_DEQUEUED);
@@ -1757,6 +1757,11 @@ static int __dwc3_gadget_get_frame(struc
  * the controller won't update the TRB progress on command
  * completion. It also won't clear the HWO bit in the TRB.
  * The command will also not complete immediately in that case.
+ *
+ * Older programming guide revisions recommended setting ForceRM to 1
+ * when ending a transfer. Newer programming guide revisions now
+ * recommend keeping ForceRM cleared, and TRBs are properly updated
+ * on command completion.
  */
 static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
 {
@@ -1882,7 +1887,7 @@ static int dwc3_gadget_start_isoc_quirk(
 		 * to wait for the next XferNotReady to test the command again
 		 */
 		if (cmd_status == 0) {
-			dwc3_stop_active_transfer(dep, true, true);
+			dwc3_stop_active_transfer(dep, false, true);
 			return 0;
 		}
 	}
@@ -2165,7 +2170,7 @@ static int dwc3_gadget_ep_dequeue(struct
 			struct dwc3_request *t;
 
 			/* wait until it is processed */
-			dwc3_stop_active_transfer(dep, true, true);
+			dwc3_stop_active_transfer(dep, false, true);
 
 			/*
 			 * Remove any started request if the transfer is
@@ -2242,7 +2247,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc
 			return 0;
 		}
 
-		dwc3_stop_active_transfer(dep, true, true);
+		dwc3_stop_active_transfer(dep, false, true);
 
 		list_for_each_entry_safe(req, tmp, &dep->started_list, list)
 			dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_STALLED);
@@ -3357,7 +3362,7 @@ static void dwc3_nostream_work(struct wo
 		dwc3_send_gadget_generic_command(dwc, cmd, dep->number);
 	} else {
 		dep->flags |= DWC3_EP_DELAY_START;
-		dwc3_stop_active_transfer(dep, true, true);
+		dwc3_stop_active_transfer(dep, false, true);
 		spin_unlock_irqrestore(&dwc->lock, flags);
 		return;
 	}
@@ -3715,7 +3720,7 @@ static bool dwc3_gadget_endpoint_trbs_co
 	if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
 		list_empty(&dep->started_list) &&
 		(list_empty(&dep->pending_list) || status == -EXDEV))
-		dwc3_stop_active_transfer(dep, true, true);
+		dwc3_stop_active_transfer(dep, false, true);
 	else if (dwc3_gadget_ep_should_continue(dep))
 		if (__dwc3_gadget_kick_transfer(dep) == 0)
 			no_started_trb = false;
author maintainer
#20 lore raw

PATCH 20/583 usb: storage: realtek_cr: fix use-after-free on disconnect

In reply to Greg Kroah-Hartman

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

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

From: Myeonghun Pak <[email protected]>

commit 4ffee1aebb0c0ffcda9faffd17834ea9b00d42cc upstream.

realtek_cr_destructor() calls timer_delete() before the chip containing the timer is freed. The timer callback may still be running and can rearm itself, resulting in a use-after-free.

Use timer_shutdown_sync() to wait for the callback and prevent further rearming. Do this unconditionally because ss_en may be changed after the timer is armed.

Move timer_setup() into init_realtek_cr() so the timer is initialized before any failure path can invoke the destructor.

Found by static analysis.

Fixes e931830bb877 ("Realtek cr: Add autosuspend function.")
Cc stable <[email protected]>
---
 drivers/usb/storage/realtek_cr.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/usb/storage/realtek_cr.c +4 -5
@@ -916,7 +916,6 @@ static int realtek_cr_autosuspend_setup(
 	us->proto_handler = rts51x_invoke_transport;
 
 	chip->timer_expires = 0;
-	timer_setup(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn, 0);
 	fw5895_init(us);
 
 	/* enable autosuspend function of the usb device */
@@ -934,10 +933,7 @@ static void realtek_cr_destructor(void *
 		return;
 
 #ifdef CONFIG_REALTEK_AUTOPM
-	if (ss_en) {
-		timer_delete(&chip->rts51x_suspend_timer);
-		chip->timer_expires = 0;
-	}
+	timer_shutdown_sync(&chip->rts51x_suspend_timer);
 #endif
 	kfree(chip->status);
 }
@@ -982,6 +978,9 @@ static int init_realtek_cr(struct us_dat
 
 	us->extra = chip;
 	us->extra_destructor = realtek_cr_destructor;
+#ifdef CONFIG_REALTEK_AUTOPM
+	timer_setup(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn, 0);
+#endif
 	us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
 	chip->us = us;
 
author maintainer
#21 lore raw

PATCH 21/583 usb: typec: qcom-pmic-typec: disable cc_debounce_dwork on stop

In reply to Greg Kroah-Hartman

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

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

From: Fan Wu <[email protected]>

commit 263f7d61a4201cde16849b2d016251806e7418be upstream.

cc_debounce_dwork is queued from the set_cc() and start_toggling() callbacks, which run from TCPM's kthread worker. port_stop() returns before tcpm_unregister_port() destroys that worker. Flushing the worker during unregister may therefore run a callback which queues the delayed work after port_stop() has returned.

The delayed work can then run after devres has freed pmic_typec_port.

Use disable_delayed_work_sync() in port_stop() to cancel a pending instance and prevent the TCPM callbacks from queueing another one.

This issue was found by an in-house static analysis tool.

Fixes a4422ff22142 ("usb: typec: qcom: Add Qualcomm PMIC Type-C driver")
Cc stable <[email protected]> # v6.10+
Assisted-by Codex:gpt-5.6
---
 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c +2 -0
@@ -693,6 +693,8 @@ static void qcom_pmic_typec_port_stop(st
 
 	for (i = 0; i < pmic_typec_port->nr_irqs; i++)
 		disable_irq(pmic_typec_port->irq_data[i].irq);
+
+	disable_delayed_work_sync(&pmic_typec_port->cc_debounce_dwork);
 }
 
 int qcom_pmic_typec_port_probe(struct platform_device *pdev,
author maintainer
#22 lore raw

PATCH 22/583 usb: typec: qcom-pmic-typec: drain cc_debounce_dwork if port_start() fails

In reply to Greg Kroah-Hartman

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

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

From: Fan Wu <[email protected]>

commit c9273c83885835dbd1e8835d5665dfb8503d65e0 upstream.

cc_debounce_dwork can be queued before port_start() fails:
tcpm_register_port() runs first, and its state machine may invoke set_cc() or start_toggling() from the TCPM worker. The error path then calls tcpm_unregister_port(), whose worker flush may queue the delayed work before devres frees pmic_typec_port.

Disable and drain the delayed work directly at port_start()'s error exit. Do not use port_stop() for this path: its IRQs use IRQF_NO_AUTOEN and are enabled only after a successful port_start().

This issue was found by an in-house static analysis tool.

Fixes a4422ff22142 ("usb: typec: qcom: Add Qualcomm PMIC Type-C driver")
Cc stable <[email protected]> # v6.10+
Assisted-by Codex:gpt-5.6
---
 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c +3 -0
@@ -683,6 +683,9 @@ static int qcom_pmic_typec_port_start(st
 		enable_irq(pmic_typec_port->irq_data[i].irq);
 
 done:
+	if (ret)
+		disable_delayed_work_sync(&pmic_typec_port->cc_debounce_dwork);
+
 	return ret;
 }
 
author maintainer
#23 lore raw

PATCH 23/583 usb: typec: qcom-pmic: cancel reset_work on stop

In reply to Greg Kroah-Hartman

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

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

From: Fan Wu <[email protected]>

commit 7b0df6efd143f8085bdb68778a013a46f1349913 upstream.

pdphy_stop() disables IRQs but leaves reset_work pending. If the IRQ handler schedules it just before disable_irq(), the work runs after remove() frees the struct via devm.

Call cancel_work_sync() after disabling IRQs to close the window.

This issue was found by an in-house static analysis tool.

Fixes a4422ff22142 ("usb: typec: qcom: Add Qualcomm PMIC Type-C driver")
Cc stable <[email protected]>
Assisted-by Codex:gpt-5.6
---
 drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c +2 -0
@@ -544,6 +544,8 @@ static void qcom_pmic_typec_pdphy_stop(s
 	for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
 		disable_irq(pmic_typec_pdphy->irq_data[i].irq);
 
+	cancel_work_sync(&pmic_typec_pdphy->reset_work);
+
 	qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
 
 	regulator_disable(pmic_typec_pdphy->vdd_pdphy);
author maintainer
#24 lore raw

PATCH 24/583 usb: typec: tcpm: constrain TCPM_SOURCING_VBUS event handling

In reply to Greg Kroah-Hartman

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

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

From: Amit Sunil Dhamne <[email protected]>

commit cd3b9cea675bbfebc223f007dc2f4e79524fa54c upstream.

When a sink detach occurs while waiting for TX send status, the old TCPM_SOURCING_VBUS event along with TCPM_VBUS_EVENT and TCPM_CC_EVENT can be queued in port->pd_events. Because TCPM_SOURCING_VBUS is evaluated after TCPM_VBUS_EVENT and TCPM_CC_EVENT in tcpm_pd_event_handler(), a stale TCPM_SOURCING_VBUS event can override the detach handling and incorrectly set port->vbus_source and port->vbus_present to true.

Add a state guard to check that the port is either operating as a Source (tcpm_port_is_source(port)) or in a Fast Role Swap (FRS) state up to FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED before processing TCPM_SOURCING_VBUS. Otherwise, discard and log the event.

Log snippet for error condition before fix:

[72792.204955] state change SRC_ATTACHED -> SRC_STARTUP [rev3 NONE_AMS]
[72792.204960] sourcing vbus
[72792.204962] VBUS on
[72792.204970] AMS POWER_NEGOTIATION start
[72792.204974] cc:=4
[72792.205319] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATION]
[72792.205325] state change AMS_START -> SRC_SEND_CAPABILITIES [rev3 POWER_NEGOTIATION]
[72792.205332] PD TX, header: 0x11a1
[72792.216911] PD TX complete, status: 2
[72792.216957] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES @ 150 ms [rev3 POWER_NEGOTIATION]
[72792.218005] VBUS off
[72792.218013] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
[72792.218020] VBUS VSAFE0V
[72792.218024] state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED [rev3 POWER_NEGOTIATION]
[72792.218458] CC1: 2 -> 0, CC2: 0 -> 0 [state SNK_UNATTACHED, polarity 0, disconnected]
[72792.218467] VBUS on --> VBUS left on
[72792.218980] disable vbus discharge ret:0
[72792.235193] Start toggling

After fix:

[ 1195.291691] state change SRC_ATTACHED -> SRC_STARTUP [rev3 NONE_AMS]
[ 1195.291698] sourcing vbus
[ 1195.291700] VBUS on
[ 1195.291707] AMS POWER_NEGOTIATION start
[ 1195.291710] cc:=4
[ 1195.291758] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATION]
[ 1195.291794] state change AMS_START -> SRC_SEND_CAPABILITIES [rev3 POWER_NEGOTIATION]
[ 1195.291798] PD TX, header: 0x11a1
[ 1195.297056] PD TX complete, status: 2
[ 1195.297092] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES @ 150 ms [rev3 POWER_NEGOTIATION]
[ 1195.297177] VBUS off
[ 1195.297184] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
[ 1195.297227] CC1: 2 -> 0, CC2: 0 -> 0 [state SRC_SEND_CAPABILITIES, polarity 0, disconnected]
[ 1195.307469] cc:=2
[ 1195.307544] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
[ 1195.307555] Discarding sourcing vbus! Invalid state SRC_SEND_CAPABILITIES
[ 1195.957636] state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED [delayed 650 ms]
[ 1195.957732] disable vbus discharge ret:0
[ 1195.970196] Start toggling
[ 1195.970468] VBUS off
[ 1196.051637] VBUS off
[ 1196.051642] VBUS VSAFE0V
Fixes 8dc4bd073663 ("usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS)")
Cc stable <[email protected]>
Assisted-by Gemini:gemini-3.1-pro
---
 drivers/usb/typec/tcpm/tcpm.c |   28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)
drivers/usb/typec/tcpm/tcpm.c +22 -6
@@ -6509,16 +6509,32 @@ static void tcpm_pd_event_handler(struct
 			}
 		}
 		if (events & TCPM_SOURCING_VBUS) {
-			tcpm_log(port, "sourcing vbus");
 			/*
 			 * In fast role swap case TCPC autonomously sources vbus. Set vbus_source
-			 * true as TCPM wouldn't have called tcpm_set_vbus.
+			 * true conditionally as TCPM wouldn't have called tcpm_set_vbus.
+			 * If TCPM calls tcpm_set_vbus to source vbus, vbus_source would already
+			 * be true.
 			 *
-			 * When vbus is sourced on the command on TCPM i.e. TCPM called
-			 * tcpm_set_vbus to source vbus, vbus_source would already be true.
+			 * When TCPM_FRS_EVENT and TCPM_SOURCING_VBUS arrive simultaneously,
+			 * handling TCPM_FRS_EVENT above transitions the state to AMS_START
+			 * with upcoming_state FR_SWAP_SEND.
 			 */
-			port->vbus_source = true;
-			_tcpm_pd_vbus_on(port);
+
+			if (tcpm_port_is_source(port) ||
+			    tcpm_port_is_debug_source(port) ||
+			    (port->state == AMS_START && port->upcoming_state == FR_SWAP_SEND) ||
+			    port->state == FR_SWAP_SEND ||
+			    port->state == FR_SWAP_SEND_TIMEOUT ||
+			    port->state == FR_SWAP_SNK_SRC_TRANSITION_TO_OFF ||
+			    port->state == FR_SWAP_SNK_SRC_NEW_SINK_READY ||
+			    port->state == FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED) {
+				tcpm_log(port, "sourcing vbus");
+				port->vbus_source = true;
+				_tcpm_pd_vbus_on(port);
+			} else {
+				tcpm_log(port, "Discarding sourcing vbus! Invalid state %s",
+					 tcpm_states[port->state]);
+			}
 		}
 		if (events & TCPM_PORT_CLEAN) {
 			tcpm_log(port, "port clean");
author maintainer
#25 lore raw

PATCH 25/583 usb: typec: tipd: Fix Thunderbolt altmode VDOs for cd321x

In reply to Greg Kroah-Hartman

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

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

From: Sven Peter <[email protected]>

commit e24e3370356bddb65d667985a332b5f8aeeb5f97 upstream.

The Intel VID status register is actually 9 bytes long and doesn't contain the raw VDOs but only the upper 16bits for device mode and enter mode. Shift those two fields into place and reconstruct the cable discover mode VDO from the data status register instead since it's not directly accessible. With this fixed now the correct VDOs are forwarded to the PHY and the to-be-submitted Thunderbolt/USB4 native host interface so that the right mode can be negotiated and the link actually comes up.

Fixes 0b31c978935f ("usb: typec: tipd: Read USB4, Thunderbolt and DisplayPort status for cd321x")
Fixes 82432bbfb9e8 ("usb: typec: tipd: Handle mode transitions for CD321x")
Cc stable <[email protected]>
---
 drivers/usb/typec/tipd/core.c     |   17 +++++++++++++----
 drivers/usb/typec/tipd/tps6598x.h |    4 ++--
 2 files changed, 15 insertions(+), 6 deletions(-)
drivers/usb/typec/tipd/core.c +13 -4
@@ -114,7 +114,6 @@ struct tps6598x_intel_vid_status_reg {
 	__le32 attention_vdo;
 	__le16 enter_vdo;
 	__le16 device_mode;
-	__le16 cable_mode;
 } __packed;
 
 /* Standard Task return codes */
@@ -694,9 +693,19 @@ static void cd321x_typec_update_mode(str
 		   cd321x->state.mode == TYPEC_TBT_MODE)
 			return;
 
-		tbt_data.cable_mode = le16_to_cpu(st->intel_vid_status.cable_mode);
-		tbt_data.device_mode = le16_to_cpu(st->intel_vid_status.device_mode);
-		tbt_data.enter_vdo = le16_to_cpu(st->intel_vid_status.enter_vdo);
+		tbt_data.cable_mode = TBT_MODE |
+			TBT_SET_CABLE_SPEED(TPS_DATA_STATUS_TBT_CABLE_SPEED(st->data_status)) |
+			TBT_SET_CABLE_ROUNDED(TPS_DATA_STATUS_TBT_CABLE_GEN(st->data_status));
+		if (st->data_status & TPS_DATA_STATUS_OPTICAL_CABLE)
+			tbt_data.cable_mode |= TBT_CABLE_OPTICAL;
+		if (st->data_status & TPS_DATA_STATUS_ACTIVE_LINK_TRAIN)
+			tbt_data.cable_mode |= TBT_CABLE_LINK_TRAINING;
+		if (st->data_status & TPS_DATA_STATUS_ACTIVE_CABLE)
+			tbt_data.cable_mode |= TBT_CABLE_ACTIVE_PASSIVE;
+		tbt_data.device_mode = TBT_MODE |
+			(u32)le16_to_cpu(st->intel_vid_status.device_mode) << 16;
+		tbt_data.enter_vdo =
+			(u32)le16_to_cpu(st->intel_vid_status.enter_vdo) << 16;
 		cd321x->state.alt = cd321x->port_altmode_tbt;
 		cd321x->state.mode = TYPEC_TBT_MODE;
 		cd321x->state.data = &tbt_data;
drivers/usb/typec/tipd/tps6598x.h +2 -2
@@ -206,10 +206,10 @@
 #define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) \
 	TPS_FIELD_GET(TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK, (x))
 #define TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK   GENMASK(27, 25)
-#define TPS_DATA_STATUS_TBT_CABLE_SPEED \
+#define TPS_DATA_STATUS_TBT_CABLE_SPEED(x) \
 	TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK, (x))
 #define TPS_DATA_STATUS_TBT_CABLE_GEN_MASK     GENMASK(29, 28)
-#define TPS_DATA_STATUS_TBT_CABLE_GEN \
+#define TPS_DATA_STATUS_TBT_CABLE_GEN(x) \
 	TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_GEN_MASK, (x))
 
 /* Map data status to DP spec assignments */
author maintainer
#26 lore raw

PATCH 26/583 usb: typec: ucsi: displayport: Fix OOB altmode array index

In reply to Greg Kroah-Hartman

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

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

From: Jameson Thies <[email protected]>

commit 04cec690b1fd9d1c4c314b91a10d8c68a3acfe18 upstream.

The UCSI displayport driver indexes the connector's port altmode array with the GET_CURRENT_CAM response after checking it is not 0xff. The port altmode array is UCSI_MAX_ALTMODES elements long. If the PPM returns an invalid GET_CURRENT_CAM response above UCSI_MAX_ALTMODES and not equal to 0xff, the kernel may crash with an array index OOB error.

Update the UCSI displayport driver to verify the current cam is less than UCSI_MAX_ALTMODES before accessing the port altmode array.

Fixes af8622f6a585 ("usb: typec: ucsi: Support for DisplayPort alt mode")
---
 drivers/usb/typec/ucsi/displayport.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/typec/ucsi/displayport.c +1 -1
@@ -74,7 +74,7 @@ static int ucsi_displayport_enter(struct
 		cur = 0xff;
 	}
 
-	if (cur != 0xff) {
+	if (cur < UCSI_MAX_ALTMODES) {
 		ret = dp->con->port_altmode[cur] == alt ? 0 : -EBUSY;
 		goto err_unlock;
 	}
author maintainer
#27 lore raw

PATCH 27/583 usb: gadget: midi2: Fix null-pointer dereference in f_midi2_free_ep_reqs

In reply to Greg Kroah-Hartman

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

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

From: Aleksandr Nogikh <[email protected]>

commit f0efaf1872949e96d213c8e910fd9517f7d7c406 upstream.

A null-pointer dereference occurs in f_midi2_free_ep_reqs() when attempting to clean up an endpoint that was never initialized.

When configuring the MIDI 2.0 gadget via configfs and setting the block direction to SNDRV_UMP_DIR_INPUT, the initialization of the midi1_ep_out endpoint is explicitly skipped during the gadget bind phase (f_midi2_bind()). As a result, the usb_ep->card field remains NULL.

Later, when the host sets the alternate setting, f_midi2_set_alt() unconditionally stops both the IN and OUT endpoints by calling f_midi2_stop_eps(), which in turn calls f_midi2_free_ep_reqs() for both endpoints. When f_midi2_free_ep_reqs() is called for the uninitialized midi1_ep_out, it attempts to dereference usb_ep->card to determine the number of requests to free, leading to a crash.

Fix this by using usb_ep->num_reqs instead of usb_ep->card->info.num_reqs in f_midi2_free_ep_reqs(). usb_ep->num_reqs is correctly set during f_midi2_init_ep() and remains 0 if the endpoint was never initialized, safely avoiding the loop. For consistency, apply the same change to f_midi2_alloc_ep_reqs().

Oops: general protection fault, probably for non-canonical address
0xdffffc00000000ee: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000770-0x0000000000000777]
...
RIP: 0010:f_midi2_free_ep_reqs drivers/usb/gadget/function/f_midi2.c:1166
[inline]
RIP: 0010:f_midi2_stop_eps+0x28e/0x4d0
drivers/usb/gadget/function/f_midi2.c:1246
...
Call Trace:
 <TASK>
 f_midi2_set_alt+0x11c/0xf00 drivers/usb/gadget/function/f_midi2.c:1296
 composite_setup+0x1ffd/0x3480 drivers/usb/gadget/composite.c:1933
 configfs_composite_setup+0xbd/0x100 drivers/usb/gadget/configfs.c:1877
---
 drivers/usb/gadget/function/f_midi2.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/usb/gadget/function/f_midi2.c +2 -3
@@ -1145,7 +1145,7 @@ static int f_midi2_alloc_ep_reqs(struct
 	if (!usb_ep->reqs)
 		return -EINVAL;
 
-	for (i = 0; i < midi2->info.num_reqs; i++) {
+	for (i = 0; i < usb_ep->num_reqs; i++) {
 		if (usb_ep->reqs[i].req)
 			continue;
 		usb_ep->reqs[i].req = alloc_ep_req(usb_ep->usb_ep,
@@ -1160,10 +1160,9 @@ static int f_midi2_alloc_ep_reqs(struct
 /* Free allocated requests */
 static void f_midi2_free_ep_reqs(struct f_midi2_usb_ep *usb_ep)
 {
-	struct f_midi2 *midi2 = usb_ep->card;
 	int i;
 
-	for (i = 0; i < midi2->info.num_reqs; i++) {
+	for (i = 0; i < usb_ep->num_reqs; i++) {
 		if (!usb_ep->reqs[i].req)
 			continue;
 		free_ep_req(usb_ep->usb_ep, usb_ep->reqs[i].req);
author maintainer
#28 lore raw

PATCH 28/583 usb: gadget: f_midi2: fix use-after-free in string attribute show path

In reply to Greg Kroah-Hartman

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

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

From: Ivy Lopez <[email protected]>

commit fed0aa7c6eaedc6c0d4e362fc91724aa47be4a7b upstream.

f_midi2_opts_str_show() takes the string lock internally, but its callers dereference the opts->info.<field> pointer before calling it, outside the lock. This races with f_midi2_opts_str_store(), which frees the old string under opts->lock when the attribute is written concurrently, the show path can read a pointer that gets freed before the lock inside str_show() is even taken.

Change f_midi2_opts_str_show() to take a pointer to the string field, matching the existing pattern in f_midi2_opts_str_store(), and dereference it only after the lock is held. Update all three callers (iface_name, block name, and the EP string option macro) accordingly.

---
 drivers/usb/gadget/function/f_midi2.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/usb/gadget/function/f_midi2.c +6 -6
@@ -2178,13 +2178,13 @@ end:
 
 /* generic show/store for string */
 static ssize_t f_midi2_opts_str_show(struct f_midi2_opts *opts,
-				     const char *str, char *page)
+				     const char **strp, char *page)
 {
 	int result = 0;
 
 	mutex_lock(&opts->lock);
-	if (str)
-		result = scnprintf(page, PAGE_SIZE, "%s\n", str);
+	if (*strp)
+		result = scnprintf(page, PAGE_SIZE, "%s\n", *strp);
 	mutex_unlock(&opts->lock);
 	return result;
 }
@@ -2278,7 +2278,7 @@ static ssize_t f_midi2_block_opts_name_s
 {
 	struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item);
 
-	return f_midi2_opts_str_show(opts->ep->opts, opts->info.name, page);
+	return f_midi2_opts_str_show(opts->ep->opts, &opts->info.name, page);
 }
 
 static ssize_t f_midi2_block_opts_name_store(struct config_item *item,
@@ -2435,7 +2435,7 @@ static ssize_t f_midi2_ep_opts_##name##_
 					     char *page)		\
 {									\
 	struct f_midi2_ep_opts *opts = to_f_midi2_ep_opts(item);	\
-	return f_midi2_opts_str_show(opts->opts, opts->info.name, page);\
+	return f_midi2_opts_str_show(opts->opts, &opts->info.name, page);\
 }									\
 									\
 static ssize_t f_midi2_ep_opts_##name##_store(struct config_item *item,	\
@@ -2590,7 +2590,7 @@ static ssize_t f_midi2_opts_iface_name_s
 {
 	struct f_midi2_opts *opts = to_f_midi2_opts(item);
 
-	return f_midi2_opts_str_show(opts, opts->info.iface_name, page);
+	return f_midi2_opts_str_show(opts, &opts->info.iface_name, page);
 }
 
 static ssize_t f_midi2_opts_iface_name_store(struct config_item *item,
author maintainer
#29 lore raw

PATCH 29/583 usb: gadget: f_midi: initialize work in f_midi_alloc()

In reply to Greg Kroah-Hartman

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

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

From: Jeffin Philip <[email protected]>

commit 7e07d3e4c389217d7d7171d80edf2e23ac70f1ea upstream.

f_midi_alloc initializes free_ref to 1 and it can only be incremented when a sound card is registered via f_midi_register_card(). f_midi_register_card() is only called in f_midi_bind() which actually performs INIT_WORK. If f_midi_bind() is never run, work is not initialized and the if condition in f_midi_free becomes true, this results in a warning later in __flush_work as work->func = 0. Fix this by moving INIT_WORK from f_midi_bind() to f_midi_alloc().

---
 drivers/usb/gadget/function/f_midi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/function/f_midi.c +1 -1
@@ -878,7 +878,6 @@ static int f_midi_bind(struct usb_config
 	int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0;
 
 	midi->gadget = cdev->gadget;
-	INIT_WORK(&midi->work, f_midi_in_work);
 	status = f_midi_register_card(midi);
 	if (status < 0)
 		goto fail_register;
@@ -1371,6 +1370,7 @@ static struct usb_function *f_midi_alloc
 		status = -ENOMEM;
 		goto midi_free;
 	}
+	INIT_WORK(&midi->work, f_midi_in_work);
 	midi->out_ports = opts->out_ports;
 	midi->index = opts->index;
 	midi->buflen = opts->buflen;
author maintainer
#30 lore raw

PATCH 30/583 USB: gadget: fix NULL pointer dereference in gadget_dev_ioctl()

In reply to Greg Kroah-Hartman

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

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

From: Lovekesh Solanki <[email protected]>

commit dd0eed9e165b1a6292f49e622e3dd0b7d99b106d upstream.

gadget_dev_ioctl() reads dev->gadget before acquiring dev->lock, but dev->state is checked after acquiring the lock. Therefore a concurrent bind can change the device state between these operations, which can leave ioctl with a stale NULL gadget pointer and causing a NULL pointer dereference at gadget->ops->ioctl.

Read dev->gadget while holding dev->lock so that the gadget pointer and device state are sampled consistently.

---
 drivers/usb/gadget/legacy/inode.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/gadget/legacy/inode.c +2 -1
@@ -1253,10 +1253,11 @@ out:
 static long gadget_dev_ioctl (struct file *fd, unsigned code, unsigned long value)
 {
 	struct dev_data		*dev = fd->private_data;
-	struct usb_gadget	*gadget = dev->gadget;
+	struct usb_gadget	*gadget;
 	long ret = -ENOTTY;
 
 	spin_lock_irq(&dev->lock);
+	gadget = dev->gadget;
 	if (dev->state == STATE_DEV_OPENED ||
 			dev->state == STATE_DEV_UNBOUND) {
 		/* Not bound to a UDC */
author maintainer
#31 lore raw

PATCH 31/583 usb: gadget: fix null pointer dereference in usb_put_function_instance()

In reply to Greg Kroah-Hartman

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

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

From: Jeffin Philip <[email protected]>

commit 6e74ac5c596fd246e37eadfc354567179ccbe9aa upstream.

usb_put_function_instance() attempts to dereference fd inside fi struct to get mod in uvc_alloc_inst() error path. However, fd is not allocated until later in try_get_usb_function_instance() after allocating fi in uvc_alloc_inst() and thus guranteed to be null in error path. Fix this by adding a null check for fi->fd that returns if fd is null.

Reported-by [email protected]
Fixes 0062f6e56f70 ("usb: gadget: add a forward pointer from usb_function to its "instance"")
Cc stable <[email protected]>
---
 drivers/usb/gadget/functions.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/functions.c +1 -1
@@ -70,7 +70,7 @@ void usb_put_function_instance(struct us
 {
 	struct module *mod;
 
-	if (!fi)
+	if (!fi || !fi->fd)
 		return;
 
 	mod = fi->fd->mod;
author maintainer
#32 lore raw

PATCH 32/583 staging: rtl8723bs: fix OOB read / stack overflow in rtw_get_wps_attr()

In reply to Greg Kroah-Hartman

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

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

From: Muhammad Bilal <[email protected]>

commit 99aa998dec83ba180822f70e6d48a514fc81c20d upstream.

rtw_get_wps_attr() walks WPS attributes inside a WPS IE taken from a wireless management frame. For each candidate attribute it only checks that the fixed 4-byte attribute header (2-byte ID + 2-byte length) fits inside the IE:

	if (attr_ptr + 4 > wps_ie + wps_ielen)
		break;
	u16 attr_id = get_unaligned_be16(attr_ptr);
	u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
	u16 attr_len = attr_data_len + 4;

attr_data_len (and therefore attr_len) is read directly from the wire and is never checked against the remaining bytes in the IE before being used as the size of:

	memcpy(buf_attr, attr_ptr, attr_len);

Since attr_len is fully attacker controlled (0 to 65535+4), this is both a heap OOB read of wps_ie, and, more seriously, a stack buffer overflow at several call sites where buf_attr is a single-byte stack variable, e.g. rtw_get_wps_attr_content()'s callers passing WPS_ATTR_SELECTED_REGISTRAR into a stack "u8 sr"/"u8 selected_registrar" (drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c, drivers/staging/rtl8723bs/core/rtw_mlme_ext.c). A crafted WPS IE in a beacon or probe response processed during scanning can therefore smash the stack of the parsing thread.

rtw_get_wps_attr_content() itself has no independent length check and simply trusts the attr_len it gets back from rtw_get_wps_attr(), so fixing the bound here also fixes that caller.

The "attr_ptr + 4 > wps_ie + wps_ielen" header check above was added by commit 1463ca3ec6601 ("staging: rtl8723bs: fix OOB reads in rtw_get_sec_ie(), rtw_get_wapi_ie(), and rtw_get_wps_attr()"), which bounded the fixed header but never extended the check to cover the variable-length attribute data that follows it. Add that missing check before attr_len is used as a memcpy() length or accepted as a match.

---
 drivers/staging/rtl8723bs/core/rtw_ieee80211.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/staging/rtl8723bs/core/rtw_ieee80211.c +4 -0
@@ -746,6 +746,10 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wp
 		u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
 		u16 attr_len = attr_data_len + 4;
 
+		/* Reject attributes whose claimed length runs past the IE */
+		if (attr_ptr + attr_len > wps_ie + wps_ielen)
+			break;
+
 		if (attr_id == target_attr_id) {
 			target_attr_ptr = attr_ptr;
 
author maintainer
#33 lore raw

PATCH 33/583 staging: rtl8723bs: fix OOB read in rtw_action_frame_parse()

In reply to Greg Kroah-Hartman

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

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

From: Muhammad Bilal <[email protected]>

commit ff917923f4fb9c83717ba135ee47d7e4c1567bb7 upstream.

rtw_action_frame_parse() takes a frame_len parameter but never actually checks it before indexing into the frame body:

	const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr);
	...
	c = frame_body[0];
	...
	a = frame_body[1];

frame_body already points 24 bytes (sizeof(struct ieee80211_hdr_3addr)) into frame, so reading frame_body[0] and frame_body[1] requires frame_len >= 26. A management action frame shorter than that (e.g. exactly 24 bytes, the minimum a malicious peer can send) causes a 1-2 byte out-of-bounds read.

This is reachable from rtw_cfg80211_monitor_if_xmit_entry() and cfg80211_rtw_mgmt_tx() in ioctl_cfg80211.c, both of which pass attacker/user-influenced frame buffers and lengths straight through.

Add the missing length check before frame_body is dereferenced.

Fixes 554c0a3abf216 ("staging: Add rtl8723bs sdio wifi driver")
---
 drivers/staging/rtl8723bs/core/rtw_ieee80211.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/staging/rtl8723bs/core/rtw_ieee80211.c +3 -0
@@ -1152,6 +1152,9 @@ int rtw_action_frame_parse(const u8 *fra
 	u8 c;
 	u8 a = ACT_PUBLIC_MAX;
 
+	if (frame_len < sizeof(struct ieee80211_hdr_3addr) + 2)
+		return false;
+
 	fc = le16_to_cpu(((struct ieee80211_hdr_3addr *)frame)->frame_control);
 
 	if ((fc & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE))
author maintainer
#34 lore raw

PATCH 34/583 xhci: fix lost bounce buffers on TDs spanning several ring segments

In reply to Greg Kroah-Hartman

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

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

From: Arthur Gautier <[email protected]>

commit ff44dfb03a293bf30e31f98772a1dd316a6071d1 upstream.

When a TD reaches a link TRB with data that is not aligned to the endpoint's wMaxPacketSize, xhci_align_td() stages the unalignable tail through the bounce buffer of the ring segment holding that link TRB. xhci_unmap_td_bounce_buffer() later unmaps it and, for IN transfers, copies the data back into the URB's buffer.

The enqueue path records the segment that was bounced in td->bounce_seg, under the assumption that a TD never spans more than two ring segments. That assumption does not hold: a TD large enough to span three or more segments crosses several link TRBs and can be bounced at each of them. Only the last one survives in td->bounce_seg, so every earlier bounce buffer is neither copied back nor DMA unmapped.

The URB still completes with actual_length equal to the requested length and no error, so the transfer looks successful while a wMaxPacketSize sized hole in the destination buffer silently keeps its previous contents. It also leaks a DMA mapping per dropped bounce.

Any sufficiently large and fragmented bulk transfer can hit this. It was found with a USB mass storage device behind xHCI backing a dm-verity target with 512 byte hash blocks, where the stale data is detected rather than silently consumed. The device enumerates as SuperSpeed, so wMaxPacketSize is 1024, while dm-bufio issues one 512 byte bio per hash block. verity_prefetch_io() makes the block layer merge hundreds of them into a single request of up to 512 scatterlist entries of 512 bytes each. At 256 TRBs per ring segment such a TD spans three segments, and every segment boundary falls on an odd multiple of 512, i.e. unaligned to wMaxPacketSize. dm-bufio then caches a hash block holding stale data and dm-verity declares the metadata block corrupted:

device-mapper: verity: 8:2: metadata block 10850 is corrupted

A reproducer running this under qemu is available at
https://github.com/baloo/xhci-verity

The bounce state (bounce_buf, bounce_dma, bounce_len, bounce_offs) already lives on the ring segment, so there is nothing extra to track. Keep recording the last bounced segment in td->bounce_seg and, on completion, walk the segments from td->start_seg up to it, unmapping every segment that still has a pending bounce.

Stopping at td->bounce_seg rather than td->end_seg matters: a bounce implies the TD continues past that segment's link TRB, so bounce_seg is always strictly before end_seg, and a later TD may already have started in end_seg and been bounced there. Walking that far would copy a foreign bounce buffer into this URB and unmap it twice. It also keeps the walk correct if a TD ever wraps the whole ring so that end_seg == start_seg.

[mn: Add ring->num_segs check to prevent unlikely infinite for loop.]

Fixes f9c589e142d0 ("xhci: TD-fragment, align the unsplittable case with a bounce buffer")
---
 drivers/usb/host/xhci-ring.c |   32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)
drivers/usb/host/xhci-ring.c +24 -8
@@ -841,21 +841,18 @@ static void xhci_giveback_urb_in_irq(str
 	usb_hcd_giveback_urb(hcd, urb, status);
 }
 
-static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
-		struct xhci_ring *ring, struct xhci_td *td)
+static void xhci_unmap_one_bounce_buffer(struct xhci_hcd *xhci,
+		struct xhci_ring *ring, struct xhci_td *td,
+		struct xhci_segment *seg)
 {
 	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
-	struct xhci_segment *seg = td->bounce_seg;
 	struct urb *urb = td->urb;
 	size_t len;
 
-	if (!ring || !seg || !urb)
-		return;
-
 	if (usb_urb_dir_out(urb)) {
 		dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
 				 DMA_TO_DEVICE);
-		return;
+		goto done;
 	}
 
 	dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
@@ -871,10 +868,29 @@ static void xhci_unmap_td_bounce_buffer(
 		memcpy(urb->transfer_buffer + seg->bounce_offs, seg->bounce_buf,
 		       seg->bounce_len);
 	}
+done:
 	seg->bounce_len = 0;
 	seg->bounce_offs = 0;
 }
 
+static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
+		struct xhci_ring *ring, struct xhci_td *td)
+{
+	struct xhci_segment *seg;
+	int i = 0;
+
+	if (!td->bounce_seg || !ring || !td->urb)
+		return;
+
+	/* td->bounce_seg is the last one bounced, unmap them all */
+	for (seg = td->start_seg; i++ < ring->num_segs; seg = seg->next) {
+		if (seg->bounce_len)
+			xhci_unmap_one_bounce_buffer(xhci, ring, td, seg);
+		if (seg == td->bounce_seg)
+			break;
+	}
+}
+
 static void xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
 			    struct xhci_ring *ep_ring, int status)
 {
@@ -3739,7 +3755,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
 						  &trb_buff_len,
 						  ring->enq_seg)) {
 					send_addr = ring->enq_seg->bounce_dma;
-					/* assuming TD won't span 2 segs */
+					/* TD bounced at least, and last on this seg */
 					td->bounce_seg = ring->enq_seg;
 				}
 			}
author maintainer
#35 lore raw

PATCH 35/583 thermal/drivers/imx: Disable clock on runtime resume failure

In reply to Greg Kroah-Hartman

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

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

From: Can Peng <[email protected]>

commit bcc6d886e5006a4656901d2d7fb6a215c96068a0 upstream.

imx_thermal_runtime_resume() enables the thermal clock before powering up the sensor and enabling measurements.

If either regmap_write() fails, the function returns with the clock still enabled. This leaves the clock enable count unbalanced after a failed runtime resume.

Disable the clock on those failure paths before returning the error.

Fixes 4cf2ddf16e17 ("thermal/drivers/imx: Implement runtime PM support")
---
 drivers/thermal/imx_thermal.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/thermal/imx_thermal.c +7 -2
@@ -832,12 +832,12 @@ static int imx_thermal_runtime_resume(st
 	ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
 			   socdata->power_down_mask);
 	if (ret)
-		return ret;
+		goto disable_clk;
 
 	ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
 			   socdata->measure_temp_mask);
 	if (ret)
-		return ret;
+		goto disable_clk;
 
 	/*
 	 * According to the temp sensor designers, it may require up to ~17us
@@ -846,6 +846,11 @@ static int imx_thermal_runtime_resume(st
 	usleep_range(20, 50);
 
 	return 0;
+
+disable_clk:
+	clk_disable_unprepare(data->thermal_clk);
+
+	return ret;
 }
 
 static const struct dev_pm_ops imx_thermal_pm_ops = {
author maintainer
#36 lore raw

PATCH 36/583 thermal/drivers/qoriq: Disable clock on resume failure

In reply to Greg Kroah-Hartman

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

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

From: Can Peng <[email protected]>

commit fcbf9964b67a6d6704c50ed28daa24c3b164f01c upstream.

qoriq_tmu_resume() enables the TMU clock before clearing the power-down bit and enabling monitoring.

If either register update fails, the function returns with the clock still enabled. This leaves the clock enable count unbalanced after a failed resume.

Disable the clock on those failure paths before returning the error.

---
 drivers/thermal/qoriq_thermal.c |   13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/thermal/qoriq_thermal.c +11 -2
@@ -366,11 +366,20 @@ static int qoriq_tmu_resume(struct devic
 	if (data->ver > TMU_VER1) {
 		ret = regmap_clear_bits(data->regmap, REGS_TMR, TMR_CMD);
 		if (ret)
-			return ret;
+			goto disable_clk;
 	}
 
 	/* Enable monitoring */
-	return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, TMR_ME);
+	ret = regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, TMR_ME);
+	if (ret)
+		goto disable_clk;
+
+	return 0;
+
+disable_clk:
+	clk_disable_unprepare(data->clk);
+
+	return ret;
 }
 
 static DEFINE_SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
author maintainer
#37 lore raw

PATCH 37/583 userfaultfd: reset err to be 0 when move_pages_ptes succeeded

In reply to Greg Kroah-Hartman

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

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

From: Bryan Lim <[email protected]>

commit f025ca73decda1f895a4b80b961d3bc88825298a upstream.

During move_pages() operation, when move_pages_ptes() returns EAGAIN, the error code is not cleared even after we processed it. This leads to a successful retry but then the same pages are retried again due to the stale error code. This time move fails because pages are already moved, loop is terminated and move_pages() reports a failure. Clear the error code once we processes EAGAIN.

Fixes 50944692052b ("userfaultfd: opportunistic TLB-flush batching for present pages in MOVE")
Assisted-by ChatGPT:GPT-5.6-Luna
Cc Peter Xu <[email protected]>
---
 mm/userfaultfd.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
mm/userfaultfd.c +3 -1
@@ -1956,8 +1956,10 @@ ssize_t move_pages(struct userfaultfd_ct
 		}
 
 		if (err) {
-			if (err == -EAGAIN)
+			if (err == -EAGAIN) {
+				err = 0;
 				continue;
+			}
 			break;
 		}
 
author maintainer
#38 lore raw

PATCH 38/583 ublk: clear VM_MAYWRITE on read-only ublk char device mmap

In reply to Greg Kroah-Hartman

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

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

From: Kanishka De Silva <[email protected]>

commit 6e2b571b0a54755b06e092501913e1dfefe75d6c upstream.

ublk_ch_mmap() rejects mmap requests with VM_WRITE set, but never clears VM_MAYWRITE on the resulting read-only mapping. This allows a userspace daemon to mmap the per-queue command buffer PROT_READ, then upgrade it to PROT_WRITE via mprotect(), since VM_MAYWRITE was never cleared.

The command buffer holds struct ublksrv_io_desc entries that are kernel-written ABI; a writable mapping lets an unprivileged daemon process corrupt fields such as addr, op_flags, nr_sectors, and start_sector.

Same bug class as the drm/panthor and drm/vc4 VM_MAYWRITE fixes, and the 2026-08-13 ptp/vmclock fix (a5edadbae57e).

Verified via mprotect() PoC: before the fix, a PROT_READ mapping can be upgraded to PROT_READ|PROT_WRITE and a write into the command buffer corrupts io_desc fields (confirmed under KASAN). After the fix, mprotect() returns -EACCES.

---
 drivers/block/ublk_drv.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/block/ublk_drv.c +6 -0
@@ -1862,6 +1862,12 @@ static int ublk_ch_mmap(struct file *fil
 	if (vma->vm_flags & VM_WRITE)
 		return -EPERM;
 
+	/*
+	 * The per-queue command buffer is kernel-written ABI; prevent
+	 * the daemon from upgrading to writable via mprotect().
+	 */
+	vm_flags_clear(vma, VM_MAYWRITE);
+
 	end = UBLKSRV_CMD_BUF_OFFSET + ub->dev_info.nr_hw_queues * max_sz;
 	if (phys_off < UBLKSRV_CMD_BUF_OFFSET || phys_off >= end)
 		return -EINVAL;
author maintainer
#39 lore raw

PATCH 39/583 soc: qcom: geni-se: Use HW PROG_RAM_DEPTH to validate firmware size

In reply to Greg Kroah-Hartman

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

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

From: Viken Dadhaniya <[email protected]>

commit 522bfb4f33c0930b3d14d5c5ee80bc93a883b544 upstream.

The hardcoded MAX_GENI_CFG_RAMn_CNT limit is not accurate for all SoCs:
some targets have less CFG RAM than the constant implies, while others like QCS615 need more entries than the old limit of 455 allowed, causing valid firmware to be rejected at load time.

Rather than hardcoding a constant, read PROG_RAM_DEPTH from SE_HW_PARAM_2 at runtime to get the actual CFG RAM depth of the hardware instance and use that as the upper bound for firmware size validation.

---
 drivers/soc/qcom/qcom-geni-se.c  |   24 +++++++++++++-----------
 include/linux/soc/qcom/geni-se.h |    4 ++++
 2 files changed, 17 insertions(+), 11 deletions(-)
drivers/soc/qcom/qcom-geni-se.c +13 -11
@@ -152,8 +152,6 @@ struct se_fw_hdr {
 /*Magic numbers*/
 #define SE_MAGIC_NUM			0x57464553
 
-#define MAX_GENI_CFG_RAMn_CNT		455
-
 #define MI_PBT_NON_PAGED_SEGMENT	0x0
 #define MI_PBT_HASH_SEGMENT		0x2
 #define MI_PBT_NOTUSED_SEGMENT		0x3
@@ -990,24 +988,27 @@ EXPORT_SYMBOL_GPL(geni_icc_disable);
 
 /**
  * geni_find_protocol_fw() - Locate and validate SE firmware for a protocol.
- * @dev: Pointer to the device structure.
+ * @se: Pointer to the serial engine structure.
  * @fw: Pointer to the firmware image.
  * @protocol: Expected serial engine protocol type.
  *
  * Identifies the appropriate firmware image or configuration required for a
- * specific communication protocol instance running on a  Qualcomm GENI
- * controller.
+ * specific communication protocol instance running on a Qualcomm GENI
+ * controller. Validates the firmware size against the hardware PROG_RAM_DEPTH
+ * read from SE_HW_PARAM_2.
  *
  * Return: pointer to a valid 'struct se_fw_hdr' if found, or NULL otherwise.
  */
-static struct se_fw_hdr *geni_find_protocol_fw(struct device *dev, const struct firmware *fw,
+static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct firmware *fw,
 					       enum geni_se_protocol_type protocol)
 {
+	struct device *dev = se->dev;
 	const struct elf32_hdr *ehdr;
 	const struct elf32_phdr *phdrs;
 	const struct elf32_phdr	*phdr;
 	struct se_fw_hdr *sefw;
 	u32 fw_end, cfg_idx_end, cfg_val_end;
+	u32 prog_ram_depth;
 	u16 fw_size;
 	int i;
 
@@ -1066,10 +1067,11 @@ static struct se_fw_hdr *geni_find_proto
 			sefw->fw_size_in_items = cpu_to_le16(fw_size);
 		}
 
-		if (fw_size >= MAX_GENI_CFG_RAMn_CNT) {
-			dev_err(dev,
-				"Firmware size (%u) exceeds max allowed RAMn count (%u)\n",
-				fw_size, MAX_GENI_CFG_RAMn_CNT);
+		prog_ram_depth = FIELD_GET(PROG_RAM_DEPTH_MSK,
+					   readl_relaxed(se->base + SE_HW_PARAM_2));
+		if (fw_size >= prog_ram_depth) {
+			dev_err(dev, "Firmware size (%u) exceeds RAM size (%u)\n",
+				fw_size, prog_ram_depth);
 			continue;
 		}
 
@@ -1193,7 +1195,7 @@ static int geni_load_se_fw(struct geni_s
 	int ret;
 	struct se_fw_hdr *hdr;
 
-	hdr = geni_find_protocol_fw(se->dev, fw, protocol);
+	hdr = geni_find_protocol_fw(se, fw, protocol);
 	if (!hdr)
 		return -EINVAL;
 
include/linux/soc/qcom/geni-se.h +4 -0
@@ -118,6 +118,7 @@ struct geni_se {
 #define SE_DMA_RX_FSM_RST		0xd58
 #define SE_HW_PARAM_0			0xe24
 #define SE_HW_PARAM_1			0xe28
+#define SE_HW_PARAM_2			0xe2c
 
 /* GENI_FORCE_DEFAULT_REG fields */
 #define FORCE_DEFAULT	BIT(0)
@@ -285,6 +286,9 @@ struct geni_se {
 #define RX_FIFO_DEPTH_MSK		GENMASK(21, 16)
 #define RX_FIFO_DEPTH_SHFT		16
 
+/* SE_HW_PARAM_2 fields */
+#define PROG_RAM_DEPTH_MSK		GENMASK(10, 0)
+
 #define HW_VER_MAJOR_MASK		GENMASK(31, 28)
 #define HW_VER_MAJOR_SHFT		28
 #define HW_VER_MINOR_MASK		GENMASK(27, 16)
author maintainer
#40 lore raw

PATCH 40/583 spi: bcm63xx-hsspi: disable clocks on resume failure

In reply to Greg Kroah-Hartman

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

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

From: Can Peng <[email protected]>

commit 3b0cee02664041aea7e4f787c66cb86c82eb4e97 upstream.

bcm63xx_hsspi_resume() enables the HSSPI clock, and optionally the PLL clock, before restarting the SPI controller queue.

If spi_controller_resume() fails, the function currently reports success and leaves those clocks enabled. Propagate the error and disable the clocks before returning.

---
 drivers/spi/spi-bcm63xx-hsspi.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/spi/spi-bcm63xx-hsspi.c +7 -1
@@ -921,7 +921,13 @@ static int bcm63xx_hsspi_resume(struct d
 		}
 	}
 
-	spi_controller_resume(host);
+	ret = spi_controller_resume(host);
+	if (ret) {
+		if (bs->pll_clk)
+			clk_disable_unprepare(bs->pll_clk);
+		clk_disable_unprepare(bs->clk);
+		return ret;
+	}
 
 	return 0;
 }
author maintainer
#41 lore raw

PATCH 41/583 spi: bcm63xx: disable clock on resume failure

In reply to Greg Kroah-Hartman

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

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

From: Can Peng <[email protected]>

commit 2b62c2c134fa32d9d3a9e7323c8ac74518eeb4ac upstream.

bcm63xx_spi_resume() enables the controller clock before restarting the SPI controller queue.

If spi_controller_resume() fails, the function currently reports success and leaves the clock enabled. Propagate the error and disable the clock before returning.

Fixes b42dfed83d95 ("spi: add Broadcom BCM63xx SPI controller driver")
---
 drivers/spi/spi-bcm63xx.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/spi/spi-bcm63xx.c +5 -1
@@ -661,7 +661,11 @@ static int bcm63xx_spi_resume(struct dev
 	if (ret)
 		return ret;
 
-	spi_controller_resume(host);
+	ret = spi_controller_resume(host);
+	if (ret) {
+		clk_disable_unprepare(bs->clk);
+		return ret;
+	}
 
 	return 0;
 }
author maintainer
#42 lore raw

PATCH 42/583 spi: bcmbca-hsspi: disable clocks on resume failure

In reply to Greg Kroah-Hartman

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

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

From: Can Peng <[email protected]>

commit d2f5a606710ad70c341dc609430a20a5645618d5 upstream.

bcmbca_hsspi_resume() enables the HSSPI clock, and optionally the PLL clock, before restarting the SPI controller queue.

If spi_controller_resume() fails, the function currently reports success and leaves those clocks enabled. Propagate the error and disable the clocks before returning.

Fixes a38a2233f23b ("spi: bcmbca-hsspi: Add driver for newer HSSPI controller")
---
 drivers/spi/spi-bcmbca-hsspi.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/spi/spi-bcmbca-hsspi.c +7 -1
@@ -612,7 +612,13 @@ static int bcmbca_hsspi_resume(struct de
 		}
 	}
 
-	spi_controller_resume(host);
+	ret = spi_controller_resume(host);
+	if (ret) {
+		if (bs->pll_clk)
+			clk_disable_unprepare(bs->pll_clk);
+		clk_disable_unprepare(bs->clk);
+		return ret;
+	}
 
 	return 0;
 }
author maintainer
#43 lore raw

PATCH 43/583 spi: Fix DMA mapping ownership on partial map failure

In reply to Greg Kroah-Hartman

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

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

From: Honghui Jiang <[email protected]>

commit 367cea239fc93094e5c16a72724800e0358f5c46 upstream.

If RX mapping fails after TX mapping succeeds, __spi_map_msg() unmaps TX but leaves tx_sg_mapped set. If TX mapping fails on a later transfer, mappings created for earlier transfers remain active.

In both cases, cur_{tx,rx}_dma_dev have not yet been updated because they are assigned only after every transfer has been mapped. The subsequent spi_unmap_msg() may therefore unmap the TX mapping again or release earlier mappings using a NULL or stale device. Using a NULL device can trigger an oops. An empty SG table does not prevent the NULL dereference because dma_unmap_sg_attrs() accesses the device before checking the entry count.

Publish both mapping devices before mapping starts and unwind all failures through __spi_unmap_msg(). This clears the mapping flags and releases each mapping once with the device that created it.

Publishing the devices before the loop also refreshes them when no transfer needs mapping. No mapping flag is set in that case, so current users do not use the pointers as mapping owners.

Fixes e289df82344f ("spi: Rework per message DMA mapped flag to be per transfer")
---
 drivers/spi/spi.c |   34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)
drivers/spi/spi.c +18 -16
@@ -1216,6 +1216,8 @@ void spi_unmap_buf(struct spi_controller
 	spi_unmap_buf_attrs(ctlr, dev, sgt, dir, 0);
 }
 
+static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg);
+
 static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
 {
 	struct device *tx_dev, *rx_dev;
@@ -1239,7 +1241,13 @@ static int __spi_map_msg(struct spi_cont
 	else
 		rx_dev = ctlr->dev.parent;
 
-	ret = -ENOMSG;
+	/*
+	 * Store the devices before mapping so partial failures can be unwound
+	 * with the device that created each mapping.
+	 */
+	ctlr->cur_tx_dma_dev = tx_dev;
+	ctlr->cur_rx_dma_dev = rx_dev;
+
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		/* The sync is done before each transfer. */
 		unsigned long attrs = DMA_ATTR_SKIP_CPU_SYNC;
@@ -1252,8 +1260,8 @@ static int __spi_map_msg(struct spi_cont
 						(void *)xfer->tx_buf,
 						xfer->len, DMA_TO_DEVICE,
 						attrs);
-			if (ret != 0)
-				return ret;
+			if (ret)
+				goto unwind;
 
 			xfer->tx_sg_mapped = true;
 		}
@@ -1262,25 +1270,19 @@ static int __spi_map_msg(struct spi_cont
 			ret = spi_map_buf_attrs(ctlr, rx_dev, &xfer->rx_sg,
 						xfer->rx_buf, xfer->len,
 						DMA_FROM_DEVICE, attrs);
-			if (ret != 0) {
-				spi_unmap_buf_attrs(ctlr, tx_dev,
-						&xfer->tx_sg, DMA_TO_DEVICE,
-						attrs);
-
-				return ret;
-			}
+			if (ret)
+				goto unwind;
 
 			xfer->rx_sg_mapped = true;
 		}
 	}
-	/* No transfer has been mapped, bail out with success */
-	if (ret)
-		return 0;
-
-	ctlr->cur_rx_dma_dev = rx_dev;
-	ctlr->cur_tx_dma_dev = tx_dev;
 
 	return 0;
+
+unwind:
+	__spi_unmap_msg(ctlr, msg);
+
+	return ret;
 }
 
 static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg)
author maintainer
#44 lore raw

PATCH 44/583 scsi: target: iscsi: Reserve a terminator byte for the login payload

In reply to Greg Kroah-Hartman

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

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

From: Sujal Tuladhar <[email protected]>

commit f4825922d2fb371e2b969697d792077f1b62b62c upstream.

iscsi_target_check_login_request() rejects a login PDU whose DataSegmentLength exceeds MAX_KEY_VALUE_PAIRS, but the test is '>' and login->req_buf is allocated with exactly MAX_KEY_VALUE_PAIRS bytes. Since iscsit_get_login_rx() receives payload_length + padding bytes, where

	padding = ((-payload_length) & 3);

any payload_length from 8189 to 8192 fills the whole 8192 byte buffer. The write stays in bounds, but no byte is left for a NUL terminator.

The buffer is subsequently consumed as a C string. In the CHAP path chap_check_algorithm() calls kstrdup(a_str), and extract_param() calls strstr(in_buf, pattern) followed by strlen_semi(), none of which take a length. convert_null_to_semi() additionally rewrites every embedded NUL to ';', so even a payload made of well formed NUL separated key=value records is left without a terminator. These walk past the end of the object into adjacent slab memory. It is reachable by an unauthenticated initiator against a portal configured for CHAP; when authentication is not required iscsi_login_zero_tsih_s2() rewrites AuthMethod to None and the CHAP path is never entered.

Allocate one extra byte. kzalloc() zeroes it and nothing ever writes to it, as every writer copies to offset 0 for at most MAX_KEY_VALUE_PAIRS bytes, so the buffer is always terminated.

Fixes e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
Assisted-by Claude Opus5 (custom harness)
---
 drivers/target/iscsi/iscsi_target_login.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/target/iscsi/iscsi_target_login.c +1 -1
@@ -47,7 +47,7 @@ static struct iscsi_login *iscsi_login_i
 	login->conn = conn;
 	login->first_request = 1;
 
-	login->req_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL);
+	login->req_buf = kzalloc(MAX_KEY_VALUE_PAIRS + 1, GFP_KERNEL);
 	if (!login->req_buf) {
 		pr_err("Unable to allocate memory for response buffer.\n");
 		goto out_login;
author maintainer
#45 lore raw

PATCH 45/583 scsi: megaraid_sas: Limit NVMe request size to the PRP chain frame

In reply to Greg Kroah-Hartman

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

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

From: Thomas Lamprecht <[email protected]>

commit af8c27375733fb6a6df9fa484cda77cc3dd0cb80 upstream.

megasas_make_prp_nvme() builds a command's PRP list in cmd->sg_frame, a DMA pool buffer of instance->max_chain_frame_sz bytes, spending one entry per NVMe page of the transfer plus one per page of the buffer for the chain pointer. The loop runs until the transfer is described and never checks the buffer bound.

max_hw_sectors comes straight from the MDTS the firmware reports for the drive. On drives with a large MDTS the only thing keeping the list inside the buffer was the block layer default of 1280 KiB, which needs 320 entries, which fit into a 4 KiB frame as that holds 512. But since commit 9b8b84879d4a ("block: Increase BLK_DEF_MAX_SECTORS_CAP") that default is 4 MiB, and such a transfer needs 1025 entries, so the list runs a full page past the end of the frame:

sd 1:0:1:0: [sdb] tag#630 page boundary ptr_sgl: 0x00000000ba62d13f

  BUG: unable to handle page fault for address: ff663bcb81e7c000
  #PF: supervisor write access in kernel mode
  #PF: error_code(0x0002) - not-present page
  RIP: 0010:megasas_build_and_issue_cmd_fusion+0xeaa/0x1870 [megaraid_sas]

If the page after the frame happens to be mapped, the overrun does not fault but silently corrupts the neighbouring pool entry, which is another in-flight command's PRP list.

Cap max_hw_sectors at what the chain frame can describe, less one page for transfers that do not start on a page boundary and so need one entry more. This is the megaraid_sas counterpart of commit 04631f55afc5 ("scsi: mpt3sas: Limit NVMe request size to 2 MiB"), but derives the limit from max_chain_frame_sz rather than hardcoding it.

---
 drivers/scsi/megaraid/megaraid_sas_base.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/scsi/megaraid/megaraid_sas_base.c +12 -1
index f0152b043e18..b95f187297ae 100644
@@ -1973,12 +1973,23 @@ megasas_set_nvme_device_properties(struct scsi_device *sdev,
 {
 	struct megasas_instance *instance;
 	u32 mr_nvme_pg_size;
+	u64 max_prp_io;
 
 	instance = (struct megasas_instance *)sdev->host->hostdata;
 	mr_nvme_pg_size = max_t(u32, instance->nvme_page_size,
 				MR_DEFAULT_NVME_PAGE_SIZE);
 
-	lim->max_hw_sectors = max_io_size / 512;
+	/*
+	 * megasas_make_prp_nvme() builds the PRP list in cmd->sg_frame without
+	 * bounding it against that buffer, and spends one entry per page of
+	 * it on the chain pointer. Cap the transfer at what the buffer holds,
+	 * less one page for lists that start off a page boundary.
+	 */
+	max_prp_io = (u64)((instance->max_chain_frame_sz / sizeof(u64)) -
+			   (instance->max_chain_frame_sz / mr_nvme_pg_size) - 1) *
+		     mr_nvme_pg_size;
+
+	lim->max_hw_sectors = min_t(u64, max_io_size, max_prp_io) >> SECTOR_SHIFT;
 	lim->virt_boundary_mask = mr_nvme_pg_size - 1;
 }
 
Signature · 1 line
2.55.0
author maintainer
#46 lore raw

PATCH 46/583 scsi: pm8001: Use rollback index when freeing MSI-X vectors

In reply to Greg Kroah-Hartman

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

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

From: Runyu Xiao <[email protected]>

commit 3f92a64545165bdbb36dee8fa35626b295463313 upstream.

pm8001_request_msix() unwinds previously registered handlers with free_irq() when request_irq() fails. The rollback loop uses the failing index i for every iteration instead of the already registered vector index j.

That passes the wrong IRQ/dev_id pair to free_irq() and leaves the earlier handlers installed. Use j for both pci_irq_vector() and the matching irq_vector entry in the rollback loop.

Fixes a76037ff3479 ("scsi: pm8001: switch to pci_irq_alloc_vectors")
Assisted-by Codex:GPT-5
---
 drivers/scsi/pm8001/pm8001_init.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/pm8001/pm8001_init.c +2 -2
@@ -1029,8 +1029,8 @@ static u32 pm8001_request_msix(struct pm
 			&(pm8001_ha->irq_vector[i]));
 		if (rc) {
 			for (j = 0; j < i; j++) {
-				free_irq(pci_irq_vector(pm8001_ha->pdev, i),
-					&(pm8001_ha->irq_vector[i]));
+				free_irq(pci_irq_vector(pm8001_ha->pdev, j),
+					 &pm8001_ha->irq_vector[j]);
 			}
 			pci_free_irq_vectors(pm8001_ha->pdev);
 			break;
author maintainer
#47 lore raw

PATCH 47/583 mm/damon/vaddr-kunit: check region count in three_regions test

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 5fea07e460874c8c7cf00f728efbe22abc62c8d8 upstream.

damon_do_test_apply_three_regions() iterates regions after damon_set_regions() call assuming the function would succeed at setting the number of regions the same to the expected one. It might have failed. In this case, __nth_region_of() in the iteration could return NULL and NULL dereference can happen in the test.

The consequent user impact (NULL dereference) is quite bad. The realistic user impact would be limited, though. It would affect only test run setups.

Fix it by testing if the number of regions was also changed as expected and exit early for the failure.

The issue was discovered [1] by Sashiko.

---
 mm/damon/tests/vaddr-kunit.h |    5 +++++
 1 file changed, 5 insertions(+)
mm/damon/tests/vaddr-kunit.h +5 -0
@@ -149,12 +149,17 @@ static void damon_do_test_apply_three_re
 
 	damon_set_regions(t, three_regions, 3, DAMON_MIN_REGION);
 
+	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), nr_expected / 2);
+	if (damon_nr_regions(t) != nr_expected / 2)
+		goto out;
+
 	for (i = 0; i < nr_expected / 2; i++) {
 		r = __nth_region_of(t, i);
 		KUNIT_EXPECT_EQ(test, r->ar.start, expected[i * 2]);
 		KUNIT_EXPECT_EQ(test, r->ar.end, expected[i * 2 + 1]);
 	}
 
+out:
 	damon_destroy_target(t, NULL);
 }
 
author maintainer
#48 lore raw

PATCH 48/583 samples/damon/mtier: handle damon_start() failure

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit c7230d08ee79b13127bd2b45a3648d361ac912fc upstream.

damon_sample_mtier_start() callers assume it will clean up resources when it fails. And the function does the cleanup for context buildup failures. However, it is not doing the cleanup for damon_start() failure.

As a result, when damon_start() fails, it could leak the memory for DAMON context. Also, if damon_start() fails for only the second context, the first context will indefinitely run, and avoid starting other DAMON contexts since it is running in the exclusive mode. Stop possibly started DAMON context and free the contexts in case of the failure to fix the issues.

Note that the issue can reliably be reproduced because the module calls damon_start() in the exclusive mode. For example,

    $ sudo damo start
    $ echo Y | sudo tee /sys/module/damon_sample_mtier/parameters/enabled
    $ sudo cat /proc/allocinfo | grep damon_new_ctx

Because the first command is running another DAMON instance, the second command fails the damon_start() call because the new DAMON instance cannot exclusively run. And without this fix, by repeating the second and the third commands above, we can show the memory consumption is only increasing due to the leaks. It requires the sudo permission though.

The issue was discovered [1] by Sashiko.

---
 samples/damon/mtier.c |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
samples/damon/mtier.c +10 -1
@@ -177,6 +177,7 @@ free_out:
 static int damon_sample_mtier_start(void)
 {
 	struct damon_ctx *ctx;
+	int err;
 
 	ctx = damon_sample_mtier_build_ctx(true);
 	if (!ctx)
@@ -188,7 +189,15 @@ static int damon_sample_mtier_start(void
 		return -ENOMEM;
 	}
 	ctxs[1] = ctx;
-	return damon_start(ctxs, 2, true);
+	err = damon_start(ctxs, 2, true);
+	if (!err)
+		return 0;
+
+	if (damon_is_running(ctxs[0]))
+		damon_stop(ctxs, 1);
+	damon_destroy_ctx(ctxs[0]);
+	damon_destroy_ctx(ctxs[1]);
+	return err;
 }
 
 static void damon_sample_mtier_stop(void)
author maintainer
#49 lore raw

PATCH 49/583 samples/damon/mtier: handle damon_stop() failure

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 9dc5b6d66fd51b103eff21ed0df3e292f489ebc0 upstream.

damon_sample_mtier_stop() assumes its damon_stop() call will always successfully stops the two DAMON contexts. Hence it deallocates the two DAMON contexts after the damon_stop() call. However, if a given context is already stopped, damon_stop() fails and returns an error while letting the DAMON contexts that have not yet stopped keep running. This kind of unexpected early DAMON context stops could happen due to memory allocation failures in kdamond_fn(). Because damon_sample_mtier_stop() just deallocates all DAMON contexts with damon_target and damon_region objects that are linked to the contexts, the execution of the unstopped DAMON context (kdamond) ends up using the memory that freed (use-after-free). Fix the issue by separating the damon_stop() to be invoked per context.

Note that DAMON_SYSFS also allows multiple DAMON contexts execution. But, it calls damon_stop() for each context one by one. Hence this issue is only in mtier.

For the long term, it would be better to refactor damon_stop() to always ensure stopping all contexts regardless of the failures in the middle. Make this fix in the current way, though, to keep it simple and easy to backport. I will do the refactoring later.

The issue was discovered [1] by Sashiko.

---
 samples/damon/mtier.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
samples/damon/mtier.c +2 -1
@@ -202,7 +202,8 @@ static int damon_sample_mtier_start(void
 
 static void damon_sample_mtier_stop(void)
 {
-	damon_stop(ctxs, 2);
+	damon_stop(ctxs, 1);
+	damon_stop(&ctxs[1], 1);
 	damon_destroy_ctx(ctxs[0]);
 	damon_destroy_ctx(ctxs[1]);
 }
author maintainer
#50 lore raw

PATCH 50/583 samples/damon/prcl: handle damon_start() failure

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 8b724349229bb6ebbf781178be011ba9bc2cca57 upstream.

damon_sample_prcl_start() callers assume it will clean up resources when it fails. And the function does the cleanup for context buildup failures. However, it is not doing the cleanup for damon_start() failure. As a result, when damon_start() fails, it leaks the memory for DAMON context. Free the context in case of the failure to fix the issues.

Note that the issue can reliably be reproduced because the module calls damon_start() in the exclusive mode. For example,

    $ sudo damo start
    $ echo $$ | sudo tee /sys/module/damon_sample_prcl/parameters/target_pid
    $ echo Y | sudo tee /sys/module/damon_sample_prcl/parameters/enabled
    $ sudo cat /proc/allocinfo | grep damon_new_ctx

Because the first command is running another DAMON instance, the third command fails the damon_start() call because the new DAMON instance cannot exclusively run. And without this fix, by repeating the third and the fourth commands above, we can show the memory consumption is only increasing due to the leaks. It requires the sudo permission though.

The issue was discovered [1] by Sashiko.

Fixes 2aca254620a8 ("samples/damon: introduce a skeleton of a smaple DAMON module for proactive reclamation")
Cc <[email protected]> # 6.14.x
---
 samples/damon/prcl.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
samples/damon/prcl.c +3 -1
@@ -106,8 +106,10 @@ static int damon_sample_prcl_start(void)
 	damon_set_schemes(ctx, &scheme, 1);
 
 	err = damon_start(&ctx, 1, true);
-	if (err)
+	if (err) {
+		damon_destroy_ctx(ctx);
 		return err;
+	}
 
 	repeat_call_control.data = ctx;
 	return damon_call(ctx, &repeat_call_control);
author maintainer
#51 lore raw

PATCH 51/583 samples/damon/prcl: stop and free damon ctx when damon_call() fails

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit a73fa45d3f0f42c446ae55c5799e3d5ef044cd5d upstream.

damon_sample_prcl_start() calls damon_call() right after damon_start() is succeeded. The kdamond that has started by the damon_start() could be terminated by itself before or in the middle of the damon_call() execution. There could be multiple reasons for such a stop including monitoring target process termination and kdamond_fn() internal memory allocation failures. In the case, damon_call() will fail and return an error without cleaning up the DAMON context object. The damon_sample_prcl_start() caller assumes it would clean up the object, though. When the user requests to start DAMON again, damon_sample_prcl_start() is called again, allocates a new DAMON context object and overwrites the pointer for the previous object. As a result, the previous context object is leaked.

Safely stop the kdamond and deallocate the context object when the failure is returned. Note that the kdamond should be stopped first, because damon_call() failure means not complete termination of the kdamond but only the fact that the termination process has started.

The user impact shouldn't be that significant because the race is not easy to happen, and only up to one DAMON context object can be leaked per race.

The issue was discovered [1] by Sashiko.

Fixes a6c33f1054e3 ("samples/damon/prcl: use damon_call() repeat mode instead of damon_callback")
Cc <[email protected]> # 6.17.x
---
 samples/damon/prcl.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
samples/damon/prcl.c +6 -1
index 0db259894691..edeae145c4a8 100644
@@ -112,7 +112,12 @@ static int damon_sample_prcl_start(void)
 	}
 
 	repeat_call_control.data = ctx;
-	return damon_call(ctx, &repeat_call_control);
+	err = damon_call(ctx, &repeat_call_control);
+	if (err) {
+		damon_stop(&ctx, 1);
+		damon_destroy_ctx(ctx);
+	}
+	return err;
 }
 
 static void damon_sample_prcl_stop(void)
Signature · 1 line
2.55.0
author maintainer
#52 lore raw

PATCH 52/583 samples/damon/wsse: handle damon_start() failure

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit e4742be45ea45bf554399ce89a09f71e525d7981 upstream.

Patch series "samples/damon: handle damon_{start,stop}() failures".

All DAMON sample modules are not correctly handling failures from damon_start(). Among those, mtier also has an additional problem for handling of damon_stop() failures. wsse and prcl also have a problem in their damon_call() failure handling. As a result, memory leaks, next DAMON operation disruptions, and use-after-free can happen. Fix those.

Note that only the damon_start() failure caused issues can reliably be reproduced. Reproducing those issues require the admin permission, though.

This patch (of 6):

damon_sample_wsse_start() callers assume it will clean up resources when it fails. And the function does the cleanup for context buildup failures. However, it is not doing the cleanup for damon_start() failure. As a result, when damon_start() fails, it leaks the memory for DAMON context. Free the context in case of the failure to fix the issues.

Note that the issue can reliably be reproduced because the module calls damon_start() in the exclusive mode. For example,

    $ sudo damo start
    $ echo $$ | sudo tee /sys/module/damon_sample_wsse/parameters/target_pid
    $ echo Y | sudo tee /sys/module/damon_sample_wsse/parameters/enabled
    $ sudo cat /proc/allocinfo | grep damon_new_ctx

Because the first command is running another DAMON instance, the third command fails the damon_start() call because the new DAMON instance cannot exclusively run. And without this fix, by repeating the third and the fourth commands above, we can show the memory consumption is only increasing due to the leaks. It requires the sudo permission though.

The issue was discovered [1] by Sashiko.

Fixes b757c6cfc696 ("samples/damon/wsse: start and stop DAMON as the user requests")
Cc <[email protected]> # 6.14.x
---
 samples/damon/wsse.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
samples/damon/wsse.c +3 -1
index 799ad4443943..bbd9392ab5b3 100644
@@ -87,8 +87,10 @@ static int damon_sample_wsse_start(void)
 	target->pid = target_pidp;
 
 	err = damon_start(&ctx, 1, true);
-	if (err)
+	if (err) {
+		damon_destroy_ctx(ctx);
 		return err;
+	}
 	repeat_call_control.data = ctx;
 	return damon_call(ctx, &repeat_call_control);
 }
Signature · 1 line
2.55.0
author maintainer
#53 lore raw

PATCH 53/583 samples/damon/wsse: stop and free damon ctx when damon_call() fails

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit a2c6fa6c23ad87c61e1379b05dc05cf5fed4bf8d upstream.

damon_sample_wsse_start() calls damon_call() right after damon_start() is succeeded. The kdamond that has started by the damon_start() could be terminated by itself before or in the middle of the damon_call() execution. There could be multiple reasons for such a stop including monitoring target process termination and kdamond_fn() internal memory allocation failures. In the case, damon_call() will fail and return an error without cleaning up the DAMON context object. The damon_sample_wsse_start() caller assumes it would clean up the object, though. When the user requests to start DAMON again, damon_sample_wsse_start() is called again, allocates a new DAMON context object and overwrites the pointer for the previous object. As a result, the previous context object is leaked.

Safely stop the kdamond and deallocate the context object when the failure is returned. Note that the kdamond should be stopped first, because damon_call() failure means not complete termination of the kdamond but only the fact that the termination process has started.

The user impact shouldn't be that significant because the race is not easy to happen, and only up to one DAMON context object can be leaked per race.

The issue was discovered [1] by Sashiko.

Fixes cc9c1b8c205b ("samples/damon/wsse: use damon_call() repeat mode instead of damon_callback")
Cc <[email protected]> # 6.17.x
---
 samples/damon/wsse.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
samples/damon/wsse.c +6 -1
index bbd9392ab5b3..ff5e8a890f44 100644
@@ -92,7 +92,12 @@ static int damon_sample_wsse_start(void)
 		return err;
 	}
 	repeat_call_control.data = ctx;
-	return damon_call(ctx, &repeat_call_control);
+	err = damon_call(ctx, &repeat_call_control);
+	if (err) {
+		damon_stop(&ctx, 1);
+		damon_destroy_ctx(ctx);
+	}
+	return err;
 }
 
 static void damon_sample_wsse_stop(void)
Signature · 1 line
2.55.0
author maintainer
#54 lore raw

PATCH 54/583 mm/damon/sysfs-schemes: kobject_del() scheme action destination dirs

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 286380c78bc51e6c578621b9ae660bf9e5ad2563 upstream.

On CONFIG_DEBUG_KOBJECT_RELEASE enabled kernel, lack of kobject_del() could cause directories creation failures due to the name conflicts. Fix those issues for scheme action destination directories by adding kobject_del() calls.

Fixes 2cd0bf85a203 ("mm/damon/sysfs-schemes: implement DAMOS action destinations directory")
Cc <[email protected]> # 6.17.x
---
 mm/damon/sysfs-schemes.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
mm/damon/sysfs-schemes.c +3 -1
@@ -1762,8 +1762,10 @@ static void damos_sysfs_dests_rm_dirs(
 	struct damos_sysfs_dest **dests_arr = dests->dests_arr;
 	int i;
 
-	for (i = 0; i < dests->nr; i++)
+	for (i = 0; i < dests->nr; i++) {
+		kobject_del(&dests_arr[i]->kobj);
 		kobject_put(&dests_arr[i]->kobj);
+	}
 	dests->nr = 0;
 	kfree(dests_arr);
 	dests->dests_arr = NULL;
author maintainer
#55 lore raw

PATCH 55/583 mm/damon/sysfs-schemes: kobject_del() scheme dirs

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 05fb6ac98c49be870c5f9ccdfdf95f0107e564ae upstream.

On CONFIG_DEBUG_KOBJECT_RELEASE enabled kernel, lack of kobject_del() could cause directories creation failures due to the name conflicts. Fix those issues for scheme directories by adding kobject_del() calls.

Fixes 7e84b1f8212a ("mm/damon/sysfs: support DAMON-based Operation Schemes")
Cc <[email protected]> # 5.18.x
---
 mm/damon/sysfs-schemes.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
mm/damon/sysfs-schemes.c +4 -1
@@ -2305,6 +2305,7 @@ void damon_sysfs_schemes_rm_dirs(struct
 
 	for (i = 0; i < schemes->nr; i++) {
 		damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
+		kobject_del(&schemes_arr[i]->kobj);
 		kobject_put(&schemes_arr[i]->kobj);
 	}
 	schemes->nr = 0;
@@ -2346,13 +2347,15 @@ static int damon_sysfs_schemes_add_dirs(
 			goto out;
 		err = damon_sysfs_scheme_add_dirs(scheme);
 		if (err)
-			goto out;
+			goto del_out;
 
 		schemes_arr[i] = scheme;
 		schemes->nr++;
 	}
 	return 0;
 
+del_out:
+	kobject_del(&scheme->kobj);
 out:
 	damon_sysfs_schemes_rm_dirs(schemes);
 	kobject_put(&scheme->kobj);
author maintainer
#56 lore raw

PATCH 56/583 mm/damon/sysfs-schemes: kobject_del() scheme filter dirs

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 3c453bddacd4c04ecb38cf79dbfa41e7dfe0531b upstream.

On CONFIG_DEBUG_KOBJECT_RELEASE enabled kernel, lack of kobject_del() could cause directories creation failures due to the name conflicts. Fix those issues for scheme filter directories by adding kobject_del() calls.

Fixes 472e2b70eda6 ("mm/damon/sysfs-schemes: connect filter directory and filters directory")
Cc <[email protected]> # 6.3.x
---
 mm/damon/sysfs-schemes.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
mm/damon/sysfs-schemes.c +3 -1
@@ -704,8 +704,10 @@ static void damon_sysfs_scheme_filters_r
 	struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr;
 	int i;
 
-	for (i = 0; i < filters->nr; i++)
+	for (i = 0; i < filters->nr; i++) {
+		kobject_del(&filters_arr[i]->kobj);
 		kobject_put(&filters_arr[i]->kobj);
+	}
 	filters->nr = 0;
 	kfree(filters_arr);
 	filters->filters_arr = NULL;
author maintainer
#57 lore raw

PATCH 57/583 mm/damon/sysfs-schemes: kobject_del() scheme quota goal dirs

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 0d4397ca921ceaf80fc3eca4c8194812ff79a979 upstream.

On CONFIG_DEBUG_KOBJECT_RELEASE enabled kernel, lack of kobject_del() could cause directories creation failures due to the name conflicts. Fix those issues for scheme quota goal directories by adding kobject_del() calls.

Fixes 7f262da0a30d ("mm/damon/sysfs-schemes: implement files for scheme quota goals setup")
Cc <[email protected]> # 6.8.x
---
 mm/damon/sysfs-schemes.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
mm/damon/sysfs-schemes.c +3 -1
@@ -1193,8 +1193,10 @@ static void damos_sysfs_quota_goals_rm_d
 	struct damos_sysfs_quota_goal **goals_arr = goals->goals_arr;
 	int i;
 
-	for (i = 0; i < goals->nr; i++)
+	for (i = 0; i < goals->nr; i++) {
+		kobject_del(&goals_arr[i]->kobj);
 		kobject_put(&goals_arr[i]->kobj);
+	}
 	goals->nr = 0;
 	kfree(goals_arr);
 	goals->goals_arr = NULL;
author maintainer
#58 lore raw

PATCH 58/583 mm/damon/sysfs-schemes: kobject_del() scheme region dirs

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit f3ec3271210781c255e737498b84d5790e8176b4 upstream.

On CONFIG_DEBUG_KOBJECT_RELEASE enabled kernel, lack of kobject_del() could cause directories creation failures due to the name conflicts. Fix those issues for scheme region directories by adding kobject_del() calls.

This issue was discovered [1] by Sashiko, though its analysis was partially incorrect.

Fixes 9277d0367ba1 ("mm/damon/sysfs-schemes: implement scheme region directory")
Cc <[email protected]> # 6.2.x
---
 mm/damon/sysfs-schemes.c |    1 +
 1 file changed, 1 insertion(+)
mm/damon/sysfs-schemes.c +1 -0
@@ -166,6 +166,7 @@ static void damon_sysfs_scheme_regions_r
 
 	list_for_each_entry_safe(r, next, &regions->regions_list, list) {
 		list_del(&r->list);
+		kobject_del(&r->kobj);
 		kobject_put(&r->kobj);
 		regions->nr_regions--;
 	}
author maintainer
#59 lore raw

PATCH 59/583 mm/damon/sysfs: kobject_del() region and target (error) dirs

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 2603ef6f6ec3d3f7de2d6a07e7c9a683cebac419 upstream.

On CONFIG_DEBUG_KOBJECT_RELEASE enabled kernel, lack of kobject_del() could cause directories creation failures due to the name conflicts. Fix those issues for the normal creation path of region directories and the error path of target directories, by adding kobject_del() calls.

Fixes 2031b14ea757 ("mm/damon/sysfs: support the physical address space monitoring")
Cc <[email protected]> # 5.18.x
---
 mm/damon/sysfs.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
mm/damon/sysfs.c +6 -2
@@ -107,8 +107,10 @@ static void damon_sysfs_regions_rm_dirs(
 	struct damon_sysfs_region **regions_arr = regions->regions_arr;
 	int i;
 
-	for (i = 0; i < regions->nr; i++)
+	for (i = 0; i < regions->nr; i++) {
+		kobject_del(&regions_arr[i]->kobj);
 		kobject_put(&regions_arr[i]->kobj);
+	}
 	regions->nr = 0;
 	kfree(regions_arr);
 	regions->regions_arr = NULL;
@@ -343,13 +345,15 @@ static int damon_sysfs_targets_add_dirs(
 
 		err = damon_sysfs_target_add_dirs(target);
 		if (err)
-			goto out;
+			goto del_out;
 
 		targets_arr[i] = target;
 		targets->nr++;
 	}
 	return 0;
 
+del_out:
+	kobject_del(&target->kobj);
 out:
 	damon_sysfs_targets_rm_dirs(targets);
 	kobject_put(&target->kobj);
author maintainer
#60 lore raw

PATCH 60/583 mm/damon/sysfs: kobject_del() target (normal), context and kdamond dirs

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 263af33a72d1995ae6cdc22b08d527e2bda17259 upstream.

Patch series "mm/damon/sysfs: kobject_del() directories that users can create/remove".

DAMON sysfs interface allows users to create and remove arbitrary number of directories on sysfs, using a few files having 'nr_' prefix. For example, 'nr_kdamonds'. When the user writes a number 'N' to the files, directories having name starting from '0' to 'N - 1' are created in the same directory. The pre-existing number-named directories are removed before creating the new directories.

For the removal of the existing directories, DAMON sysfs interface use only kobject_put(). Because DAMON sysfs interface is the only kernel component that manages the directories, there is no problem in normal situations. However, if CONFIG_DEBUG_KOBJECT_RELEASE is enabled, the removal of dirs are delayed. Let's suppose a user writes a non-zero number to the 'nr_*' files while there are pre-existing number-named directories, on the config enabled kernel. DAMON sysfs interface decreases the reference counts of the existing directories and immediately creates new directories. Because the removal of the sysfs directories is delayed, it shows some pre-existing directories of the same names when it tries to create the new directories, and fails.

For example, the issue can be triggered like below:

    # grep DEBUG_KOBJECT_RELEASE /boot/config-$(uname -r)
    CONFIG_DEBUG_KOBJECT_RELEASE=y
    # ls
    nr_kdamonds
    # echo 1 > nr_kdamonds
    # echo 1 > nr_kdamonds
    bash: echo: write error: File exists
    # dmesg
    [...]
    [  300.880458] kobject: kobject_add_internal failed for 0 with -EEXIST, don't try to register things with the same name in the same directory.
    [...]

Some of the error handling paths of the directories also lack the kobject_del() call. If the user uses nr_* file right after the errors, similar issues can happen.

This doesn't cause catastrophic issues like kernel panics or memory corruptions. Users can work around by removing all directories first (write 0 to the nr_* files) and then create new directories after confirming the old directories are gone. But, this is definitely a bug that causes a bad user experience.

Fix the issues by calling kobject_del() before creating new directories.

This patch (of 11)

On CONFIG_DEBUG_KOBJECT_RELEASE enabled kernel, lack of kobject_del() could cause directories creation failures due to the name conflicts. Fix those issues for normal creation paths of target, context and kdamond directories, and error paths of context and kdamond directories by adding kobject_del() calls.

Note that this fix for target directories is not complete since it has a similar issue in the damon_sysfs_targets_add_dirs() error path. Because the normal path issue and the error path issue are introduced by different commits, this commit is fixing only the normal path issue. A commit for the error path will be added next.

Fixes c951cd3b8901 ("mm/damon: implement a minimal stub for sysfs-based DAMON interface")
Cc <[email protected]> # 5.18.x
---
 mm/damon/sysfs.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
mm/damon/sysfs.c +9 -2
@@ -307,6 +307,7 @@ static void damon_sysfs_targets_rm_dirs(
 
 	for (i = 0; i < targets->nr; i++) {
 		damon_sysfs_target_rm_dirs(targets_arr[i]);
+		kobject_del(&targets_arr[i]->kobj);
 		kobject_put(&targets_arr[i]->kobj);
 	}
 	targets->nr = 0;
@@ -1082,6 +1083,7 @@ static void damon_sysfs_contexts_rm_dirs
 
 	for (i = 0; i < contexts->nr; i++) {
 		damon_sysfs_context_rm_dirs(contexts_arr[i]);
+		kobject_del(&contexts_arr[i]->kobj);
 		kobject_put(&contexts_arr[i]->kobj);
 	}
 	contexts->nr = 0;
@@ -1120,13 +1122,15 @@ static int damon_sysfs_contexts_add_dirs
 
 		err = damon_sysfs_context_add_dirs(context);
 		if (err)
-			goto out;
+			goto del_out;
 
 		contexts_arr[i] = context;
 		contexts->nr++;
 	}
 	return 0;
 
+del_out:
+	kobject_del(&context->kobj);
 out:
 	damon_sysfs_contexts_rm_dirs(contexts);
 	kobject_put(&context->kobj);
@@ -1871,6 +1875,7 @@ static void damon_sysfs_kdamonds_rm_dirs
 
 	for (i = 0; i < kdamonds->nr; i++) {
 		damon_sysfs_kdamond_rm_dirs(kdamonds_arr[i]);
+		kobject_del(&kdamonds_arr[i]->kobj);
 		kobject_put(&kdamonds_arr[i]->kobj);
 	}
 	kdamonds->nr = 0;
@@ -1925,13 +1930,15 @@ static int damon_sysfs_kdamonds_add_dirs
 
 		err = damon_sysfs_kdamond_add_dirs(kdamond);
 		if (err)
-			goto out;
+			goto del_out;
 
 		kdamonds_arr[i] = kdamond;
 		kdamonds->nr++;
 	}
 	return 0;
 
+del_out:
+	kobject_del(&kdamond->kobj);
 out:
 	damon_sysfs_kdamonds_rm_dirs(kdamonds);
 	kobject_put(&kdamond->kobj);
author maintainer
#61 lore raw

PATCH 61/583 mm/damon/core-kunit: check region count before testing in split_at()

In reply to Greg Kroah-Hartman

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

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

From: SJ Park <[email protected]>

commit 9b18ef3c3aa1ce24176e340061caf15fa2742564 upstream.

damon_test_split_at() test next region that is assumed to be created by damon_split_region_at() invocation. But the split might fail. In this case, the succeeding test may dereference invalid pointers returned by damon_next_region().

The invalid pointer may not cause a really bad user impact, because of the implementation detail. It would only read wrong contents in the belonging damon_target struct. Depending on the future change of the offset from the link header to the accessing field, this could also be really dangerous, though. Still, the realistic user impact would be limited. It would affect only test run setups.

Fix it by testing if the number of regions was also changed as expected and exit early for the failure.

The issue was discovered [1] by Sashiko.

---
 mm/damon/tests/core-kunit.h |    5 +++++
 1 file changed, 5 insertions(+)
mm/damon/tests/core-kunit.h +5 -0
@@ -166,6 +166,10 @@ static void damon_test_split_at(struct k
 	r->last_nr_accesses = 15;
 	damon_add_region(r, t);
 	damon_split_region_at(t, r, 25);
+	KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
+	if (damon_nr_regions(t) != 2)
+		goto out;
+
 	KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
 	KUNIT_EXPECT_EQ(test, r->ar.end, 25ul);
 
@@ -177,6 +181,7 @@ static void damon_test_split_at(struct k
 	KUNIT_EXPECT_EQ(test, r->nr_accesses, r_new->nr_accesses);
 	KUNIT_EXPECT_EQ(test, r->last_nr_accesses, r_new->last_nr_accesses);
 
+out:
 	damon_free_target(t);
 	damon_destroy_ctx(c);
 }
author maintainer
#62 lore raw

PATCH 62/583 futex: Prevent rcuwait use-after-free during requeue PI

In reply to Greg Kroah-Hartman

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

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

From: Yao Kai <[email protected]>

commit a3b8d46fe401cba3a5c46dea610e6eb3dc15370e upstream.

On PREEMPT_RT, FUTEX_CMP_REQUEUE_PI can trigger a KASAN report (slab-out-of-bounds) in futex_requeue_pi_complete() invocation of rcuwait_wake_up().

The futex_q used by futex_wait_requeue_pi() is allocated on the waiter's stack. An early wakeup can race with a PI requeue as follows:

waiter requeue task
------ ------------
futex_wait_requeue_pi()
futex_do_wait()

    schedule()
                                       futex_requeue
                                         futex_proxy_trylock_atomic()
                                           futex_requeue_pi_prepare()
                                            Q_REQUEUE_PI_NONE -> Q_REQUEUE_PI_IN_PROGRESS
* timeout/ signal wakes waiter *
  futex_requeue_pi_wakeup_sync()
   Q_REQUEUE_PI_IN_PROGRESS -> Q_REQUEUE_PI_WAIT
                                           requeue_pi_wake_futex
                                             futex_requeue_pi_complete()
                                               cmpxchg Q_REQUEUE_PI_WAIT -> Q_REQUEUE_PI_LOCKED
    rcuwait_wait_event()
      if (atomic_read(&q->requeue_state) != Q_REQUEUE_PI_WAIT)
       break /* no schedule() */

/* q.pi_state->owner == current */
futex_private_hash_put()
/* return from syscall */

                                              rcuwait_wake_up(&q->requeue_wait)
                                                /* q is gone */

futex_requeue_pi_complete() publishes Q_REQUEUE_PI_LOCKED before calling rcuwait_wake_up(). The waiter observes this state in rcuwait_wait_event() before invoking schedule() in rcuwait_wait_event(). Here, the waiter is free leave the syscall before requeue task can complete the wake.

To address this race skip rcuwait_wake_up() in the Q_REQUEUE_PI_LOCKED case.
This state is only published by requeue_pi_wake_futex(), which saves q->task before futex_requeue_pi_complete() and wakes the waiter via wake_up_state().

This wake is intended to wake the waiter from its futex_do_wait() sleep. If the waiter is still sleeping there, it can not get into the Q_REQUEUE_PI_WAIT state (and require this removed wake). Should the waiter be woken up from futex_do_wait() by other means (as in this example) and sleep in futex_requeue_pi_wakeup_sync() then the wake_up_state() from requeue_pi_wake_futex() will wake it, too. Should the waiter task terminate before wake_up_state() had a chance to wake the task then the task pointer does not become invalid because the futex_hash_bucket::lock is held and the task pointer is RCU protected.

[bigeasy: Updated comment and commit message]

---
 kernel/futex/requeue.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
kernel/futex/requeue.c +10 -2
@@ -154,8 +154,16 @@ static inline void futex_requeue_pi_comp
 	} while (!atomic_try_cmpxchg(&q->requeue_state, &old, new));
 
 #ifdef CONFIG_PREEMPT_RT
-	/* If the waiter interleaved with the requeue let it know */
-	if (unlikely(old == Q_REQUEUE_PI_WAIT))
+	/*
+	 * The waiter in futex_requeue_pi_wakeup_sync() can interleave with the
+	 * wake below: It will assign Q_REQUEUE_PI_IN_PROGRESS and here it will
+	 * be updated to Q_REQUEUE_PI_LOCKED (locked = 1). The rcuwait_wait_event()
+	 * will already read Q_REQUEUE_PI_LOCKED and skip the schedule() invocation,
+	 * leading to an access of futex_q::requeue_wait after the waiter returned.
+	 * In this case only we skip the wake here and rely on following wake in
+	 * requeue_pi_wake_futex() to perform the wake if needed.
+	 */
+	if (unlikely(old == Q_REQUEUE_PI_WAIT) && new != Q_REQUEUE_PI_LOCKED)
 		rcuwait_wake_up(&q->requeue_wait);
 #endif
 }
author maintainer
#63 lore raw

PATCH 63/583 ftrace: Synchronize the initialization of ftrace_ops

In reply to Greg Kroah-Hartman

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

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

From: Steven Rostedt <[email protected]>

commit 4617721c502b2ddaa4e324e86da4997edf738fa5 upstream.

There's some internal state that ftrace_ops needs to have set, but since it can be declared outside of the ftrace.c code, it calls ftrace_ops_init() on the ops in every global function. The issue is that if two tasks call it on the same ops at the same time it is possible to have the initialization of one corrupt the initialization of the other call.

Create a ops_mutex to use to synchronize every initialization of the ftrace_ops. The mutex is taken within checking the ftrace_ops flag that states it was initializied but the flag is checked again after the mutex has been taken. Checking first outside the mutex allows it to shortcut having to take the mutex. But then the check needs to be done again after the mute is taken in case of races.

Fixes f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock")
Reported-by [email protected]

Close: https://lore.kernel.org/all/[email protected]/

---
 kernel/trace/ftrace.c |   13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
kernel/trace/ftrace.c +11 -2
@@ -76,6 +76,8 @@
 	.func_hash		= &opsname.local_hash,			\
 	.local_hash.regex_lock	= __MUTEX_INITIALIZER(opsname.local_hash.regex_lock), \
 	.subop_list		= LIST_HEAD_INIT(opsname.subop_list),
+/* Used only to synchronize the initialization of ftrace_ops */
+static DEFINE_MUTEX(ops_mutex);
 #else
 #define INIT_OPS_HASH(opsname)
 #endif
@@ -160,11 +162,18 @@ const struct ftrace_ops ftrace_nop_ops =
 static inline void ftrace_ops_init(struct ftrace_ops *ops)
 {
 #ifdef CONFIG_DYNAMIC_FTRACE
-	if (!(ops->flags & FTRACE_OPS_FL_INITIALIZED)) {
+	unsigned long flags = smp_load_acquire(&ops->flags);
+
+	if (!(flags & FTRACE_OPS_FL_INITIALIZED)) {
+		guard(mutex)(&ops_mutex);
+		/* Could have been initialized before lock taken */
+		if (unlikely(ops->flags & FTRACE_OPS_FL_INITIALIZED))
+			return;
 		mutex_init(&ops->local_hash.regex_lock);
 		INIT_LIST_HEAD(&ops->subop_list);
 		ops->func_hash = &ops->local_hash;
-		ops->flags |= FTRACE_OPS_FL_INITIALIZED;
+		flags = ops->flags | FTRACE_OPS_FL_INITIALIZED;
+		smp_store_release(&ops->flags, flags);
 	}
 #endif
 }
author maintainer
#64 lore raw

PATCH 64/583 HID: bpf: serialize device reference release in struct_ops destroy path

In reply to Greg Kroah-Hartman

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

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

From: Shen Yongchao <[email protected]>

commit 9cdc7e6dc7a99ad7311ad5e7c145f2b9ce4e24b0 upstream.

__hid_bpf_ops_destroy_device() and hid_bpf_unreg() can race on the same registration reference, double-putting struct hid_device and freeing it while hid_destroy_device() still uses it. Serialize the remove/NULL decision under hdev->bpf.prog_list_lock so exactly one path releases each registration reference: unreg re-checks ops->hdev under the lock and returns without putting when the destroy path already cleared it; all put_device() calls happen after the lock is dropped, which is safe because a concurrent unreg then observes ops->hdev == NULL under the lock.

Background: each successful attach (hid_bpf_ops_reg) acquires one device reference (hid_get_device()). Two paths can release it:

- device destruction: hid_destroy_device() -> hid_bpf_destroy_device() -> __hid_bpf_ops_destroy_device(), which walks hdev->bpf.prog_list under rcu_read_lock() and drops one reference per attached program;
- BPF link release: bpf map delete (no BPF_F_LINK) synchronously calls st_ops->unreg() -> hid_bpf_unreg(), which drops the reference for its own registration.

The coordination handshake (e->hdev = NULL on the destroy side vs "if (!hdev) return" on the unreg side) is a TOCTOU check: the two paths run under different lock domains (rcu_read_lock vs prog_list_lock), so a concurrent unreg can read ops->hdev as non-NULL, block on prog_list_lock, and then proceed while the destroy traversal executes - both paths then drop the same reference. The refcount reaches zero legitimately (each decrement is individually valid), so no refcount_t saturation fires: the device is simply freed while the transport is still inside hid_destroy_device(), and subsequent teardown touches freed memory.

The fix serializes the remove/NULL decision under prog_list_lock on both sides and moves the destroy-side puts outside the lock. With the lock held, plain reads/writes of ops->hdev are sufficient; no READ_ONCE/WRITE_ONCE are added, keeping the patch minimal.

Unlocked-read safety: the unlocked read of ops->hdev at the top of hid_bpf_unreg() cannot touch a freed device, because the unreg path itself still holds this registration's reference (released only by its own hid_put_device() after the lock is dropped), and a destroy traversal that already cleared ops->hdev makes the lock-internal re-check return early without any put. At most one of the two paths releases each registration reference.

Fixes ebc0d8093e8c ("HID: bpf: implement HID-BPF through bpf_struct_ops")
Assisted-by Hermes:kimi-k3
---
 drivers/hid/bpf/hid_bpf_struct_ops.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/hid/bpf/hid_bpf_struct_ops.c +13 -4
@@ -250,6 +250,11 @@ static void hid_bpf_unreg(void *kdata, s
 
 	mutex_lock(&hdev->bpf.prog_list_lock);
 
+	if (!ops->hdev) {
+		mutex_unlock(&hdev->bpf.prog_list_lock);
+		return;
+	}
+
 	list_del_rcu(&ops->list);
 	synchronize_srcu(&hdev->bpf.srcu);
 	ops->hdev = NULL;
@@ -310,13 +315,17 @@ static struct bpf_struct_ops bpf_hid_bpf
 void __hid_bpf_ops_destroy_device(struct hid_device *hdev)
 {
 	struct hid_bpf_ops *e;
+	int count = 0;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
-		hid_put_device(hdev);
+	mutex_lock(&hdev->bpf.prog_list_lock);
+	list_for_each_entry(e, &hdev->bpf.prog_list, list) {
 		e->hdev = NULL;
+		count++;
 	}
-	rcu_read_unlock();
+	mutex_unlock(&hdev->bpf.prog_list_lock);
+
+	while (count--)
+		hid_put_device(hdev);
 }
 
 static int __init hid_bpf_struct_ops_init(void)
author maintainer
#65 lore raw

PATCH 65/583 HID: rmi: fix OOB access with undersized RMI reports

In reply to Greg Kroah-Hartman

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

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

From: Wei Jie Law <[email protected]>

commit 4956993bb3befdf791d71a4952d8d13bcfd44c7b upstream.

The hid-rmi driver sizes its writeReport/readReport buffer purely from the report descriptor supplied by the device, with no minimum bound:

	data->input_report_size  = hid_report_len(input_report);
	data->output_report_size = hid_report_len(output_report);
	alloc_size = data->output_report_size + data->input_report_size;
	data->writeReport = devm_kzalloc(&hdev->dev, alloc_size, GFP_KERNEL);
	data->readReport = data->writeReport + data->output_report_size;

but then reads and writes fixed offsets into it. A device declaring a 1-byte output and a 1-byte input report makes hid_report_len() return 2 for each, so alloc_size is 4, while rmi_set_page() -- reached unconditionally at probe time through rmi_input_configured() -- stores writeReport[4] and rmi_hid_read_block() stores writeReport[0..5]. Since readReport lives at writeReport + output_report_size, those stores also corrupt the window the next reply is parsed out of.

The read path is worse: the copy length comes from readReport[1], which the device fills in and can be up to 255, and the copy starts at &readReport[2] with no regard for input_report_size, so it runs past the end of the allocation into adjacent slab objects. This does not even need a lying device -- rmi_f01_probe() issues a fixed 21-byte register read, so any device declaring an input report smaller than 23 bytes reads out of bounds even when it answers truthfully. Those bytes become the register values the RMI core acts on: rmi_f01_probe() prints them to the kernel log as the product id and exports them through the mode 0444 sysfs attribute of the same name, and rmi_driver_set_irq_bits() sends them back to the device as the interrupt mask, so an undersized report descriptor leaks heap contents both to unprivileged userspace and to the device itself.

The write path has no bound either: rmi_hid_write_block() copies an unbounded len to &writeReport[4], and the largest caller a device can drive at probe time is rmi_driver_set_irq_bits(), whose length is derived from the interrupt source counts the device declares in its Page Description Table.

Finally, the read loop cannot terminate on a zero-length reply: such a reply copies nothing and advances neither bytes_read nor bytes_needed, and because a reply did arrive the one second wait_event_timeout() does not fire either, so a device answering 0 forever keeps the loop running inside the probe worker with page_mutex held. khungtaskd does not notice, because every reply wakes the task.

Reject reports too small for what the driver builds -- 6 output bytes for the write reports and 3 input bytes for the read handshake -- at probe time, clamp the write and the read copy to the report sizes the device declared, and treat a zero-length reply as an error. A device refused this way is started as an ordinary HID device, like one that does not carry the RMI report ids at all.

RMI_DEVICE must not be left set in device_flags on that path, because rmi_input_configured() would then run the RMI setup and reach rmi_set_page(), which writes the writeReport buffer the refusal just skipped allocating. The bit can arrive set: rmi_probe() copies id->driver_data into device_flags before the report checks, and a bind through the new_id sysfs attribute can supply driver_data with RMI_DEVICE (BIT(0)) set. Strip the bit where driver_data is copied, so RMI_DEVICE keeps meaning exactly "this probe validated the reports"; the three jumps to start that predate this patch are covered as well.

The error path also clears RMI_READ_DATA_PENDING on its way out, because that flag is what the wait at the top of the loop tests: leaving it set would make every later wait_event_timeout() return immediately on the stale reply and kill the read path for the rest of the device's life.

Clamping does not regress working hardware: the read loop already handles a reply carrying fewer bytes than requested, and a write longer than the output report was overrunning the buffer already.

Verified on v6.12.69 and on v6.12.105 built with CONFIG_KASAN=y and booted kasan_multi_shot, whose hid-rmi.c is identical to mainline here. An emulated RMI4 device driven over /dev/uhid, and the same device again over dummy_hcd plus raw-gadget, give identical results:

  BUG: KASAN: slab-out-of-bounds in rmi_hid_read_block+0x409/0x750 [hid_rmi]
  Read of size 21 at addr ffff88800bf33bba by task kworker/0:3/285
   __asan_memcpy+0x23/0x60
   rmi_hid_read_block+0x409/0x750 [hid_rmi]
   rmi_f01_probe+0x5dd/0x1dc0 [rmi_core]

  BUG: KASAN: slab-out-of-bounds in rmi_hid_write_block+0x1a9/0x350 [hid_rmi]
  Write of size 35 at addr ffff88810a2b24ac by task kworker/1:10/666
   __asan_memcpy+0x3c/0x60
   rmi_hid_write_block+0x1a9/0x350 [hid_rmi]
   rmi_driver_set_irq_bits+0x1f6/0x4d0 [rmi_core]
   rmi_driver_probe+0x636/0xbf0 [rmi_core]
   rmi_input_configured+0x184/0x2e0 [hid_rmi]
   rmi_probe+0x952/0xcf0 [hid_rmi]

and, for the zero-length reply, a probe worker left in D state in rmi_hid_read_block() after 225 replies at 200 ms intervals.

After this change the undersized descriptor is refused at probe with "rmi reports too small (out=2 in=2)", the oversized read and write are both rejected, the zero-length reply fails the read with -EIO while later reads on the same device keep working, and a device declaring reports large enough for a 21-byte register read still probes normally and reports its real product id. A device bound through new_id with RMI_DEVICE in its driver_data no longer reaches rmi_set_page() with an unallocated writeReport either.

---
 drivers/hid/hid-rmi.c |   46 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 43 insertions(+), 3 deletions(-)
drivers/hid/hid-rmi.c +43 -3
@@ -235,7 +235,23 @@ static int rmi_hid_read_block(struct rmi
 				break;
 			}
 
-			read_input_count = data->readReport[1];
+			read_input_count = min_t(int, data->readReport[1],
+						 data->input_report_size - 2);
+			if (!read_input_count) {
+				/*
+				 * A zero length reply advances neither
+				 * bytes_read nor bytes_needed, and because a
+				 * reply did arrive the wait above does not
+				 * time out either, so a device answering 0
+				 * forever would spin here indefinitely with
+				 * page_mutex held.
+				 */
+				hid_warn(hdev, "%s: zero-length read reply\n",
+					 __func__);
+				clear_bit(RMI_READ_DATA_PENDING, &data->flags);
+				ret = -EIO;
+				break;
+			}
 			memcpy(buf + bytes_read, &data->readReport[2],
 				min(read_input_count, bytes_needed));
 
@@ -271,6 +287,11 @@ static int rmi_hid_write_block(struct rm
 			goto exit;
 	}
 
+	if (len + 4 > data->output_report_size) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
 	data->writeReport[0] = RMI_WRITE_REPORT_ID;
 	data->writeReport[1] = len;
 	data->writeReport[2] = addr & 0xFF;
@@ -666,8 +687,16 @@ static int rmi_probe(struct hid_device *
 		return ret;
 	}
 
-	if (id->driver_data)
-		data->device_flags = id->driver_data;
+	/*
+	 * RMI_DEVICE can only mean "this probe validated the RMI reports and
+	 * allocated writeReport": every bail-out to start below skips that
+	 * allocation, and device_flags left carrying RMI_DEVICE from
+	 * driver_data would send rmi_input_configured() into rmi_set_page()
+	 * with writeReport still NULL.  A bind through the new_id sysfs
+	 * attribute can supply driver_data with the bit set, so do not let
+	 * driver_data grant it.
+	 */
+	data->device_flags = id->driver_data & ~RMI_DEVICE;
 
 	/*
 	 * Check for the RMI specific report ids. If they are misisng
@@ -696,6 +725,17 @@ static int rmi_probe(struct hid_device *
 
 	data->output_report_size = hid_report_len(output_report);
 
+	/*
+	 * The write reports built by this driver occupy 6 bytes and the read
+	 * handshake looks at the first 3 bytes of an input report, so refuse
+	 * to drive a device whose reports cannot hold them.
+	 */
+	if (data->output_report_size < 6 || data->input_report_size < 3) {
+		hid_err(hdev, "rmi reports too small (out=%u in=%u)\n",
+			data->output_report_size, data->input_report_size);
+		goto start;
+	}
+
 	data->device_flags |= RMI_DEVICE;
 	alloc_size = data->output_report_size + data->input_report_size;
 
author maintainer
#66 lore raw

PATCH 66/583 HID: wacom: validate report length in wacom_intuos_pro2_bt_irq

In reply to Greg Kroah-Hartman

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

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

From: Ibrahim Hashimov <[email protected]>

commit a8e04f3f894ccb52cfcd7e60125a9f35da4a616d upstream.

wacom_intuos_pro2_bt_irq() receives the wire report length in len but never consults it before parsing. After the report-id gate it unconditionally calls wacom_intuos_pro2_bt_pen() and then, selected by features.type, a fixed chain of sub-parsers, none of which receive len:

	wacom_intuos_pro2_bt_pen(wacom);
	if (type == INTUOSP2_BT || type == INTUOSP2S_BT) {
		wacom_intuos_pro2_bt_touch(wacom);
		wacom_intuos_pro2_bt_pad(wacom);
		wacom_intuos_pro2_bt_battery(wacom);
	} else {
		wacom_intuos_gen3_bt_pad(wacom);
		wacom_intuos_gen3_bt_battery(wacom);
	}

Each sub-parser dereferences wacom->data at fixed offsets. The furthest byte touched on each branch is:

INTUOSP2_BT / INTUOSP2S_BT: wacom_intuos_pro2_bt_pad() reads data[285]

	(the touchring byte), so the report must be at least 286 bytes;

INTUOSHT3_BT ("gen3"): wacom_intuos_gen3_bt_battery() reads data[45],
so the report must be at least 46 bytes.

features.type is selected from the VID/PID id_table entry and wacom_setup_device_quirks() force-registers the pen/pad/touch inputs for that type independent of the report descriptor, so a malicious or malfunctioning paired/spoofed Bluetooth peripheral can advertise that VID/PID and send an undersized report that still satisfies the data[0] == 0x80/0x81 gate. The driver then reads past the received report and forwards the bytes to userspace via evdev (MSC_SERIAL / ABS_MISC / ABS_WHEEL on the pen and pad input nodes), an out-of-bounds read with a concrete userspace read-back channel, and a true out-of-bounds read on transports whose backing buffer is sized to the (small) report descriptor rather than a fixed-size staging buffer.

This is the same class of bug commit 2f1763f62909 ("HID: wacom: fix out-of-bounds read in wacom_intuos_bt_irq") already hardened in the sibling wacom_intuos_bt_irq(), which guards each report id against its minimum length before parsing.

Guard wacom_intuos_pro2_bt_irq() the same way: before parsing, reject reports shorter than the furthest offset the selected branch actually dereferences, warn, and bail out. Because the whole pen/touch/pad/ battery chain runs unconditionally per branch, a single up-front check against the maximum offset (286 bytes for INTUOSP2_BT/INTUOSP2S_BT, 46 bytes for the gen3 branch) bounds every sub-parser. Returning 0 on a short report also skips those calls for the same malformed report, which is the safe, conservative behavior.

Fixes 4922cd26f03c ("HID: wacom: Support 2nd-gen Intuos Pro's Bluetooth classic interface")
Assisted-by AuditCode-AI:2026.07
---
 drivers/hid/wacom_wac.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)
drivers/hid/wacom_wac.c +13 -0
@@ -1548,6 +1548,19 @@ static int wacom_intuos_pro2_bt_irq(stru
 		return 0;
 	}
 
+	if (wacom->features.type == INTUOSP2_BT ||
+	    wacom->features.type == INTUOSP2S_BT) {
+		if (len < 286) {
+			dev_warn(wacom->pen_input->dev.parent,
+				 "Pro2 BT report too short: %zu bytes\n", len);
+			return 0;
+		}
+	} else if (len < 46) {
+		dev_warn(wacom->pen_input->dev.parent,
+			 "Pro2 BT report too short: %zu bytes\n", len);
+		return 0;
+	}
+
 	wacom_intuos_pro2_bt_pen(wacom);
 	if (wacom->features.type == INTUOSP2_BT ||
 	    wacom->features.type == INTUOSP2S_BT) {
author maintainer
#67 lore raw

PATCH 67/583 dm: fix race when loading and unloading a table

In reply to Greg Kroah-Hartman

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

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

From: Mikulas Patocka <[email protected]>

commit 5380c7f6335cc6d77eb77d065105e81155c4d9d3 upstream.

If the userspace calls two concurrent table load ioctls and one of them succeeds and the other fails, there is a race condition because dm_setup_md_queue walks &md->table_devices without any lock. If the walk races with dm_table_destroy -> free_devices -> dm_put_table_device, there is access to invalid memory.

Fix this race by extending the lock over the list walk.

---
 drivers/md/dm.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/md/dm.c +8 -4
@@ -2615,9 +2615,10 @@ int dm_setup_md_queue(struct mapped_devi
 	 */
 	mutex_lock(&md->table_devices_lock);
 	r = add_disk(md->disk);
-	mutex_unlock(&md->table_devices_lock);
-	if (r)
+	if (r) {
+		mutex_unlock(&md->table_devices_lock);
 		return r;
+	}
 
 	/*
 	 * Register the holder relationship for devices added before the disk
@@ -2628,18 +2629,21 @@ int dm_setup_md_queue(struct mapped_devi
 		if (r)
 			goto out_undo_holders;
 	}
+	mutex_unlock(&md->table_devices_lock);
 
 	r = dm_sysfs_init(md);
 	if (r)
-		goto out_undo_holders;
+		goto lock_out_undo_holders;
 
 	md->type = type;
+
 	return 0;
 
+lock_out_undo_holders:
+	mutex_lock(&md->table_devices_lock);
 out_undo_holders:
 	list_for_each_entry_continue_reverse(td, &md->table_devices, list)
 		bd_unlink_disk_holder(td->dm_dev.bdev, md->disk);
-	mutex_lock(&md->table_devices_lock);
 	del_gendisk(md->disk);
 	mutex_unlock(&md->table_devices_lock);
 	return r;
author maintainer
#68 lore raw

PATCH 68/583 dm: fix resume-vs-remove race

In reply to Greg Kroah-Hartman

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

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

From: Mikulas Patocka <[email protected]>

commit 44b43ec132f1cf3275ecc182d0c82f50c3c4c3d5 upstream.

If the user issues the resume ioctl and the remove ioctl at the same time, it may be possible that the device is resumed after it is suspended in __dm_destroy. The result is that the table is destroyed without calling the postsuspend method.

Dm targets expect that they may be removed only after the postsuspend method method was called. If we break this expectation, it can cause misbehavior in various targets. For example - in the dm-integrity target, the reboot notifier is not unregistered, leading to use-after-free.

Fix this bug by refusing to resume if the device is being destroyed.

---
 drivers/md/dm.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm.c +1 -1
@@ -3119,7 +3119,7 @@ retry:
 	r = -EINVAL;
 	mutex_lock_nested(&md->suspend_lock, SINGLE_DEPTH_NESTING);
 
-	if (!dm_suspended_md(md))
+	if (!dm_suspended_md(md) || test_bit(DMF_FREEING, &md->flags))
 		goto out;
 
 	if (dm_suspended_internally_md(md)) {
author maintainer
#69 lore raw

PATCH 69/583 dma-direct: return struct page from dma_direct_alloc_from_pool()

In reply to Greg Kroah-Hartman

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

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

From: Aneesh Kumar K.V (Arm) <[email protected]>

commit 94a04ad732c9f8b9554270fc4038a06737de5c22 upstream.

Commit 5b138c534fda ("dma-direct: factor out a dma_direct_alloc_from_pool helper") changed dma_direct_alloc_from_pool() to return the CPU address from dma_alloc_from_pool(). That fits dma_direct_alloc(), but dma_direct_alloc_pages() also uses the helper and expects a struct page *.

Fix this by making dma_direct_alloc_from_pool() return the struct page * again, and pass the CPU address back through an out-parameter for the dma_direct_alloc() caller.

---
 kernel/dma/direct.c |   18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
kernel/dma/direct.c +10 -8
@@ -164,22 +164,21 @@ static bool dma_direct_use_pool(struct d
 	return !gfpflags_allow_blocking(gfp) && !is_swiotlb_for_alloc(dev);
 }
 
-static void *dma_direct_alloc_from_pool(struct device *dev, size_t size,
-		dma_addr_t *dma_handle, gfp_t gfp)
+static struct page *dma_direct_alloc_from_pool(struct device *dev, size_t size,
+		dma_addr_t *dma_handle, void **cpu_addr, gfp_t gfp)
 {
 	struct page *page;
 	u64 phys_limit;
-	void *ret;
 
 	if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_DMA_COHERENT_POOL)))
 		return NULL;
 
 	gfp |= dma_direct_optimal_gfp_mask(dev, &phys_limit);
-	page = dma_alloc_from_pool(dev, size, &ret, gfp, dma_coherent_ok);
+	page = dma_alloc_from_pool(dev, size, cpu_addr, gfp, dma_coherent_ok);
 	if (!page)
 		return NULL;
 	*dma_handle = phys_to_dma_direct(dev, page_to_phys(page));
-	return ret;
+	return page;
 }
 
 static void *dma_direct_alloc_no_mapping(struct device *dev, size_t size,
@@ -247,8 +246,11 @@ void *dma_direct_alloc(struct device *de
 	 * the atomic pools instead if we aren't allowed block.
 	 */
 	if ((remap || force_dma_unencrypted(dev)) &&
-	    dma_direct_use_pool(dev, gfp))
-		return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
+	    dma_direct_use_pool(dev, gfp)) {
+		page = dma_direct_alloc_from_pool(dev, size, dma_handle,
+						  &ret, gfp);
+		return page ? ret : NULL;
+	}
 
 	/* we always manually zero the memory once we are done */
 	page = __dma_direct_alloc_pages(dev, size, gfp & ~__GFP_ZERO, true);
@@ -357,7 +359,7 @@ struct page *dma_direct_alloc_pages(stru
 	void *ret;
 
 	if (force_dma_unencrypted(dev) && dma_direct_use_pool(dev, gfp))
-		return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
+		return dma_direct_alloc_from_pool(dev, size, dma_handle, &ret, gfp);
 
 	page = __dma_direct_alloc_pages(dev, size, gfp, false);
 	if (!page)
author maintainer
#70 lore raw

PATCH 70/583 dmaengine: fsl-edma: tracing: no ptr dereference during log output

In reply to Greg Kroah-Hartman

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

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

From: Martin Kaiser <[email protected]>

commit 2ea04dca8e627f722caa7a2037cfbae0257f3501 upstream.

The fsl edma events store a pointer to a struct fsl_edma_engine in the ringbuffer and dereference it when a log entry is printed. At this time, the pointer may no longer be valid.

Event injection can be used to trigger a crash:

$ cd /sys/kernel/tracing
$ echo 'value = 0' > events/fsl_edma/edma_writeb/inject
$ cat trace

The log output needs only edma->membase. Add a membase field at the end of the event and use the new field for log output. Keep the existing fields for backward compatibility.

---
 drivers/dma/fsl-edma-trace.h |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/fsl-edma-trace.h +3 -1
@@ -19,14 +19,16 @@ DECLARE_EVENT_CLASS(edma_log_io,
 		__field(struct fsl_edma_engine *, edma)
 		__field(void __iomem *, addr)
 		__field(u32, value)
+		__field(void __iomem *, membase)
 	),
 	TP_fast_assign(
 		__entry->edma = edma;
 		__entry->addr = addr;
 		__entry->value = value;
+		__entry->membase = edma->membase;
 	),
 	TP_printk("offset %08x: value %08x",
-		(u32)(__entry->addr - __entry->edma->membase), __entry->value)
+		(u32)(__entry->addr - __entry->membase), __entry->value)
 );
 
 DEFINE_EVENT(edma_log_io, edma_readl,
author maintainer
#71 lore raw

PATCH 71/583 dmaengine: dw-edma: Fix HDMA channel status register access

In reply to Greg Kroah-Hartman

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

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

From: Koichiro Den <[email protected]>

commit ef1b080e03acc83d5bde841da67036985acd50dc upstream.

GET_CH_32() takes the direction before the channel ID, but dw_hdma_v0_core_ch_status() passed them in the opposite order. This can make the status callback read another HDMA channel status register.

Use the same argument order as the other HDMA register accesses.

---
 drivers/dma/dw-edma/dw-hdma-v0-core.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/dw-edma/dw-hdma-v0-core.c +1 -1
@@ -79,7 +79,7 @@ static enum dma_status dw_hdma_v0_core_c
 	u32 tmp;
 
 	tmp = FIELD_GET(HDMA_V0_CH_STATUS_MASK,
-			GET_CH_32(dw, chan->id, chan->dir, ch_stat));
+			GET_CH_32(dw, chan->dir, chan->id, ch_stat));
 
 	if (tmp == 1)
 		return DMA_IN_PROGRESS;
author maintainer
#72 lore raw

PATCH 72/583 dmaengine: dw-edma: Complete descriptors before pausing

In reply to Greg Kroah-Hartman

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

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

From: Koichiro Den <[email protected]>

commit c154060016a9db2ac889bfdb0a3c1322f9be8ded upstream.

If PAUSE is requested while the final burst of a descriptor is in flight, the DONE interrupt takes the PAUSE path without checking whether the descriptor has been depleted. The depleted descriptor remains on the issued list and the channel enters EDMA_ST_PAUSE.

On resume, dw_edma_start_transfer() can select that depleted descriptor again even though no burst remains, leaving the channel in an invalid busy state.

Check for descriptor completion before acknowledging PAUSE. If there is no work to start on resume, leave the channel idle. Also ignore DONE interrupts while the channel is paused so a stale or repeated interrupt cannot change its state or start queued work.

---
 drivers/dma/dw-edma/dw-edma-core.c |   20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +14 -6
@@ -260,7 +260,8 @@ static int dw_edma_device_resume(struct
 		err = -EPERM;
 	} else {
 		chan->status = EDMA_ST_BUSY;
-		dw_edma_start_transfer(chan);
+		if (!dw_edma_start_transfer(chan))
+			chan->status = EDMA_ST_IDLE;
 	}
 
 	return err;
@@ -610,10 +611,16 @@ static void dw_edma_done_interrupt(struc
 	unsigned long flags;
 
 	spin_lock_irqsave(&chan->vc.lock, flags);
+	if (chan->status == EDMA_ST_PAUSE) {
+		spin_unlock_irqrestore(&chan->vc.lock, flags);
+		return;
+	}
+
 	vd = vchan_next_desc(&chan->vc);
 	if (vd) {
 		switch (chan->request) {
 		case EDMA_REQ_NONE:
+		case EDMA_REQ_PAUSE:
 			desc = vd2dw_edma_desc(vd);
 			if (!desc->chunks_alloc) {
 				dw_hdma_set_callback_result(vd,
@@ -622,6 +629,12 @@ static void dw_edma_done_interrupt(struc
 				vchan_cookie_complete(vd);
 			}
 
+			if (chan->request == EDMA_REQ_PAUSE) {
+				chan->request = EDMA_REQ_NONE;
+				chan->status = EDMA_ST_PAUSE;
+				break;
+			}
+
 			/* Continue transferring if there are remaining chunks or issued requests.
 			 */
 			chan->status = dw_edma_start_transfer(chan) ? EDMA_ST_BUSY : EDMA_ST_IDLE;
@@ -634,11 +647,6 @@ static void dw_edma_done_interrupt(struc
 			chan->status = EDMA_ST_IDLE;
 			break;
 
-		case EDMA_REQ_PAUSE:
-			chan->request = EDMA_REQ_NONE;
-			chan->status = EDMA_ST_PAUSE;
-			break;
-
 		default:
 			break;
 		}
author maintainer
#73 lore raw

PATCH 73/583 dmaengine: dw-edma: Initialize IRQ data before requesting IRQs

In reply to Greg Kroah-Hartman

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

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

From: Koichiro Den <[email protected]>

commit 647217abea849d3d45f8cb0b8ee5b78d50f26985 upstream.

dw_edma_irq_request() passes struct dw_edma_irq to request_irq() before dw_edma_channel_setup() fills the back pointer. A shared interrupt can therefore enter the handler with dw_irq->dw still NULL, leading to a NULL pointer dereference.

Set the back pointer before installing each handler.

---
 drivers/dma/dw-edma/dw-edma-core.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/dma/dw-edma/dw-edma-core.c +2 -1
@@ -782,7 +782,6 @@ static int dw_edma_channel_setup(struct
 		else
 			irq->rd_mask |= BIT(chan->id);
 
-		irq->dw = dw;
 		memcpy(&chan->msi, &irq->msi, sizeof(chan->msi));
 
 		dev_vdbg(dev, "MSI:\t\tChannel %s[%u] addr=0x%.8x%.8x, data=0x%.8x\n",
@@ -870,6 +869,7 @@ static int dw_edma_irq_request(struct dw
 	if (chip->nr_irqs == 1) {
 		/* Common IRQ shared among all channels */
 		irq = chip->ops->irq_vector(dev, 0);
+		dw->irq[0].dw = dw;
 		err = request_irq(irq, dw_edma_interrupt_common,
 				  IRQF_SHARED, dw->name, &dw->irq[0]);
 		if (err) {
@@ -895,6 +895,7 @@ static int dw_edma_irq_request(struct dw
 
 		for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
 			irq = chip->ops->irq_vector(dev, i);
+			dw->irq[i].dw = dw;
 			err = request_irq(irq,
 					  i < *wr_alloc ?
 						dw_edma_interrupt_write :
author maintainer
#74 lore raw

PATCH 74/583 cpuidle: dt_idle_genpd: kfree() the original name allocation

In reply to Greg Kroah-Hartman

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

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

From: Linkai Gong <[email protected]>

commit 2b0ac85512b7f67479127b2713254490662eb13d upstream.

dt_idle_pd_alloc() kasprintf()s the full node path, then points pd->name at kbasename() of that string. dt_idle_pd_free() kfree()s pd->name, which is no longer the start of the allocation.

Copy the basename instead.

Fixes 9d976d6721df ("cpuidle: Factor-out power domain related code from PSCI domain driver")
---
 drivers/cpuidle/dt_idle_genpd.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/cpuidle/dt_idle_genpd.c +1 -2
@@ -99,7 +99,7 @@ struct generic_pm_domain *dt_idle_pd_all
 	if (!pd)
 		goto out;
 
-	pd->name = kasprintf(GFP_KERNEL, "%pOF", np);
+	pd->name = kstrdup(kbasename(of_node_full_name(np)), GFP_KERNEL);
 	if (!pd->name)
 		goto free_pd;
 
@@ -112,7 +112,6 @@ struct generic_pm_domain *dt_idle_pd_all
 		goto free_name;
 
 	pd->free_states = pd_free_states;
-	pd->name = kbasename(pd->name);
 	pd->states = states;
 	pd->state_count = state_count;
 
author maintainer
#75 lore raw

PATCH 75/583 cpuidle: psci: Fix support for probe deferral by dropping the faux device

In reply to Greg Kroah-Hartman

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

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

From: Ulf Hansson <[email protected]>

commit 0606f2114e2dc88fe293858fd991cda2688b8c3a upstream.

At the conversion to the faux driver/device we broke the support for probe deferral. In hindsight, the move to the faux device seems questionable, as it simply makes the code more complicated and for no good reason.

To fix the support for the probe deferral let's therefore restore the old code and drop the faux device.

Fixes af5376a77e87 ("cpuidle: psci: Transition to the faux device interface")
Fixes 5836ebeb4a2b ("cpuidle: psci: Avoid initializing faux device if no DT idle states are present")
Fixes 39cdf87a97fd ("cpuidle: psci: Fix uninitialized variable in dt_idle_state_present()")
---
 drivers/cpuidle/cpuidle-psci.c |   42 +++++++++++++++--------------------------
 1 file changed, 16 insertions(+), 26 deletions(-)
drivers/cpuidle/cpuidle-psci.c +16 -26
@@ -16,7 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/device/faux.h>
+#include <linux/platform_device.h>
 #include <linux/psci.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
@@ -424,14 +424,14 @@ deinit:
  * to register cpuidle driver then rollback to cancel all CPUs
  * registration.
  */
-static int psci_cpuidle_probe(struct faux_device *fdev)
+static int psci_cpuidle_probe(struct platform_device *pdev)
 {
 	int cpu, ret;
 	struct cpuidle_driver *drv;
 	struct cpuidle_device *dev;
 
 	for_each_present_cpu(cpu) {
-		ret = psci_idle_init_cpu(&fdev->dev, cpu);
+		ret = psci_idle_init_cpu(&pdev->dev, cpu);
 		if (ret)
 			goto out_fail;
 	}
@@ -451,36 +451,26 @@ out_fail:
 	return ret;
 }
 
-static struct faux_device_ops psci_cpuidle_ops = {
+static struct platform_driver psci_cpuidle_driver = {
 	.probe = psci_cpuidle_probe,
+	.driver = {
+		.name = "psci-cpuidle",
+	},
 };
 
-static bool __init dt_idle_state_present(void)
-{
-	struct device_node *cpu_node __free(device_node) =
-			of_cpu_device_node_get(cpumask_first(cpu_possible_mask));
-	if (!cpu_node)
-		return false;
-
-	struct device_node *state_node __free(device_node) =
-			of_get_cpu_state_node(cpu_node, 0);
-	if (!state_node)
-		return false;
-
-	return !!of_match_node(psci_idle_state_match, state_node);
-}
-
 static int __init psci_idle_init(void)
 {
-	struct faux_device *fdev;
+	struct platform_device *pdev;
+	int ret;
 
-	if (!dt_idle_state_present())
-		return 0;
+	ret = platform_driver_register(&psci_cpuidle_driver);
+	if (ret)
+		return ret;
 
-	fdev = faux_device_create("psci-cpuidle", NULL, &psci_cpuidle_ops);
-	if (!fdev) {
-		pr_err("Failed to create psci-cpuidle device\n");
-		return -ENODEV;
+	pdev = platform_device_register_simple("psci-cpuidle", -1, NULL, 0);
+	if (IS_ERR(pdev)) {
+		platform_driver_unregister(&psci_cpuidle_driver);
+		return PTR_ERR(pdev);
 	}
 
 	return 0;
author maintainer
#76 lore raw

PATCH 76/583 block: flag zoned disks with GENHD_FL_NO_PART

In reply to Greg Kroah-Hartman

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

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

From: Damien Le Moal <[email protected]>

commit 3f9c7a108c0e8f14425384912017071b71341e3b upstream.

Zoned block devices do not support partitions. However, the partition table is nevertheless still inspected, and any partition found ignored with a warning in add_partition(). While this is generally not a problem, and in fact beneficial to the user as it indicates an invalid use of a zoned block device, scanning for a partition table on the device may result in issuing read operations to offline zones (e.g. after a disk head is depopulated for disks that support head management operations).

Since partitions are ignored anyway, completely disable partition scanning for zoned gendisks by setting the flag GENHD_FL_NO_PART in __add_disk(). The existing check in add_partition() is left as-is to ensure that we still get a warning if for whatever reason, despite GENHD_FL_NO_PART, we still endup trying to add partitions.

Flagging zoned disks with GENHD_FL_NO_PART also has the benefit to expose through sysfs the ext_range attribute with the value of 1 instead of the default DISK_MAX_PARTS, thus correctly advertizing the fact that zoned disks do not support partitions.

---
 block/genhd.c |    7 +++++++
 1 file changed, 7 insertions(+)
block/genhd.c +7 -0
@@ -448,6 +448,13 @@ static int __add_disk(struct device *par
 	}
 
 	/*
+	 * We do not support partitions with zoned block devices, so do not try
+	 * to scan the partitions table.
+	 */
+	if (blk_queue_is_zoned(disk->queue))
+		disk->flags |= GENHD_FL_NO_PART;
+
+	/*
 	 * If the driver provides an explicit major number it also must provide
 	 * the number of minors numbers supported, and those will be used to
 	 * setup the gendisk.
author maintainer
#77 lore raw

PATCH 77/583 bpf: Fix infinite loop in pcpu_freelist push with one possible CPU

In reply to Greg Kroah-Hartman

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

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

From: Hui Su <[email protected]>

commit efebf6496685c93150df5bb0794363ae70c5f58a upstream.

__pcpu_freelist_push() can loop forever when only one CPU is possible and an NMI re-enters pcpu_freelist_push() while the interrupted context holds that CPU's freelist lock.

After the current-CPU fast path fails, the fallback loop walks cpu_possible_mask while skipping the current CPU. With CONFIG_SMP=n, or when an SMP kernel is limited to one possible CPU with nr_cpus=1 or possible_cpus=1, there are no other possible CPUs to examine. The loop therefore makes no lock acquisition attempt and can never make progress.

The following stack was observed on a UP system:

NMI context:
pcpu_freelist_push
free_htab_elem
htab_map_delete_elem
[perf-event BPF program]
__perf_event_overflow
perf_event_nmi_handler
exc_nmi

Interrupted context:
__pcpu_freelist_push
pcpu_freelist_push
free_htab_elem
htab_map_delete_elem
[raw_tp/sys_enter BPF program]
__bpf_trace_sys_enter
do_syscall_64

raw_res_spin_lock() detects the same-CPU recursive acquisition and returns -EDEADLK, but the subsequent fallback loop has no candidate head on a system with one possible CPU.

Restore the extra fallback head that existed before the rqspinlock conversion. Keep the current-CPU fast path, then try the other possible CPUs and finally the extra head. The additional head lets a push, which cannot fail without losing a preallocated element, make progress when the only per-CPU head is held by the interrupted context.

Also check the extra head from the pop path so that nodes placed there can be reused.

---
 kernel/bpf/percpu_freelist.c | 35 +++++++++++++++++++++++++++--------
 kernel/bpf/percpu_freelist.h |  1 +
 2 files changed, 28 insertions(+), 8 deletions(-)
kernel/bpf/percpu_freelist.c +27 -8
index 632762b57299..06ce588d13a3 100644
@@ -17,6 +17,8 @@ int pcpu_freelist_init(struct pcpu_freelist *s)
 		raw_res_spin_lock_init(&head->lock);
 		head->first = NULL;
 	}
+	raw_res_spin_lock_init(&s->extralist.lock);
+	s->extralist.first = NULL;
 	return 0;
 }
 
@@ -46,22 +48,28 @@ void __pcpu_freelist_push(struct pcpu_freelist *s,
 			struct pcpu_freelist_node *node)
 {
 	struct pcpu_freelist_head *head;
-	int cpu;
+	int cpu, this_cpu;
 
 	if (___pcpu_freelist_push(this_cpu_ptr(s->freelist), node))
 		return;
 
+	this_cpu = raw_smp_processor_id();
 	while (true) {
-		for_each_cpu_wrap(cpu, cpu_possible_mask, raw_smp_processor_id()) {
-			if (cpu == raw_smp_processor_id())
+		for_each_cpu_wrap(cpu, cpu_possible_mask, this_cpu) {
+			if (cpu == this_cpu)
 				continue;
+
 			head = per_cpu_ptr(s->freelist, cpu);
-			if (raw_res_spin_lock(&head->lock))
-				continue;
-			pcpu_freelist_push_node(head, node);
-			raw_res_spin_unlock(&head->lock);
-			return;
+			if (___pcpu_freelist_push(head, node))
+				return;
 		}
+
+		/*
+		 * Push cannot fail. Use the extra list when none of the
+		 * per-CPU freelists can accept the node.
+		 */
+		if (___pcpu_freelist_push(&s->extralist, node))
+			return;
 	}
 }
 
@@ -117,6 +125,17 @@ static struct pcpu_freelist_node *___pcpu_freelist_pop(struct pcpu_freelist *s)
 		}
 		raw_res_spin_unlock(&head->lock);
 	}
+
+	/* Per-CPU lists are empty or unavailable, try the extra list. */
+	head = &s->extralist;
+	if (!READ_ONCE(head->first))
+		return NULL;
+	if (raw_res_spin_lock(&head->lock))
+		return NULL;
+	node = head->first;
+	if (node)
+		WRITE_ONCE(head->first, node->next);
+	raw_res_spin_unlock(&head->lock);
 	return node;
 }
 
kernel/bpf/percpu_freelist.h +1 -0
index 914798b74967..980cf2884fd2 100644
@@ -14,6 +14,7 @@ struct pcpu_freelist_head {
 
 struct pcpu_freelist {
 	struct pcpu_freelist_head __percpu *freelist;
+	struct pcpu_freelist_head extralist;
 };
 
 struct pcpu_freelist_node {
Signature · 1 line
2.55.0
author maintainer
#78 lore raw

PATCH 78/583 ceph: lock mutex in ceph_mds_check_access()

In reply to Greg Kroah-Hartman

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

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

From: Max Kellermann <[email protected]>

commit a61c6ae1dae2611082b831b4aaa780878099c012 upstream.

MDS session OPEN handling replaces mdsc->s_cap_auths under mdsc->mutex, freeing the previous array and its strings.

ceph_mds_check_access() traverses this array without holding the mutex. A concurrent session reopen can therefore free the array while it is being inspected, resulting in a use-after-free like this:

  Unable to handle kernel paging request at virtual address 003aaad64b2c8bb9
  [...]
  Internal error: Oops: 0000000096000004 [#1]  SMP
  Modules linked in:
  CPU: 56 UID: 2953037534 PID: 1253231 Comm: php-cgi8.4 Not tainted 6.18.45-i2-ampere #1146 NONE
  [..]
  pc : ceph_mds_check_access+0xd4/0x550
  lr : ceph_mds_check_access+0xc8/0x550
  [...]
  Call trace:
   ceph_mds_check_access+0xd4/0x550 (P)
   ceph_atomic_open+0x138/0xbe8
   path_openat+0xa24/0xfa8
   do_filp_open+0x94/0x158
   do_sys_openat2+0x88/0xf8
Fixes 596afb0b8933 ("ceph: add ceph_mds_check_access() helper")
---
 fs/ceph/mds_client.c |    4 ++++
 fs/ceph/mds_client.h |    1 +
 2 files changed, 5 insertions(+)
fs/ceph/mds_client.c +4 -0
@@ -5798,11 +5798,13 @@ int ceph_mds_check_access(struct ceph_md
 	doutc(cl, "tpath '%s', mask %d, caller_uid %d, caller_gid %d\n",
 	      tpath, mask, caller_uid, caller_gid);
 
+	mutex_lock(&mdsc->mutex);
 	for (i = 0; i < mdsc->s_cap_auths_num; i++) {
 		struct ceph_mds_cap_auth *s = &mdsc->s_cap_auths[i];
 
 		err = ceph_mds_auth_match(mdsc, s, cred, tpath);
 		if (err < 0) {
+			mutex_unlock(&mdsc->mutex);
 			put_cred(cred);
 			return err;
 		} else if (err > 0) {
@@ -5824,6 +5826,7 @@ int ceph_mds_check_access(struct ceph_md
 	doutc(cl, "root_squash_perms %d, rw_perms_s %p\n", root_squash_perms,
 	      rw_perms_s);
 	if (root_squash_perms && rw_perms_s == NULL) {
+		mutex_unlock(&mdsc->mutex);
 		doutc(cl, "access allowed\n");
 		return 0;
 	}
@@ -5838,6 +5841,7 @@ int ceph_mds_check_access(struct ceph_md
 		      !!(mask & MAY_READ), !!(mask & MAY_WRITE));
 	}
 	doutc(cl, "access denied\n");
+	mutex_unlock(&mdsc->mutex);
 	return -EACCES;
 }
 
fs/ceph/mds_client.h +1 -0
@@ -545,6 +545,7 @@ struct ceph_mds_client {
 	struct rw_semaphore     pool_perm_rwsem;
 	struct rb_root		pool_perm_tree;
 
+	/* protected by mutex */
 	u32			 s_cap_auths_num;
 	struct ceph_mds_cap_auth *s_cap_auths;
 
author maintainer
#79 lore raw

PATCH 79/583 ata: ahci: work around lost interrupts on Marvell 88SE61xx

In reply to Greg Kroah-Hartman

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

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

From: Hajo Noerenberg <[email protected]>

commit dc3565a4ae538e584e5e63b3b3cd1eaf502593c1 upstream.

ahci_single_level_irq_intr() services the ports first and clears the global HOST_IRQ_STAT afterwards, as recommended by AHCI 1.1 section 10.6.2. The Marvell 88SE6111/6121/6145 family stops reporting interrupts for a port when HOST_IRQ_STAT is cleared while PxIS still holds bits:
PxIS keeps its content, HOST_IRQ_STAT reads back as 0, the port is never looked at again, and the command in flight only ends in a timeout.

Measured on a Seagate Blackarmor NAS440 (Marvell 88F6281 Kirkwood, 88SE6121 rev B2 behind PCIe) by polling the AHCI registers from userspace while an IDENTIFY was outstanding:

t=303.046 irqs 127 PxIS 0x00000000 PxCI 0x00000001
IDENTIFY issued
t=303.057 irqs 128 PxIS 0x00000020 PxCI 0x00000000
CI cleared, DPS set, one interrupt taken ... PxIS stays 0x00000020, HOST_IRQ_STAT stays 0 ...
t~308.05 qc timeout after 5000 msecs

The command had completed - PxCI was clear and PxIS had DPS set - so ahci_qc_complete() would have completed it. It never got the chance because the handler read HOST_IRQ_STAT as 0 and returned IRQ_NONE.

Marvell's own driver for these chips clears the two registers in the opposite order and says so ("clear global before channel"), and ahci_xgene handles its broken edge latch the same way. Since the reordering costs at most one spurious interrupt per valid one on conforming controllers, do it in a private interrupt handler selected for board_ahci_mv instead of changing libahci for everyone.

With this applied, SATA-2 and SATA-3 disks work at 3.0 Gbps on the 88SE6121 without the drive-side 1.5 Gbps jumper that was needed before. Time from link up to a successful IDENTIFY:

  WDC WD5000AADS-00S9B0  port 0    7 ms  (never identified before)
  WDC WD3202ABYS-01B7A0  port 1   28 ms
  WDC WD30EFRX-68EUZN0   port 1  200 ms  (3 TB, HPA detection ok)

Only the 88SE6121 was tested; board_ahci_mv also covers the 88SE6145, which Marvell's driver treats identically.

---
 drivers/ata/ahci.c |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)
drivers/ata/ahci.c +49 -0
@@ -1686,6 +1686,51 @@ static irqreturn_t ahci_thunderx_irq_han
 }
 #endif
 
+/*
+ * The Marvell 88SE6111/6121/6145 ("Thor") family stops reporting interrupts
+ * for a port when HOST_IRQ_STAT is cleared while PxIS still holds bits: PxIS
+ * keeps its content, HOST_IRQ_STAT reads back as 0, the port is never looked
+ * at again and the command in flight only ends in a timeout.  On a 88SE6121
+ * this makes every SATA-2 or SATA-3 disk fail to IDENTIFY, while SATA-1 disks
+ * happen to win the race often enough to work.
+ *
+ * Clearing the host status before servicing the ports avoids it.  Marvell's
+ * own driver for these chips does the same and says so ("clear global before
+ * channel"), and ahci_xgene handles its broken edge latch the same way.  The
+ * price is at most one spurious interrupt per valid one, which is why this is
+ * not the generic behaviour - see AHCI 1.1 section 10.6.2.
+ *
+ * Link: https://bugzilla.kernel.org/show_bug.cgi?id=216094
+ */
+static irqreturn_t ahci_mv_irq_handler(int irq, void *dev_instance)
+{
+	struct ata_host *host = dev_instance;
+	struct ahci_host_priv *hpriv = host->private_data;
+	void __iomem *mmio = hpriv->mmio;
+	unsigned int rc;
+	u32 irq_stat, irq_masked;
+
+	irq_stat = readl(mmio + HOST_IRQ_STAT);
+	if (!irq_stat)
+		return IRQ_NONE;
+
+	irq_masked = irq_stat & hpriv->port_map;
+
+	spin_lock(&host->lock);
+
+	/*
+	 * Use the unmasked value to clear the interrupt, as a spurious pending
+	 * event on a dummy port might cause a screaming IRQ.
+	 */
+	writel(irq_stat, mmio + HOST_IRQ_STAT);
+
+	rc = ahci_handle_port_intr(host, irq_masked);
+
+	spin_unlock(&host->lock);
+
+	return IRQ_RETVAL(rc);
+}
+
 static void ahci_remap_check(struct pci_dev *pdev, int bar,
 		struct ahci_host_priv *hpriv)
 {
@@ -1971,6 +2016,10 @@ static int ahci_init_one(struct pci_dev
 		return -ENOMEM;
 	hpriv->flags |= (unsigned long)pi.private_data;
 
+	/* the Marvell "Thor" family needs HOST_IRQ_STAT cleared first */
+	if (board_id == board_ahci_mv)
+		hpriv->irq_handler = ahci_mv_irq_handler;
+
 	/* MCP65 revision A1 and A2 can't do MSI */
 	if (board_id == board_ahci_mcp65 &&
 	    (pdev->revision == 0xa1 || pdev->revision == 0xa2))
author maintainer
#80 lore raw

PATCH 80/583 ima: Check for ERR_PTR from dentry_path() in validate_hash_algo()

In reply to Greg Kroah-Hartman

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

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

From: Bradley Morgan <[email protected]>

commit 8861f6d5c0678a7c5089c7b272509fc5931b8437 upstream.

dentry_path() returns ERR_PTR(-ENAMETOOLONG) when the path exceeds the buffer. validate_hash_algo() passes the result straight to integrity_audit_msg() without checking. ERR_PTR is not NULL, so integrity_audit_message() sees a valid pointer and calls strlen() on it, which faults:

    BUG: unable to handle page fault for address: ffffffffffffffdc
    RIP: 0010:strlen+0x30/0xa0
    Call Trace:
     audit_log_untrustedstring+0x19/0x30
     integrity_audit_message+0x366/0x4f0
     ima_inode_setxattr+0x512/0x5f0

Check for IS_ERR() and use NULL instead, which makes the audit message skip the name= field instead of crashing.

Fixes 4f2946aa0c45 ("IMA: introduce a new policy option func=SETXATTR_CHECK")
Reported-by [email protected]
---
 security/integrity/ima/ima_appraise.c |    2 ++
 1 file changed, 2 insertions(+)
security/integrity/ima/ima_appraise.c +2 -0
@@ -777,6 +777,8 @@ static int validate_hash_algo(struct den
 		return -EACCES;
 
 	path = dentry_path(dentry, pathbuf, PATH_MAX);
+	if (IS_ERR(path))
+		path = NULL;
 
 	integrity_audit_msg(AUDIT_INTEGRITY_DATA, d_inode(dentry), path,
 			    "set_data", errmsg, -EACCES, 0);
author maintainer
#81 lore raw

PATCH 81/583 irqchip/stm32mp-exti: Fix the unit of the hwspinlock timeout

In reply to Greg Kroah-Hartman

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

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

From: Ju Nan <[email protected]>

commit d31fbbade43f880b7e59e2b3a72722fe2725d93f upstream.

HWSPNLCK_TIMEOUT is passed to hwspin_lock_timeout_in_atomic(), whose timeout argument is in milliseconds, not microseconds:

  atomic_delay += HWSPINLOCK_RETRY_DELAY_US;
  if (atomic_delay > to * 1000)
          return -ETIMEDOUT;

So stm32mp_exti_set_type() asks for a 1 second timeout where the comment next to the macro says it wants 1 millisecond. The semaphore is polled with udelay() from a section that holds chip_data->rlock, a raw_spinlock_t, so preemption stays disabled for the whole wait on every configuration, PREEMPT_RT included.

The hwspinlock core documents this explicitly:

If the mode is HWLOCK_IN_ATOMIC (called from an atomic context) the timeout is handled with busy-waiting delays, hence shall not exceed few msecs.

Fixes 5257169ade8c ("irqchip/stm32-exti: Use the hwspin_lock_timeout_in_atomic() API")
---
 drivers/irqchip/irq-stm32mp-exti.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/irqchip/irq-stm32mp-exti.c +2 -2
@@ -23,7 +23,7 @@
 
 #define IRQS_PER_BANK			32
 
-#define HWSPNLCK_TIMEOUT		1000 /* usec */
+#define HWSPNLCK_TIMEOUT_MS		1
 
 #define EXTI_EnCIDCFGR(n)		(0x180 + (n) * 4)
 #define EXTI_HWCFGR1			0x3f0
@@ -377,7 +377,7 @@ static int stm32mp_exti_set_type(struct
 	raw_spin_lock(&chip_data->rlock);
 
 	if (hwlock) {
-		err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT);
+		err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT_MS);
 		if (err) {
 			pr_err("%s can't get hwspinlock (%d)\n", __func__, err);
 			goto unlock;
author maintainer
#82 lore raw

PATCH 82/583 kprobes: Protect kprobe_blacklist with RCU

In reply to Greg Kroah-Hartman

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

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

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

commit 0c4256196b3a105307e2235fbfd85e768bbcdd0f upstream.

__within_kprobe_blacklist() traverses kprobe_blacklist without holding kprobe_mutex. When a module is unloaded, kprobe_remove_area_blacklist() removes blacklist entries and immediately frees them with kfree(). A concurrent call to within_kprobe_blacklist() can therefore dereference freed memory.

Furthermore, within_kprobe_blacklist() can be called in atomic or non-preemptible contexts where the sleeping kprobe_mutex cannot be taken.

Protect kprobe_blacklist with RCU. Use guard(rcu)() and list_for_each_entry_rcu() for traversal, list_add_tail_rcu() for insertions, list_del_rcu() for deletions, and kfree_rcu() to reclaim entries safely after a grace period.

Fixes 376e242429bf ("kprobes: Introduce NOKPROBE_SYMBOL() macro to maintain kprobes blacklist")
Assisted-by Antigravity:gemini-3.7-flash
---
 include/linux/kprobes.h |    1 +
 kernel/kprobes.c        |   14 ++++++++++----
 2 files changed, 11 insertions(+), 4 deletions(-)
include/linux/kprobes.h +1 -0
@@ -181,6 +181,7 @@ struct kprobe_blacklist_entry {
 	struct list_head list;
 	unsigned long start_addr;
 	unsigned long end_addr;
+	struct rcu_head rcu;
 };
 
 #ifdef CONFIG_KPROBES
kernel/kprobes.c +10 -4
@@ -1373,8 +1373,14 @@ static bool __within_kprobe_blacklist(un
 	/*
 	 * If 'kprobe_blacklist' is defined, check the address and
 	 * reject any probe registration in the prohibited area.
+	 * Note: this can return true during transition period where
+	 * (start_addr, end_addr) in the black list is shrinking
+	 * but old entry has not been removed yet. This is acceptable
+	 * because the worst case is that we reject more probes than
+	 * we should.
 	 */
-	list_for_each_entry(ent, &kprobe_blacklist, list) {
+	guard(rcu)();
+	list_for_each_entry_rcu(ent, &kprobe_blacklist, list) {
 		if (addr >= ent->start_addr && addr < ent->end_addr)
 			return true;
 	}
@@ -2435,7 +2441,7 @@ int kprobe_add_ksym_blacklist(unsigned l
 	ent->start_addr = entry;
 	ent->end_addr = entry + size;
 	INIT_LIST_HEAD(&ent->list);
-	list_add_tail(&ent->list, &kprobe_blacklist);
+	list_add_tail_rcu(&ent->list, &kprobe_blacklist);
 
 	return (int)size;
 }
@@ -2529,8 +2535,8 @@ static void kprobe_remove_area_blacklist
 	list_for_each_entry_safe(ent, n, &kprobe_blacklist, list) {
 		if (ent->start_addr < start || ent->start_addr >= end)
 			continue;
-		list_del(&ent->list);
-		kfree(ent);
+		list_del_rcu(&ent->list);
+		kfree_rcu(ent, rcu);
 	}
 }
 
author maintainer
#83 lore raw

PATCH 83/583 mm/mempolicy: fix sleeping allocation in alloc_pages_bulk_weighted_interleave()

In reply to Greg Kroah-Hartman

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

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

From: Eric Dumazet <[email protected]>

commit 540e583b66d6402bf556fde5e53c817a54c1afe5 upstream.

syzbot reported a sleeping function called from invalid context splat in bucket_table_alloc().

When rhashtable_insert_slow() rehashes the table under rcu_read_lock(), it calls bucket_table_alloc(..., GFP_ATOMIC | __GFP_NOWARN). If the bucket table allocation uses vmalloc, __vmalloc_node_range_noprof() invokes vm_area_alloc_pages() -> alloc_pages_bulk_mempolicy_noprof() with the passed GFP_ATOMIC flags.

If the current task has an MPOL_WEIGHTED_INTERLEAVE mempolicy, alloc_pages_bulk_weighted_interleave() is called and currently hardcodes GFP_KERNEL when allocating the temporary weights array, triggering a might_alloc() splat in atomic/RCU contexts.

Pass the gfp flags (masked with GFP_RECLAIM_MASK to strip page-allocator zone modifiers like __GFP_HIGHMEM) received by alloc_pages_bulk_weighted_interleave() to kmalloc() instead of hardcoding GFP_KERNEL. Since the weights buffer is immediately initialized in full, kmalloc() is sufficient.

---
 mm/mempolicy.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/mempolicy.c +1 -1
@@ -2606,7 +2606,7 @@ static unsigned long alloc_pages_bulk_we
 	prev_node = node;
 
 	/* create a local copy of node weights to operate on outside rcu */
-	weights = kzalloc(nr_node_ids, GFP_KERNEL);
+	weights = kmalloc(nr_node_ids, gfp & GFP_RECLAIM_MASK);
 	if (!weights)
 		return total_allocated;
 
author maintainer
#84 lore raw

PATCH 84/583 fs/ntfs3: fix KMSAN uninit-value in ni_create_attr_list

In reply to Greg Kroah-Hartman

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

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

From: Nirbhay Sharma <[email protected]>

[ Upstream commit 5f33da04e6ceee849e76e6592cc283c72fef7af9 ]

The call to kmalloc() to allocate the attribute list buffer is given a size of al_aligned(rs). This size can be larger than the data subsequently copied into the buffer, leaving trailing bytes uninitialized.

This can trigger a KMSAN "uninit-value" warning if that memory is later accessed.

Fix this by using kzalloc() instead, which ensures the entire allocated buffer is zero-initialized, preventing the warning.

---
 fs/ntfs3/frecord.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ntfs3/frecord.c +1 -1
index 3a458975181c4..b24035c351925 100644
@@ -769,7 +769,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
 	 * Skip estimating exact memory requirement.
 	 * Looks like one record_size is always enough.
 	 */
-	le = kmalloc(al_aligned(rs), GFP_NOFS);
+	le = kzalloc(al_aligned(rs), GFP_NOFS);
 	if (!le)
 		return -ENOMEM;
 
Signature · 1 line
2.53.0
author maintainer
#85 lore raw

PATCH 85/583 fs/ntfs3: fix slab-out-of-bounds write in ni_create_attr_list()

In reply to Greg Kroah-Hartman

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

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

From: HE WEI(ギカク) <[email protected]>

[ Upstream commit 7c4841e2a62794a3bab7c1ff0540580f387e377f ]

ni_create_attr_list() allocates a fixed buffer of al_aligned(record_size) (== record_size) bytes and then walks every attribute of the primary MFT record, writing one ATTR_LIST_ENTRY per attribute and advancing the cursor by le_size(name_len), with no check against the end of the buffer; the total size is only computed after the loop.

A minimum-size resident attribute occupies SIZEOF_RESIDENT (0x18 = 24) bytes on disk, but an unnamed attribute expands to le_size(0) (0x20 = 32) bytes in the list. Because the number of attributes in a record is not bounded (mi_enum_attr() accepts arbitrarily many equal-type, nameless minimum-size attributes), a crafted record packed with such attributes produces a list larger than record_size and overflows the heap buffer.

This is reachable from a crafted, loop-mounted NTFS image: opening the file and adding an attribute (e.g. via setxattr) drives ntfs_set_ea() -> ni_insert_resident() -> ni_insert_attr() -> ni_ins_attr_ext() -> ni_create_attr_list().

  BUG: KASAN: slab-out-of-bounds in ni_create_attr_list+0xc48/0x1058
  Write of size 4 at addr ffff000008984c00 by task setfattr/345
   ni_create_attr_list+0xc48/0x1058
   ni_ins_attr_ext+0x510/0x7c0
   ni_insert_attr+0x3f8/0x70c
   ni_insert_resident+0xc8/0x3b0
   ntfs_set_ea+0x66c/0xd28
   ntfs_setxattr+0x4d8/0x5b0
   __arm64_sys_setxattr+0xa4/0x124
  Allocated by task 345:
   ni_create_attr_list+0x188/0x1058
  The buggy address belongs to the cache kmalloc-1k of size 1024
  (the write lands at object+1024).

Size the buffer from the actual attributes instead of assuming a single record_size is always enough.

Fixes 4342306f0f0d ("fs/ntfs3: Add file operations and implementation")
---
 fs/ntfs3/frecord.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
fs/ntfs3/frecord.c +16 -4
index b24035c351925..7aa37cf01df5a 100644
@@ -766,10 +766,23 @@ int ni_create_attr_list(struct ntfs_inode *ni)
 	rs = sbi->record_size;
 
 	/*
-	 * Skip estimating exact memory requirement.
-	 * Looks like one record_size is always enough.
+	 * Compute the exact size of the attribute list.  Each attribute in the
+	 * record yields one ATTR_LIST_ENTRY of le_size(name_len) bytes.  The
+	 * minimum on-disk attribute is SIZEOF_RESIDENT (0x18) bytes, but an
+	 * unnamed one expands to le_size(0) (0x20) here, so a record crafted
+	 * with many such attributes needs more than a single record_size; the
+	 * previous fixed kzalloc(record_size) could therefore be overflowed by
+	 * an attacker-controlled record.
 	 */
-	le = kzalloc(al_aligned(rs), GFP_NOFS);
+	lsize = 0;
+	attr = NULL;
+	while ((attr = mi_enum_attr(ni, &ni->mi, attr)))
+		lsize += le_size(attr->name_len);
+
+	if (!lsize)
+		return -EINVAL;
+
+	le = kzalloc(al_aligned(lsize), GFP_NOFS);
 	if (!le)
 		return -ENOMEM;
 
@@ -779,7 +792,6 @@ int ni_create_attr_list(struct ntfs_inode *ni)
 	attr = NULL;
 	nb = 0;
 	free_b = 0;
-	attr = NULL;
 
 	for (; (attr = mi_enum_attr(ni, &ni->mi, attr)); le = Add2Ptr(le, sz)) {
 		sz = le_size(attr->name_len);
Signature · 1 line
2.53.0
author maintainer
#86 lore raw

PATCH 86/583 Input: aiptek - validate raw macro indices before updating state

In reply to Greg Kroah-Hartman

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

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

From: Pengpeng Hou <[email protected]>

commit 95dffe32a66cbed07fbfa7afed39d56d5014e04f upstream.

aiptek_irq() derives macro key indices directly from tablet reports and then uses them to index macroKeyEvents[]. Report types 4 and 5 also save the derived value in aiptek->lastMacro and later use that state to release the previous key.

Validate the raw macro index once before it enters that state machine, so lastMacro only ever stores an in-range macro key. Keep direct bounds checks for report type 6, which reads the macro number from the packet body and uses it immediately.

---
 drivers/input/tablet/aiptek.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/input/tablet/aiptek.c +9 -4
@@ -658,6 +658,8 @@ static void aiptek_irq(struct urb *urb)
 		pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
 
 		macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
+		if (macro >= ARRAY_SIZE(macroKeyEvents))
+			macro = -1;
 		z = get_unaligned_le16(data + 4);
 
 		if (dv) {
@@ -699,7 +701,9 @@ static void aiptek_irq(struct urb *urb)
 		left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
 		right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
 		middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
-		macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0;
+		macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : -1;
+		if (macro >= ARRAY_SIZE(macroKeyEvents))
+			macro = -1;
 
 		if (dv) {
 		        /* If the selected tool changed, reset the old
@@ -737,11 +741,11 @@ static void aiptek_irq(struct urb *urb)
 	 */
 	else if (data[0] == 6) {
 		macro = get_unaligned_le16(data + 1);
-		if (macro > 0) {
+		if (macro > 0 && macro - 1 < ARRAY_SIZE(macroKeyEvents)) {
 			input_report_key(inputdev, macroKeyEvents[macro - 1],
 					 0);
 		}
-		if (macro < 25) {
+		if (macro + 1 < ARRAY_SIZE(macroKeyEvents)) {
 			input_report_key(inputdev, macroKeyEvents[macro + 1],
 					 0);
 		}
@@ -760,7 +764,8 @@ static void aiptek_irq(struct urb *urb)
 				aiptek->curSetting.toolMode;
 		}
 
-		input_report_key(inputdev, macroKeyEvents[macro], 1);
+		if (macro < ARRAY_SIZE(macroKeyEvents))
+			input_report_key(inputdev, macroKeyEvents[macro], 1);
 		input_report_abs(inputdev, ABS_MISC,
 				 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
 		input_sync(inputdev);
author maintainer
#87 lore raw

PATCH 87/583 memcg: bypass the reclaim and oom killer for dying tasks once oom_reaper is done

In reply to Greg Kroah-Hartman

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

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

From: Shakeel Butt <[email protected]>

commit 6b0d1083364fc8e7cc2f7d1f93ee3ee78f4d52f7 upstream.

At Meta, we are seeing instances where an OOM killed job is stuck in the exit path for several hours. In one particular case, the job was stuck for more than 8 hours and I had to manually remove the memory.max limits to allow the process to exit.

The job was a single process job and had ~55 GiB memory.max and zswap enabled. It had almost 0 anon in memory and ~111 GiB in zswap compressed to ~51 GiB zswap pool (i.e. almost all of memory.current was zswap). Nothing was left on the LRUs to reclaim.

On further inspection, I observed ~20k threads of that process stuck with the following stack:

[<0>] mem_cgroup_out_of_memory+0x4e/0xa0
[<0>] charge_memcg+0x8bf/0x990
[<0>] mem_cgroup_swapin_charge_folio+0x4e/0x80
[<0>] __read_swap_cache_async+0x10c/0x260
[<0>] swapin_readahead+0x116/0x3f0
[<0>] do_swap_page+0x13c/0x1ce0
[<0>] handle_mm_fault+0x61d/0x11f0
[<0>] do_user_addr_fault+0x3e7/0x6d0
[<0>] exc_page_fault+0x8f/0x110
[<0>] asm_exc_page_fault+0x22/0x30
[<0>] __get_user_8+0x14/0x20
[<0>] futex_cleanup+0x27/0x1c0
[<0>] futex_exit_release+0x47/0x60
[<0>] do_exit+0x107/0x940
[<0>] do_group_exit+0x81/0xa0
[<0>] get_signal+0x2b1/0x6e0
[<0>] arch_do_signal_or_restart+0x1a/0x1c0
[<0>] exit_to_user_mode_loop+0xa8/0x1c0
[<0>] do_syscall_64+0x152/0x250
[<0>] entry_SYSCALL_64_after_hwframe+0x4b/0x53

In addition the dmesg was filled with "Out of memory and no killable processes..." messages.

I have no idea why oom reaper was not able to reap/unmap the process. My guess is that since oom reaper tries to acquire mmap_lock in read mode limited number of times and then gives up, there might be a thread of that process which had mmap_lock in write mode at that time.

My initial suspicion was the futex_cleanup and kernel page fault causing infinite fault and charge retries but that was put to rest in previous discussions happened on similar problem [1].

My current theory is that it is just a simple slow serialization behind the oom_lock. Unlike page allocator, memcg charge code takes the oom_lock without the "try". Though memcg oom code uses mutex_lock_killable(), note that in the call stack get_signal() consumes SIGKILL (or sigdelset(SIGKILL)) before calling do_group_exit(). So this mutex_lock_killable() is just a mutex_lock() here. Therefore 10s of thousands of threads are waiting on oom_lock and one by one they get -EFAULT from get_user() in the futex cleanup code and bails out.

Discussion from [1] led to commit a75ffa26122b ("memcg, oom: do not bypass oom killer for dying tasks") which routes dying tasks into the OOM path precisely so the oom_reaper can reap their mm and free the memory asynchronously. But the reaper is best-effort and one-shot: if it cannot take mmap_lock for read (e.g. a sibling thread holds it for write) it sets MMF_OOM_SKIP and never retries, leaving only the glacial oom_lock-serialized synchronous drain.

Once MMF_OOM_SKIP is set there is no more asynchronous reclaim coming for the mm, so a dying task charging against it has nothing left to wait for:
it frees its memory only once it finishes exiting. Running reclaim and the (no-victim) OOM killer for it is then pointless, and doing it for 10s of thousands of exiting threads is what serializes them behind oom_lock. So before reclaim, if current is an OOM victim whose reaper is done, fail the charge.

Reproduced with 20k threads, each parking a robust futex head on its own zswapped page, OOM-group-killed while a sibling holds mmap_lock for write so the reaper gives up and sets MMF_OOM_SKIP. Tested on next-20260728 and baseline show ~90 seconds exit time while with the patch the exit time reduced to ~3 seconds.

---
 mm/memcontrol.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)
mm/memcontrol.c +13 -0
@@ -2352,6 +2352,19 @@ retry:
 	if (!gfpflags_allow_blocking(gfp_mask))
 		goto nomem;
 
+	/*
+	 * OOM victim still needs to charge memory to exit. OOM reaper should
+	 * help but it might fail on mmap_lock contention. If the victim is a
+	 * large thread group then all exiting threads might compete on oom_lock
+	 * just to learn that there is nothing really killable anymore. Bail
+	 * out early and fail the charge to expedite their exit. They are
+	 * considered fully reclaimed by the oom reaper and they shouldn't
+	 * contribute further charges.
+	 */
+	if (tsk_is_oom_victim(current) &&
+	    mm_flags_test(MMF_OOM_SKIP, current->signal->oom_mm))
+		goto nomem;
+
 	__memcg_memory_event(mem_over_limit, MEMCG_MAX, allow_spinning);
 	raised_max_event = true;
 
author maintainer
#88 lore raw

PATCH 88/583 memcg: make the v1 soft limit knob inert

In reply to Greg Kroah-Hartman

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

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

From: Shakeel Butt <[email protected]>

commit a3417097fb107cea3358b19bcbb4eb655fd67f8c upstream.

The v1 soft limit has been deprecated since v6.12 and nobody has reported depending on it. Start the removal by decoupling the interface from the
implementation: keep memory.soft_limit_in_bytes, but ignore writes to it and always report the maximum value on read similar to what memory.kmem.limit_in_bytes already does.

Writes are still parsed, so malformed input keeps returning -EINVAL. The knob now also behaves the same everywhere: it used to return -EOPNOTSUPP on PREEMPT_RT, where soft limit reclaim has always been disabled.

This also fixes the syzbot report linked below. Soft limit reclaim is the only caller that runs shrink_lruvec() from kswapd against a specific memcg, so it is the only way to reach lru_gen_shrink_lruvec() and in turn set_mm_walk(), which warns when called from kswapd.

---
 Documentation/admin-guide/cgroup-v1/memory.rst |   49 +++----------------------
 mm/memcontrol-v1.c                             |   43 +++++++++++++--------
 2 files changed, 32 insertions(+), 60 deletions(-)
Documentation/admin-guide/cgroup-v1/memory.rst +6 -43
@@ -47,7 +47,6 @@ Features:
  - pages are linked to per-memcg LRU exclusively, and there is no global LRU.
  - optionally, memory+swap usage can be accounted and limited.
  - hierarchical accounting
- - soft limit
  - moving (recharging) account at moving a task is selectable.
  - usage threshold notifier
  - memory pressure notifier
@@ -76,10 +75,9 @@ Brief summary of control files.
  memory.memsw.failcnt		     show the number of memory+Swap hits limits
  memory.max_usage_in_bytes	     show max memory usage recorded
  memory.memsw.max_usage_in_bytes     show max memory+Swap usage recorded
- memory.soft_limit_in_bytes	     set/show soft limit of memory usage
-				     This knob is not available on CONFIG_PREEMPT_RT systems.
-                                     This knob is deprecated and shouldn't be
-                                     used.
+ memory.soft_limit_in_bytes	     This knob is deprecated and has no effect.
+                                     Writes are ignored and reads always
+                                     return the maximum value.
  memory.stat			     show various statistics
  memory.use_hierarchy		     set/show hierarchical account enabled
                                      This knob is deprecated and shouldn't be
@@ -341,9 +339,6 @@ memory.kmem.usage_in_bytes, or in a sepa
 The main "kmem" counter is fed into the main counter, so kmem charges will
 also be visible from the user counter.
 
-Currently no soft limit is implemented for kernel memory. It is future work
-to trigger slab reclaim when those limits are reached.
-
 2.7.1 Current Kernel Memory resources accounted
 -----------------------------------------------
 
@@ -711,42 +706,10 @@ For compatibility reasons writing 1 to m
 
 THIS IS DEPRECATED!
 
-Soft limits allow for greater sharing of memory. The idea behind soft limits
-is to allow control groups to use as much of the memory as needed, provided
-
-a. There is no memory contention
-b. They do not exceed their hard limit
-
-When the system detects memory contention or low memory, control groups
-are pushed back to their soft limits. If the soft limit of each control
-group is very high, they are pushed back as much as possible to make
-sure that one control group does not starve the others of memory.
-
-Please note that soft limits is a best-effort feature; it comes with
-no guarantees, but it does its best to make sure that when memory is
-heavily contended for, memory is allocated based on the soft limit
-hints/setup. Currently soft limit based reclaim is set up such that
-it gets invoked from balance_pgdat (kswapd).
-
-7.1 Interface
--------------
+Writing to memory.soft_limit_in_bytes has no effect and reading it will
+always return the maximum value.
 
-Soft limits can be setup by using the following commands (in this example we
-assume a soft limit of 256 MiB)::
-
-	# echo 256M > memory.soft_limit_in_bytes
-
-If we want to change this to 1G, we can at any time use::
-
-	# echo 1G > memory.soft_limit_in_bytes
-
-.. note::
-       Soft limits take effect over a long period of time, since they involve
-       reclaiming memory for balancing between memory cgroups
-
-.. note::
-       It is recommended to set the soft limit always below the hard limit,
-       otherwise the hard limit will take precedence.
+Use memory.low and memory.min in cgroup v2 instead.
 
 .. _cgroup-v1-memory-move-charges:
 
mm/memcontrol-v1.c +26 -17

73 lines not on this page · raw message

author maintainer
#89 lore raw

PATCH 89/583 rtc: rzn1: Handle EPROBE_DEFER for optional pps interrupt

In reply to Greg Kroah-Hartman

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

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

From: Lad Prabhakar <[email protected]>

commit 708546aa39560a11cf44c7ba99492c8395a6c2fb upstream.

Check for -EPROBE_DEFER from platform_get_irq_byname_optional() and handle the deferred probe request properly.

Although the "pps" interrupt is optional, an error code of -EPROBE_DEFER indicates that the interrupt subsystem is not yet ready. Intercept this specific error condition, assign it to the return value, and jump to the dis_runtime_pm label to avoid ignoring a valid probe deferral.

---
 drivers/rtc/rtc-rzn1.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/rtc/rtc-rzn1.c +4 -0
@@ -465,6 +465,10 @@ static int rzn1_rtc_probe(struct platfor
 	}
 
 	irq = platform_get_irq_byname_optional(pdev, "pps");
+	if (irq == -EPROBE_DEFER) {
+		ret = irq;
+		goto dis_runtime_pm;
+	}
 	if (irq >= 0)
 		ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc);
 
author maintainer
#90 lore raw

PATCH 90/583 rtc: rzn1: Fix weekday underflow when alarm crosses month boundary

In reply to Greg Kroah-Hartman

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

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

From: Lad Prabhakar <[email protected]>

commit 022a2839a52006531804a8db55d3228084400b48 upstream.

rzn1_rtc_set_alarm() calculates the alarm weekday from the difference between the alarm day and the current day of the month. When the alarm crosses a month boundary, this difference can become negative. Since days_ahead is unsigned, it underflows and results in an incorrect weekday being programmed into RZN1_RTC_ALW.

The RTC core already provides a fully populated struct rtc_time for the alarm, including the correct tm_wday. Use tm->tm_wday directly instead of recalculating the weekday from the day-of-month.

This avoids the underflow and ensures alarms scheduled across a month boundary use the correct weekday.

---
 drivers/rtc/rtc-rzn1.c |    7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/rtc/rtc-rzn1.c +1 -6
@@ -261,7 +261,6 @@ static int rzn1_rtc_set_alarm(struct dev
 	struct rzn1_rtc *rtc = dev_get_drvdata(dev);
 	struct rtc_time *tm = &alrm->time, tm_now;
 	unsigned long alarm, farest;
-	unsigned int days_ahead, wday;
 	int ret;
 
 	ret = rzn1_rtc_read_time(dev, &tm_now);
@@ -274,13 +273,9 @@ static int rzn1_rtc_set_alarm(struct dev
 	if (time_after(alarm, farest))
 		return -ERANGE;
 
-	/* Convert alarm day into week day */
-	days_ahead = tm->tm_mday - tm_now.tm_mday;
-	wday = (tm_now.tm_wday + days_ahead) % 7;
-
 	writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM);
 	writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH);
-	writel(BIT(wday), rtc->base + RZN1_RTC_ALW);
+	writel(BIT(tm->tm_wday), rtc->base + RZN1_RTC_ALW);
 
 	rtc->tm_alarm = alrm->time;
 
author maintainer
#91 lore raw

PATCH 91/583 rtc: rzn1: Handle unset alarm weekday in rzn1_rtc_read_alarm

In reply to Greg Kroah-Hartman

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

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

From: Lad Prabhakar <[email protected]>

commit 457b5dbce31209e65e1184716ed3af59cb1c0372 upstream.

RZN1_RTC_ALW is a weekday bitmask where bit N represents weekday N. When no alarm has been configured, the register has its power-on-reset value of zero.

rzn1_rtc_read_alarm() uses fls() to convert the weekday bitmask into a weekday number. When RZN1_RTC_ALW is zero, fls(0) returns zero and fls(wday) - 1 evaluates to -1. This invalid weekday is then used to calculate the alarm date and can either leave tm_wday set to -1 or produce a fabricated alarm date.

Treat a zero RZN1_RTC_ALW value as an unset alarm weekday and return without calculating the alarm date. Move reading RZN1_RTC_CTL1 before this check so that alrm->enabled is updated for both configured and unconfigured alarms.

---
 drivers/rtc/rtc-rzn1.c |   16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/rtc/rtc-rzn1.c +12 -4
@@ -235,13 +235,24 @@ static int rzn1_rtc_read_alarm(struct de
 	if (ret)
 		return ret;
 
+	ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
+	alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE));
+
 	min = readl(rtc->base + RZN1_RTC_ALM);
 	hour = readl(rtc->base + RZN1_RTC_ALH);
-	wday = readl(rtc->base + RZN1_RTC_ALW);
 
 	tm->tm_sec = 0;
 	tm->tm_min = bcd2bin(min);
 	tm->tm_hour = bcd2bin(hour);
+
+	/*
+	 * If wday is zero, no bit is set in RZN1_RTC_ALW. This is the
+	 * register's power-on reset value.
+	 */
+	wday = readl(rtc->base + RZN1_RTC_ALW);
+	if (!wday)
+		return 0;
+
 	delta_days = ((fls(wday) - 1) - tm->tm_wday + 7) % 7;
 	tm->tm_wday = fls(wday) - 1;
 
@@ -250,9 +261,6 @@ static int rzn1_rtc_read_alarm(struct de
 		rtc_time64_to_tm(alarm, tm);
 	}
 
-	ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
-	alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE));
-
 	return 0;
 }
 
author maintainer
#92 lore raw

PATCH 92/583 rtc: rzn1: Disable alarm interrupt before reprogramming alarm registers

In reply to Greg Kroah-Hartman

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

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

From: Lad Prabhakar <[email protected]>

commit 51458d5b0a1cfb1b6013400abc95aadf16ed2a57 upstream.

rzn1_rtc_set_alarm() updates RZN1_RTC_ALM, RZN1_RTC_ALH and RZN1_RTC_ALW using separate MMIO writes without first disabling the alarm interrupt. If a previous alarm is still enabled, the interrupt can fire while the alarm registers contain a mixture of old and newly written values.

Fix this by disabling the alarm interrupt before reprogramming ALM, ALH and ALW with a call to rzn1_rtc_alarm_irq_enable().

---
 drivers/rtc/rtc-rzn1.c |    5 +++++
 1 file changed, 5 insertions(+)
drivers/rtc/rtc-rzn1.c +5 -0
@@ -281,6 +281,11 @@ static int rzn1_rtc_set_alarm(struct dev
 	if (time_after(alarm, farest))
 		return -ERANGE;
 
+	/* Disable alarm interrupts before reprogramming the alarm. */
+	ret = rzn1_rtc_alarm_irq_enable(dev, 0);
+	if (ret)
+		return ret;
+
 	writel(bin2bcd(tm->tm_min), rtc->base + RZN1_RTC_ALM);
 	writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH);
 	writel(BIT(tm->tm_wday), rtc->base + RZN1_RTC_ALW);
author maintainer
#93 lore raw

PATCH 93/583 perf/x86/intel: Fix kernel address leakages in LBR stack

In reply to Greg Kroah-Hartman

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

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

From: Dapeng Mi <[email protected]>

commit e2b0575900ff72aa82748af96e7bd564ade5157a upstream.

Before Arch LBR gained CPL filtering support, a user-only branch stack could still contain kernel addresses. As a result, kernel branch records may be exposed to user space even when PERF_SAMPLE_BRANCH_USER is requested.

For example, on Intel Tiger Lake, the following command can still report SYSRET/ERET entries with kernel-space from addresses:

$ ./perf record -e cycles:p -o - --branch-filter any,save_type,u -- \
 	./perf bench syscall basic --loop 1000 | \
	./perf script -i - --fields brstack|tr ' ' '\n'| \
	grep -E '0x[89a-f][0-9a-f]{15}'
    Total time: 0.000 [sec]

      0.219000 usecs/op
     4,566,210 ops/sec

[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.551 MB - ] 0xffffffff93c001c8/0x7f12a2b1d647/P/-/-/16959/SYSRET/- 0xffffffff93c001c8/0x7f12a2b1d5c2/P/-/-/17535/SYSRET/- 0xffffffff93c01928/0x7f12a2861000/P/-/-/6719/ERET/- 0xffffffff93c01928/0x7f12a297a000/P/-/-/8575/ERET/-

The problem is that intel_pmu_lbr_filter() does not fully validate the privilege level of sampled entries. It filters some mismatches based on the branch type and the to address, but it does not reject entries whose from address violates the requested branch privilege filter.

Fix this by extending software filtering to validate both from and to addresses against br_sel. Any LBR entry contains kernel address does not match the requested user filter is dropped. This prevents kernel addresses from appearing in user-only branch stacks.

---
 arch/x86/events/intel/lbr.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
arch/x86/events/intel/lbr.c +9 -3
@@ -1211,7 +1211,7 @@ intel_pmu_lbr_filter(struct cpu_hw_event
 {
 	u64 from, to;
 	int br_sel = cpuc->br_sel;
-	int i, j, type, to_plm;
+	int i, j, type, from_plm, to_plm;
 	bool compress = false;
 
 	/* if sampling all branches, then nothing to filter */
@@ -1243,8 +1243,14 @@ intel_pmu_lbr_filter(struct cpu_hw_event
 				type |= X86_BR_NO_TX;
 		}
 
-		/* if type does not correspond, then discard */
-		if (type == X86_BR_NONE || (br_sel & type) != type) {
+		from_plm = kernel_ip(from) ? X86_BR_KERNEL : X86_BR_USER;
+		/*
+		 * If type does not correspond, then discard.
+		 * Specifically reject entries whose from address is in
+		 * kernel space when only X86_BR_USER is requested.
+		 */
+		if (type == X86_BR_NONE || (br_sel & type) != type ||
+		    (!(br_sel & X86_BR_KERNEL) && (from_plm & X86_BR_KERNEL))) {
 			cpuc->lbr_entries[i].from = 0;
 			compress = true;
 		}
author maintainer
#94 lore raw

PATCH 94/583 perf trace: Factor out BPF loop body

In reply to Greg Kroah-Hartman

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

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

From: Viktor Malik <[email protected]>

commit acff3e1a9cc29a6a039b76b81a438c56016bc0e3 upstream.

The BPF program in augmented_raw_syscalls uses a for loop to iterate all syscall arguments. The loop body is quite complex and often poses problems for the BPF verifier. As a preparation step for addressing this issue, factor out the loop body into a separate function.

---
 tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c |  128 ++++++++++--------
 1 file changed, 73 insertions(+), 55 deletions(-)
tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c +73 -55
@@ -429,15 +429,80 @@ static bool pid_filter__has(struct pids_
 	return bpf_map_lookup_elem(pids, &pid) != NULL;
 }
 
+/*
+ * Determine what type of argument and how many bytes to read from user space, using the
+ * value in the beauty_map. This is the relation of parameter type and its corresponding
+ * value in the beauty map, and how many bytes we read eventually:
+ *
+ * string: 1			      -> size of string
+ * struct: size of struct	      -> size of struct
+ * buffer: -1 * (index of paired len) -> value of paired len (maximum: TRACE_AUG_MAX_BUF)
+ */
+static inline int augment_arg(struct syscall_enter_args *args, int i,
+			      unsigned int *beauty_map,
+			      struct augmented_arg *payload_offset)
+{
+	int index, value_size = sizeof(struct augmented_arg) - offsetof(struct augmented_arg, value);
+	s64 aug_size, size;
+	bool augmented;
+	void *arg;
+
+	arg = (void *)args->args[i];
+	augmented = false;
+	size = beauty_map[i];
+	aug_size = size; /* size of the augmented data read from user space */
+
+	if (size == 0 || arg == NULL)
+		return 0;
+
+	if (size == 1) { /* string */
+		aug_size = bpf_probe_read_user_str(payload_offset->value, value_size, arg);
+		/* minimum of 0 to pass the verifier */
+		if (aug_size < 0)
+			aug_size = 0;
+
+		augmented = true;
+	} else if (size > 0 && size <= value_size) { /* struct */
+		if (!bpf_probe_read_user(payload_offset->value, size, arg))
+			augmented = true;
+	} else if ((int)size < 0 && size >= -6) { /* buffer */
+		index = -(size + 1);
+		barrier_var(index); // Prevent clang (noticed with v18) from removing the &= 7 trick.
+		index &= 7;	    // Satisfy the bounds checking with the verifier in some kernels.
+		aug_size = args->args[index] > TRACE_AUG_MAX_BUF ? TRACE_AUG_MAX_BUF : args->args[index];
+
+		if (aug_size > 0) {
+			if (!bpf_probe_read_user(payload_offset->value, aug_size, arg))
+				augmented = true;
+		}
+	}
+
+	/* Augmented data size is limited to sizeof(augmented_arg->unnamed union with value field) */
+	if (aug_size > value_size)
+		aug_size = value_size;
+
+	/* write data to payload */
+	if (augmented) {
+		int written = offsetof(struct augmented_arg, value) + aug_size;
+
+		if (written < 0 || written > sizeof(struct augmented_arg))
+			return -1;
+
+		payload_offset->size = aug_size;
+		return written;
+	}
+
+	return 0;
+}
+
 static int augment_sys_enter(void *ctx, struct syscall_enter_args *args)
 {
-	bool augmented, do_output = false;
-	int zero = 0, index, value_size = sizeof(struct augmented_arg) - offsetof(struct augmented_arg, value);
+	bool do_output = false;
+	int zero = 0, written;
 	u64 output = 0; /* has to be u64, otherwise it won't pass the verifier */
-	s64 aug_size, size;
 	unsigned int nr, *beauty_map;
 	struct beauty_payload_enter *payload;
-	void *arg, *payload_offset;
+	void *payload_offset;
 
 	/* fall back to do predefined tail call */
 	if (args == NULL)
@@ -457,58 +522,11 @@ static int augment_sys_enter(void *ctx,
 	/* copy the sys_enter header, which has the syscall_nr */
 	__builtin_memcpy(&payload->args, args, sizeof(struct syscall_enter_args));
 
-	/*
-	 * Determine what type of argument and how many bytes to read from user space, using the
-	 * value in the beauty_map. This is the relation of parameter type and its corresponding
-	 * value in the beauty map, and how many bytes we read eventually:
-	 *
-	 * string: 1			      -> size of string
-	 * struct: size of struct	      -> size of struct
-	 * buffer: -1 * (index of paired len) -> value of paired len (maximum: TRACE_AUG_MAX_BUF)
-	 */
 	for (int i = 0; i < 6; i++) {
-		arg = (void *)args->args[i];
-		augmented = false;
-		size = beauty_map[i];
-		aug_size = size; /* size of the augmented data read from user space */
-
-		if (size == 0 || arg == NULL)
-			continue;
-
-		if (size == 1) { /* string */
-			aug_size = bpf_probe_read_user_str(((struct augmented_arg *)payload_offset)->value, value_size, arg);
-			/* minimum of 0 to pass the verifier */
-			if (aug_size < 0)
-				aug_size = 0;
-
-			augmented = true;
-		} else if (size > 0 && size <= value_size) { /* struct */
-			if (!bpf_probe_read_user(((struct augmented_arg *)payload_offset)->value, size, arg))
-				augmented = true;
-		} else if ((int)size < 0 && size >= -6) { /* buffer */
-			index = -(size + 1);
-			barrier_var(index); // Prevent clang (noticed with v18) from removing the &= 7 trick.
-			index &= 7;	    // Satisfy the bounds checking with the verifier in some kernels.
-			aug_size = args->args[index] > TRACE_AUG_MAX_BUF ? TRACE_AUG_MAX_BUF : args->args[index];
-
-			if (aug_size > 0) {
-				if (!bpf_probe_read_user(((struct augmented_arg *)payload_offset)->value, aug_size, arg))
-					augmented = true;
-			}
-		}
-
-		/* Augmented data size is limited to sizeof(augmented_arg->unnamed union with value field) */
-		if (aug_size > value_size)
-			aug_size = value_size;
-
-		/* write data to payload */
-		if (augmented) {
-			int written = offsetof(struct augmented_arg, value) + aug_size;
-
-			if (written < 0 || written > sizeof(struct augmented_arg))
-				return 1;
-
-			((struct augmented_arg *)payload_offset)->size = aug_size;
+		written = augment_arg(args, i, beauty_map, (struct augmented_arg *)payload_offset);
+		if (written < 0)
+			return 1;
+		if (written > 0) {
 			output += written;
 			payload_offset += written;
 			do_output = true;
author maintainer
#95 lore raw

PATCH 95/583 perf trace: Refactor augmented_raw_syscalls using bpf_for

In reply to Greg Kroah-Hartman

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

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

From: Viktor Malik <[email protected]>

commit ea6992784d65ef2c01f3525217dbf3a44afa9917 upstream.

The loop for processing syscall args in augment_raw_syscalls has a history of breaking with Clang updates, see e.g. commit 013eb043f37b ("perf trace: Fix BPF loading failure (-E2BIG)") from Clang 15 to 16.

Now, a similar thing happened between Clang 21 and 22. While the issue is mitigated on the main line by a recent verifier update, it remains broken on the 6.12 and 6.18 stable branches:

[linux-6.18.y]# sudo perf trace true
libbpf: prog 'sys_enter': BPF program load failed: -E2BIG
libbpf: prog 'sys_enter': -- BEGIN PROG LOAD LOG --
[...]
BPF program is too large. Processed 1000001 insn
processed 1000001 insns (limit 1000000) max_states_per_insn 40 total_states 37941 peak_states 232 mark_read 0 -- END PROG LOAD LOG --
libbpf: prog 'sys_enter': failed to load: -E2BIG
libbpf: failed to load object 'augmented_raw_syscalls_bpf'
libbpf: failed to load BPF skeleton 'augmented_raw_syscalls_bpf': -E2BIG
Error: failed to get syscall or beauty map fd
[...]

The reason is that the loop is quite complex and the BPF verifier often struggles to prove that it terminates.

Fix the issue by replacing the standard for loop with the bpf_for macro, which uses a numeric BPF iterator. This should prevent future breakages of this kind since the verifier has a much easier job proving that the loop terminates.

Small adjustments were necessary for the loop to make it work. The main problem is that the verifier sometimes has problems with bpf_for loops that use a carry-over state, such as the payload_offset and output vars here, since the verifier tries to track their values too precisely and cannot prove loop convergence. To resolve the issue, we (1) explicitly recompute payload_offset in every iteration and (2) use a trick with adding a global zero to output to help the verifier forget its precise state and use a range instead.

Finally, to keep backwards compatibility with older kernel versions that don't have bpf_for (i.e. numeric iterators), fall back to standard loop.

Fixes a68fd6a6cdd3 ("perf trace: Collect augmented data using BPF")
---
 tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c |   47 +++++++++++++-----
 1 file changed, 35 insertions(+), 12 deletions(-)
tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c +35 -12
@@ -429,6 +429,8 @@ static bool pid_filter__has(struct pids_
 	return bpf_map_lookup_elem(pids, &pid) != NULL;
 }
 
+u64 ZERO = 0;
+
 /*
  * Determine what type of argument and how many bytes to read from user space, using the
  * value in the beauty_map. This is the relation of parameter type and its corresponding
@@ -440,9 +442,10 @@ static bool pid_filter__has(struct pids_
  */
 static inline int augment_arg(struct syscall_enter_args *args, int i,
 			      unsigned int *beauty_map,
-			      struct augmented_arg *payload_offset)
+			      struct beauty_payload_enter *payload, u64 offset)
 {
 	int index, value_size = sizeof(struct augmented_arg) - offsetof(struct augmented_arg, value);
+	struct augmented_arg *payload_offset;
 	s64 aug_size, size;
 	bool augmented;
 	void *arg;
@@ -455,6 +458,12 @@ static inline int augment_arg(struct sys
 	if (size == 0 || arg == NULL)
 		return 0;
 
+	/* bounds check for the verifier */
+	if (offset > sizeof(payload->aug_args) - sizeof(payload->aug_args[0]))
+		return -1;
+	barrier_var(offset);
+	payload_offset = (struct augmented_arg *)((void *)&payload->aug_args + offset);
+
 	if (size == 1) { /* string */
 		aug_size = bpf_probe_read_user_str(payload_offset->value, value_size, arg);
 		/* minimum of 0 to pass the verifier */
@@ -498,11 +507,10 @@ static inline int augment_arg(struct sys
 static int augment_sys_enter(void *ctx, struct syscall_enter_args *args)
 {
 	bool do_output = false;
-	int zero = 0, written;
+	int i, zero = 0, written;
 	u64 output = 0; /* has to be u64, otherwise it won't pass the verifier */
 	unsigned int nr, *beauty_map;
 	struct beauty_payload_enter *payload;
-	void *payload_offset;
 
 	/* fall back to do predefined tail call */
 	if (args == NULL)
@@ -514,7 +522,6 @@ static int augment_sys_enter(void *ctx,
 
 	/* set up payload for output */
 	payload        = bpf_map_lookup_elem(&beauty_payload_enter_map, &zero);
-	payload_offset = (void *)&payload->aug_args;
 
 	if (beauty_map == NULL || payload == NULL)
 		return 1;
@@ -522,14 +529,30 @@ static int augment_sys_enter(void *ctx,
 	/* copy the sys_enter header, which has the syscall_nr */
 	__builtin_memcpy(&payload->args, args, sizeof(struct syscall_enter_args));
 
-	for (int i = 0; i < 6; i++) {
-		written = augment_arg(args, i, beauty_map, (struct augmented_arg *)payload_offset);
-		if (written < 0)
-			return 1;
-		if (written > 0) {
-			output += written;
-			payload_offset += written;
-			do_output = true;
+	if (bpf_ksym_exists(bpf_iter_num_new)) {
+		bpf_for(i, 0, 6) {
+			written = augment_arg(args, i, beauty_map, payload, output);
+			if (written < 0)
+				return 1;
+			if (written > 0) {
+				output += written;
+				/*
+				 * guide the verifier to forget range of `output`, which
+				 * helps to prove convergence of the loop
+				 */
+				output += ZERO;
+				do_output = true;
+			}
+		}
+	} else {
+		for (i = 0; i < 6; i++) {
+			written = augment_arg(args, i, beauty_map, payload, output);
+			if (written < 0)
+				return 1;
+			if (written > 0) {
+				output += written;
+				do_output = true;
+			}
 		}
 	}
 
author maintainer
#96 lore raw

PATCH 96/583 perf hisi-ptt: Fix PTT trace TLP header parsing

In reply to Greg Kroah-Hartman

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

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

From: Sizhe Liu <[email protected]>

commit 2b8a2e5d424f0b3369054305d0bf6a5b9faee6c1 upstream.

TLP Headers traced by HiSilicon PCIe tune and trace device (PTT) in 4DW format are shown in the document as below:

bits [31:30] [ 29:25 ][24][23][22][21][    20:11   ][    10:0    ]
     |-----|---------|---|---|---|---|-------------|-------------|
DW0  [ Fmt ][  Type  ][T9][T8][TH][SO][   Length   ][    Time    ]
DW1  [                     Header DW1                            ]
DW2  [                     Header DW2                            ]
DW3  [                     Header DW3                            ]

Problem:
The DW0 bit field layout of the hisi_ptt_4dw union does not match the actual bit ordering in little-endian memory, causing incorrect field decoding.

Test on Kunpeng 930 SOC, generating data flow with iperf commands:
- server side:
iperf -s
- client side:

    iperf -c $ip_addr -t 30

Trace the TLP headers with hisi_ptt on server side at the same time:
perf record -e hisi_ptt12_0/type=4,filter=0x05101,direction=2,format=0/ \
--max-size 50M -o perf.data &
The trace aims to capture completion TLPs, learn more in the document:
https://docs.kernel.org/trace/hisi-ptt.html

Decode perf.data with hisi_ptt decoder:
perf report -D

The hisi_ptt decoder produces the following result:
[...perf headers and other information]
. ... HISI PTT data: size 8388608 bytes

.  00000000: 68 87 20 94                                 Format 3 Type 1a T9 0 T8 1 TH 1 SO 1 Length 10 Time 4a1
.  00000004: 40 00 00 00                                 Header DW1
.  00000008: 40 00 01 51                                 Header DW2
.  0000000c: 00 00 00 00                                 Header DW3

[...other hisi_ptt TLP headers]

According to PCIe r5.0 sec 2.2.1, the Fmt & Type of Cpl/CplD is supposed to be 8b'00001010' / 8b'01001010'
However, the Format & Type decoder analyzing result is 8b'01111010'. It does not match field encodings of any TLP.

Correct decoder result should be:
[...perf headers and other information]
. ... HISI PTT data: size 8388608 bytes

.  00000000: 94 20 87 68                                 Format 2 Type a T9 0 T8 0 TH 0 SO 1 Length 10 Time 768
.  00000004: 00 00 00 40                                 Header DW1
.  00000008: 51 01 00 40                                 Header DW2
.  0000000c: 00 00 00 00                                 Header DW3

[...other hisi_ptt TLP headers]

To solve the problem:
1. Drop the union and C bitfield struct, store the raw DW value in a plain uint32_t, and extract the fields with FIELD_GET() against GENMASK/BIT masks declared in the header so they can be reused by other translation units. The masks are portable across endianness and compilers.

2. Print all DW hex values in big-endian byte order for readability, matching the bit field layout shown in the 4DW format diagram.

3. Read the DW value with get_unaligned_le32() instead of an unaligned pointer cast, avoiding both strict-aliasing violations and alignment hazards on hosts that do not support unaligned access.

Fixes 5e91e57e6809 ("perf auxtrace arm64: Add support for parsing HiSilicon PCIe Trace packet")
---
 Documentation/trace/hisi-ptt.rst                        |   28 ++++-----
 tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c |   47 ++++++++--------
 tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h |   12 ++++
 3 files changed, 50 insertions(+), 37 deletions(-)
Documentation/trace/hisi-ptt.rst +14 -14
@@ -285,20 +285,20 @@ according to the format described previo
     [...perf headers and other information]
     . ... HISI PTT data: size 4194304 bytes
     .  00000000: 00 00 00 00                                 Prefix
-    .  00000004: 01 00 00 60                                 Header DW0
-    .  00000008: 0f 1e 00 01                                 Header DW1
-    .  0000000c: 04 00 00 00                                 Header DW2
-    .  00000010: 40 00 81 02                                 Header DW3
-    .  00000014: 33 c0 04 00                                 Time
+    .  00000004: 60 00 00 01                                 Header DW0
+    .  00000008: 01 00 1e 0f                                 Header DW1
+    .  0000000c: 00 00 00 04                                 Header DW2
+    .  00000010: 02 81 00 40                                 Header DW3
+    .  00000014: 00 04 c0 33                                 Time
     .  00000020: 00 00 00 00                                 Prefix
-    .  00000024: 01 00 00 60                                 Header DW0
-    .  00000028: 0f 1e 00 01                                 Header DW1
-    .  0000002c: 04 00 00 00                                 Header DW2
-    .  00000030: 40 00 81 02                                 Header DW3
-    .  00000034: 02 00 00 00                                 Time
+    .  00000024: 60 00 00 01                                 Header DW0
+    .  00000028: 01 00 1e 0f                                 Header DW1
+    .  0000002c: 00 00 00 04                                 Header DW2
+    .  00000030: 02 81 00 40                                 Header DW3
+    .  00000034: 00 00 00 02                                 Time
     .  00000040: 00 00 00 00                                 Prefix
-    .  00000044: 01 00 00 60                                 Header DW0
-    .  00000048: 0f 1e 00 01                                 Header DW1
-    .  0000004c: 04 00 00 00                                 Header DW2
-    .  00000050: 40 00 81 02                                 Header DW3
+    .  00000044: 60 00 00 01                                 Header DW0
+    .  00000048: 01 00 1e 0f                                 Header DW1
+    .  0000004c: 00 00 00 04                                 Header DW2
+    .  00000050: 02 81 00 40                                 Header DW3
     [...]
tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c +24 -23

81 lines not on this page · raw message

tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h +12 -0
@@ -9,12 +9,24 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include <linux/bits.h>
+#include <linux/bitfield.h>
 
 #define HISI_PTT_8DW_CHECK_MASK		GENMASK(31, 11)
 #define HISI_PTT_IS_8DW_PKT		GENMASK(31, 11)
 #define HISI_PTT_MAX_SPACE_LEN		10
 #define HISI_PTT_FIELD_LENTH		4
 
+/* Header DW0 fields for 4DW format */
+#define HISI_PTT_HEAD0_4DW_TIME		GENMASK_U32(10, 0)
+#define HISI_PTT_HEAD0_4DW_LEN		GENMASK_U32(20, 11)
+#define HISI_PTT_HEAD0_4DW_SO		BIT_U32(21)
+#define HISI_PTT_HEAD0_4DW_TH		BIT_U32(22)
+#define HISI_PTT_HEAD0_4DW_T8		BIT_U32(23)
+#define HISI_PTT_HEAD0_4DW_T9		BIT_U32(24)
+#define HISI_PTT_HEAD0_4DW_TYPE		GENMASK_U32(29, 25)
+#define HISI_PTT_HEAD0_4DW_FORMAT	GENMASK_U32(31, 30)
+
 enum hisi_ptt_pkt_type {
 	HISI_PTT_4DW_PKT,
 	HISI_PTT_8DW_PKT,
author maintainer
#97 lore raw

PATCH 97/583 i2c: designware: Enable interrupt mask workaround for HJMC3001

In reply to Greg Kroah-Hartman

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

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

From: Hongbo Yao <[email protected]>

commit 77549d01edecc20da73c8599e14648877198ce9b upstream.

On HJMicro ARM64 servers, the DesignWare I2C controller does not retrigger a pending interrupt if the interrupt status changes after the current status bits have been cleared.

The issue is exposed under heavy system load when the corresponding SPI is routed across sockets to a core in the remote socket. The interrupt is then lost and the I2C transfer times out.

Enable ACCESS_INTR_MASK for HJMC3001. This toggles DW_IC_INTR_MASK before returning from the interrupt handler and retriggers any pending interrupt.

Fixes 6816ce57c479 ("i2c: designware: Add a new ACPI HID for HJMC01 I2C controller")
Cc <[email protected]> # v6.13+
---
 drivers/i2c/busses/i2c-designware-platdrv.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-designware-platdrv.c +1 -1
@@ -364,7 +364,7 @@ static const struct acpi_device_id dw_i2
 	{ "HISI02A1", 0 },
 	{ "HISI02A2", 0 },
 	{ "HISI02A3", 0 },
-	{ "HJMC3001", 0 },
+	{ "HJMC3001", ACCESS_INTR_MASK },
 	{ "HYGO0010", ACCESS_INTR_MASK },
 	{ "INT33C2", 0 },
 	{ "INT33C3", 0 },
author maintainer
#98 lore raw

PATCH 98/583 i2c: qcom-geni: update frequency table to fix timing parameters

In reply to Greg Kroah-Hartman

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

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

From: Kathiravan Thirumoorthy <[email protected]>

commit a4f3fbccb65de757569686baaf2b72e329096aba upstream.

In IPQ5424, to meet the setup and hold timing requirements in the standard mode, update the frequency table with the values recommended by HW design team.

Also remove the stray space in the I2C_MAX_FAST_MODE_FREQ entry.

Fixes 85c34532849d ("i2c: qcom-geni: fix I2C frequency table to achieve accurate bus rates")
Fixes 506bb2ab0075 ("i2c: qcom-geni: Support systems with 32MHz serial engine clock")
Cc <[email protected]> # v6.13+
---
 drivers/i2c/busses/i2c-qcom-geni.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-qcom-geni.c +2 -2
@@ -156,8 +156,8 @@ static const struct geni_i2c_clk_fld gen
 
 /* source_clock = 32 MHz */
 static const struct geni_i2c_clk_fld geni_i2c_clk_map_32mhz[] = {
-	{ I2C_MAX_STANDARD_MODE_FREQ, 8, 14, 18, 38 },
-	{ I2C_MAX_FAST_MODE_FREQ, 4,  3, 9, 19 },
+	{ I2C_MAX_STANDARD_MODE_FREQ, 12, 9, 10, 26 },
+	{ I2C_MAX_FAST_MODE_FREQ, 4, 3, 9, 19 },
 	{ I2C_MAX_FAST_MODE_PLUS_FREQ, 2, 3, 5, 15 },
 	{}
 };
author maintainer
#99 lore raw

PATCH 99/583 i2c: core: fix debugfs UAF on adapter removal

In reply to Greg Kroah-Hartman

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

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

From: Vasileios Almpanis <[email protected]>

commit b15b548d52b43ba8ac4652bc2c7244a8dd1e9622 upstream.

i2c_del_adapter() frees the adapter's debugfs directory before it unregisters the adapter device, but the new_device sysfs attribute stays writable until device_del(). A write racing with removal still reaches i2c_device_probe(), which passes the freed adap->debugfs to debugfs_create_dir() as the new client's parent:

  BUG: KASAN: slab-use-after-free in lookup_noperm_common+0x407/0x430
  Read of size 4 at addr ffff88803ef87810 by task syz.0.61/6090
   lookup_noperm_common+0x407/0x430
   simple_start_creating+0x9c/0x110
   debugfs_start_creating+0xdb/0x1a0
   debugfs_create_dir+0x24/0x350
   i2c_device_probe+0x814/0xbf0

It's technically possible to create a client after i2c_deregister_clients has run. That client will never be unregistered and make wait_for_completion hang.

Close the window by removing the new_device attribute at the start of i2c_del_adapter(). device_remove_file() will drain any clients left.

---
 drivers/i2c/i2c-core-base.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/i2c/i2c-core-base.c +6 -0
@@ -1814,6 +1814,12 @@ void i2c_del_adapter(struct i2c_adapter
 		return;
 	}
 
+	/*
+	 * This drains any in-flight writers, so all
+	 * clients will be caught by i2c_deregister_clients().
+	 */
+	device_remove_file(&adap->dev, &dev_attr_new_device);
+
 	i2c_acpi_remove_space_handler(adap);
 
 	i2c_deregister_clients(adap);
author maintainer
#100 lore raw

PATCH 100/583 i2c: mux: Fix channel node leak on adapter add failure

In reply to Greg Kroah-Hartman

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

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

From: Ahmad Byagowi <[email protected]>

commit 385c7af4e3b95d0769fd211831674e83b16a2ebf upstream.

i2c_mux_add_adapter() takes a reference to the Device Tree channel node before registering the new adapter. If adapter registration fails, the error path frees the private data without dropping that reference.

Release the channel node before freeing the private data.

---
 drivers/i2c/i2c-mux.c |    1 +
 1 file changed, 1 insertion(+)
drivers/i2c/i2c-mux.c +1 -0
@@ -408,6 +408,7 @@ int i2c_mux_add_adapter(struct i2c_mux_c
 	return 0;
 
 err_free_priv:
+	of_node_put(priv->adap.dev.of_node);
 	kfree(priv);
 	return ret;
 }
author maintainer
#101 lore raw

PATCH 101/583 arm64: mm: Fix the lockless page-table walk in show_pte()

In reply to Greg Kroah-Hartman

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

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

From: Karl Mehltretter <[email protected]>

commit a77644d009dece1104b6fcc6e322b0e4503db0d6 upstream.

show_pte() walks page tables locklessly and can run with interrupts enabled. A concurrent teardown can free a table page while it is being walked. It can also clear a parent entry after show_pte() checked it; the regular pXd_offset() helpers then reread the cleared entry and can derive a bogus lower-level pointer and fault again.

Use the lockless offset helpers with the saved parent entries, as gup_fast() does, and pass the saved PMD to pte_offset_map().

For task page tables, arm64 selects MMU_GATHER_RCU_TABLE_FREE. Disable local interrupts around the walk to hold off RCU-deferred table frees and block the tlb_remove_table_sync_one() IPI until the walk is finished.

Place the IRQ guard after the header print. This does not make the output a consistent snapshot, but prevents the task page-table walk from dereferencing a released table page or deriving a pointer from a different parent value.

Fixes 1d18c47c735e ("arm64: MMU fault handling and page table management")
Assisted-by LLM
---
 arch/arm64/mm/fault.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm64/mm/fault.c +8 -4
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/init.h>
+#include <linux/irqflags.h>
 #include <linux/kasan.h>
 #include <linux/kprobes.h>
 #include <linux/uaccess.h>
@@ -151,6 +152,9 @@ static void show_pte(unsigned long addr)
 	pr_alert("%s pgtable: %luk pages, %llu-bit VAs, pgdp=%016lx\n",
 		 mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K,
 		 vabits_actual, mm_to_pgd_phys(mm));
+
+	guard(irqsave)();
+
 	pgdp = pgd_offset(mm, addr);
 	pgd = READ_ONCE(*pgdp);
 	pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd));
@@ -164,25 +168,25 @@ static void show_pte(unsigned long addr)
 		if (pgd_none(pgd) || pgd_bad(pgd))
 			break;
 
-		p4dp = p4d_offset(pgdp, addr);
+		p4dp = p4d_offset_lockless(pgdp, pgd, addr);
 		p4d = READ_ONCE(*p4dp);
 		pr_cont(", p4d=%016llx", p4d_val(p4d));
 		if (p4d_none(p4d) || p4d_bad(p4d))
 			break;
 
-		pudp = pud_offset(p4dp, addr);
+		pudp = pud_offset_lockless(p4dp, p4d, addr);
 		pud = READ_ONCE(*pudp);
 		pr_cont(", pud=%016llx", pud_val(pud));
 		if (pud_none(pud) || pud_bad(pud))
 			break;
 
-		pmdp = pmd_offset(pudp, addr);
+		pmdp = pmd_offset_lockless(pudp, pud, addr);
 		pmd = READ_ONCE(*pmdp);
 		pr_cont(", pmd=%016llx", pmd_val(pmd));
 		if (pmd_none(pmd) || pmd_bad(pmd))
 			break;
 
-		ptep = pte_offset_map(pmdp, addr);
+		ptep = pte_offset_map(&pmd, addr);
 		if (!ptep)
 			break;
 
author maintainer
#102 lore raw

PATCH 102/583 arm64: errata: pass REVIDR when matching target implementation CPUs

In reply to Greg Kroah-Hartman

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

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

From: Khushit Shah <[email protected]>

commit 5541432e09dc2031978188f3e8a00b9fc78cf097 upstream.

When target implementation CPUs are provided, is_affected_midr_range() accidentally passed the MIDR as both arguments to __is_affected_midr_range(), so the REVIDR mask check operated on the wrong register.

Pass REVIDR as intended.

Fixes 86edf6bdcf05 ("smccc/kvm_guest: Enable errata based on implementation CPUs")
---
 arch/arm64/kernel/cpu_errata.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kernel/cpu_errata.c +1 -1
@@ -82,7 +82,7 @@ is_affected_midr_range(const struct arm6
 
 	for (i = 0; i < target_impl_cpu_num; i++) {
 		if (__is_affected_midr_range(entry, target_impl_cpus[i].midr,
-					     target_impl_cpus[i].midr))
+					     target_impl_cpus[i].revidr))
 			return true;
 	}
 	return false;
author maintainer
#103 lore raw

PATCH 103/583 ALSA: rawmidi: Return the error from snd_rawmidi_input_params()

In reply to Greg Kroah-Hartman

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

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

From: HyeongJun An <[email protected]>

commit f4a23e17d84fd2a152d9e12369761934e1af0ee8 upstream.

The snd_rawmidi_input_params() computes err for the three invalid mode combinations and for resize_runtime_buffer(), applies the new framing and clock type only when err is zero, and then returns 0 anyway. A caller that asked for parameters the kernel rejected is told the change succeeded, and the substream keeps its old buffer.

The open_mutex conversion turned the early returns into assignments. It handled the output sibling correctly, which still returns err, and left this one behind.

Fixes 94b98194b62e ("ALSA: rawmidi: Take open_mutex around parameter changes")
Assisted-by Claude:claude-opus-5
---
 sound/core/rawmidi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/core/rawmidi.c +1 -1
@@ -782,7 +782,7 @@ int snd_rawmidi_input_params(struct snd_
 		substream->framing = framing;
 		substream->clock_type = clock_type;
 	}
-	return 0;
+	return err;
 }
 EXPORT_SYMBOL(snd_rawmidi_input_params);
 
author maintainer
#104 lore raw

PATCH 104/583 ALSA: harmony: initialize locks before requesting IRQ

In reply to Greg Kroah-Hartman

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

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

From: Runyu Xiao <[email protected]>

commit 33abb7491e89285a41565670945293dda841afc4 upstream.

snd_harmony_create() registers the IRQ before initializing h->lock and h->mixer_lock. A pending interrupt can invoke the handler while these locks are uninitialized.

Initialize both locks before requesting the IRQ so the handler always sees valid lock state.

---
 sound/parisc/harmony.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
sound/parisc/harmony.c +3 -3
@@ -868,6 +868,9 @@ snd_harmony_create(struct snd_card *card
 		goto free_and_ret;
 	}
 		
+	spin_lock_init(&h->mixer_lock);
+	spin_lock_init(&h->lock);
+
 	err = request_irq(padev->irq, snd_harmony_interrupt, 0,
 			  "harmony", h);
 	if (err) {
@@ -877,9 +880,6 @@ snd_harmony_create(struct snd_card *card
 	}
 	h->irq = padev->irq;
 
-	spin_lock_init(&h->mixer_lock);
-	spin_lock_init(&h->lock);
-
 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, h, &ops);
 	if (err < 0)
 		goto free_and_ret;
author maintainer
#105 lore raw

PATCH 105/583 ALSA: pcm: Fix race between non-atomic ops and trigger-start

In reply to Greg Kroah-Hartman

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

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

From: Takashi Iwai <[email protected]>

commit acac7b5e07349a9d10d78873afb4b93cd1dc721f upstream.

We protect the races of the concurrent state transitions between atomic PCM ops, but the checks between the non-atomic ops (hw_params, hw_free and prepare) and the atomic ops aren't perfect; there is a check of the conflicting PCM state at the beginning of hw_params & co, but the atomic PCM ops can be still issued during the non-atomic PCM operations. An example such scenario is that a thread A re-issues the PREPARE or HW_PARAMS for the already prepared stream, while another thread B triggers the PCM start in the middle of the prepare operation. Although this usually doesn't lead to much serious issues, it can give some inconsistency as reported by syzkaller (such as ODEBUG warning).

There are various atomic PCM ops, and basically the only problem is the PCM start as it operates from the PREPARED state. Other trigger commands (stop, etc) are for the running or the other special state, hence they are filtered as pre-condition.

This patch is for preventing the PCM trigger-start during the non- atomic operations in order to address the problems above. Fortunately, the hw_params, hw_free and prepare operations call snd_pcm_buffer_access_lock(), and this can be used for checking the concurrent operations at the PCM trigger -- which sets the runtime->buffer_accessing to a negative (if possible), so the PCM trigger just needs to check the runtime->buffer_accessing value; if it's negative, it means the concurrent non-atomic PCM ops is running.

---
 sound/core/pcm_native.c |    2 ++
 1 file changed, 2 insertions(+)
sound/core/pcm_native.c +2 -0
@@ -1441,6 +1441,8 @@ static int snd_pcm_pre_start(struct snd_
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	if (runtime->state != SNDRV_PCM_STATE_PREPARED)
 		return -EBADFD;
+	if (atomic_read(&runtime->buffer_accessing) < 0)
+		return -EBADFD; /* during hw_params, hw_free or prepare */
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	    !snd_pcm_playback_data(substream))
 		return -EPIPE;
author maintainer
#106 lore raw

PATCH 106/583 nvme-fabrics: fix DHCHAP secret leak on parse failure

In reply to Greg Kroah-Hartman

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

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

From: Xu Rao <[email protected]>

commit afdee49a1b88ed9bb44e2b30e855297c169bcc53 upstream.

nvmf_parse_options() duplicates dhchap_secret and dhchap_ctrl_secret with match_strdup() before validating the DHHC-1: representation.

If validation fails, the parser returns -EINVAL before the temporary string in p is assigned to opts->dhchap_secret or opts->dhchap_ctrl_secret. nvmf_create_ctrl() subsequently frees opts, but nvmf_free_options() cannot release the unassigned temporary string. Each rejected option therefore leaks one allocation.

This is easy to miss because valid secrets transfer ownership to opts and are freed normally, while the malformed-secret path still returns the expected -EINVAL to userspace.

With CONFIG_NVME_HOST_AUTH enabled, the leak is reachable before the required-option checks and transport lookup. No NVMe-oF target or working transport connection is required; for example, repeatedly writing

dhchap_secret=BAD

or

dhchap_ctrl_secret=BAD

to /dev/nvme-fabrics deterministically takes the leaking parse path.

Free the temporary string before leaving both validation error paths. Use kfree_sensitive() because the copied option may contain secret material even when its representation is rejected, matching the sensitive cleanup used for stored DHCHAP secrets.

Fixes f50fff73d620 ("nvme: implement In-Band authentication")
---
 drivers/nvme/host/fabrics.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/nvme/host/fabrics.c +2 -0
@@ -1028,6 +1028,7 @@ static int nvmf_parse_options(struct nvm
 			}
 			if (strlen(p) < 11 || strncmp(p, "DHHC-1:", 7)) {
 				pr_err("Invalid DH-CHAP secret %s\n", p);
+				kfree_sensitive(p);
 				ret = -EINVAL;
 				goto out;
 			}
@@ -1042,6 +1043,7 @@ static int nvmf_parse_options(struct nvm
 			}
 			if (strlen(p) < 11 || strncmp(p, "DHHC-1:", 7)) {
 				pr_err("Invalid DH-CHAP secret %s\n", p);
+				kfree_sensitive(p);
 				ret = -EINVAL;
 				goto out;
 			}
author maintainer
#107 lore raw

PATCH 107/583 nvme-fc: fix double free of fabrics options when nvme_add_ctrl() fails

In reply to Greg Kroah-Hartman

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

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

From: Niklas Cassel <[email protected]>

commit 56e6279266f6962bb2d38a54397e3c605165b0c5 upstream.

nvmf_create_ctrl() owns the fabrics options and frees them whenever ->create_ctrl() returns an error, so a transport must not free them on its own error paths. nvme-fc tracks this by testing ctrl->ctrl.opts in nvme_fc_ctrl_free(), which requires nvme_fc_init_ctrl() to clear that pointer on every error exit.

The coupling is implicit, and commit 1a9e218195a5 ("nvme: split device add from initialization") broke it by adding a second error exit. When nvme_add_ctrl() fails, nvme_fc_init_ctrl() jumps to out_put_ctrl:, past the "ctrl->ctrl.opts = NULL" that only sits on the fail_ctrl: path, so nvme_fc_ctrl_free() frees the options and nvmf_create_ctrl() frees them a second time:

  BUG: KASAN: slab-use-after-free in nvmf_free_options+0x30/0x190
   nvmf_free_options+0x30/0x190 drivers/nvme/host/fabrics.c:1284
   nvmf_create_ctrl drivers/nvme/host/fabrics.c:1374 [inline]
  Freed by task 5534:
   nvme_fc_ctrl_free drivers/nvme/host/fc.c:2374 [inline]
   nvme_fc_init_ctrl+0xe17/0x1450 drivers/nvme/host/fc.c:3605

nvme_add_ctrl() fails when dev_set_name() cannot allocate, so this is reachable under memory pressure or fault injection. Without KASAN the options are freed twice.

Rather than clear the pointer on the second exit as well, derive ownership the way nvme-tcp, nvme-rdma and nvme-loop do, from list
membership: their free_ctrl leaves the options alone unless the controller made it onto the transport list.

The list cannot simply be populated on the success path as it is there. nvme-fc runs the initial connect synchronously via flush_delayed_work(), and the controller has to be reachable on rport->ctrl_list for the whole of it: nvme_fc_unregister_remoteport() needs to find it to signal connectivity loss, nvme_fc_match_disconn_ls() matches an incoming Disconnect Association LS against ctrl->association_id, which is only assigned during that window, nvme_fc_resume_controller() needs it on remoteport re-registration, and nvme_fc_existing_controller() uses it to reject a duplicate connect racing the one in flight.

Keep the insertion where it is and add a fail_unlist: label, falling into fail_ctrl:, for the error paths that run after it. The earlier error paths never reach the insertion and keep using fail_ctrl:
directly, so the list is only touched where the controller is actually on it.

nvme_fc_ctrl_free() cannot use the plain "goto free_ctrl" the other transports use, because it still has to put_device(), release the rport reference and free the ida entry for resources taken before the insertion. Sample list_empty() under rport->lock instead.

ctrl->ctrl.opts also stays valid for the whole teardown now. That is not the bug being fixed, but it removes some fragility around the old
idiom: nvme_free_ctrl() calls nvme_auth_free() before ->free_ctrl(), and ctrl_max_dhchaps() dereferences ctrl->opts without a NULL check when ctrl->dhchap_ctxs is set, which nvme-fc permits since NVMF_ALLOWED_OPTS allows the dhchap options. The nvme sysfs attributes that dereference ctrl->opts, such as hostnqn and address, evaluate their is_visible() test once at device_add() time and stay readable until cdev_device_del().

---
 drivers/nvme/host/fc.c |   26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)
drivers/nvme/host/fc.c +20 -6
@@ -2356,9 +2356,15 @@ nvme_fc_ctrl_free(struct kref *ref)
 	struct nvme_fc_ctrl *ctrl =
 		container_of(ref, struct nvme_fc_ctrl, ref);
 	unsigned long flags;
+	bool owns_opts;
 
-	/* remove from rport list */
+	/*
+	 * Presence on the rport list means nvme_fc_init_ctrl() completed,
+	 * and with it ownership of the fabrics options passed to it. If it
+	 * failed instead, the options still belong to nvmf_create_ctrl().
+	 */
 	spin_lock_irqsave(&ctrl->rport->lock, flags);
+	owns_opts = !list_empty(&ctrl->ctrl_list);
 	list_del(&ctrl->ctrl_list);
 	spin_unlock_irqrestore(&ctrl->rport->lock, flags);
 
@@ -2368,7 +2374,7 @@ nvme_fc_ctrl_free(struct kref *ref)
 	nvme_fc_rport_put(ctrl->rport);
 
 	ida_free(&nvme_fc_ctrl_cnt, ctrl->cnum);
-	if (ctrl->ctrl.opts)
+	if (owns_opts)
 		nvmf_free_options(ctrl->ctrl.opts);
 	kfree(ctrl);
 }
@@ -3558,14 +3564,14 @@ nvme_fc_init_ctrl(struct device *dev, st
 	if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
 		dev_err(ctrl->ctrl.device,
 			"NVME-FC{%d}: failed to init ctrl state\n", ctrl->cnum);
-		goto fail_ctrl;
+		goto fail_unlist;
 	}
 
 	if (!queue_delayed_work(nvme_wq, &ctrl->connect_work, 0)) {
 		dev_err(ctrl->ctrl.device,
 			"NVME-FC{%d}: failed to schedule initial connect\n",
 			ctrl->cnum);
-		goto fail_ctrl;
+		goto fail_unlist;
 	}
 
 	flush_delayed_work(&ctrl->connect_work);
@@ -3576,14 +3582,22 @@ nvme_fc_init_ctrl(struct device *dev, st
 
 	return &ctrl->ctrl;
 
+fail_unlist:
+	/*
+	 * Leaving the list hands the options back to nvmf_create_ctrl();
+	 * see nvme_fc_ctrl_free().  Re-init so that list_empty() there
+	 * reports the controller as unlisted.
+	 */
+	spin_lock_irqsave(&rport->lock, flags);
+	list_del_init(&ctrl->ctrl_list);
+	spin_unlock_irqrestore(&rport->lock, flags);
+
 fail_ctrl:
 	nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
 	cancel_work_sync(&ctrl->ioerr_work);
 	cancel_work_sync(&ctrl->ctrl.reset_work);
 	cancel_delayed_work_sync(&ctrl->connect_work);
 
-	ctrl->ctrl.opts = NULL;
-
 	if (ctrl->ctrl.admin_tagset)
 		nvme_remove_admin_tag_set(&ctrl->ctrl);
 	/* initiate nvme ctrl ref counting teardown */
author maintainer
#108 lore raw

PATCH 108/583 nvme-tcp: check the data direction of a C2HData PDU

In reply to Greg Kroah-Hartman

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

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

From: Yehyeong Lee <[email protected]>

commit f83af377c148f6ad94b41c0e8313f12adf45e1c1 upstream.

nvme_tcp_handle_c2h_data() finds the request by command id and checks that it has a payload, but it does not check that the command asked for data to be read. A controller that answers a write command with C2HData therefore reaches nvme_tcp_recv_data(), where _copy_to_iter() hits WARN_ON_ONCE(i->data_source) and returns 0. The receive path turns that into -EFAULT and resets the controller.

No data is copied, so this is not memory corruption. What a controller gets is a kernel warning it can raise at will, which is fatal on a host booted with panic_on_warn.

The send path already knows the direction - it consults rq_data_dir() when it builds a command - and nvme_tcp_handle_r2t() checks the length and the offset of the request it names. The C2HData path does not check the direction at all.

Reject a C2HData PDU whose command is not a read. Rejecting it fails the command and resets the controller, as the neighbouring check in this function does; what goes away is the warning.

  [    6.885580] ------------[ cut here ]------------
  [    6.886457] WARNING: lib/iov_iter.c:193 at _copy_to_iter+0x289/0x1330, CPU#0: kworker/0:1H/71
  [    6.888137] CPU: 0 UID: 0 PID: 71 Comm: kworker/0:1H Not tainted 7.2.0-rc5-NVMETCP-gf5098b6bae76 #1 PREEMPT(lazy)
  [    6.891165] Workqueue: nvme_tcp_wq nvme_tcp_io_work
  [    6.891875] RIP: 0010:_copy_to_iter+0x289/0x1330
  [    6.903739] Call Trace:
  [    6.904085]  <TASK>
  [    6.909254]  __skb_datagram_iter+0x433/0x820
  [    6.911026]  skb_copy_datagram_iter+0x37/0x120
  [    6.911622]  nvme_tcp_recv_skb+0xa07/0x4320
  [    6.913378]  __tcp_read_sock+0x1ab/0x810
  [    6.915788]  nvme_tcp_try_recv+0x152/0x1e0
  [    6.918222]  nvme_tcp_io_work+0x1e4/0x6c0
  [    6.926906]  </TASK>
  [    6.927226] ---[ end trace 0000000000000000 ]---
  [    6.927878] nvme nvme0: queue 1 failed to copy request 0x71 data
  [    6.928709] nvme nvme0: receive failed:  -14
Fixes 3f2304f8c6d6 ("nvme-tcp: add NVMe over TCP host driver")
---
 drivers/nvme/host/tcp.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/nvme/host/tcp.c +7 -0
@@ -688,6 +688,13 @@ static int nvme_tcp_handle_c2h_data(stru
 		return -ENOENT;
 	}
 
+	if (rq_data_dir(rq) != READ) {
+		dev_err(queue->ctrl->ctrl.device,
+			"queue %d tag %#x unexpected data for a write\n",
+			nvme_tcp_queue_id(queue), rq->tag);
+		return -EIO;
+	}
+
 	req = blk_mq_rq_to_pdu(rq);
 	if (!blk_rq_payload_bytes(rq) || !req->curr_bio || !req->data_len) {
 		dev_err(queue->ctrl->ctrl.device,
author maintainer
#109 lore raw

PATCH 109/583 nvme: add missing SRCU grace period in error path

In reply to Greg Kroah-Hartman

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

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

From: Tristan Madani <[email protected]>

commit ef248d5de4469fb6bbaf8dbe0c4c47800080d648 upstream.

nvme_alloc_ns() error path at out_unlink_ns removes ns from the namespace head siblings list with list_del_rcu(&ns->siblings) but does not wait for SRCU readers before freeing the namespace struct. Multipath code iterates the head->list under srcu_read_lock() in nvme_find_path() and nvme_mpath_revalidate_paths(), so a concurrent reader can still hold a reference to ns when kfree(ns) runs.

The normal removal path in nvme_ns_remove() correctly calls synchronize_srcu(&ns->head->srcu) after list_del_rcu() to wait for in-progress readers. Add the same grace period in the error path.

---
 drivers/nvme/host/core.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/nvme/host/core.c +3 -0
@@ -4218,6 +4218,9 @@ static void nvme_alloc_ns(struct nvme_ct
 			last_path = true;
 	}
 	mutex_unlock(&ctrl->subsys->lock);
+
+	/* guarantee not available in head->list */
+	synchronize_srcu(&ns->head->srcu);
 	if (last_path)
 		nvme_put_ns_head(ns->head);
 	nvme_put_ns_head(ns->head);
author maintainer
#110 lore raw

PATCH 110/583 nvmet-auth: Synchronize timeout work during SQ teardown

In reply to Greg Kroah-Hartman

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

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

From: Kazuki Hanai <[email protected]>

commit eaa948c0e19b1bb2d93262207bca0c3d19cc3406 upstream.

nvmet_auth_sq_free() cancels auth_expired_work with cancel_delayed_work(). If the work has already started, cancellation does not wait for the callback. Transport teardown can consequently free or reuse the queue containing struct nvmet_sq while nvmet_auth_expired_work() still accesses that SQ.

Add a teardown-specific helper that synchronously drains the delayed work before freeing authentication state, and use it from nvmet_sq_destroy(). Keep the non-synchronous helper for in-band authentication state cleanup, where the SQ owner remains alive.

Fixes 1a70200f404a ("nvmet-auth: expire authentication sessions")
---
 drivers/nvme/target/auth.c  |    6 ++++++
 drivers/nvme/target/core.c  |    2 +-
 drivers/nvme/target/nvmet.h |    2 ++
 3 files changed, 9 insertions(+), 1 deletion(-)
drivers/nvme/target/auth.c +6 -0
@@ -250,6 +250,12 @@ void nvmet_auth_sq_free(struct nvmet_sq
 	sq->dhchap_skey = NULL;
 }
 
+void nvmet_auth_sq_destroy(struct nvmet_sq *sq)
+{
+	cancel_delayed_work_sync(&sq->auth_expired_work);
+	nvmet_auth_sq_free(sq);
+}
+
 void nvmet_destroy_auth(struct nvmet_ctrl *ctrl)
 {
 	ctrl->shash_id = 0;
drivers/nvme/target/core.c +1 -1
@@ -968,7 +968,7 @@ void nvmet_sq_destroy(struct nvmet_sq *s
 	wait_for_completion(&sq->confirm_done);
 	wait_for_completion(&sq->free_done);
 	percpu_ref_exit(&sq->ref);
-	nvmet_auth_sq_free(sq);
+	nvmet_auth_sq_destroy(sq);
 	nvmet_cq_put(sq->cq);
 
 	/*
drivers/nvme/target/nvmet.h +2 -0
@@ -901,6 +901,7 @@ u8 nvmet_setup_auth(struct nvmet_ctrl *c
 void nvmet_auth_sq_init(struct nvmet_sq *sq);
 void nvmet_destroy_auth(struct nvmet_ctrl *ctrl);
 void nvmet_auth_sq_free(struct nvmet_sq *sq);
+void nvmet_auth_sq_destroy(struct nvmet_sq *sq);
 int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, u8 dhgroup_id);
 bool nvmet_check_auth_status(struct nvmet_req *req);
 int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
@@ -927,6 +928,7 @@ static inline void nvmet_auth_sq_init(st
 }
 static inline void nvmet_destroy_auth(struct nvmet_ctrl *ctrl) {};
 static inline void nvmet_auth_sq_free(struct nvmet_sq *sq) {};
+static inline void nvmet_auth_sq_destroy(struct nvmet_sq *sq) {};
 static inline bool nvmet_check_auth_status(struct nvmet_req *req)
 {
 	return true;
author maintainer
#111 lore raw

PATCH 111/583 nvmet-tcp: fix out-of-bounds write when receiving an over-long PDU

In reply to Greg Kroah-Hartman

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

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

From: Shivam Kumar <[email protected]>

commit 14cc5a7e77731497d5bea70f3bb05df7eda982e4 upstream.

nvmet_tcp_try_recv_pdu() reads a PDU header into the fixed 128-byte queue->pdu union, then computes the remaining payload length as

	queue->left = hdr->hlen - queue->offset + hdgst;

and reads that many more bytes into &queue->pdu + queue->offset, without ever bounding the result against sizeof(queue->pdu).

A struct nvme_tcp_icreq_pdu is itself 128 bytes, exactly the size of the union. Once a header digest has been negotiated (hdgst = 4), a second ICReq passes the hlen == nvmet_tcp_pdu_size() check but yields queue->left = 128 - 8 + 4 = 124, so bytes 8..132 are written into the 128-byte buffer -- 4 bytes past its end, over queue->hdr_digest and queue->data_digest. Those bytes are attacker-controlled (an ICReq carries no digest), and the duplicate ICReq is only rejected later, after the overflow. A remote unauthenticated host can thus corrupt kernel memory adjacent to the receive buffer.

Reject any PDU whose declared length would read past the end of queue->pdu before the second recv.

Fixes 872d26a391da ("nvmet-tcp: add NVMe over TCP target driver")
Assisted-by Claude:claude-opus-4-8
---
 drivers/nvme/target/tcp.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/nvme/target/tcp.c +2 -0
@@ -1262,6 +1262,8 @@ recv:
 		}
 
 		queue->left = hdr->hlen - queue->offset + hdgst;
+		if (queue->left > sizeof(queue->pdu) - queue->offset)
+			return -EPROTO;
 		goto recv;
 	}
 
author maintainer
#112 lore raw

PATCH 112/583 nvmet-tcp: reject unsolicited H2CData PDUs

In reply to Greg Kroah-Hartman

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

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

From: Shivam Kumar <[email protected]>

commit db62b35cbca052860c519cbcabe7650708528738 upstream.

nvmet_tcp_handle_h2c_data_pdu() accepts an H2CData PDU after only checking that its TTAG is a valid in-range command index and that the command's data buffers are mapped. It never checks that the target has actually solicited that data by sending an R2T for the command.

A remote host can abuse this. It submits a write command that takes the R2T path and, before the target transmits the R2T, sends an H2CData PDU for that command's tag. The data completes the command early, and when the command then fails synchronously (e.g. a length mismatch caught by nvmet_check_transfer_len()), it is completed a second time. Each completion calls nvmet_tcp_queue_response(), so the same command is added to queue->resp_list twice while it is still linked; the second llist_add() makes the node point to itself (lentry->next == lentry).

nvmet_tcp_process_resp_list() then walks that self-referential node and adds the command to resp_send_list twice. With CONFIG_DEBUG_LIST this trips the "list_add double add" check (kernel BUG); without it the loop never terminates and the nvmet_tcp workqueue wedges (soft-lockup). It is remotely triggerable and needs no authentication on an allow_any_host subsystem.

Track whether an R2T has been transmitted for a command and reject an H2CData PDU that arrives before it. The flag is cleared on command reuse (nvmet_tcp_get_cmd() zeroes cmd->flags) and stays set across the multiple H2CData PDUs of a single solicited transfer.

Fixes 872d26a391da ("nvmet-tcp: add NVMe over TCP target driver")
---
 drivers/nvme/target/tcp.c |    8 ++++++++
 1 file changed, 8 insertions(+)
drivers/nvme/target/tcp.c +8 -0
@@ -103,6 +103,7 @@ enum nvmet_tcp_recv_state {
 
 enum {
 	NVMET_TCP_F_INIT_FAILED = (1 << 0),
+	NVMET_TCP_F_R2T_SENT	= (1 << 1),
 };
 
 struct nvmet_tcp_cmd {
@@ -787,6 +788,7 @@ static int nvmet_try_send_r2t(struct nvm
 		return -EAGAIN;
 
 	cmd->queue->snd_cmd = NULL;
+	cmd->flags |= NVMET_TCP_F_R2T_SENT;
 	return 1;
 }
 
@@ -1022,6 +1024,12 @@ static int nvmet_tcp_handle_h2c_data_pdu
 		cmd = &queue->connect;
 	}
 
+	if (unlikely(!(cmd->flags & NVMET_TCP_F_R2T_SENT))) {
+		pr_err("queue %d: unsolicited H2CData (ttag %u)\n",
+		       queue->idx, data->ttag);
+		goto err_proto;
+	}
+
 	if (le32_to_cpu(data->data_offset) != cmd->rbytes_done) {
 		pr_err("ttag %u unexpected data offset %u (expected %u)\n",
 			data->ttag, le32_to_cpu(data->data_offset),
author maintainer
#113 lore raw

PATCH 113/583 pmdomain: airoha: fix unselectable AIROHA_CPU_PM_DOMAIN kconfig

In reply to Greg Kroah-Hartman

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

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

From: Christian Marangi <[email protected]>

commit 6d94c47a2e3a38170a0a141547e4c52fbe232cc3 upstream.

The AIROHA_CPU_PM_DOMAIN config was wrongly guarded under the Mediatek PM Domains menu and was unselectable.

Move it outside the menu so it's now visible and correctly selectable by default on Airoha SoC.

Fixes 82e703dd438b ("pmdomain: airoha: Add Airoha CPU PM Domain support")
---
 drivers/pmdomain/mediatek/Kconfig |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/pmdomain/mediatek/Kconfig +3 -2
@@ -26,9 +26,12 @@ config MTK_SCPSYS_PM_DOMAINS
 	  Control Processor System (SCPSYS) has several power management related
 	  tasks in the system.
 
+endmenu
+
 config AIROHA_CPU_PM_DOMAIN
 	tristate "Airoha CPU power domain"
 	default ARCH_AIROHA
+	depends on ARCH_AIROHA || COMPILE_TEST
 	depends on HAVE_ARM_SMCCC
 	depends on PM
 	select PM_GENERIC_DOMAINS
@@ -37,5 +40,3 @@ config AIROHA_CPU_PM_DOMAIN
 
 	  CPU frequency and power is controlled by ATF with SMC command to
 	  set performance states.
-
-endmenu
author maintainer
#114 lore raw

PATCH 114/583 Revert "irqchip/mbigen: Fix mbigen node address layout"

In reply to Greg Kroah-Hartman

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

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

From: caina <[email protected]>

commit e67091609cf85962f64391c1b0f93d4cbfcd4e22 upstream.

This reverts commit 6be6cba9c4371d27f78d900ccfe34bb880d9ee20.

Commit 6be6cba9c437 ("irqchip/mbigen: Fix mbigen node address layout") appears to cause a regression on Hi1616.

On-board hns NIC has two ports, enahisic2i0 and enahisic2i1, both behind mbigen-v2. Port 0 works; port 1 cannot pass any traffic.

Their interrupt pins fall on different mbigen nodes:

enahisic2i0: pins 1152-1198 -> all in node 9
enahisic2i1: pins 1200-1246 -> node 9 (1200-1215) + node 10 (1216-1246)

(nid = (hwirq - 64) / 128 + 1; pin 1215 = node 9, pin 1216 = node 10)

/proc/interrupts shows the break happens exactly at the node boundary:

  enahisic2i1-rx0  pin 1200  count 102   <- node 9
  enahisic2i1-rx5  pin 1215  count   1   <- node 9, last pin
  enahisic2i1-tx5  pin 1216  count   0   <- node 10, first pin
  enahisic2i1-rx6  pin 1218  count   0   <- node 10

...all node 10 pins stay at zero.

Port 0 (entirely node 9) is unaffected. Reverting the commit restores normal operation.

The commit assumes CLEAR occupies a full 4 KB page at [0xa000, 0xb000) and collides with node 10, so node 10+ gets shifted by 0x1000.

But get_mbigen_clear_reg() uses flat, chip-wide addressing -- it never multiplies by the node ID:

    *addr = (hwirq / 32) * 4 + REG_MBIGEN_CLEAR_OFFSET;  /* 0xa000 */

Over the valid hwirq range [64, 1407], CLEAR only spans 0xa008-0xa0af (168 bytes). Node 10's registers are:

    TYPE: 0xa000-0xa00f  (16 B)   overlaps CLEAR by 8 B (0xa008-0xa00f)
    VEC:  0xa200-0xa3ff  (512 B)  no overlap with CLEAR

Shifting the whole page moves VEC from 0xa200 to 0xb200. The hardware reads the event ID from the fixed silicon address 0xa200 on interrupt firing, but software wrote it to 0xb200 -- so the hardware gets an uninitialised value and the interrupt is lost.

The only real overlap is 8 bytes of TYPE. It can only trigger when a single mbigen instance has devices on both node 1 (CLEAR 0xa008) and node 10 (TYPE 0xa008). On Hi1616 those nodes are on separate mbigen instances, so it never triggers.

Fixes 6be6cba9c4371d27f78d900ccfe34bb880d9ee20 ("irqchip/mbigen: Fix mbigen node address layout")
---
 drivers/irqchip/irq-mbigen.c |   20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)
drivers/irqchip/irq-mbigen.c +4 -16
@@ -64,20 +64,6 @@ struct mbigen_device {
 	void __iomem		*base;
 };
 
-static inline unsigned int get_mbigen_node_offset(unsigned int nid)
-{
-	unsigned int offset = nid * MBIGEN_NODE_OFFSET;
-
-	/*
-	 * To avoid touched clear register in unexpected way, we need to directly
-	 * skip clear register when access to more than 10 mbigen nodes.
-	 */
-	if (nid >= (REG_MBIGEN_CLEAR_OFFSET / MBIGEN_NODE_OFFSET))
-		offset += MBIGEN_NODE_OFFSET;
-
-	return offset;
-}
-
 static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
 {
 	unsigned int nid, pin;
@@ -86,7 +72,8 @@ static inline unsigned int get_mbigen_ve
 	nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
 	pin = hwirq % IRQS_PER_MBIGEN_NODE;
 
-	return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET;
+	return pin * 4 + nid * MBIGEN_NODE_OFFSET
+			+ REG_MBIGEN_VEC_OFFSET;
 }
 
 static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
@@ -101,7 +88,8 @@ static inline void get_mbigen_type_reg(i
 	*mask = 1 << (irq_ofst % 32);
 	ofst = irq_ofst / 32 * 4;
 
-	*addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET;
+	*addr = ofst + nid * MBIGEN_NODE_OFFSET
+		+ REG_MBIGEN_TYPE_OFFSET;
 }
 
 static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
author maintainer
#115 lore raw

PATCH 115/583 mm/hugetlb: fix missing migratable flag on same-node hugetlb migration

In reply to Greg Kroah-Hartman

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

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

From: Wupeng Ma <[email protected]>

commit 8ee1ef0f2f8ce29338f4ab00a3d344c010208058 upstream.

Commit ba23f58de896 ("mm/migrate: don't call folio_putback_active_hugetlb() on dst hugetlb folio") moved setting of the migratable flag and active-list placement from folio_putback_active_hugetlb(dst) into move_hugetlb_state(), so that the freshly allocated destination folio is handled where allocation is known to have succeeded.

Unfortunately, the new code was appended after the existing temporary-folio block in move_hugetlb_state(), which contains an early return added earlier by commit 5af1ab1d24e08 ("mm/hugetlb: optimize the surplus state transfer code in move_hugetlb_state()"):

  if (folio_test_hugetlb_temporary(new_folio)) {
      ...
      if (new_nid == old_nid)
          return;                       <-- skips the new code
      ...
  }

  /* added by ba23f58 */
  folio_set_hugetlb_migratable(new_folio);
  list_move_tail(&new_folio->lru, ...&h->hugepage_activelist);

When the destination folio is temporary (i.e. the hugetlb pool was exhausted and the migration callback fell back to alloc_migrate_hugetlb_folio()) and the migration does not cross a node -- the common case, and always true on a single-NUMA system -- move_hugetlb_state() returns before setting the migratable flag or adding the new folio to the active list. The destination folio is then installed in the page table but cannot be isolated afterwards, since folio_isolate_hugetlb() rejects folios without the migratable flag; a subsequent soft-offline, hard-offline or memory-hotplug offline of that folio fails with -EBUSY.

This was reproduced on a single-NUMA arm64 VM: a second MADV_SOFT_OFFLINE on an already-migrated hugetlb page returned EBUSY and logged "hugepage isolation failed".

Keep the surplus adjustment, which is the only part that depends on the node crossing, guarded by `if (new_nid != old_nid)', while making the migratable flag and active-list placement unconditional. This preserves the cleanup intent of ba23f58 and closes the early-return hole.

Fixes ba23f58de896 ("mm/migrate: don't call folio_putback_active_hugetlb() on dst hugetlb folio")
Cc Baolin Wang <[email protected]>
Cc Muchun Song <[email protected]>
Cc Oscar Salvador <[email protected]>
---
 mm/hugetlb.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
mm/hugetlb.c +7 -7
@@ -7916,14 +7916,14 @@ void move_hugetlb_state(struct folio *ol
 		 * There is no need to transfer the per-node surplus state
 		 * when we do not cross the node.
 		 */
-		if (new_nid == old_nid)
-			return;
-		spin_lock_irq(&hugetlb_lock);
-		if (h->surplus_huge_pages_node[old_nid]) {
-			h->surplus_huge_pages_node[old_nid]--;
-			h->surplus_huge_pages_node[new_nid]++;
+		if (new_nid != old_nid) {
+			spin_lock_irq(&hugetlb_lock);
+			if (h->surplus_huge_pages_node[old_nid]) {
+				h->surplus_huge_pages_node[old_nid]--;
+				h->surplus_huge_pages_node[new_nid]++;
+			}
+			spin_unlock_irq(&hugetlb_lock);
 		}
-		spin_unlock_irq(&hugetlb_lock);
 	}
 
 	/*
author maintainer
#116 lore raw

PATCH 116/583 mm/hugetlb: keep max_huge_pages when dissolving surplus folios

In reply to Greg Kroah-Hartman

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

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

From: Longlong Xia <[email protected]>

commit 267bede12d3b108ca29997ce280e927a570ec97f upstream.

dissolve_free_hugetlb_folio() can remove a free folio as surplus when its node has surplus pages. In that case remove_hugetlb_folio() decrements both nr_huge_pages and surplus_huge_pages, leaving the persistent pool size unchanged.

Updating max_huge_pages as if a persistent folio had been removed can therefore corrupt the persistent pool target and underflow it when max_huge_pages is zero. Keep max_huge_pages unchanged for surplus folios, including the vmemmap restoration rollback path.

Fixes cb402bbdabca ("mm/hugetlb: fix surplus pages in dissolve_free_huge_page()")
Assisted-by Codex:gpt-5.6-sol
Cc David Hildenbrand <[email protected]>
Cc Jinjiang Tu <[email protected]>
Cc Longlong Xia <[email protected]>
Cc Oscar Salvador <[email protected]>
---
 mm/hugetlb.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
mm/hugetlb.c +4 -2
@@ -2140,7 +2140,8 @@ retry:
 		if (h->surplus_huge_pages_node[folio_nid(folio)])
 			adjust_surplus = true;
 		remove_hugetlb_folio(h, folio, adjust_surplus);
-		h->max_huge_pages--;
+		if (!adjust_surplus)
+			h->max_huge_pages--;
 		spin_unlock_irq(&hugetlb_lock);
 
 		/*
@@ -2160,7 +2161,8 @@ retry:
 			if (rc) {
 				spin_lock_irq(&hugetlb_lock);
 				add_hugetlb_folio(h, folio, adjust_surplus);
-				h->max_huge_pages++;
+				if (!adjust_surplus)
+					h->max_huge_pages++;
 				goto out;
 			}
 		} else
author maintainer
#117 lore raw

PATCH 117/583 mm/hugetlb_cgroup: call page_counter_set_max() outside VM_BUG_ON()

In reply to Greg Kroah-Hartman

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

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

From: Narek Jilavyan <[email protected]>

commit eedc8474d469a2e88f4dc61f8cfe05c147478b43 upstream.

hugetlb_cgroup_css_alloc() rounds the counter limit down to a multiple of the huge page size and then applies it inside an assertion:

	VM_BUG_ON(page_counter_set_max(fault, limit));
	VM_BUG_ON(page_counter_set_max(rsvd, limit));

With CONFIG_DEBUG_VM=n, VM_BUG_ON(cond) is BUILD_BUG_ON_INVALID(cond), i.e. ((void)(sizeof((__force long)(cond)))), whose operand is never evaluated. page_counter_set_max() is not a predicate - it performs xchg(&counter->max, nr_pages) - so on every non-debug kernel the limit is never applied and the counters keep page_counter_init()'s PAGE_COUNTER_MAX.

That is user-visible, because hugetlb_cgroup_read_u64_max() recomputes the same rounded value and uses equality as its "unlimited" sentinel. PAGE_COUNTER_MAX is LONG_MAX / PAGE_SIZE = 2251799813685247, which is odd, so round_down() really does change it and the two sides disagree. With CONFIG_DEBUG_VM=n:

	$ cat /sys/fs/cgroup/t/hugetlb.2MB.max
	9223372036854771712

and with this patch:

	$ cat /sys/fs/cgroup/t/hugetlb.2MB.max
	max

A debug option should not change cgroup output.

Call the function, then assert the result, as v6.12 did. Use VM_WARN_ON_ONCE() rather than restoring VM_BUG_ON(): the two are identical under CONFIG_DEBUG_VM=n, and checkpatch asks that new code not use BUG() variants.

Fixes 0e2759afcaf9 ("page_counter: track failcnt only for legacy cgroups")
Cc David Hildenbrand <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Shakeel Butt <[email protected]>
---
 mm/hugetlb_cgroup.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
mm/hugetlb_cgroup.c +5 -2
@@ -104,6 +104,7 @@ static void hugetlb_cgroup_init(struct h
 		struct page_counter *fault, *fault_parent = NULL;
 		struct page_counter *rsvd, *rsvd_parent = NULL;
 		unsigned long limit;
+		int ret;
 
 		if (parent_h_cgroup) {
 			fault_parent = hugetlb_cgroup_counter_from_cgroup(
@@ -125,8 +126,10 @@ static void hugetlb_cgroup_init(struct h
 		limit = round_down(PAGE_COUNTER_MAX,
 				   pages_per_huge_page(&hstates[idx]));
 
-		VM_BUG_ON(page_counter_set_max(fault, limit));
-		VM_BUG_ON(page_counter_set_max(rsvd, limit));
+		ret = page_counter_set_max(fault, limit);
+		VM_WARN_ON_ONCE(ret);
+		ret = page_counter_set_max(rsvd, limit);
+		VM_WARN_ON_ONCE(ret);
 	}
 }
 
author maintainer
#118 lore raw

PATCH 118/583 nvdimm/btt: reject an arena whose nfree is below the lane count

In reply to Greg Kroah-Hartman

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

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

From: Bryam Vargas <[email protected]>

commit 6a1f2e5ed9267ca19187038ac635393c165213ac upstream.

The BTT info block's nfree field, the number of reserve free blocks, is read from the medium without validation. btt_freelist_init() and btt_rtt_init() size the per-lane freelist[] and rtt[] arrays by nfree, but the I/O path indexes them by the lane from nd_region_acquire_lane(), which is bounded by nd_region->num_lanes (ND_MAX_LANES), not by nfree. A crafted or foreign arena whose nfree is below the lane count makes freelist[lane]/rtt[lane] run past the allocation: an out-of-bounds write.

btt.rst documents the nlanes = min(nfree, num_cpus) invariant, which the code does not currently honor: num_lanes is ND_MAX_LANES regardless of nfree. Reject an arena whose nfree is below num_lanes at discovery, before the per-lane arrays are allocated, enforcing that invariant.

---
 drivers/nvdimm/btt.c |    8 ++++++++
 1 file changed, 8 insertions(+)
drivers/nvdimm/btt.c +8 -0
@@ -885,6 +885,14 @@ static int discover_arenas(struct btt *b
 		arena->external_lba_start = cur_nlba;
 		parse_arena_meta(arena, super, cur_off);
 
+		if (arena->nfree < btt->nd_region->num_lanes) {
+			dev_err(to_dev(arena),
+				"nfree %u smaller than lane count %d\n",
+				arena->nfree, btt->nd_region->num_lanes);
+			ret = -ENODEV;
+			goto out;
+		}
+
 		ret = log_set_indices(arena);
 		if (ret) {
 			dev_err(to_dev(arena),
author maintainer
#119 lore raw

PATCH 119/583 parisc: eisa: Fix infinite loop when parsing invalid IRQ value

In reply to Greg Kroah-Hartman

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

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

From: Pei Xiao <[email protected]>

commit 8b585431a16cfb9d8f2955a9fa0787ce3dceb3c2 upstream.

When an invalid value is passed via the "eisa_irq_edge=" kernel command line parameter (e.g. "eisa_irq_edge=16,5"), eisa_irq_setup() prints an error message and continues without advancing the current position. As a result the same invalid value is parsed again and again, causing an infinite loop while the kernel boots.

Advance to the next comma-separated entry, or stop parsing when there is no next entry, before continuing so that the remaining entries are processed normally.

---
 drivers/parisc/eisa.c |    5 +++++
 1 file changed, 5 insertions(+)
drivers/parisc/eisa.c +5 -0
@@ -442,6 +442,11 @@ static int __init eisa_irq_setup(char *s
 		val = (int) simple_strtoul(cur, &pe, 0);
 		if (val > 15 || val < 0) {
 			printk(KERN_ERR "eisa: EISA irq value are 0-15\n");
+			cur = strchr(cur, ',');
+			if (cur)
+				cur++;
+			else
+				break;
 			continue;
 		}
 		if (val == 2) {
author maintainer
#120 lore raw

PATCH 120/583 parisc: Fix alignment of asm statements in head.S

In reply to Greg Kroah-Hartman

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

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

From: Helge Deller <[email protected]>

commit 04cf68c9a76e3c6b67ad056a66a14923abf85925 upstream.

All assembler statements need to be 4-byte aligned. Prevent a possible misalignment if someone changes the preceeding string and it's length is then suddenly not a multiple of 4 any longer.

---
 arch/parisc/kernel/head.S |    1 +
 1 file changed, 1 insertion(+)
arch/parisc/kernel/head.S +1 -0
@@ -105,6 +105,7 @@ $iodc_panic:
 	or		%r10,%r10,%r10	/* qemu idle sleep */
 msg1:	.ascii "Can't boot kernel which was built for PA8x00 CPUs on this machine.\r\n"
 msg1_end:
+	.align 4
 
 $cpu_ok:
 #endif
author maintainer
#121 lore raw

PATCH 121/583 powerpc/kexec_file: Fix null-ptr-def in extra size calculation

In reply to Greg Kroah-Hartman

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

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

From: Jinjie Ruan <[email protected]>

commit 761eda315a6e1fda3e8e2185b28430771fb1ac29 upstream.

A static Sashiko AI review identified a potential NULL pointer dereference in kexec_extra_fdt_size_ppc64().

On platforms without any reserved memory regions, get_reserved_memory_ranges() can return 0 while leaving 'rmem' unallocated as NULL. Passing it directly leads to a kernel panic when evaluating 'rmem->nr_ranges'.

Add a NULL check for 'rmem' to prevent this crash.

Fixes 0d3ff067331e ("powerpc/kexec_file: fix extra size calculation for kexec FDT")
---
 arch/powerpc/kexec/file_load_64.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kexec/file_load_64.c +1 -1
@@ -664,7 +664,7 @@ unsigned int kexec_extra_fdt_size_ppc64(
 		extra_size += (cpu_nodes - boot_cpu_node_count) * cpu_node_size();
 
 	/* Consider extra space for reserved memory ranges if any */
-	if (rmem->nr_ranges > 0)
+	if (rmem && rmem->nr_ranges > 0)
 		extra_size += sizeof(struct fdt_reserve_entry) * rmem->nr_ranges;
 
 	return extra_size + kdump_extra_fdt_size_ppc64(image, cpu_nodes);
author maintainer
#122 lore raw

PATCH 122/583 powerpc/kexec_file: Prevent kexec range truncation

In reply to Greg Kroah-Hartman

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

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

From: Jinjie Ruan <[email protected]>

commit fa40f9dbdd4af53e7445d9135b5b207eb8adf372 upstream.

Sashiko AI review pointed out the following issue.

The __merge_memory_ranges() function incorrectly handles overlapping memory ranges when merging them. Although sort_memory_ranges() sorts all ranges by their start address in ascending order beforehand, the merge logic remains defective in two ways:

1. It compares the current range's start against the previous element (i-1) instead of the running target index (idx)

2. It unconditionally overwrites 'ranges[idx].end' with 'ranges[i].end'.

This logic flaw leads to critical memory truncation when a larger memory range completely subsumes subsequent smaller ranges.

For example, consider a sorted input array with three ranges:
Range A (idx=0): [0x1000 - 0x9000]
Range B (i=1): [0x2000 - 0x5000] (completely inside Range A)
Range C (i=2): [0x6000 - 0x8000] (completely inside Range A)

1. When i=1 (Range B):
ranges[1].start (0x2000) <= ranges[0].end + 1 (0x9001) is TRUE. The code executes: ranges[0].end = ranges[1].end, which erroneously shrinks Range A's end from 0x9000 down to 0x5000.

2. When i=2 (Range C):
ranges[2].start (0x6000) <= ranges[1].end + 1 (0x5001) is FALSE. The code falls into the else block, creating a broken new range.

As a result, valid memory fragments [0x5001 - 0x5fff] and [0x8001 - 0x9000] are completely lost from the kexec exclude lists, potentially allowing the crash kernel to overwrite active memory, causing data corruption or crashes.

Fix this by ensuring the start of the current range is compared against the end of the active merged range (idx), and use max() to safely prevent the outer boundary from being truncated.

Fixes 180adfc532a8 ("powerpc/kexec_file: Add helper functions for getting memory ranges")
---
 arch/powerpc/kexec/ranges.c |   12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)
arch/powerpc/kexec/ranges.c +5 -7
@@ -21,6 +21,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/memblock.h>
+#include <linux/minmax.h>
 #include <linux/crash_core.h>
 #include <asm/sections.h>
 #include <asm/kexec_ranges.h>
@@ -105,19 +106,16 @@ static void __merge_memory_ranges(struct
 	struct range *ranges;
 	int i, idx;
 
-	if (!mem_rngs)
+	if (!mem_rngs || mem_rngs->nr_ranges <= 1)
 		return;
 
 	idx = 0;
-	ranges = &(mem_rngs->ranges[0]);
+	ranges = mem_rngs->ranges;
 	for (i = 1; i < mem_rngs->nr_ranges; i++) {
-		if (ranges[i].start <= (ranges[i-1].end + 1))
-			ranges[idx].end = ranges[i].end;
+		if (ranges[i].start <= (ranges[idx].end + 1))
+			ranges[idx].end = max(ranges[idx].end, ranges[i].end);
 		else {
 			idx++;
-			if (i == idx)
-				continue;
-
 			ranges[idx] = ranges[i];
 		}
 	}
author maintainer
#123 lore raw

PATCH 123/583 powerpc/mm: fix wrong addr_pfn tracking in compound vmemmap population

In reply to Greg Kroah-Hartman

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

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

From: Muchun Song <[email protected]>

commit 89a4ae32764172468dea303eb6ae90fe6c859712 upstream.

vmemmap_populate_compound_pages() uses addr_pfn to determine the PFN offset within a compound page and to decide whether the current vmemmap slot should be populated as a head page mapping or should reuse a tail page mapping.

However, addr_pfn is advanced manually in parallel with addr. The loop itself progresses in vmemmap address space, so each PAGE_SIZE step in addr covers PAGE_SIZE / sizeof(struct page) struct page slots. Since addr_pfn is compared against nr_pages in data-PFN units, it should advance by the same number of PFNs. The existing manual increments do not match that and therefore do not reliably track the PFN corresponding to the current addr.

As a result, pfn_offset can be computed from the wrong PFN and the code can make the head/tail decision for the wrong compound-page position.

Fix this by deriving addr_pfn directly from the current vmemmap address instead of carrying it as loop state.

Fixes f2b79c0d7968 ("powerpc/book3s64/radix: add support for vmemmap optimization for radix")
Cc "Aneesh Kumar K.V" <[email protected]>
Cc David Hildenbrand <[email protected]>
Cc Frank van der Linden <[email protected]>
Cc Liam R. Howlett <[email protected]>
Cc Lorenzo Stoakes <[email protected]>
Cc Madhavan Srinivasan <[email protected]>
Cc Michael Ellerman <[email protected]>
Cc Mike Rapoport (Microsoft) <[email protected]>
Cc Nicholas Piggin <[email protected]>
Cc Oscar Salvador (SUSE) <[email protected]>
Cc Usama Arif <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 arch/powerpc/mm/book3s64/radix_pgtable.c |    7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
arch/powerpc/mm/book3s64/radix_pgtable.c +1 -6
@@ -1313,7 +1313,6 @@ int __meminit vmemmap_populate_compound_
 	 * covering out both edges.
 	 */
 	unsigned long addr;
-	unsigned long addr_pfn = start_pfn;
 	unsigned long next;
 	pgd_t *pgd;
 	p4d_t *p4d;
@@ -1334,7 +1333,6 @@ int __meminit vmemmap_populate_compound_
 
 		if (pmd_leaf(READ_ONCE(*pmd))) {
 			/* existing huge mapping. Skip the range */
-			addr_pfn += (PMD_SIZE >> PAGE_SHIFT);
 			next = pmd_addr_end(addr, end);
 			continue;
 		}
@@ -1347,11 +1345,11 @@ int __meminit vmemmap_populate_compound_
 			 * page whose VMEMMAP_RESERVE_NR pages were mapped and
 			 * this request fall in those pages.
 			 */
-			addr_pfn += 1;
 			next = addr + PAGE_SIZE;
 			continue;
 		} else {
 			unsigned long nr_pages = pgmap_vmemmap_nr(pgmap);
+			unsigned long addr_pfn = page_to_pfn((struct page *)addr);
 			unsigned long pfn_offset = addr_pfn - ALIGN_DOWN(addr_pfn, nr_pages);
 			pte_t *tail_page_pte;
 
@@ -1375,7 +1373,6 @@ int __meminit vmemmap_populate_compound_
 				if (!pte)
 					return -ENOMEM;
 
-				addr_pfn += 2;
 				next = addr + 2 * PAGE_SIZE;
 				continue;
 			}
@@ -1391,7 +1388,6 @@ int __meminit vmemmap_populate_compound_
 					return -ENOMEM;
 				vmemmap_verify(pte, node, addr, addr + PAGE_SIZE);
 
-				addr_pfn += 1;
 				next = addr + PAGE_SIZE;
 				continue;
 			}
@@ -1401,7 +1397,6 @@ int __meminit vmemmap_populate_compound_
 				return -ENOMEM;
 			vmemmap_verify(pte, node, addr, addr + PAGE_SIZE);
 
-			addr_pfn += 1;
 			next = addr + PAGE_SIZE;
 			continue;
 		}
author maintainer
#124 lore raw

PATCH 124/583 powerpc/pseries: Handle and log pseries-wdt registration failures

In reply to Greg Kroah-Hartman

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

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

From: Sourabh Jain <[email protected]>

commit e65b526affa621b50646cafdf6b06505af07032e upstream.

The pseries watchdog initialization registers the pseries-wdt platform device using platform_device_register_simple(), but currently ignores its return value.

Check the returned pointer for errors, log a descriptive error message when registration fails, and propagate the failure code to the caller. This avoids silently ignoring platform device registration failures.

---
 arch/powerpc/platforms/pseries/setup.c |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
arch/powerpc/platforms/pseries/setup.c +12 -2
@@ -193,8 +193,18 @@ static void __init fwnmi_init(void)
  */
 static __init int pseries_wdt_init(void)
 {
-	if (firmware_has_feature(FW_FEATURE_WATCHDOG))
-		platform_device_register_simple("pseries-wdt", 0, NULL, 0);
+	struct platform_device *pdev;
+
+	if (!firmware_has_feature(FW_FEATURE_WATCHDOG))
+		return 0;
+
+	pdev = platform_device_register_simple("pseries-wdt", 0, NULL, 0);
+
+	if (IS_ERR(pdev)) {
+		pr_err("Failed to register pseries-wdt platform device\n");
+		return PTR_ERR(pdev);
+	}
+
 	return 0;
 }
 machine_subsys_initcall(pseries, pseries_wdt_init);
author maintainer
#125 lore raw

PATCH 125/583 powerpc/pseries: Move H_WATCHDOG definitions to a common header

In reply to Greg Kroah-Hartman

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

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

From: Sourabh Jain <[email protected]>

commit 516a254918453ec99660201263d01189c082332c upstream.

The H_WATCHDOG input and output definitions are currently local to the pseries watchdog driver. The next patch in this series also needs these definitions to issue H_WATCHDOG hypercalls outside the watchdog driver.

Move the H_WATCHDOG definitions to a new common header, asm/papr-watchdog.h, so they can be shared without duplicating the PAPR watchdog definitions.

No functional changes.

---
 arch/powerpc/include/asm/papr-watchdog.h |   58 +++++++++++++++++++++++++++++++
 drivers/watchdog/pseries-wdt.c           |   53 ----------------------------
 2 files changed, 59 insertions(+), 52 deletions(-)
 create mode 100644 arch/powerpc/include/asm/papr-watchdog.h
arch/powerpc/include/asm/papr-watchdog.h new file +58 -0
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ASM_POWERPC_PAPR_WATCHDOG_H
+#define _ASM_POWERPC_PAPR_WATCHDOG_H
+
+/*
+ * H_WATCHDOG Input
+ *
+ * R4: "flags":
+ *
+ *         Bits 48-55: "operation"
+ */
+#define PSERIES_WDTF_OP_START	0x100UL		/* start timer */
+#define PSERIES_WDTF_OP_STOP	0x200UL		/* stop timer */
+#define PSERIES_WDTF_OP_QUERY	0x300UL		/* query timer capabilities */
+
+/*
+ *         Bits 56-63: "timeoutAction" (for "Start Watchdog" only)
+ */
+#define PSERIES_WDTF_ACTION_HARD_POWEROFF	0x1UL	/* poweroff */
+#define PSERIES_WDTF_ACTION_HARD_RESTART	0x2UL	/* restart */
+#define PSERIES_WDTF_ACTION_DUMP_RESTART	0x3UL	/* dump + restart */
+
+/*
+ * H_WATCHDOG Output
+ *
+ * R3: Return code
+ *
+ *     H_SUCCESS    The operation completed.
+ *
+ *     H_BUSY	    The hypervisor is too busy; retry the operation.
+ *
+ *     H_PARAMETER  The given "flags" are somehow invalid.  Either the
+ *                  "operation" or "timeoutAction" is invalid, or a
+ *                  reserved bit is set.
+ *
+ *     H_P2         The given "watchdogNumber" is zero or exceeds the
+ *                  supported maximum value.
+ *
+ *     H_P3         The given "timeoutInMs" is below the supported
+ *                  minimum value.
+ *
+ *     H_NOOP       The given "watchdogNumber" is already stopped.
+ *
+ *     H_HARDWARE   The operation failed for ineffable reasons.
+ *
+ *     H_FUNCTION   The H_WATCHDOG hypercall is not supported by this
+ *                  hypervisor.
+ *
+ * R4:
+ *
+ * - For the "Query Watchdog Capabilities" operation, a 64-bit
+ *   structure:
+ */
+#define PSERIES_WDTQ_MIN_TIMEOUT(cap)	(((cap) >> 48) & 0xffff)
+#define PSERIES_WDTQ_MAX_NUMBER(cap)	(((cap) >> 32) & 0xffff)
+
+#endif /* _ASM_POWERPC_PAPR_WATCHDOG_H */
drivers/watchdog/pseries-wdt.c +1 -52

62 lines not on this page · raw message